]>
git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/TcpDxe/SockInterface.c
2 Interface function of the Socket.
4 Copyright (c) 2009 - 2012, 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 Status
= SockProcessRcvToken (Sock
, RcvToken
);
729 if (EFI_ERROR (Status
)) {
733 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
736 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
737 Status
= EFI_OUT_OF_RESOURCES
;
742 EfiReleaseLock (&(Sock
->Lock
));
747 Reset the socket and its associated protocol control block.
749 @param[in, out] Sock Pointer to the socket to be flushed.
751 @retval EFI_SUCCESS The socket is flushed successfully.
752 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
762 ASSERT (SockStream
== Sock
->Type
);
764 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
765 if (EFI_ERROR (Status
)) {
769 "SockFlush: Get the access for socket failed with %r",
773 return EFI_ACCESS_DENIED
;
776 if (!SOCK_IS_CONFIGURED (Sock
)) {
778 Status
= EFI_ACCESS_DENIED
;
782 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
783 if (EFI_ERROR (Status
)) {
787 "SockFlush: Protocol failed handling SOCK_FLUSH with %r",
794 SOCK_ERROR (Sock
, EFI_ABORTED
);
795 SockConnFlush (Sock
);
796 SockSetState (Sock
, SO_CLOSED
);
798 Sock
->ConfigureState
= SO_UNCONFIGURED
;
801 EfiReleaseLock (&(Sock
->Lock
));
806 Close or abort the socket associated connection.
808 @param[in, out] Sock Pointer to the socket of the connection to close
810 @param[in] Token The token for a close operation.
811 @param[in] OnAbort TRUE for aborting the connection; FALSE to close it.
813 @retval EFI_SUCCESS The close or abort operation initialized
815 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
816 socket is closed, or the socket is not in a
817 synchronized state , or the token is already in one
818 of this socket's lists.
819 @retval EFI_NO_MAPPING The IP address configuration operation is not
821 @retval EFI_NOT_STARTED The socket is not configured.
834 ASSERT (SockStream
== Sock
->Type
);
836 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
837 if (EFI_ERROR (Status
)) {
840 "SockClose: Get the access for socket failed with %r",
844 return EFI_ACCESS_DENIED
;
847 if (SOCK_IS_NO_MAPPING (Sock
)) {
848 Status
= EFI_NO_MAPPING
;
852 if (SOCK_IS_UNCONFIGURED (Sock
)) {
853 Status
= EFI_NOT_STARTED
;
857 if (SOCK_IS_DISCONNECTING (Sock
)) {
858 Status
= EFI_ACCESS_DENIED
;
862 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
864 if (SockTokenExisted (Sock
, Event
)) {
865 Status
= EFI_ACCESS_DENIED
;
869 Sock
->CloseToken
= Token
;
870 SockSetState (Sock
, SO_DISCONNECTING
);
873 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
875 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
879 EfiReleaseLock (&(Sock
->Lock
));
884 Get the mode data of the low layer protocol.
886 @param[in] Sock Pointer to the socket to get mode data from.
887 @param[in, out] Mode Pointer to the data to store the low layer mode
890 @retval EFI_SUCCESS The mode data was obtained successfully.
891 @retval EFI_NOT_STARTED The socket is not configured.
900 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
904 Configure the low level protocol to join a multicast group for
905 this socket's connection.
907 @param[in] Sock Pointer to the socket of the connection to join the
908 specific multicast group.
909 @param[in] GroupInfo Pointer to the multicast group info.
911 @retval EFI_SUCCESS The configuration completed successfully.
912 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
913 @retval EFI_NOT_STARTED The socket is not configured.
924 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
926 if (EFI_ERROR (Status
)) {
930 "SockGroup: Get the access for socket failed with %r",
934 return EFI_ACCESS_DENIED
;
937 if (SOCK_IS_UNCONFIGURED (Sock
)) {
938 Status
= EFI_NOT_STARTED
;
942 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
945 EfiReleaseLock (&(Sock
->Lock
));
950 Add or remove route information in IP route table associated
953 @param[in] Sock Pointer to the socket associated with the IP route
955 @param[in] RouteInfo Pointer to the route information to be processed.
957 @retval EFI_SUCCESS The route table updated successfully.
958 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
959 @retval EFI_NO_MAPPING The IP address configuration operation is not
961 @retval EFI_NOT_STARTED The socket is not configured.
972 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
973 if (EFI_ERROR (Status
)) {
976 "SockRoute: Get the access for socket failed with %r",
980 return EFI_ACCESS_DENIED
;
983 if (SOCK_IS_NO_MAPPING (Sock
)) {
984 Status
= EFI_NO_MAPPING
;
988 if (SOCK_IS_UNCONFIGURED (Sock
)) {
989 Status
= EFI_NOT_STARTED
;
993 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
996 EfiReleaseLock (&(Sock
->Lock
));