]>
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.
36 SockTokenExistedInList (
41 LIST_ENTRY
*ListEntry
;
42 SOCK_TOKEN
*SockToken
;
44 NET_LIST_FOR_EACH (ListEntry
, List
) {
45 SockToken
= NET_LIST_USER_STRUCT (
51 if (Event
== SockToken
->Token
->Event
) {
61 Call SockTokenExistedInList() to check whether the Event is
62 in the related socket's lists.
64 @param Sock Pointer to the instance's socket.
65 @param Event The event to be checked.
67 @return The specific Event exists in one of socket's lists or not.
77 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
78 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
79 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
80 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)
86 if ((Sock
->ConnectionToken
!= NULL
) &&
87 (Sock
->ConnectionToken
->Event
== Event
)) {
92 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
101 Buffer a token into the specific list of socket Sock.
103 @param Sock Pointer to the instance's socket.
104 @param List Pointer to the list to store the token.
105 @param Token Pointer to the token to be buffered.
106 @param DataLen The data length of the buffer contained in Token.
108 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
119 SOCK_TOKEN
*SockToken
;
121 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
122 if (NULL
== SockToken
) {
124 DEBUG ((EFI_D_ERROR
, "SockBufferIOToken: No Memory "
125 "to allocate SockToken\n"));
130 SockToken
->Sock
= Sock
;
131 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
132 SockToken
->RemainDataLen
= DataLen
;
133 InsertTailList (List
, &SockToken
->TokenList
);
140 Destory the socket Sock and its associated protocol control block.
142 @param Sock The socket to be destroyed.
144 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
145 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
155 ASSERT (Sock
&& Sock
->ProtoHandler
);
157 if (Sock
->IsDestroyed
) {
161 Sock
->IsDestroyed
= TRUE
;
163 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
164 if (EFI_ERROR (Status
)) {
166 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Get the lock to "
167 "access socket failed with %r\n", Status
));
169 return EFI_ACCESS_DENIED
;
173 // force protocol layer to detach the PCB
175 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
177 if (EFI_ERROR (Status
)) {
179 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Protocol detach socket"
180 " failed with %r\n", Status
));
182 Sock
->IsDestroyed
= FALSE
;
183 } else if (SOCK_IS_CONFIGURED (Sock
)) {
185 SockConnFlush (Sock
);
186 SockSetState (Sock
, SO_CLOSED
);
188 Sock
->ConfigureState
= SO_UNCONFIGURED
;
191 EfiReleaseLock (&(Sock
->Lock
));
193 if (EFI_ERROR (Status
)) {
203 Create a socket and its associated protocol control block
204 with the intial data SockInitData and protocol specific
207 @param SockInitData Inital data to setting the socket.
209 @return Pointer to the newly created socket. If NULL, error condition occured.
214 IN SOCK_INIT_DATA
*SockInitData
221 // create a new socket
223 Sock
= SockCreate (SockInitData
);
226 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
227 "create a new socket\n"));
232 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
233 if (EFI_ERROR (Status
)) {
235 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
236 "access socket failed with %r\n", Status
));
242 // inform the protocol layer to attach the socket
243 // with a new protocol control block
245 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
246 if (EFI_ERROR (Status
)) {
248 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
249 " attach a socket with %r\n", Status
));
255 EfiReleaseLock (&(Sock
->Lock
));
261 Configure the specific socket Sock using configuration data
264 @param Sock Pointer to the socket to be configured.
265 @param ConfigData Pointer to the configuration data.
267 @retval EFI_SUCCESS The socket is configured successfully.
268 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
269 socket is already configured.
280 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
281 if (EFI_ERROR (Status
)) {
283 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
284 "socket failed with %r", Status
));
286 return EFI_ACCESS_DENIED
;
289 if (SOCK_IS_CONFIGURED (Sock
)) {
290 Status
= EFI_ACCESS_DENIED
;
294 ASSERT (Sock
->State
== SO_CLOSED
);
296 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
299 EfiReleaseLock (&(Sock
->Lock
));
306 Initiate a connection establishment process.
308 @param Sock Pointer to the socket to initiate the initate the
310 @param Token Pointer to the token used for the connection
313 @retval EFI_SUCCESS The connection is initialized successfully.
314 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
315 socket is closed, or the socket is not configured to
316 be an active one, or the token is already in one of
318 @retval EFI_NO_MAPPING The IP address configuration operation is not
320 @retval EFI_NOT_STARTED The socket is not configured.
332 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
333 if (EFI_ERROR (Status
)) {
335 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
336 "socket failed with %r", Status
));
338 return EFI_ACCESS_DENIED
;
341 if (SOCK_IS_NO_MAPPING (Sock
)) {
342 Status
= EFI_NO_MAPPING
;
346 if (SOCK_IS_UNCONFIGURED (Sock
)) {
348 Status
= EFI_NOT_STARTED
;
352 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
354 Status
= EFI_ACCESS_DENIED
;
358 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
360 if (SockTokenExisted (Sock
, Event
)) {
362 Status
= EFI_ACCESS_DENIED
;
366 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
367 SockSetState (Sock
, SO_CONNECTING
);
368 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
371 EfiReleaseLock (&(Sock
->Lock
));
377 Issue a listen token to get an existed connected network instance
378 or wait for a connection if there is none.
380 @param Sock Pointer to the socket to accept connections.
381 @param Token The token to accept a connection.
383 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
384 buffered for further acception.
385 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
386 socket is closed, or the socket is not configured to
387 be a passive one, or the token is already in one of
389 @retval EFI_NO_MAPPING The IP address configuration operation is not
391 @retval EFI_NOT_STARTED The socket is not configured.
392 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
401 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
402 LIST_ENTRY
*ListEntry
;
407 ASSERT (SOCK_STREAM
== Sock
->Type
);
409 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
410 if (EFI_ERROR (Status
)) {
412 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
413 " failed with %r", Status
));
415 return EFI_ACCESS_DENIED
;
418 if (SOCK_IS_NO_MAPPING (Sock
)) {
419 Status
= EFI_NO_MAPPING
;
423 if (SOCK_IS_UNCONFIGURED (Sock
)) {
425 Status
= EFI_NOT_STARTED
;
429 if (!SOCK_IS_LISTENING (Sock
)) {
431 Status
= EFI_ACCESS_DENIED
;
435 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
437 if (SockTokenExisted (Sock
, Event
)) {
439 Status
= EFI_ACCESS_DENIED
;
443 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
446 // Check if a connection has already in this Sock->ConnectionList
448 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
450 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
452 if (SOCK_IS_CONNECTED (Socket
)) {
453 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
454 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
456 RemoveEntryList (ListEntry
);
458 ASSERT (Socket
->Parent
);
460 Socket
->Parent
->ConnCnt
--;
464 "SockAccept: Accept a socket, now conncount is %d",
465 Socket
->Parent
->ConnCnt
)
467 Socket
->Parent
= NULL
;
474 // Buffer this token for latter incoming connection request
476 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
478 Status
= EFI_OUT_OF_RESOURCES
;
482 EfiReleaseLock (&(Sock
->Lock
));
489 Issue a token with data to the socket to send out.
491 @param Sock Pointer to the socket to process the token with
493 @param Token The token with data that needs to send out.
495 @retval EFI_SUCCESS The token is processed successfully.
496 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
497 socket is closed, or the socket is not in a
498 synchronized state , or the token is already in one
499 of this socket's lists.
500 @retval EFI_NO_MAPPING The IP address configuration operation is not
502 @retval EFI_NOT_STARTED The socket is not configured.
503 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
512 SOCK_IO_TOKEN
*SndToken
;
515 EFI_TCP4_TRANSMIT_DATA
*TxData
;
517 SOCK_TOKEN
*SockToken
;
520 ASSERT (SOCK_STREAM
== Sock
->Type
);
522 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
523 if (EFI_ERROR (Status
)) {
525 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
526 " failed with %r", Status
));
528 return EFI_ACCESS_DENIED
;
531 if (SOCK_IS_NO_MAPPING (Sock
)) {
532 Status
= EFI_NO_MAPPING
;
536 SndToken
= (SOCK_IO_TOKEN
*) Token
;
537 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
539 if (SOCK_IS_UNCONFIGURED (Sock
)) {
540 Status
= EFI_NOT_STARTED
;
544 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
546 Status
= EFI_ACCESS_DENIED
;
551 // check if a token is already in the token buffer
553 Event
= SndToken
->Token
.Event
;
555 if (SockTokenExisted (Sock
, Event
)) {
556 Status
= EFI_ACCESS_DENIED
;
560 DataLen
= (UINT32
) TxData
->DataLength
;
563 // process this sending token now or buffer it only?
565 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
567 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
569 SockToken
= SockBufferToken (
576 if (NULL
== SockToken
) {
577 Status
= EFI_OUT_OF_RESOURCES
;
581 SockToken
= SockBufferToken (
583 &Sock
->ProcessingSndTokenList
,
588 if (NULL
== SockToken
) {
589 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
590 " socket processing SndToken List\n", Status
));
592 Status
= EFI_OUT_OF_RESOURCES
;
596 Status
= SockProcessTcpSndData (Sock
, TxData
);
598 if (EFI_ERROR (Status
)) {
599 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
600 "Snd Data\n", Status
));
602 RemoveEntryList (&(SockToken
->TokenList
));
603 gBS
->FreePool (SockToken
);
608 EfiReleaseLock (&(Sock
->Lock
));
614 Issue a token to get data from the socket.
616 @param Sock Pointer to the socket to get data from.
617 @param Token The token to store the received data from the
620 @retval EFI_SUCCESS The token is processed successfully.
621 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
622 socket is closed, or the socket is not in a
623 synchronized state , or the token is already in one
624 of this socket's lists.
625 @retval EFI_NO_MAPPING The IP address configuration operation is not
627 @retval EFI_NOT_STARTED The socket is not configured.
628 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
629 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
638 SOCK_IO_TOKEN
*RcvToken
;
643 ASSERT (SOCK_STREAM
== Sock
->Type
);
645 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
646 if (EFI_ERROR (Status
)) {
648 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
649 " failed with %r", Status
));
651 return EFI_ACCESS_DENIED
;
654 if (SOCK_IS_NO_MAPPING (Sock
)) {
656 Status
= EFI_NO_MAPPING
;
660 if (SOCK_IS_UNCONFIGURED (Sock
)) {
662 Status
= EFI_NOT_STARTED
;
666 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
668 Status
= EFI_ACCESS_DENIED
;
672 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
675 // check if a token is already in the token buffer of this socket
677 Event
= RcvToken
->Token
.Event
;
678 if (SockTokenExisted (Sock
, Event
)) {
679 Status
= EFI_ACCESS_DENIED
;
683 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
684 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
687 // check whether an error has happened before
689 if (EFI_ABORTED
!= Sock
->SockError
) {
691 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
692 Sock
->SockError
= EFI_ABORTED
;
697 // check whether can not receive and there is no any
698 // data buffered in Sock->RcvBuffer
700 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
702 Status
= EFI_CONNECTION_FIN
;
706 if (RcvdBytes
!= 0) {
707 Status
= SockProcessRcvToken (Sock
, RcvToken
);
709 if (EFI_ERROR (Status
)) {
713 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
716 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
717 Status
= EFI_OUT_OF_RESOURCES
;
722 EfiReleaseLock (&(Sock
->Lock
));
728 Reset the socket and its associated protocol control block.
730 @param Sock Pointer to the socket to be flushed.
732 @retval EFI_SUCCESS The socket is flushed successfully.
733 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
743 ASSERT (SOCK_STREAM
== Sock
->Type
);
745 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
746 if (EFI_ERROR (Status
)) {
748 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
749 " failed with %r", Status
));
751 return EFI_ACCESS_DENIED
;
754 if (!SOCK_IS_CONFIGURED (Sock
)) {
758 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
759 if (EFI_ERROR (Status
)) {
761 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
762 " SOCK_FLUSH with %r", Status
));
767 SOCK_ERROR (Sock
, EFI_ABORTED
);
768 SockConnFlush (Sock
);
769 SockSetState (Sock
, SO_CLOSED
);
771 Sock
->ConfigureState
= SO_UNCONFIGURED
;
774 EfiReleaseLock (&(Sock
->Lock
));
780 Close or abort the socket associated connection.
782 @param Sock Pointer to the socket of the connection to close or
784 @param Token The token for close operation.
785 @param OnAbort TRUE for aborting the connection, FALSE to close it.
787 @retval EFI_SUCCESS The close or abort operation is initialized
789 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
790 socket is closed, or the socket is not in a
791 synchronized state , or the token is already in one
792 of this socket's lists.
793 @retval EFI_NO_MAPPING The IP address configuration operation is not
795 @retval EFI_NOT_STARTED The socket is not configured.
808 ASSERT (SOCK_STREAM
== Sock
->Type
);
810 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
811 if (EFI_ERROR (Status
)) {
812 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
813 " failed with %r", Status
));
815 return EFI_ACCESS_DENIED
;
818 if (SOCK_IS_NO_MAPPING (Sock
)) {
819 Status
= EFI_NO_MAPPING
;
823 if (SOCK_IS_UNCONFIGURED (Sock
)) {
824 Status
= EFI_NOT_STARTED
;
828 if (SOCK_IS_DISCONNECTING (Sock
)) {
829 Status
= EFI_ACCESS_DENIED
;
833 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
835 if (SockTokenExisted (Sock
, Event
)) {
836 Status
= EFI_ACCESS_DENIED
;
840 Sock
->CloseToken
= Token
;
841 SockSetState (Sock
, SO_DISCONNECTING
);
844 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
846 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
850 EfiReleaseLock (&(Sock
->Lock
));
856 Get the mode data of the low layer protocol.
858 @param Sock Pointer to the socket to get mode data from.
859 @param Mode Pointer to the data to store the low layer mode
862 @retval EFI_SUCCESS The mode data is got successfully.
863 @retval EFI_NOT_STARTED The socket is not configured.
872 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
877 Configure the low level protocol to join a multicast group for
878 this socket's connection.
880 @param Sock Pointer to the socket of the connection to join the
881 specific multicast group.
882 @param GroupInfo Pointer to the multicast group info.
884 @retval EFI_SUCCESS The configuration is done successfully.
885 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
886 @retval EFI_NOT_STARTED The socket is not configured.
897 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
899 if (EFI_ERROR (Status
)) {
901 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
902 " failed with %r", Status
));
904 return EFI_ACCESS_DENIED
;
907 if (SOCK_IS_UNCONFIGURED (Sock
)) {
908 Status
= EFI_NOT_STARTED
;
912 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
915 EfiReleaseLock (&(Sock
->Lock
));
921 Add or remove route information in IP route table associated
924 @param Sock Pointer to the socket associated with the IP route
926 @param RouteInfo Pointer to the route information to be processed.
928 @retval EFI_SUCCESS The route table is updated successfully.
929 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
930 @retval EFI_NO_MAPPING The IP address configuration operation is not
932 @retval EFI_NOT_STARTED The socket is not configured.
943 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
944 if (EFI_ERROR (Status
)) {
945 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
946 " failed with %r", Status
));
948 return EFI_ACCESS_DENIED
;
951 if (SOCK_IS_NO_MAPPING (Sock
)) {
952 Status
= EFI_NO_MAPPING
;
956 if (SOCK_IS_UNCONFIGURED (Sock
)) {
957 Status
= EFI_NOT_STARTED
;
961 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
964 EfiReleaseLock (&(Sock
->Lock
));