]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
3 Copyright (c) 2005 - 2006, Intel Corporation
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
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.
26 Check whether the Event is in the List.
28 @param List Pointer to the token list to be searched.
29 @param Event The event to be checked.
31 @retval BOOLEAN If TRUE, the specific Event exists in the List. If
32 FALSE, the specific Event is not in the List.
37 SockTokenExistedInList (
38 IN NET_LIST_ENTRY
*List
,
42 NET_LIST_ENTRY
*ListEntry
;
43 SOCK_TOKEN
*SockToken
;
45 NET_LIST_FOR_EACH (ListEntry
, List
) {
46 SockToken
= NET_LIST_USER_STRUCT (
52 if (Event
== SockToken
->Token
->Event
) {
62 Call SockTokenExistedInList() to check whether the Event is
63 in the related socket's lists.
65 @param Sock Pointer to the instance's socket.
66 @param Event The event to be checked.
68 @return The specific Event exists in one of socket's lists or not.
78 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
79 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
80 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
81 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)
87 if ((Sock
->ConnectionToken
!= NULL
) &&
88 (Sock
->ConnectionToken
->Event
== Event
)) {
93 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
102 Buffer a token into the specific list of socket Sock.
104 @param Sock Pointer to the instance's socket.
105 @param List Pointer to the list to store the token.
106 @param Token Pointer to the token to be buffered.
107 @param DataLen The data length of the buffer contained in Token.
109 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
115 IN NET_LIST_ENTRY
*List
,
120 SOCK_TOKEN
*SockToken
;
122 SockToken
= NetAllocatePool (sizeof (SOCK_TOKEN
));
123 if (NULL
== SockToken
) {
125 SOCK_DEBUG_ERROR (("SockBufferIOToken: No Memory "
126 "to allocate SockToken\n"));
131 SockToken
->Sock
= Sock
;
132 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
133 SockToken
->RemainDataLen
= DataLen
;
134 NetListInsertTail (List
, &SockToken
->TokenList
);
141 Destory the socket Sock and its associated protocol control block.
143 @param Sock The socket to be destroyed.
145 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
146 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
156 ASSERT (Sock
&& Sock
->ProtoHandler
);
158 if (Sock
->IsDestroyed
) {
162 Sock
->IsDestroyed
= TRUE
;
164 Status
= NET_TRYLOCK (&(Sock
->Lock
));
165 if (EFI_ERROR (Status
)) {
167 SOCK_DEBUG_ERROR (("SockDestroyChild: Get the lock to "
168 "access socket failed with %r\n", Status
));
170 return EFI_ACCESS_DENIED
;
174 // force protocol layer to detach the PCB
176 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
178 if (EFI_ERROR (Status
)) {
180 SOCK_DEBUG_ERROR (("SockDestroyChild: Protocol detach socket"
181 " failed with %r\n", Status
));
183 Sock
->IsDestroyed
= FALSE
;
184 } else if (SOCK_IS_CONFIGURED (Sock
)) {
186 SockConnFlush (Sock
);
187 SockSetState (Sock
, SO_CLOSED
);
189 Sock
->ConfigureState
= SO_UNCONFIGURED
;
192 NET_UNLOCK (&(Sock
->Lock
));
194 if (EFI_ERROR (Status
)) {
204 Create a socket and its associated protocol control block
205 with the intial data SockInitData and protocol specific
208 @param SockInitData Inital data to setting the socket.
209 @param ProtoData Pointer to the protocol specific data.
210 @param Len Length of the protocol specific data.
212 @return Pointer to the newly created socket. If NULL, error condition occured.
217 IN SOCK_INIT_DATA
*SockInitData
,
225 ASSERT (ProtoData
&& (Len
<= PROTO_RESERVED_LEN
));
228 // create a new socket
230 Sock
= SockCreate (SockInitData
);
233 SOCK_DEBUG_ERROR (("SockCreateChild: No resource to "
234 "create a new socket\n"));
244 // copy the protodata into socket
246 NetCopyMem (Sock
->ProtoReserved
, ProtoData
, Len
);
248 Status
= NET_TRYLOCK (&(Sock
->Lock
));
249 if (EFI_ERROR (Status
)) {
251 SOCK_DEBUG_ERROR (("SockCreateChild: Get the lock to "
252 "access socket failed with %r\n", Status
));
258 // inform the protocol layer to attach the socket
259 // with a new protocol control block
261 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
262 if (EFI_ERROR (Status
)) {
264 SOCK_DEBUG_ERROR (("SockCreateChild: Protocol failed to"
265 " attach a socket with %r\n", Status
));
271 NET_UNLOCK (&(Sock
->Lock
));
277 Configure the specific socket Sock using configuration data
280 @param Sock Pointer to the socket to be configured.
281 @param ConfigData Pointer to the configuration data.
283 @retval EFI_SUCCESS The socket is configured successfully.
284 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
285 socket is already configured.
296 Status
= NET_TRYLOCK (&(Sock
->Lock
));
297 if (EFI_ERROR (Status
)) {
299 SOCK_DEBUG_ERROR (("SockConfigure: Get the access for "
300 "socket failed with %r", Status
));
302 return EFI_ACCESS_DENIED
;
305 if (SOCK_IS_CONFIGURED (Sock
)) {
306 Status
= EFI_ACCESS_DENIED
;
310 ASSERT (Sock
->State
== SO_CLOSED
);
312 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
315 NET_UNLOCK (&(Sock
->Lock
));
322 Initiate a connection establishment process.
324 @param Sock Pointer to the socket to initiate the initate the
326 @param Token Pointer to the token used for the connection
329 @retval EFI_SUCCESS The connection is initialized successfully.
330 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
331 socket is closed, or the socket is not configured to
332 be an active one, or the token is already in one of
334 @retval EFI_NO_MAPPING The IP address configuration operation is not
336 @retval EFI_NOT_STARTED The socket is not configured.
348 Status
= NET_TRYLOCK (&(Sock
->Lock
));
349 if (EFI_ERROR (Status
)) {
351 SOCK_DEBUG_ERROR (("SockConnect: Get the access for "
352 "socket failed with %r", Status
));
354 return EFI_ACCESS_DENIED
;
357 if (SOCK_IS_NO_MAPPING (Sock
)) {
358 Status
= EFI_NO_MAPPING
;
362 if (SOCK_IS_UNCONFIGURED (Sock
)) {
364 Status
= EFI_NOT_STARTED
;
368 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
370 Status
= EFI_ACCESS_DENIED
;
374 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
376 if (SockTokenExisted (Sock
, Event
)) {
378 Status
= EFI_ACCESS_DENIED
;
382 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
383 SockSetState (Sock
, SO_CONNECTING
);
384 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
387 NET_UNLOCK (&(Sock
->Lock
));
393 Issue a listen token to get an existed connected network instance
394 or wait for a connection if there is none.
396 @param Sock Pointer to the socket to accept connections.
397 @param Token The token to accept a connection.
399 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
400 buffered for further acception.
401 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
402 socket is closed, or the socket is not configured to
403 be a passive one, or the token is already in one of
405 @retval EFI_NO_MAPPING The IP address configuration operation is not
407 @retval EFI_NOT_STARTED The socket is not configured.
408 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
417 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
418 NET_LIST_ENTRY
*ListEntry
;
423 ASSERT (SOCK_STREAM
== Sock
->Type
);
425 Status
= NET_TRYLOCK (&(Sock
->Lock
));
426 if (EFI_ERROR (Status
)) {
428 SOCK_DEBUG_ERROR (("SockAccept: Get the access for socket"
429 " failed with %r", Status
));
431 return EFI_ACCESS_DENIED
;
434 if (SOCK_IS_NO_MAPPING (Sock
)) {
435 Status
= EFI_NO_MAPPING
;
439 if (SOCK_IS_UNCONFIGURED (Sock
)) {
441 Status
= EFI_NOT_STARTED
;
445 if (!SOCK_IS_LISTENING (Sock
)) {
447 Status
= EFI_ACCESS_DENIED
;
451 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
453 if (SockTokenExisted (Sock
, Event
)) {
455 Status
= EFI_ACCESS_DENIED
;
459 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
462 // Check if a connection has already in this Sock->ConnectionList
464 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
466 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
468 if (SOCK_IS_CONNECTED (Socket
)) {
469 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
470 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
472 NetListRemoveEntry (ListEntry
);
474 ASSERT (Socket
->Parent
);
476 Socket
->Parent
->ConnCnt
--;
478 SOCK_DEBUG_WARN (("SockAccept: Accept a socket,"
479 "now conncount is %d", Socket
->Parent
->ConnCnt
)
481 Socket
->Parent
= NULL
;
488 // Buffer this token for latter incoming connection request
490 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
492 Status
= EFI_OUT_OF_RESOURCES
;
496 NET_UNLOCK (&(Sock
->Lock
));
503 Issue a token with data to the socket to send out.
505 @param Sock Pointer to the socket to process the token with
507 @param Token The token with data that needs to send out.
509 @retval EFI_SUCCESS The token is processed successfully.
510 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
511 socket is closed, or the socket is not in a
512 synchronized state , or the token is already in one
513 of this socket's lists.
514 @retval EFI_NO_MAPPING The IP address configuration operation is not
516 @retval EFI_NOT_STARTED The socket is not configured.
517 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
526 SOCK_IO_TOKEN
*SndToken
;
529 EFI_TCP4_TRANSMIT_DATA
*TxData
;
531 SOCK_TOKEN
*SockToken
;
534 ASSERT (SOCK_STREAM
== Sock
->Type
);
536 Status
= NET_TRYLOCK (&(Sock
->Lock
));
537 if (EFI_ERROR (Status
)) {
539 SOCK_DEBUG_ERROR (("SockSend: Get the access for socket"
540 " failed with %r", Status
));
542 return EFI_ACCESS_DENIED
;
545 if (SOCK_IS_NO_MAPPING (Sock
)) {
546 Status
= EFI_NO_MAPPING
;
550 SndToken
= (SOCK_IO_TOKEN
*) Token
;
551 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
553 if (SOCK_IS_UNCONFIGURED (Sock
)) {
554 Status
= EFI_NOT_STARTED
;
558 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
560 Status
= EFI_ACCESS_DENIED
;
565 // check if a token is already in the token buffer
567 Event
= SndToken
->Token
.Event
;
569 if (SockTokenExisted (Sock
, Event
)) {
570 Status
= EFI_ACCESS_DENIED
;
574 DataLen
= (UINT32
) TxData
->DataLength
;
577 // process this sending token now or buffer it only?
579 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
581 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
583 SockToken
= SockBufferToken (
590 if (NULL
== SockToken
) {
591 Status
= EFI_OUT_OF_RESOURCES
;
595 SockToken
= SockBufferToken (
597 &Sock
->ProcessingSndTokenList
,
602 if (NULL
== SockToken
) {
603 SOCK_DEBUG_ERROR (("SockSend: Failed to buffer IO token into"
604 " socket processing SndToken List\n", Status
));
606 Status
= EFI_OUT_OF_RESOURCES
;
610 Status
= SockProcessTcpSndData (Sock
, TxData
);
612 if (EFI_ERROR (Status
)) {
613 SOCK_DEBUG_ERROR (("SockSend: Failed to process "
614 "Snd Data\n", Status
));
616 NetListRemoveEntry (&(SockToken
->TokenList
));
617 NetFreePool (SockToken
);
622 NET_UNLOCK (&(Sock
->Lock
));
628 Issue a token to get data from the socket.
630 @param Sock Pointer to the socket to get data from.
631 @param Token The token to store the received data from the
634 @retval EFI_SUCCESS The token is processed successfully.
635 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
636 socket is closed, or the socket is not in a
637 synchronized state , or the token is already in one
638 of this socket's lists.
639 @retval EFI_NO_MAPPING The IP address configuration operation is not
641 @retval EFI_NOT_STARTED The socket is not configured.
642 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
643 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
652 SOCK_IO_TOKEN
*RcvToken
;
657 ASSERT (SOCK_STREAM
== Sock
->Type
);
659 Status
= NET_TRYLOCK (&(Sock
->Lock
));
660 if (EFI_ERROR (Status
)) {
662 SOCK_DEBUG_ERROR (("SockRcv: Get the access for socket"
663 " failed with %r", Status
));
665 return EFI_ACCESS_DENIED
;
668 if (SOCK_IS_NO_MAPPING (Sock
)) {
670 Status
= EFI_NO_MAPPING
;
674 if (SOCK_IS_UNCONFIGURED (Sock
)) {
676 Status
= EFI_NOT_STARTED
;
680 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
682 Status
= EFI_ACCESS_DENIED
;
686 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
689 // check if a token is already in the token buffer of this socket
691 Event
= RcvToken
->Token
.Event
;
692 if (SockTokenExisted (Sock
, Event
)) {
693 Status
= EFI_ACCESS_DENIED
;
697 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
698 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
701 // check whether an error has happened before
703 if (EFI_ABORTED
!= Sock
->SockError
) {
705 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
706 Sock
->SockError
= EFI_ABORTED
;
711 // check whether can not receive and there is no any
712 // data buffered in Sock->RcvBuffer
714 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
716 Status
= EFI_CONNECTION_FIN
;
720 if (RcvdBytes
!= 0) {
721 Status
= SockProcessRcvToken (Sock
, RcvToken
);
723 if (EFI_ERROR (Status
)) {
727 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
730 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
731 Status
= EFI_OUT_OF_RESOURCES
;
736 NET_UNLOCK (&(Sock
->Lock
));
742 Reset the socket and its associated protocol control block.
744 @param Sock Pointer to the socket to be flushed.
746 @retval EFI_SUCCESS The socket is flushed successfully.
747 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
757 ASSERT (SOCK_STREAM
== Sock
->Type
);
759 Status
= NET_TRYLOCK (&(Sock
->Lock
));
760 if (EFI_ERROR (Status
)) {
762 SOCK_DEBUG_ERROR (("SockFlush: Get the access for socket"
763 " failed with %r", Status
));
765 return EFI_ACCESS_DENIED
;
768 if (!SOCK_IS_CONFIGURED (Sock
)) {
772 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
773 if (EFI_ERROR (Status
)) {
775 SOCK_DEBUG_ERROR (("SockFlush: Protocol failed handling"
776 " SOCK_FLUSH with %r", Status
));
781 SOCK_ERROR (Sock
, EFI_ABORTED
);
782 SockConnFlush (Sock
);
783 SockSetState (Sock
, SO_CLOSED
);
785 Sock
->ConfigureState
= SO_UNCONFIGURED
;
788 NET_UNLOCK (&(Sock
->Lock
));
794 Close or abort the socket associated connection.
796 @param Sock Pointer to the socket of the connection to close or
798 @param Token The token for close operation.
799 @param OnAbort TRUE for aborting the connection, FALSE to close it.
801 @retval EFI_SUCCESS The close or abort operation is initialized
803 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
804 socket is closed, or the socket is not in a
805 synchronized state , or the token is already in one
806 of this socket's lists.
807 @retval EFI_NO_MAPPING The IP address configuration operation is not
809 @retval EFI_NOT_STARTED The socket is not configured.
822 ASSERT (SOCK_STREAM
== Sock
->Type
);
824 Status
= NET_TRYLOCK (&(Sock
->Lock
));
825 if (EFI_ERROR (Status
)) {
826 SOCK_DEBUG_ERROR (("SockClose: Get the access for socket"
827 " failed with %r", Status
));
829 return EFI_ACCESS_DENIED
;
832 if (SOCK_IS_NO_MAPPING (Sock
)) {
833 Status
= EFI_NO_MAPPING
;
837 if (SOCK_IS_UNCONFIGURED (Sock
)) {
838 Status
= EFI_NOT_STARTED
;
842 if (SOCK_IS_DISCONNECTING (Sock
)) {
843 Status
= EFI_ACCESS_DENIED
;
847 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
849 if (SockTokenExisted (Sock
, Event
)) {
850 Status
= EFI_ACCESS_DENIED
;
854 Sock
->CloseToken
= Token
;
855 SockSetState (Sock
, SO_DISCONNECTING
);
858 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
860 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
864 NET_UNLOCK (&(Sock
->Lock
));
870 Get the mode data of the low layer protocol.
872 @param Sock Pointer to the socket to get mode data from.
873 @param Mode Pointer to the data to store the low layer mode
876 @retval EFI_SUCCESS The mode data is got successfully.
877 @retval EFI_NOT_STARTED The socket is not configured.
886 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
891 Configure the low level protocol to join a multicast group for
892 this socket's connection.
894 @param Sock Pointer to the socket of the connection to join the
895 specific multicast group.
896 @param GroupInfo Pointer to the multicast group info.
898 @retval EFI_SUCCESS The configuration is done successfully.
899 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
900 @retval EFI_NOT_STARTED The socket is not configured.
911 Status
= NET_TRYLOCK (&(Sock
->Lock
));
913 if (EFI_ERROR (Status
)) {
915 SOCK_DEBUG_ERROR (("SockGroup: Get the access for socket"
916 " failed with %r", Status
));
918 return EFI_ACCESS_DENIED
;
921 if (SOCK_IS_UNCONFIGURED (Sock
)) {
922 Status
= EFI_NOT_STARTED
;
926 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
929 NET_UNLOCK (&(Sock
->Lock
));
935 Add or remove route information in IP route table associated
938 @param Sock Pointer to the socket associated with the IP route
940 @param RouteInfo Pointer to the route information to be processed.
942 @retval EFI_SUCCESS The route table is updated successfully.
943 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
944 @retval EFI_NO_MAPPING The IP address configuration operation is not
946 @retval EFI_NOT_STARTED The socket is not configured.
957 Status
= NET_TRYLOCK (&(Sock
->Lock
));
958 if (EFI_ERROR (Status
)) {
959 SOCK_DEBUG_ERROR (("SockRoute: Get the access for socket"
960 " failed with %r", Status
));
962 return EFI_ACCESS_DENIED
;
965 if (SOCK_IS_NO_MAPPING (Sock
)) {
966 Status
= EFI_NO_MAPPING
;
970 if (SOCK_IS_UNCONFIGURED (Sock
)) {
971 Status
= EFI_NOT_STARTED
;
975 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
978 NET_UNLOCK (&(Sock
->Lock
));