]>
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
224 // create a new socket
226 Sock
= SockCreate (SockInitData
);
229 SOCK_DEBUG_ERROR (("SockCreateChild: No resource to "
230 "create a new socket\n"));
235 Status
= NET_TRYLOCK (&(Sock
->Lock
));
236 if (EFI_ERROR (Status
)) {
238 SOCK_DEBUG_ERROR (("SockCreateChild: Get the lock to "
239 "access socket failed with %r\n", Status
));
245 // inform the protocol layer to attach the socket
246 // with a new protocol control block
248 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
249 if (EFI_ERROR (Status
)) {
251 SOCK_DEBUG_ERROR (("SockCreateChild: Protocol failed to"
252 " attach a socket with %r\n", Status
));
258 NET_UNLOCK (&(Sock
->Lock
));
264 Configure the specific socket Sock using configuration data
267 @param Sock Pointer to the socket to be configured.
268 @param ConfigData Pointer to the configuration data.
270 @retval EFI_SUCCESS The socket is 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
= NET_TRYLOCK (&(Sock
->Lock
));
284 if (EFI_ERROR (Status
)) {
286 SOCK_DEBUG_ERROR (("SockConfigure: Get the access for "
287 "socket failed with %r", Status
));
289 return EFI_ACCESS_DENIED
;
292 if (SOCK_IS_CONFIGURED (Sock
)) {
293 Status
= EFI_ACCESS_DENIED
;
297 ASSERT (Sock
->State
== SO_CLOSED
);
299 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
302 NET_UNLOCK (&(Sock
->Lock
));
309 Initiate a connection establishment process.
311 @param Sock Pointer to the socket to initiate the initate the
313 @param Token Pointer to the token used for the connection
316 @retval EFI_SUCCESS The connection is initialized successfully.
317 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
318 socket is closed, or the socket is not configured to
319 be an active one, or the token is already in one of
321 @retval EFI_NO_MAPPING The IP address configuration operation is not
323 @retval EFI_NOT_STARTED The socket is not configured.
335 Status
= NET_TRYLOCK (&(Sock
->Lock
));
336 if (EFI_ERROR (Status
)) {
338 SOCK_DEBUG_ERROR (("SockConnect: Get the access for "
339 "socket failed with %r", Status
));
341 return EFI_ACCESS_DENIED
;
344 if (SOCK_IS_NO_MAPPING (Sock
)) {
345 Status
= EFI_NO_MAPPING
;
349 if (SOCK_IS_UNCONFIGURED (Sock
)) {
351 Status
= EFI_NOT_STARTED
;
355 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
357 Status
= EFI_ACCESS_DENIED
;
361 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
363 if (SockTokenExisted (Sock
, Event
)) {
365 Status
= EFI_ACCESS_DENIED
;
369 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
370 SockSetState (Sock
, SO_CONNECTING
);
371 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
374 NET_UNLOCK (&(Sock
->Lock
));
380 Issue a listen token to get an existed connected network instance
381 or wait for a connection if there is none.
383 @param Sock Pointer to the socket to accept connections.
384 @param Token The token to accept a connection.
386 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
387 buffered for further acception.
388 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
389 socket is closed, or the socket is not configured to
390 be a passive one, or the token is already in one of
392 @retval EFI_NO_MAPPING The IP address configuration operation is not
394 @retval EFI_NOT_STARTED The socket is not configured.
395 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
404 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
405 NET_LIST_ENTRY
*ListEntry
;
410 ASSERT (SOCK_STREAM
== Sock
->Type
);
412 Status
= NET_TRYLOCK (&(Sock
->Lock
));
413 if (EFI_ERROR (Status
)) {
415 SOCK_DEBUG_ERROR (("SockAccept: Get the access for socket"
416 " failed with %r", Status
));
418 return EFI_ACCESS_DENIED
;
421 if (SOCK_IS_NO_MAPPING (Sock
)) {
422 Status
= EFI_NO_MAPPING
;
426 if (SOCK_IS_UNCONFIGURED (Sock
)) {
428 Status
= EFI_NOT_STARTED
;
432 if (!SOCK_IS_LISTENING (Sock
)) {
434 Status
= EFI_ACCESS_DENIED
;
438 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
440 if (SockTokenExisted (Sock
, Event
)) {
442 Status
= EFI_ACCESS_DENIED
;
446 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
449 // Check if a connection has already in this Sock->ConnectionList
451 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
453 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
455 if (SOCK_IS_CONNECTED (Socket
)) {
456 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
457 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
459 NetListRemoveEntry (ListEntry
);
461 ASSERT (Socket
->Parent
);
463 Socket
->Parent
->ConnCnt
--;
465 SOCK_DEBUG_WARN (("SockAccept: Accept a socket,"
466 "now conncount is %d", Socket
->Parent
->ConnCnt
)
468 Socket
->Parent
= NULL
;
475 // Buffer this token for latter incoming connection request
477 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
479 Status
= EFI_OUT_OF_RESOURCES
;
483 NET_UNLOCK (&(Sock
->Lock
));
490 Issue a token with data to the socket to send out.
492 @param Sock Pointer to the socket to process the token with
494 @param Token The token with data that needs to send out.
496 @retval EFI_SUCCESS The token is processed successfully.
497 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
498 socket is closed, or the socket is not in a
499 synchronized state , or the token is already in one
500 of this socket's lists.
501 @retval EFI_NO_MAPPING The IP address configuration operation is not
503 @retval EFI_NOT_STARTED The socket is not configured.
504 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
513 SOCK_IO_TOKEN
*SndToken
;
516 EFI_TCP4_TRANSMIT_DATA
*TxData
;
518 SOCK_TOKEN
*SockToken
;
521 ASSERT (SOCK_STREAM
== Sock
->Type
);
523 Status
= NET_TRYLOCK (&(Sock
->Lock
));
524 if (EFI_ERROR (Status
)) {
526 SOCK_DEBUG_ERROR (("SockSend: Get the access for socket"
527 " failed with %r", Status
));
529 return EFI_ACCESS_DENIED
;
532 if (SOCK_IS_NO_MAPPING (Sock
)) {
533 Status
= EFI_NO_MAPPING
;
537 SndToken
= (SOCK_IO_TOKEN
*) Token
;
538 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
540 if (SOCK_IS_UNCONFIGURED (Sock
)) {
541 Status
= EFI_NOT_STARTED
;
545 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
547 Status
= EFI_ACCESS_DENIED
;
552 // check if a token is already in the token buffer
554 Event
= SndToken
->Token
.Event
;
556 if (SockTokenExisted (Sock
, Event
)) {
557 Status
= EFI_ACCESS_DENIED
;
561 DataLen
= (UINT32
) TxData
->DataLength
;
564 // process this sending token now or buffer it only?
566 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
568 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
570 SockToken
= SockBufferToken (
577 if (NULL
== SockToken
) {
578 Status
= EFI_OUT_OF_RESOURCES
;
582 SockToken
= SockBufferToken (
584 &Sock
->ProcessingSndTokenList
,
589 if (NULL
== SockToken
) {
590 SOCK_DEBUG_ERROR (("SockSend: Failed to buffer IO token into"
591 " socket processing SndToken List\n", Status
));
593 Status
= EFI_OUT_OF_RESOURCES
;
597 Status
= SockProcessTcpSndData (Sock
, TxData
);
599 if (EFI_ERROR (Status
)) {
600 SOCK_DEBUG_ERROR (("SockSend: Failed to process "
601 "Snd Data\n", Status
));
603 NetListRemoveEntry (&(SockToken
->TokenList
));
604 NetFreePool (SockToken
);
609 NET_UNLOCK (&(Sock
->Lock
));
615 Issue a token to get data from the socket.
617 @param Sock Pointer to the socket to get data from.
618 @param Token The token to store the received data from the
621 @retval EFI_SUCCESS The token is processed successfully.
622 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
623 socket is closed, or the socket is not in a
624 synchronized state , or the token is already in one
625 of this socket's lists.
626 @retval EFI_NO_MAPPING The IP address configuration operation is not
628 @retval EFI_NOT_STARTED The socket is not configured.
629 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
630 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
639 SOCK_IO_TOKEN
*RcvToken
;
644 ASSERT (SOCK_STREAM
== Sock
->Type
);
646 Status
= NET_TRYLOCK (&(Sock
->Lock
));
647 if (EFI_ERROR (Status
)) {
649 SOCK_DEBUG_ERROR (("SockRcv: Get the access for socket"
650 " failed with %r", Status
));
652 return EFI_ACCESS_DENIED
;
655 if (SOCK_IS_NO_MAPPING (Sock
)) {
657 Status
= EFI_NO_MAPPING
;
661 if (SOCK_IS_UNCONFIGURED (Sock
)) {
663 Status
= EFI_NOT_STARTED
;
667 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
669 Status
= EFI_ACCESS_DENIED
;
673 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
676 // check if a token is already in the token buffer of this socket
678 Event
= RcvToken
->Token
.Event
;
679 if (SockTokenExisted (Sock
, Event
)) {
680 Status
= EFI_ACCESS_DENIED
;
684 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
685 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
688 // check whether an error has happened before
690 if (EFI_ABORTED
!= Sock
->SockError
) {
692 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
693 Sock
->SockError
= EFI_ABORTED
;
698 // check whether can not receive and there is no any
699 // data buffered in Sock->RcvBuffer
701 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
703 Status
= EFI_CONNECTION_FIN
;
707 if (RcvdBytes
!= 0) {
708 Status
= SockProcessRcvToken (Sock
, RcvToken
);
710 if (EFI_ERROR (Status
)) {
714 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
717 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
718 Status
= EFI_OUT_OF_RESOURCES
;
723 NET_UNLOCK (&(Sock
->Lock
));
729 Reset the socket and its associated protocol control block.
731 @param Sock Pointer to the socket to be flushed.
733 @retval EFI_SUCCESS The socket is flushed successfully.
734 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
744 ASSERT (SOCK_STREAM
== Sock
->Type
);
746 Status
= NET_TRYLOCK (&(Sock
->Lock
));
747 if (EFI_ERROR (Status
)) {
749 SOCK_DEBUG_ERROR (("SockFlush: Get the access for socket"
750 " failed with %r", Status
));
752 return EFI_ACCESS_DENIED
;
755 if (!SOCK_IS_CONFIGURED (Sock
)) {
759 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
760 if (EFI_ERROR (Status
)) {
762 SOCK_DEBUG_ERROR (("SockFlush: Protocol failed handling"
763 " SOCK_FLUSH with %r", Status
));
768 SOCK_ERROR (Sock
, EFI_ABORTED
);
769 SockConnFlush (Sock
);
770 SockSetState (Sock
, SO_CLOSED
);
772 Sock
->ConfigureState
= SO_UNCONFIGURED
;
775 NET_UNLOCK (&(Sock
->Lock
));
781 Close or abort the socket associated connection.
783 @param Sock Pointer to the socket of the connection to close or
785 @param Token The token for close operation.
786 @param OnAbort TRUE for aborting the connection, FALSE to close it.
788 @retval EFI_SUCCESS The close or abort operation is initialized
790 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
791 socket is closed, or the socket is not in a
792 synchronized state , or the token is already in one
793 of this socket's lists.
794 @retval EFI_NO_MAPPING The IP address configuration operation is not
796 @retval EFI_NOT_STARTED The socket is not configured.
809 ASSERT (SOCK_STREAM
== Sock
->Type
);
811 Status
= NET_TRYLOCK (&(Sock
->Lock
));
812 if (EFI_ERROR (Status
)) {
813 SOCK_DEBUG_ERROR (("SockClose: Get the access for socket"
814 " failed with %r", Status
));
816 return EFI_ACCESS_DENIED
;
819 if (SOCK_IS_NO_MAPPING (Sock
)) {
820 Status
= EFI_NO_MAPPING
;
824 if (SOCK_IS_UNCONFIGURED (Sock
)) {
825 Status
= EFI_NOT_STARTED
;
829 if (SOCK_IS_DISCONNECTING (Sock
)) {
830 Status
= EFI_ACCESS_DENIED
;
834 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
836 if (SockTokenExisted (Sock
, Event
)) {
837 Status
= EFI_ACCESS_DENIED
;
841 Sock
->CloseToken
= Token
;
842 SockSetState (Sock
, SO_DISCONNECTING
);
845 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
847 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
851 NET_UNLOCK (&(Sock
->Lock
));
857 Get the mode data of the low layer protocol.
859 @param Sock Pointer to the socket to get mode data from.
860 @param Mode Pointer to the data to store the low layer mode
863 @retval EFI_SUCCESS The mode data is got successfully.
864 @retval EFI_NOT_STARTED The socket is not configured.
873 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
878 Configure the low level protocol to join a multicast group for
879 this socket's connection.
881 @param Sock Pointer to the socket of the connection to join the
882 specific multicast group.
883 @param GroupInfo Pointer to the multicast group info.
885 @retval EFI_SUCCESS The configuration is done successfully.
886 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
887 @retval EFI_NOT_STARTED The socket is not configured.
898 Status
= NET_TRYLOCK (&(Sock
->Lock
));
900 if (EFI_ERROR (Status
)) {
902 SOCK_DEBUG_ERROR (("SockGroup: Get the access for socket"
903 " failed with %r", Status
));
905 return EFI_ACCESS_DENIED
;
908 if (SOCK_IS_UNCONFIGURED (Sock
)) {
909 Status
= EFI_NOT_STARTED
;
913 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
916 NET_UNLOCK (&(Sock
->Lock
));
922 Add or remove route information in IP route table associated
925 @param Sock Pointer to the socket associated with the IP route
927 @param RouteInfo Pointer to the route information to be processed.
929 @retval EFI_SUCCESS The route table is updated successfully.
930 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
931 @retval EFI_NO_MAPPING The IP address configuration operation is not
933 @retval EFI_NOT_STARTED The socket is not configured.
944 Status
= NET_TRYLOCK (&(Sock
->Lock
));
945 if (EFI_ERROR (Status
)) {
946 SOCK_DEBUG_ERROR (("SockRoute: Get the access for socket"
947 " failed with %r", Status
));
949 return EFI_ACCESS_DENIED
;
952 if (SOCK_IS_NO_MAPPING (Sock
)) {
953 Status
= EFI_NO_MAPPING
;
957 if (SOCK_IS_UNCONFIGURED (Sock
)) {
958 Status
= EFI_NOT_STARTED
;
962 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
965 NET_UNLOCK (&(Sock
->Lock
));