]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
2 Interface function of the Socket.
4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php<BR>
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 Check whether the Event is in the List.
22 @param List Pointer to the token list to be searched.
23 @param Event The event to be checked.
25 @retval TRUE The specific Event exists in the List.
26 @retval FALSE The specific Event is not in the List.
30 SockTokenExistedInList (
35 LIST_ENTRY
*ListEntry
;
36 SOCK_TOKEN
*SockToken
;
38 NET_LIST_FOR_EACH (ListEntry
, List
) {
39 SockToken
= NET_LIST_USER_STRUCT (
45 if (Event
== SockToken
->Token
->Event
) {
55 Call SockTokenExistedInList() to check whether the Event is
56 in the related socket's lists.
58 @param Sock Pointer to the instance's socket.
59 @param Event The event to be checked.
61 @retval TRUE The Event exists in related socket's lists.
62 @retval FALSE The Event is not in related socket's lists.
72 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
73 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
74 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
75 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)) {
80 if ((Sock
->ConnectionToken
!= NULL
) &&
81 (Sock
->ConnectionToken
->Event
== Event
)) {
86 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
95 Buffer a token into the specific list of socket Sock.
97 @param Sock Pointer to the instance's socket.
98 @param List Pointer to the list to store the token.
99 @param Token Pointer to the token to be buffered.
100 @param DataLen The data length of the buffer contained in Token.
102 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
113 SOCK_TOKEN
*SockToken
;
115 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
116 if (NULL
== SockToken
) {
118 DEBUG ((EFI_D_ERROR
, "SockBufferIOToken: No Memory "
119 "to allocate SockToken\n"));
124 SockToken
->Sock
= Sock
;
125 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
126 SockToken
->RemainDataLen
= DataLen
;
127 InsertTailList (List
, &SockToken
->TokenList
);
134 Destroy the socket Sock and its associated protocol control block.
136 @param Sock The socket to be destroyed.
138 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
139 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
149 ASSERT ((Sock
!= NULL
) && (Sock
->ProtoHandler
!= NULL
));
151 if (Sock
->InDestroy
) {
155 Sock
->InDestroy
= TRUE
;
157 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
158 if (EFI_ERROR (Status
)) {
160 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Get the lock to "
161 "access socket failed with %r\n", Status
));
163 return EFI_ACCESS_DENIED
;
167 // force protocol layer to detach the PCB
169 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
171 if (EFI_ERROR (Status
)) {
173 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Protocol detach socket"
174 " failed with %r\n", Status
));
176 Sock
->InDestroy
= FALSE
;
177 } else if (SOCK_IS_CONFIGURED (Sock
)) {
179 SockConnFlush (Sock
);
180 SockSetState (Sock
, SO_CLOSED
);
182 Sock
->ConfigureState
= SO_UNCONFIGURED
;
185 EfiReleaseLock (&(Sock
->Lock
));
187 if (EFI_ERROR (Status
)) {
197 Create a socket and its associated protocol control block
198 with the intial data SockInitData and protocol specific
201 @param SockInitData Inital data to setting the socket.
203 @return Pointer to the newly created socket. If NULL, error condition occured.
208 IN SOCK_INIT_DATA
*SockInitData
215 // create a new socket
217 Sock
= SockCreate (SockInitData
);
220 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
221 "create a new socket\n"));
226 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
227 if (EFI_ERROR (Status
)) {
229 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
230 "access socket failed with %r\n", Status
));
236 // inform the protocol layer to attach the socket
237 // with a new protocol control block
239 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
240 EfiReleaseLock (&(Sock
->Lock
));
241 if (EFI_ERROR (Status
)) {
243 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
244 " attach a socket with %r\n", Status
));
255 Configure the specific socket Sock using configuration data ConfigData.
257 @param Sock Pointer to the socket to be configured.
258 @param ConfigData Pointer to the configuration data.
260 @retval EFI_SUCCESS The socket is configured successfully.
261 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
262 socket is already configured.
273 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
274 if (EFI_ERROR (Status
)) {
276 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
277 "socket failed with %r", Status
));
279 return EFI_ACCESS_DENIED
;
282 if (SOCK_IS_CONFIGURED (Sock
)) {
283 Status
= EFI_ACCESS_DENIED
;
287 ASSERT (Sock
->State
== SO_CLOSED
);
289 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
292 EfiReleaseLock (&(Sock
->Lock
));
299 Initiate a connection establishment process.
301 @param Sock Pointer to the socket to initiate the initate the
303 @param Token Pointer to the token used for the connection
306 @retval EFI_SUCCESS The connection is initialized successfully.
307 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
308 socket is closed, or the socket is not configured to
309 be an active one, or the token is already in one of
311 @retval EFI_NO_MAPPING The IP address configuration operation is not
313 @retval EFI_NOT_STARTED The socket is not configured.
325 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
326 if (EFI_ERROR (Status
)) {
328 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
329 "socket failed with %r", Status
));
331 return EFI_ACCESS_DENIED
;
334 if (SOCK_IS_NO_MAPPING (Sock
)) {
335 Status
= EFI_NO_MAPPING
;
339 if (SOCK_IS_UNCONFIGURED (Sock
)) {
341 Status
= EFI_NOT_STARTED
;
345 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
347 Status
= EFI_ACCESS_DENIED
;
351 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
353 if (SockTokenExisted (Sock
, Event
)) {
355 Status
= EFI_ACCESS_DENIED
;
359 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
360 SockSetState (Sock
, SO_CONNECTING
);
361 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
364 EfiReleaseLock (&(Sock
->Lock
));
370 Issue a listen token to get an existed connected network instance
371 or wait for a connection if there is none.
373 @param Sock Pointer to the socket to accept connections.
374 @param Token The token to accept a connection.
376 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
377 buffered for further acception.
378 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
379 socket is closed, or the socket is not configured to
380 be a passive one, or the token is already in one of
382 @retval EFI_NO_MAPPING The IP address configuration operation is not
384 @retval EFI_NOT_STARTED The socket is not configured.
385 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
394 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
395 LIST_ENTRY
*ListEntry
;
400 ASSERT (SockStream
== Sock
->Type
);
402 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
403 if (EFI_ERROR (Status
)) {
405 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
406 " failed with %r", Status
));
408 return EFI_ACCESS_DENIED
;
411 if (SOCK_IS_NO_MAPPING (Sock
)) {
412 Status
= EFI_NO_MAPPING
;
416 if (SOCK_IS_UNCONFIGURED (Sock
)) {
418 Status
= EFI_NOT_STARTED
;
422 if (!SOCK_IS_LISTENING (Sock
)) {
424 Status
= EFI_ACCESS_DENIED
;
428 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
430 if (SockTokenExisted (Sock
, Event
)) {
432 Status
= EFI_ACCESS_DENIED
;
436 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
439 // Check if a connection has already in this Sock->ConnectionList
441 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
443 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
445 if (SOCK_IS_CONNECTED (Socket
)) {
446 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
447 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
449 RemoveEntryList (ListEntry
);
451 ASSERT (Socket
->Parent
!= NULL
);
453 Socket
->Parent
->ConnCnt
--;
457 "SockAccept: Accept a socket, now conncount is %d",
458 Socket
->Parent
->ConnCnt
)
460 Socket
->Parent
= NULL
;
467 // Buffer this token for latter incoming connection request
469 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
471 Status
= EFI_OUT_OF_RESOURCES
;
475 EfiReleaseLock (&(Sock
->Lock
));
482 Issue a token with data to the socket to send out.
484 @param Sock Pointer to the socket to process the token with
486 @param Token The token with data that needs to send out.
488 @retval EFI_SUCCESS The token is processed successfully.
489 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
490 socket is closed, or the socket is not in a
491 synchronized state , or the token is already in one
492 of this socket's lists.
493 @retval EFI_NO_MAPPING The IP address configuration operation is not
495 @retval EFI_NOT_STARTED The socket is not configured.
496 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
505 SOCK_IO_TOKEN
*SndToken
;
508 EFI_TCP4_TRANSMIT_DATA
*TxData
;
510 SOCK_TOKEN
*SockToken
;
513 ASSERT (SockStream
== Sock
->Type
);
515 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
516 if (EFI_ERROR (Status
)) {
518 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
519 " failed with %r", Status
));
521 return EFI_ACCESS_DENIED
;
524 if (SOCK_IS_NO_MAPPING (Sock
)) {
525 Status
= EFI_NO_MAPPING
;
529 SndToken
= (SOCK_IO_TOKEN
*) Token
;
530 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
532 if (SOCK_IS_UNCONFIGURED (Sock
)) {
533 Status
= EFI_NOT_STARTED
;
537 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
539 Status
= EFI_ACCESS_DENIED
;
544 // check if a token is already in the token buffer
546 Event
= SndToken
->Token
.Event
;
548 if (SockTokenExisted (Sock
, Event
)) {
549 Status
= EFI_ACCESS_DENIED
;
553 DataLen
= (UINT32
) TxData
->DataLength
;
556 // process this sending token now or buffer it only?
558 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
560 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
562 SockToken
= SockBufferToken (
569 if (NULL
== SockToken
) {
570 Status
= EFI_OUT_OF_RESOURCES
;
574 SockToken
= SockBufferToken (
576 &Sock
->ProcessingSndTokenList
,
581 if (NULL
== SockToken
) {
582 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
583 " socket processing SndToken List\n", Status
));
585 Status
= EFI_OUT_OF_RESOURCES
;
589 Status
= SockProcessTcpSndData (Sock
, TxData
);
591 if (EFI_ERROR (Status
)) {
592 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
593 "Snd Data\n", Status
));
595 RemoveEntryList (&(SockToken
->TokenList
));
596 FreePool (SockToken
);
601 EfiReleaseLock (&(Sock
->Lock
));
607 Issue a token to get data from the socket.
609 @param Sock Pointer to the socket to get data from.
610 @param Token The token to store the received data from the
613 @retval EFI_SUCCESS The token is processed successfully.
614 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
615 socket is closed, or the socket is not in a
616 synchronized state , or the token is already in one
617 of this socket's lists.
618 @retval EFI_NO_MAPPING The IP address configuration operation is not
620 @retval EFI_NOT_STARTED The socket is not configured.
621 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
622 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
631 SOCK_IO_TOKEN
*RcvToken
;
636 ASSERT (SockStream
== Sock
->Type
);
638 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
639 if (EFI_ERROR (Status
)) {
641 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
642 " failed with %r", Status
));
644 return EFI_ACCESS_DENIED
;
647 if (SOCK_IS_NO_MAPPING (Sock
)) {
649 Status
= EFI_NO_MAPPING
;
653 if (SOCK_IS_UNCONFIGURED (Sock
)) {
655 Status
= EFI_NOT_STARTED
;
659 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
661 Status
= EFI_ACCESS_DENIED
;
665 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
668 // check if a token is already in the token buffer of this socket
670 Event
= RcvToken
->Token
.Event
;
671 if (SockTokenExisted (Sock
, Event
)) {
672 Status
= EFI_ACCESS_DENIED
;
676 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
677 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
680 // check whether an error has happened before
682 if (EFI_ABORTED
!= Sock
->SockError
) {
684 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
685 Sock
->SockError
= EFI_ABORTED
;
690 // check whether can not receive and there is no any
691 // data buffered in Sock->RcvBuffer
693 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
695 Status
= EFI_CONNECTION_FIN
;
699 if (RcvdBytes
!= 0) {
700 SockProcessRcvToken (Sock
, RcvToken
);
702 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
705 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
706 Status
= EFI_OUT_OF_RESOURCES
;
711 EfiReleaseLock (&(Sock
->Lock
));
717 Reset the socket and its associated protocol control block.
719 @param Sock Pointer to the socket to be flushed.
721 @retval EFI_SUCCESS The socket is flushed successfully.
722 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
732 ASSERT (SockStream
== Sock
->Type
);
734 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
735 if (EFI_ERROR (Status
)) {
737 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
738 " failed with %r", Status
));
740 return EFI_ACCESS_DENIED
;
743 if (!SOCK_IS_CONFIGURED (Sock
)) {
747 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
748 if (EFI_ERROR (Status
)) {
750 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
751 " SOCK_FLUSH with %r", Status
));
756 SOCK_ERROR (Sock
, EFI_ABORTED
);
757 SockConnFlush (Sock
);
758 SockSetState (Sock
, SO_CLOSED
);
760 Sock
->ConfigureState
= SO_UNCONFIGURED
;
763 EfiReleaseLock (&(Sock
->Lock
));
769 Close or abort the socket associated connection.
771 @param Sock Pointer to the socket of the connection to close or
773 @param Token The token for close operation.
774 @param OnAbort TRUE for aborting the connection, FALSE to close it.
776 @retval EFI_SUCCESS The close or abort operation is initialized
778 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
779 socket is closed, or the socket is not in a
780 synchronized state , or the token is already in one
781 of this socket's lists.
782 @retval EFI_NO_MAPPING The IP address configuration operation is not
784 @retval EFI_NOT_STARTED The socket is not configured.
797 ASSERT (SockStream
== Sock
->Type
);
799 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
800 if (EFI_ERROR (Status
)) {
801 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
802 " failed with %r", Status
));
804 return EFI_ACCESS_DENIED
;
807 if (SOCK_IS_NO_MAPPING (Sock
)) {
808 Status
= EFI_NO_MAPPING
;
812 if (SOCK_IS_UNCONFIGURED (Sock
)) {
813 Status
= EFI_NOT_STARTED
;
817 if (SOCK_IS_DISCONNECTING (Sock
)) {
818 Status
= EFI_ACCESS_DENIED
;
822 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
824 if (SockTokenExisted (Sock
, Event
)) {
825 Status
= EFI_ACCESS_DENIED
;
829 Sock
->CloseToken
= Token
;
830 SockSetState (Sock
, SO_DISCONNECTING
);
833 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
835 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
839 EfiReleaseLock (&(Sock
->Lock
));
845 Get the mode data of the low layer protocol.
847 @param Sock Pointer to the socket to get mode data from.
848 @param Mode Pointer to the data to store the low layer mode
851 @retval EFI_SUCCESS The mode data is got successfully.
852 @retval EFI_NOT_STARTED The socket is not configured.
861 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
866 Configure the low level protocol to join a multicast group for
867 this socket's connection.
869 @param Sock Pointer to the socket of the connection to join the
870 specific multicast group.
871 @param GroupInfo Pointer to the multicast group info.
873 @retval EFI_SUCCESS The configuration is done successfully.
874 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
875 @retval EFI_NOT_STARTED The socket is not configured.
886 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
888 if (EFI_ERROR (Status
)) {
890 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
891 " failed with %r", Status
));
893 return EFI_ACCESS_DENIED
;
896 if (SOCK_IS_UNCONFIGURED (Sock
)) {
897 Status
= EFI_NOT_STARTED
;
901 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
904 EfiReleaseLock (&(Sock
->Lock
));
910 Add or remove route information in IP route table associated
913 @param Sock Pointer to the socket associated with the IP route
915 @param RouteInfo Pointer to the route information to be processed.
917 @retval EFI_SUCCESS The route table is updated successfully.
918 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
919 @retval EFI_NO_MAPPING The IP address configuration operation is not
921 @retval EFI_NOT_STARTED The socket is not configured.
932 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
933 if (EFI_ERROR (Status
)) {
934 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
935 " failed with %r", Status
));
937 return EFI_ACCESS_DENIED
;
940 if (SOCK_IS_NO_MAPPING (Sock
)) {
941 Status
= EFI_NO_MAPPING
;
945 if (SOCK_IS_UNCONFIGURED (Sock
)) {
946 Status
= EFI_NOT_STARTED
;
950 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
953 EfiReleaseLock (&(Sock
->Lock
));