]>
git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/SockInterface.c
2 Interface function of the Socket.
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Check whether the Event is in the List.
21 @param[in] List Pointer to the token list to be searched.
22 @param[in] 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
) {
53 Call SockTokenExistedInList() to check whether the Event is
54 in the related socket's lists.
56 @param[in] Sock Pointer to the instance's socket.
57 @param[in] Event The event to be checked.
59 @retval TRUE The Event exists in related socket's lists.
60 @retval FALSE The Event is not in related socket's lists.
70 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
71 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
72 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
73 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)
79 if ((Sock
->ConnectionToken
!= NULL
) && (Sock
->ConnectionToken
->Event
== Event
)) {
84 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
92 Buffer a token into the specific list of the socket Sock.
94 @param[in] Sock Pointer to the instance's socket.
95 @param[in] List Pointer to the list to store the token.
96 @param[in] Token Pointer to the token to be buffered.
97 @param[in] DataLen The data length of the buffer contained in Token.
99 @return Pointer to the token that wraps Token. If NULL, an error condition occurred.
110 SOCK_TOKEN
*SockToken
;
112 SockToken
= AllocateZeroPool (sizeof (SOCK_TOKEN
));
113 if (NULL
== SockToken
) {
117 "SockBufferIOToken: No Memory to allocate SockToken\n")
123 SockToken
->Sock
= Sock
;
124 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
125 SockToken
->RemainDataLen
= DataLen
;
126 InsertTailList (List
, &SockToken
->TokenList
);
132 Destroy the socket Sock and its associated protocol control block.
134 @param[in, out] Sock The socket to be destroyed.
136 @retval EFI_SUCCESS The socket Sock was destroyed successfully.
137 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
147 ASSERT ((Sock
!= NULL
) && (Sock
->ProtoHandler
!= NULL
));
149 if (Sock
->InDestroy
) {
153 Sock
->InDestroy
= TRUE
;
155 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
156 if (EFI_ERROR (Status
)) {
160 "SockDestroyChild: Get the lock to access socket failed with %r\n",
164 return EFI_ACCESS_DENIED
;
168 // force protocol layer to detach the PCB
170 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
172 if (EFI_ERROR (Status
)) {
176 "SockDestroyChild: Protocol detach socket failed with %r\n",
180 Sock
->InDestroy
= FALSE
;
181 } else if (SOCK_IS_CONFIGURED (Sock
)) {
183 SockConnFlush (Sock
);
184 SockSetState (Sock
, SO_CLOSED
);
186 Sock
->ConfigureState
= SO_UNCONFIGURED
;
189 EfiReleaseLock (&(Sock
->Lock
));
191 if (EFI_ERROR (Status
)) {
200 Create a socket and its associated protocol control block
201 with the intial data SockInitData and protocol specific
204 @param[in] SockInitData Inital data to setting the socket.
206 @return Pointer to the newly created socket. If NULL, an error condition occured.
211 IN SOCK_INIT_DATA
*SockInitData
218 // create a new socket
220 Sock
= SockCreate (SockInitData
);
225 "SockCreateChild: No resource to create a new socket\n")
231 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
232 if (EFI_ERROR (Status
)) {
236 "SockCreateChild: Get the lock to access socket failed with %r\n",
244 // inform the protocol layer to attach the socket
245 // with a new protocol control block
247 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
248 EfiReleaseLock (&(Sock
->Lock
));
249 if (EFI_ERROR (Status
)) {
253 "SockCreateChild: Protocol failed to attach a socket with %r\n",
265 Configure the specific socket Sock using configuration data ConfigData.
267 @param[in] Sock Pointer to the socket to be configured.
268 @param[in] ConfigData Pointer to the configuration data.
270 @retval EFI_SUCCESS The socket configured successfully.
271 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
272 socket is already configured.
283 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
284 if (EFI_ERROR (Status
)) {
288 "SockConfigure: Get the access for socket failed with %r",
292 return EFI_ACCESS_DENIED
;
295 if (SOCK_IS_CONFIGURED (Sock
)) {
296 Status
= EFI_ACCESS_DENIED
;
300 ASSERT (Sock
->State
== SO_CLOSED
);
302 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
305 EfiReleaseLock (&(Sock
->Lock
));
311 Initiate a connection establishment process.
313 @param[in] Sock Pointer to the socket to initiate the initate the
315 @param[in] Token Pointer to the token used for the connection
318 @retval EFI_SUCCESS The connection initialized successfully.
319 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
320 socket is closed, or the socket is not configured to
321 be an active one, or the token is already in one of
323 @retval EFI_NO_MAPPING The IP address configuration operation is not
325 @retval EFI_NOT_STARTED The socket is not configured.
337 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
338 if (EFI_ERROR (Status
)) {
342 "SockConnect: Get the access for socket failed with %r",
346 return EFI_ACCESS_DENIED
;
349 if (SOCK_IS_NO_MAPPING (Sock
)) {
350 Status
= EFI_NO_MAPPING
;
354 if (SOCK_IS_UNCONFIGURED (Sock
)) {
356 Status
= EFI_NOT_STARTED
;
360 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
362 Status
= EFI_ACCESS_DENIED
;
366 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
368 if (SockTokenExisted (Sock
, Event
)) {
370 Status
= EFI_ACCESS_DENIED
;
374 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
375 SockSetState (Sock
, SO_CONNECTING
);
376 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
379 EfiReleaseLock (&(Sock
->Lock
));
384 Issue a listen token to get an existed connected network instance
385 or wait for a connection if there is none.
387 @param[in] Sock Pointer to the socket to accept connections.
388 @param[in] Token The token to accept a connection.
390 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
391 buffered for further acception.
392 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
393 socket is closed, or the socket is not configured to
394 be a passive one, or the token is already in one of
396 @retval EFI_NO_MAPPING The IP address configuration operation is not
398 @retval EFI_NOT_STARTED The socket is not configured.
399 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limits.
408 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
409 LIST_ENTRY
*ListEntry
;
414 ASSERT (SockStream
== Sock
->Type
);
416 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
417 if (EFI_ERROR (Status
)) {
421 "SockAccept: Get the access for socket failed with %r",
425 return EFI_ACCESS_DENIED
;
428 if (SOCK_IS_NO_MAPPING (Sock
)) {
429 Status
= EFI_NO_MAPPING
;
433 if (SOCK_IS_UNCONFIGURED (Sock
)) {
435 Status
= EFI_NOT_STARTED
;
439 if (!SOCK_IS_LISTENING (Sock
)) {
441 Status
= EFI_ACCESS_DENIED
;
445 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
447 if (SockTokenExisted (Sock
, Event
)) {
449 Status
= EFI_ACCESS_DENIED
;
453 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
456 // Check if a connection has already in this Sock->ConnectionList
458 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
460 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
462 if (SOCK_IS_CONNECTED (Socket
)) {
463 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
464 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
466 RemoveEntryList (ListEntry
);
468 ASSERT (Socket
->Parent
!= NULL
);
470 Socket
->Parent
->ConnCnt
--;
474 "SockAccept: Accept a socket, now conncount is %d",
475 Socket
->Parent
->ConnCnt
)
477 Socket
->Parent
= NULL
;
484 // Buffer this token for latter incoming connection request
486 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
488 Status
= EFI_OUT_OF_RESOURCES
;
492 EfiReleaseLock (&(Sock
->Lock
));
498 Issue a token with data to the socket to send out.
500 @param[in] Sock Pointer to the socket to process the token with
502 @param[in] Token The token with data that needs to send out.
504 @retval EFI_SUCCESS The token processed successfully.
505 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
506 socket is closed, or the socket is not in a
507 synchronized state , or the token is already in one
508 of this socket's lists.
509 @retval EFI_NO_MAPPING The IP address configuration operation is not
511 @retval EFI_NOT_STARTED The socket is not configured.
512 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limits.
521 SOCK_IO_TOKEN
*SndToken
;
524 EFI_TCP4_TRANSMIT_DATA
*TxData
;
526 SOCK_TOKEN
*SockToken
;
529 ASSERT (SockStream
== Sock
->Type
);
531 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
532 if (EFI_ERROR (Status
)) {
536 "SockSend: Get the access for socket failed with %r",
540 return EFI_ACCESS_DENIED
;
543 if (SOCK_IS_NO_MAPPING (Sock
)) {
544 Status
= EFI_NO_MAPPING
;
548 SndToken
= (SOCK_IO_TOKEN
*) Token
;
549 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
551 if (SOCK_IS_UNCONFIGURED (Sock
)) {
552 Status
= EFI_NOT_STARTED
;
556 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
558 Status
= EFI_ACCESS_DENIED
;
563 // check if a token is already in the token buffer
565 Event
= SndToken
->Token
.Event
;
567 if (SockTokenExisted (Sock
, Event
)) {
568 Status
= EFI_ACCESS_DENIED
;
572 DataLen
= TxData
->DataLength
;
575 // process this sending token now or buffer it only?
577 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
579 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
581 SockToken
= SockBufferToken (
588 if (NULL
== SockToken
) {
589 Status
= EFI_OUT_OF_RESOURCES
;
593 SockToken
= SockBufferToken (
595 &Sock
->ProcessingSndTokenList
,
600 if (NULL
== SockToken
) {
603 "SockSend: Failed to buffer IO token into socket processing SndToken List\n",
607 Status
= EFI_OUT_OF_RESOURCES
;
611 Status
= SockProcessTcpSndData (Sock
, TxData
);
613 if (EFI_ERROR (Status
)) {
616 "SockSend: Failed to process Snd Data\n",
620 RemoveEntryList (&(SockToken
->TokenList
));
621 FreePool (SockToken
);
626 EfiReleaseLock (&(Sock
->Lock
));
631 Issue a token to get data from the socket.
633 @param[in] Sock Pointer to the socket to get data from.
634 @param[in] Token The token to store the received data from the
637 @retval EFI_SUCCESS The token processed successfully.
638 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
639 socket is closed, or the socket is not in a
640 synchronized state , or the token is already in one
641 of this socket's lists.
642 @retval EFI_NO_MAPPING The IP address configuration operation is not
644 @retval EFI_NOT_STARTED The socket is not configured.
645 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
646 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
655 SOCK_IO_TOKEN
*RcvToken
;
660 ASSERT (SockStream
== Sock
->Type
);
662 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
663 if (EFI_ERROR (Status
)) {
667 "SockRcv: Get the access for socket failed with %r",
671 return EFI_ACCESS_DENIED
;
674 if (SOCK_IS_NO_MAPPING (Sock
)) {
676 Status
= EFI_NO_MAPPING
;
680 if (SOCK_IS_UNCONFIGURED (Sock
)) {
682 Status
= EFI_NOT_STARTED
;
686 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
688 Status
= EFI_ACCESS_DENIED
;
692 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
695 // check if a token is already in the token buffer of this socket
697 Event
= RcvToken
->Token
.Event
;
698 if (SockTokenExisted (Sock
, Event
)) {
699 Status
= EFI_ACCESS_DENIED
;
703 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
704 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
707 // check whether an error has happened before
709 if (EFI_ABORTED
!= Sock
->SockError
) {
711 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
712 Sock
->SockError
= EFI_ABORTED
;
717 // check whether can not receive and there is no any
718 // data buffered in Sock->RcvBuffer
720 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
722 Status
= EFI_CONNECTION_FIN
;
726 if (RcvdBytes
!= 0) {
727 SockProcessRcvToken (Sock
, RcvToken
);
729 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
732 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
733 Status
= EFI_OUT_OF_RESOURCES
;
738 EfiReleaseLock (&(Sock
->Lock
));
743 Reset the socket and its associated protocol control block.
745 @param[in, out] Sock Pointer to the socket to be flushed.
747 @retval EFI_SUCCESS The socket is flushed successfully.
748 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
758 ASSERT (SockStream
== Sock
->Type
);
760 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
761 if (EFI_ERROR (Status
)) {
765 "SockFlush: Get the access for socket failed with %r",
769 return EFI_ACCESS_DENIED
;
772 if (!SOCK_IS_CONFIGURED (Sock
)) {
774 Status
= EFI_ACCESS_DENIED
;
778 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
779 if (EFI_ERROR (Status
)) {
783 "SockFlush: Protocol failed handling SOCK_FLUSH with %r",
790 SOCK_ERROR (Sock
, EFI_ABORTED
);
791 SockConnFlush (Sock
);
792 SockSetState (Sock
, SO_CLOSED
);
794 Sock
->ConfigureState
= SO_UNCONFIGURED
;
797 EfiReleaseLock (&(Sock
->Lock
));
802 Close or abort the socket associated connection.
804 @param[in, out] Sock Pointer to the socket of the connection to close
806 @param[in] Token The token for a close operation.
807 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.
809 @retval EFI_SUCCESS The close or abort operation initialized
811 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
812 socket is closed, or the socket is not in a
813 synchronized state , or the token is already in one
814 of this socket's lists.
815 @retval EFI_NO_MAPPING The IP address configuration operation is not
817 @retval EFI_NOT_STARTED The socket is not configured.
830 ASSERT (SockStream
== Sock
->Type
);
832 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
833 if (EFI_ERROR (Status
)) {
836 "SockClose: Get the access for socket failed with %r",
840 return EFI_ACCESS_DENIED
;
843 if (SOCK_IS_NO_MAPPING (Sock
)) {
844 Status
= EFI_NO_MAPPING
;
848 if (SOCK_IS_UNCONFIGURED (Sock
)) {
849 Status
= EFI_NOT_STARTED
;
853 if (SOCK_IS_DISCONNECTING (Sock
)) {
854 Status
= EFI_ACCESS_DENIED
;
858 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
860 if (SockTokenExisted (Sock
, Event
)) {
861 Status
= EFI_ACCESS_DENIED
;
865 Sock
->CloseToken
= Token
;
866 SockSetState (Sock
, SO_DISCONNECTING
);
869 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
871 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
875 EfiReleaseLock (&(Sock
->Lock
));
880 Abort the socket associated connection, listen, transmission or receive request.
882 @param[in, out] Sock Pointer to the socket to abort.
883 @param[in] Token Pointer to a token that has been issued by
884 Connect(), Accept(), Transmit() or Receive(). If
885 NULL, all pending tokens issued by the four
886 functions listed above will be aborted.
888 @retval EFI_UNSUPPORTED The operation is not supported in the current
899 Status
= EFI_SUCCESS
;
901 ASSERT (SockStream
== Sock
->Type
);
903 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
904 if (EFI_ERROR (Status
)) {
907 "SockCancel: Get the access for socket failed with %r",
911 return EFI_ACCESS_DENIED
;
914 if (SOCK_IS_UNCONFIGURED (Sock
)) {
915 Status
= EFI_NOT_STARTED
;
920 // 1. Check ConnectionToken.
922 if (Token
== NULL
|| (SOCK_COMPLETION_TOKEN
*) Token
== Sock
->ConnectionToken
) {
923 if (Sock
->ConnectionToken
!= NULL
) {
924 SIGNAL_TOKEN (Sock
->ConnectionToken
, EFI_ABORTED
);
925 Sock
->ConnectionToken
= NULL
;
929 Status
= EFI_SUCCESS
;
935 // 2. Check ListenTokenList.
937 Status
= SockCancelToken (Token
, &Sock
->ListenTokenList
);
938 if (Token
!= NULL
&& !EFI_ERROR (Status
)) {
943 // 3. Check RcvTokenList.
945 Status
= SockCancelToken (Token
, &Sock
->RcvTokenList
);
946 if (Token
!= NULL
&& !EFI_ERROR (Status
)) {
951 // 4. Check SndTokenList.
953 Status
= SockCancelToken (Token
, &Sock
->SndTokenList
);
954 if (Token
!= NULL
&& !EFI_ERROR (Status
)) {
959 // 5. Check ProcessingSndTokenList.
961 Status
= SockCancelToken (Token
, &Sock
->ProcessingSndTokenList
);
964 EfiReleaseLock (&(Sock
->Lock
));
970 Get the mode data of the low layer protocol.
972 @param[in] Sock Pointer to the socket to get mode data from.
973 @param[in, out] Mode Pointer to the data to store the low layer mode
976 @retval EFI_SUCCESS The mode data was obtained successfully.
977 @retval EFI_NOT_STARTED The socket is not configured.
986 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
990 Configure the low level protocol to join a multicast group for
991 this socket's connection.
993 @param[in] Sock Pointer to the socket of the connection to join the
994 specific multicast group.
995 @param[in] GroupInfo Pointer to the multicast group info.
997 @retval EFI_SUCCESS The configuration completed successfully.
998 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
999 @retval EFI_NOT_STARTED The socket is not configured.
1010 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
1012 if (EFI_ERROR (Status
)) {
1016 "SockGroup: Get the access for socket failed with %r",
1020 return EFI_ACCESS_DENIED
;
1023 if (SOCK_IS_UNCONFIGURED (Sock
)) {
1024 Status
= EFI_NOT_STARTED
;
1028 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
1031 EfiReleaseLock (&(Sock
->Lock
));
1036 Add or remove route information in IP route table associated
1039 @param[in] Sock Pointer to the socket associated with the IP route
1040 table to operate on.
1041 @param[in] RouteInfo Pointer to the route information to be processed.
1043 @retval EFI_SUCCESS The route table updated successfully.
1044 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
1045 @retval EFI_NO_MAPPING The IP address configuration operation is not
1047 @retval EFI_NOT_STARTED The socket is not configured.
1058 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
1059 if (EFI_ERROR (Status
)) {
1062 "SockRoute: Get the access for socket failed with %r",
1066 return EFI_ACCESS_DENIED
;
1069 if (SOCK_IS_NO_MAPPING (Sock
)) {
1070 Status
= EFI_NO_MAPPING
;
1074 if (SOCK_IS_UNCONFIGURED (Sock
)) {
1075 Status
= EFI_NOT_STARTED
;
1079 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
1082 EfiReleaseLock (&(Sock
->Lock
));