]>
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 (
42 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.
120 SOCK_TOKEN
*SockToken
;
122 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
123 if (NULL
== SockToken
) {
125 DEBUG ((EFI_D_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 InsertTailList (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
= EfiAcquireLockOrFail (&(Sock
->Lock
));
165 if (EFI_ERROR (Status
)) {
167 DEBUG ((EFI_D_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 DEBUG ((EFI_D_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 EfiReleaseLock (&(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 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
230 "create a new socket\n"));
235 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
236 if (EFI_ERROR (Status
)) {
238 DEBUG ((EFI_D_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 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
252 " attach a socket with %r\n", Status
));
258 EfiReleaseLock (&(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
= EfiAcquireLockOrFail (&(Sock
->Lock
));
284 if (EFI_ERROR (Status
)) {
286 DEBUG ((EFI_D_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 EfiReleaseLock (&(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
= EfiAcquireLockOrFail (&(Sock
->Lock
));
336 if (EFI_ERROR (Status
)) {
338 DEBUG ((EFI_D_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 EfiReleaseLock (&(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 LIST_ENTRY
*ListEntry
;
410 ASSERT (SOCK_STREAM
== Sock
->Type
);
412 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
413 if (EFI_ERROR (Status
)) {
415 DEBUG ((EFI_D_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 RemoveEntryList (ListEntry
);
461 ASSERT (Socket
->Parent
);
463 Socket
->Parent
->ConnCnt
--;
467 "SockAccept: Accept a socket, now conncount is %d",
468 Socket
->Parent
->ConnCnt
)
470 Socket
->Parent
= NULL
;
477 // Buffer this token for latter incoming connection request
479 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
481 Status
= EFI_OUT_OF_RESOURCES
;
485 EfiReleaseLock (&(Sock
->Lock
));
492 Issue a token with data to the socket to send out.
494 @param Sock Pointer to the socket to process the token with
496 @param Token The token with data that needs to send out.
498 @retval EFI_SUCCESS The token is processed successfully.
499 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
500 socket is closed, or the socket is not in a
501 synchronized state , or the token is already in one
502 of this socket's lists.
503 @retval EFI_NO_MAPPING The IP address configuration operation is not
505 @retval EFI_NOT_STARTED The socket is not configured.
506 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
515 SOCK_IO_TOKEN
*SndToken
;
518 EFI_TCP4_TRANSMIT_DATA
*TxData
;
520 SOCK_TOKEN
*SockToken
;
523 ASSERT (SOCK_STREAM
== Sock
->Type
);
525 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
526 if (EFI_ERROR (Status
)) {
528 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
529 " failed with %r", Status
));
531 return EFI_ACCESS_DENIED
;
534 if (SOCK_IS_NO_MAPPING (Sock
)) {
535 Status
= EFI_NO_MAPPING
;
539 SndToken
= (SOCK_IO_TOKEN
*) Token
;
540 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
542 if (SOCK_IS_UNCONFIGURED (Sock
)) {
543 Status
= EFI_NOT_STARTED
;
547 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
549 Status
= EFI_ACCESS_DENIED
;
554 // check if a token is already in the token buffer
556 Event
= SndToken
->Token
.Event
;
558 if (SockTokenExisted (Sock
, Event
)) {
559 Status
= EFI_ACCESS_DENIED
;
563 DataLen
= (UINT32
) TxData
->DataLength
;
566 // process this sending token now or buffer it only?
568 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
570 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
572 SockToken
= SockBufferToken (
579 if (NULL
== SockToken
) {
580 Status
= EFI_OUT_OF_RESOURCES
;
584 SockToken
= SockBufferToken (
586 &Sock
->ProcessingSndTokenList
,
591 if (NULL
== SockToken
) {
592 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
593 " socket processing SndToken List\n", Status
));
595 Status
= EFI_OUT_OF_RESOURCES
;
599 Status
= SockProcessTcpSndData (Sock
, TxData
);
601 if (EFI_ERROR (Status
)) {
602 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
603 "Snd Data\n", Status
));
605 RemoveEntryList (&(SockToken
->TokenList
));
606 gBS
->FreePool (SockToken
);
611 EfiReleaseLock (&(Sock
->Lock
));
617 Issue a token to get data from the socket.
619 @param Sock Pointer to the socket to get data from.
620 @param Token The token to store the received data from the
623 @retval EFI_SUCCESS The token is processed successfully.
624 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
625 socket is closed, or the socket is not in a
626 synchronized state , or the token is already in one
627 of this socket's lists.
628 @retval EFI_NO_MAPPING The IP address configuration operation is not
630 @retval EFI_NOT_STARTED The socket is not configured.
631 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
632 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
641 SOCK_IO_TOKEN
*RcvToken
;
646 ASSERT (SOCK_STREAM
== Sock
->Type
);
648 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
649 if (EFI_ERROR (Status
)) {
651 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
652 " failed with %r", Status
));
654 return EFI_ACCESS_DENIED
;
657 if (SOCK_IS_NO_MAPPING (Sock
)) {
659 Status
= EFI_NO_MAPPING
;
663 if (SOCK_IS_UNCONFIGURED (Sock
)) {
665 Status
= EFI_NOT_STARTED
;
669 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
671 Status
= EFI_ACCESS_DENIED
;
675 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
678 // check if a token is already in the token buffer of this socket
680 Event
= RcvToken
->Token
.Event
;
681 if (SockTokenExisted (Sock
, Event
)) {
682 Status
= EFI_ACCESS_DENIED
;
686 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
687 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
690 // check whether an error has happened before
692 if (EFI_ABORTED
!= Sock
->SockError
) {
694 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
695 Sock
->SockError
= EFI_ABORTED
;
700 // check whether can not receive and there is no any
701 // data buffered in Sock->RcvBuffer
703 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
705 Status
= EFI_CONNECTION_FIN
;
709 if (RcvdBytes
!= 0) {
710 Status
= SockProcessRcvToken (Sock
, RcvToken
);
712 if (EFI_ERROR (Status
)) {
716 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
719 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
720 Status
= EFI_OUT_OF_RESOURCES
;
725 EfiReleaseLock (&(Sock
->Lock
));
731 Reset the socket and its associated protocol control block.
733 @param Sock Pointer to the socket to be flushed.
735 @retval EFI_SUCCESS The socket is flushed successfully.
736 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
746 ASSERT (SOCK_STREAM
== Sock
->Type
);
748 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
749 if (EFI_ERROR (Status
)) {
751 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
752 " failed with %r", Status
));
754 return EFI_ACCESS_DENIED
;
757 if (!SOCK_IS_CONFIGURED (Sock
)) {
761 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
762 if (EFI_ERROR (Status
)) {
764 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
765 " SOCK_FLUSH with %r", Status
));
770 SOCK_ERROR (Sock
, EFI_ABORTED
);
771 SockConnFlush (Sock
);
772 SockSetState (Sock
, SO_CLOSED
);
774 Sock
->ConfigureState
= SO_UNCONFIGURED
;
777 EfiReleaseLock (&(Sock
->Lock
));
783 Close or abort the socket associated connection.
785 @param Sock Pointer to the socket of the connection to close or
787 @param Token The token for close operation.
788 @param OnAbort TRUE for aborting the connection, FALSE to close it.
790 @retval EFI_SUCCESS The close or abort operation is initialized
792 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
793 socket is closed, or the socket is not in a
794 synchronized state , or the token is already in one
795 of this socket's lists.
796 @retval EFI_NO_MAPPING The IP address configuration operation is not
798 @retval EFI_NOT_STARTED The socket is not configured.
811 ASSERT (SOCK_STREAM
== Sock
->Type
);
813 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
814 if (EFI_ERROR (Status
)) {
815 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
816 " failed with %r", Status
));
818 return EFI_ACCESS_DENIED
;
821 if (SOCK_IS_NO_MAPPING (Sock
)) {
822 Status
= EFI_NO_MAPPING
;
826 if (SOCK_IS_UNCONFIGURED (Sock
)) {
827 Status
= EFI_NOT_STARTED
;
831 if (SOCK_IS_DISCONNECTING (Sock
)) {
832 Status
= EFI_ACCESS_DENIED
;
836 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
838 if (SockTokenExisted (Sock
, Event
)) {
839 Status
= EFI_ACCESS_DENIED
;
843 Sock
->CloseToken
= Token
;
844 SockSetState (Sock
, SO_DISCONNECTING
);
847 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
849 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
853 EfiReleaseLock (&(Sock
->Lock
));
859 Get the mode data of the low layer protocol.
861 @param Sock Pointer to the socket to get mode data from.
862 @param Mode Pointer to the data to store the low layer mode
865 @retval EFI_SUCCESS The mode data is got successfully.
866 @retval EFI_NOT_STARTED The socket is not configured.
875 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
880 Configure the low level protocol to join a multicast group for
881 this socket's connection.
883 @param Sock Pointer to the socket of the connection to join the
884 specific multicast group.
885 @param GroupInfo Pointer to the multicast group info.
887 @retval EFI_SUCCESS The configuration is done successfully.
888 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
889 @retval EFI_NOT_STARTED The socket is not configured.
900 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
902 if (EFI_ERROR (Status
)) {
904 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
905 " failed with %r", Status
));
907 return EFI_ACCESS_DENIED
;
910 if (SOCK_IS_UNCONFIGURED (Sock
)) {
911 Status
= EFI_NOT_STARTED
;
915 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
918 EfiReleaseLock (&(Sock
->Lock
));
924 Add or remove route information in IP route table associated
927 @param Sock Pointer to the socket associated with the IP route
929 @param RouteInfo Pointer to the route information to be processed.
931 @retval EFI_SUCCESS The route table is updated successfully.
932 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
933 @retval EFI_NO_MAPPING The IP address configuration operation is not
935 @retval EFI_NOT_STARTED The socket is not configured.
946 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
947 if (EFI_ERROR (Status
)) {
948 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
949 " failed with %r", Status
));
951 return EFI_ACCESS_DENIED
;
954 if (SOCK_IS_NO_MAPPING (Sock
)) {
955 Status
= EFI_NO_MAPPING
;
959 if (SOCK_IS_UNCONFIGURED (Sock
)) {
960 Status
= EFI_NOT_STARTED
;
964 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
967 EfiReleaseLock (&(Sock
->Lock
));