]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
3 Copyright (c) 2005 - 2006, Intel Corporation<BR>
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php<BR>
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Check whether the Event is in the List.
21 @param List Pointer to the token list to be searched.
22 @param Event The event to be checked.
24 @retval TRUE The specific Event exists in the List.
25 @retval FALSE The specific Event is not in the List.
29 SockTokenExistedInList (
34 LIST_ENTRY
*ListEntry
;
35 SOCK_TOKEN
*SockToken
;
37 NET_LIST_FOR_EACH (ListEntry
, List
) {
38 SockToken
= NET_LIST_USER_STRUCT (
44 if (Event
== SockToken
->Token
->Event
) {
54 Call SockTokenExistedInList() to check whether the Event is
55 in the related socket's lists.
57 @param Sock Pointer to the instance's socket.
58 @param Event The event to be checked.
60 @retval TRUE The Event exists in related socket's lists.
61 @retval FALSE The Event is not in related socket's lists.
71 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
72 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
73 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
74 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)) {
79 if ((Sock
->ConnectionToken
!= NULL
) &&
80 (Sock
->ConnectionToken
->Event
== Event
)) {
85 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
94 Buffer a token into the specific list of socket Sock.
96 @param Sock Pointer to the instance's socket.
97 @param List Pointer to the list to store the token.
98 @param Token Pointer to the token to be buffered.
99 @param DataLen The data length of the buffer contained in Token.
101 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
112 SOCK_TOKEN
*SockToken
;
114 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
115 if (NULL
== SockToken
) {
117 DEBUG ((EFI_D_ERROR
, "SockBufferIOToken: No Memory "
118 "to allocate SockToken\n"));
123 SockToken
->Sock
= Sock
;
124 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
125 SockToken
->RemainDataLen
= DataLen
;
126 InsertTailList (List
, &SockToken
->TokenList
);
133 Destory the socket Sock and its associated protocol control block.
135 @param Sock The socket to be destroyed.
137 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
138 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
148 ASSERT ((Sock
!= NULL
) && (Sock
->ProtoHandler
!= NULL
));
150 if (Sock
->IsDestroyed
) {
154 Sock
->IsDestroyed
= TRUE
;
156 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
157 if (EFI_ERROR (Status
)) {
159 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Get the lock to "
160 "access socket failed with %r\n", Status
));
162 return EFI_ACCESS_DENIED
;
166 // force protocol layer to detach the PCB
168 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
170 if (EFI_ERROR (Status
)) {
172 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Protocol detach socket"
173 " failed with %r\n", Status
));
175 Sock
->IsDestroyed
= FALSE
;
176 } else if (SOCK_IS_CONFIGURED (Sock
)) {
178 SockConnFlush (Sock
);
179 SockSetState (Sock
, SO_CLOSED
);
181 Sock
->ConfigureState
= SO_UNCONFIGURED
;
184 EfiReleaseLock (&(Sock
->Lock
));
186 if (EFI_ERROR (Status
)) {
196 Create a socket and its associated protocol control block
197 with the intial data SockInitData and protocol specific
200 @param SockInitData Inital data to setting the socket.
202 @return Pointer to the newly created socket. If NULL, error condition occured.
207 IN SOCK_INIT_DATA
*SockInitData
214 // create a new socket
216 Sock
= SockCreate (SockInitData
);
219 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
220 "create a new socket\n"));
225 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
226 if (EFI_ERROR (Status
)) {
228 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
229 "access socket failed with %r\n", Status
));
235 // inform the protocol layer to attach the socket
236 // with a new protocol control block
238 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
239 if (EFI_ERROR (Status
)) {
241 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
242 " attach a socket with %r\n", Status
));
248 EfiReleaseLock (&(Sock
->Lock
));
254 Configure the specific socket Sock using configuration data ConfigData.
256 @param Sock Pointer to the socket to be configured.
257 @param ConfigData Pointer to the configuration data.
259 @retval EFI_SUCCESS The socket is configured successfully.
260 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
261 socket is already configured.
272 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
273 if (EFI_ERROR (Status
)) {
275 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
276 "socket failed with %r", Status
));
278 return EFI_ACCESS_DENIED
;
281 if (SOCK_IS_CONFIGURED (Sock
)) {
282 Status
= EFI_ACCESS_DENIED
;
286 ASSERT (Sock
->State
== SO_CLOSED
);
288 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
291 EfiReleaseLock (&(Sock
->Lock
));
298 Initiate a connection establishment process.
300 @param Sock Pointer to the socket to initiate the initate the
302 @param Token Pointer to the token used for the connection
305 @retval EFI_SUCCESS The connection is initialized successfully.
306 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
307 socket is closed, or the socket is not configured to
308 be an active one, or the token is already in one of
310 @retval EFI_NO_MAPPING The IP address configuration operation is not
312 @retval EFI_NOT_STARTED The socket is not configured.
324 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
325 if (EFI_ERROR (Status
)) {
327 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
328 "socket failed with %r", Status
));
330 return EFI_ACCESS_DENIED
;
333 if (SOCK_IS_NO_MAPPING (Sock
)) {
334 Status
= EFI_NO_MAPPING
;
338 if (SOCK_IS_UNCONFIGURED (Sock
)) {
340 Status
= EFI_NOT_STARTED
;
344 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
346 Status
= EFI_ACCESS_DENIED
;
350 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
352 if (SockTokenExisted (Sock
, Event
)) {
354 Status
= EFI_ACCESS_DENIED
;
358 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
359 SockSetState (Sock
, SO_CONNECTING
);
360 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
363 EfiReleaseLock (&(Sock
->Lock
));
369 Issue a listen token to get an existed connected network instance
370 or wait for a connection if there is none.
372 @param Sock Pointer to the socket to accept connections.
373 @param Token The token to accept a connection.
375 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
376 buffered for further acception.
377 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
378 socket is closed, or the socket is not configured to
379 be a passive one, or the token is already in one of
381 @retval EFI_NO_MAPPING The IP address configuration operation is not
383 @retval EFI_NOT_STARTED The socket is not configured.
384 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
393 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
394 LIST_ENTRY
*ListEntry
;
399 ASSERT (SOCK_STREAM
== Sock
->Type
);
401 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
402 if (EFI_ERROR (Status
)) {
404 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
405 " failed with %r", Status
));
407 return EFI_ACCESS_DENIED
;
410 if (SOCK_IS_NO_MAPPING (Sock
)) {
411 Status
= EFI_NO_MAPPING
;
415 if (SOCK_IS_UNCONFIGURED (Sock
)) {
417 Status
= EFI_NOT_STARTED
;
421 if (!SOCK_IS_LISTENING (Sock
)) {
423 Status
= EFI_ACCESS_DENIED
;
427 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
429 if (SockTokenExisted (Sock
, Event
)) {
431 Status
= EFI_ACCESS_DENIED
;
435 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
438 // Check if a connection has already in this Sock->ConnectionList
440 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
442 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
444 if (SOCK_IS_CONNECTED (Socket
)) {
445 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
446 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
448 RemoveEntryList (ListEntry
);
450 ASSERT (Socket
->Parent
!= NULL
);
452 Socket
->Parent
->ConnCnt
--;
456 "SockAccept: Accept a socket, now conncount is %d",
457 Socket
->Parent
->ConnCnt
)
459 Socket
->Parent
= NULL
;
466 // Buffer this token for latter incoming connection request
468 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
470 Status
= EFI_OUT_OF_RESOURCES
;
474 EfiReleaseLock (&(Sock
->Lock
));
481 Issue a token with data to the socket to send out.
483 @param Sock Pointer to the socket to process the token with
485 @param Token The token with data that needs to send out.
487 @retval EFI_SUCCESS The token is processed successfully.
488 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
489 socket is closed, or the socket is not in a
490 synchronized state , or the token is already in one
491 of this socket's lists.
492 @retval EFI_NO_MAPPING The IP address configuration operation is not
494 @retval EFI_NOT_STARTED The socket is not configured.
495 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
504 SOCK_IO_TOKEN
*SndToken
;
507 EFI_TCP4_TRANSMIT_DATA
*TxData
;
509 SOCK_TOKEN
*SockToken
;
512 ASSERT (SOCK_STREAM
== Sock
->Type
);
514 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
515 if (EFI_ERROR (Status
)) {
517 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
518 " failed with %r", Status
));
520 return EFI_ACCESS_DENIED
;
523 if (SOCK_IS_NO_MAPPING (Sock
)) {
524 Status
= EFI_NO_MAPPING
;
528 SndToken
= (SOCK_IO_TOKEN
*) Token
;
529 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
531 if (SOCK_IS_UNCONFIGURED (Sock
)) {
532 Status
= EFI_NOT_STARTED
;
536 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
538 Status
= EFI_ACCESS_DENIED
;
543 // check if a token is already in the token buffer
545 Event
= SndToken
->Token
.Event
;
547 if (SockTokenExisted (Sock
, Event
)) {
548 Status
= EFI_ACCESS_DENIED
;
552 DataLen
= (UINT32
) TxData
->DataLength
;
555 // process this sending token now or buffer it only?
557 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
559 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
561 SockToken
= SockBufferToken (
568 if (NULL
== SockToken
) {
569 Status
= EFI_OUT_OF_RESOURCES
;
573 SockToken
= SockBufferToken (
575 &Sock
->ProcessingSndTokenList
,
580 if (NULL
== SockToken
) {
581 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
582 " socket processing SndToken List\n", Status
));
584 Status
= EFI_OUT_OF_RESOURCES
;
588 Status
= SockProcessTcpSndData (Sock
, TxData
);
590 if (EFI_ERROR (Status
)) {
591 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
592 "Snd Data\n", Status
));
594 RemoveEntryList (&(SockToken
->TokenList
));
595 gBS
->FreePool (SockToken
);
600 EfiReleaseLock (&(Sock
->Lock
));
606 Issue a token to get data from the socket.
608 @param Sock Pointer to the socket to get data from.
609 @param Token The token to store the received data from the
612 @retval EFI_SUCCESS The token is processed successfully.
613 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
614 socket is closed, or the socket is not in a
615 synchronized state , or the token is already in one
616 of this socket's lists.
617 @retval EFI_NO_MAPPING The IP address configuration operation is not
619 @retval EFI_NOT_STARTED The socket is not configured.
620 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
621 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
630 SOCK_IO_TOKEN
*RcvToken
;
635 ASSERT (SOCK_STREAM
== Sock
->Type
);
637 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
638 if (EFI_ERROR (Status
)) {
640 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
641 " failed with %r", Status
));
643 return EFI_ACCESS_DENIED
;
646 if (SOCK_IS_NO_MAPPING (Sock
)) {
648 Status
= EFI_NO_MAPPING
;
652 if (SOCK_IS_UNCONFIGURED (Sock
)) {
654 Status
= EFI_NOT_STARTED
;
658 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
660 Status
= EFI_ACCESS_DENIED
;
664 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
667 // check if a token is already in the token buffer of this socket
669 Event
= RcvToken
->Token
.Event
;
670 if (SockTokenExisted (Sock
, Event
)) {
671 Status
= EFI_ACCESS_DENIED
;
675 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
676 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
679 // check whether an error has happened before
681 if (EFI_ABORTED
!= Sock
->SockError
) {
683 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
684 Sock
->SockError
= EFI_ABORTED
;
689 // check whether can not receive and there is no any
690 // data buffered in Sock->RcvBuffer
692 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
694 Status
= EFI_CONNECTION_FIN
;
698 if (RcvdBytes
!= 0) {
699 Status
= SockProcessRcvToken (Sock
, RcvToken
);
701 if (EFI_ERROR (Status
)) {
705 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
708 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
709 Status
= EFI_OUT_OF_RESOURCES
;
714 EfiReleaseLock (&(Sock
->Lock
));
720 Reset the socket and its associated protocol control block.
722 @param Sock Pointer to the socket to be flushed.
724 @retval EFI_SUCCESS The socket is flushed successfully.
725 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
735 ASSERT (SOCK_STREAM
== Sock
->Type
);
737 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
738 if (EFI_ERROR (Status
)) {
740 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
741 " failed with %r", Status
));
743 return EFI_ACCESS_DENIED
;
746 if (!SOCK_IS_CONFIGURED (Sock
)) {
750 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
751 if (EFI_ERROR (Status
)) {
753 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
754 " SOCK_FLUSH with %r", Status
));
759 SOCK_ERROR (Sock
, EFI_ABORTED
);
760 SockConnFlush (Sock
);
761 SockSetState (Sock
, SO_CLOSED
);
763 Sock
->ConfigureState
= SO_UNCONFIGURED
;
766 EfiReleaseLock (&(Sock
->Lock
));
772 Close or abort the socket associated connection.
774 @param Sock Pointer to the socket of the connection to close or
776 @param Token The token for close operation.
777 @param OnAbort TRUE for aborting the connection, FALSE to close it.
779 @retval EFI_SUCCESS The close or abort operation is initialized
781 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
782 socket is closed, or the socket is not in a
783 synchronized state , or the token is already in one
784 of this socket's lists.
785 @retval EFI_NO_MAPPING The IP address configuration operation is not
787 @retval EFI_NOT_STARTED The socket is not configured.
800 ASSERT (SOCK_STREAM
== Sock
->Type
);
802 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
803 if (EFI_ERROR (Status
)) {
804 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
805 " failed with %r", Status
));
807 return EFI_ACCESS_DENIED
;
810 if (SOCK_IS_NO_MAPPING (Sock
)) {
811 Status
= EFI_NO_MAPPING
;
815 if (SOCK_IS_UNCONFIGURED (Sock
)) {
816 Status
= EFI_NOT_STARTED
;
820 if (SOCK_IS_DISCONNECTING (Sock
)) {
821 Status
= EFI_ACCESS_DENIED
;
825 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
827 if (SockTokenExisted (Sock
, Event
)) {
828 Status
= EFI_ACCESS_DENIED
;
832 Sock
->CloseToken
= Token
;
833 SockSetState (Sock
, SO_DISCONNECTING
);
836 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
838 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
842 EfiReleaseLock (&(Sock
->Lock
));
848 Get the mode data of the low layer protocol.
850 @param Sock Pointer to the socket to get mode data from.
851 @param Mode Pointer to the data to store the low layer mode
854 @retval EFI_SUCCESS The mode data is got successfully.
855 @retval EFI_NOT_STARTED The socket is not configured.
864 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
869 Configure the low level protocol to join a multicast group for
870 this socket's connection.
872 @param Sock Pointer to the socket of the connection to join the
873 specific multicast group.
874 @param GroupInfo Pointer to the multicast group info.
876 @retval EFI_SUCCESS The configuration is done successfully.
877 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
878 @retval EFI_NOT_STARTED The socket is not configured.
889 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
891 if (EFI_ERROR (Status
)) {
893 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
894 " failed with %r", Status
));
896 return EFI_ACCESS_DENIED
;
899 if (SOCK_IS_UNCONFIGURED (Sock
)) {
900 Status
= EFI_NOT_STARTED
;
904 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
907 EfiReleaseLock (&(Sock
->Lock
));
913 Add or remove route information in IP route table associated
916 @param Sock Pointer to the socket associated with the IP route
918 @param RouteInfo Pointer to the route information to be processed.
920 @retval EFI_SUCCESS The route table is updated successfully.
921 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
922 @retval EFI_NO_MAPPING The IP address configuration operation is not
924 @retval EFI_NOT_STARTED The socket is not configured.
935 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
936 if (EFI_ERROR (Status
)) {
937 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
938 " failed with %r", Status
));
940 return EFI_ACCESS_DENIED
;
943 if (SOCK_IS_NO_MAPPING (Sock
)) {
944 Status
= EFI_NO_MAPPING
;
948 if (SOCK_IS_UNCONFIGURED (Sock
)) {
949 Status
= EFI_NOT_STARTED
;
953 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
956 EfiReleaseLock (&(Sock
->Lock
));