]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
67aa919c338382595e38aff696c8ea6803735bc1
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 TRUE The specific Event exists in the List.
32 @retval 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
)) {
85 if ((Sock
->ConnectionToken
!= NULL
) &&
86 (Sock
->ConnectionToken
->Event
== Event
)) {
91 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
100 Buffer a token into the specific list of socket Sock.
102 @param Sock Pointer to the instance's socket.
103 @param List Pointer to the list to store the token.
104 @param Token Pointer to the token to be buffered.
105 @param DataLen The data length of the buffer contained in Token.
107 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
118 SOCK_TOKEN
*SockToken
;
120 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
121 if (NULL
== SockToken
) {
123 DEBUG ((EFI_D_ERROR
, "SockBufferIOToken: No Memory "
124 "to allocate SockToken\n"));
129 SockToken
->Sock
= Sock
;
130 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
131 SockToken
->RemainDataLen
= DataLen
;
132 InsertTailList (List
, &SockToken
->TokenList
);
139 Destory the socket Sock and its associated protocol control block.
141 @param Sock The socket to be destroyed.
143 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
144 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
154 ASSERT ((Sock
!= NULL
) && (Sock
->ProtoHandler
!= NULL
));
156 if (Sock
->IsDestroyed
) {
160 Sock
->IsDestroyed
= TRUE
;
162 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
163 if (EFI_ERROR (Status
)) {
165 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Get the lock to "
166 "access socket failed with %r\n", Status
));
168 return EFI_ACCESS_DENIED
;
172 // force protocol layer to detach the PCB
174 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
176 if (EFI_ERROR (Status
)) {
178 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Protocol detach socket"
179 " failed with %r\n", Status
));
181 Sock
->IsDestroyed
= FALSE
;
182 } else if (SOCK_IS_CONFIGURED (Sock
)) {
184 SockConnFlush (Sock
);
185 SockSetState (Sock
, SO_CLOSED
);
187 Sock
->ConfigureState
= SO_UNCONFIGURED
;
190 EfiReleaseLock (&(Sock
->Lock
));
192 if (EFI_ERROR (Status
)) {
202 Create a socket and its associated protocol control block
203 with the intial data SockInitData and protocol specific
206 @param SockInitData Inital data to setting the socket.
208 @return Pointer to the newly created socket. If NULL, error condition occured.
213 IN SOCK_INIT_DATA
*SockInitData
220 // create a new socket
222 Sock
= SockCreate (SockInitData
);
225 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
226 "create a new socket\n"));
231 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
232 if (EFI_ERROR (Status
)) {
234 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
235 "access socket failed with %r\n", Status
));
241 // inform the protocol layer to attach the socket
242 // with a new protocol control block
244 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
245 if (EFI_ERROR (Status
)) {
247 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
248 " attach a socket with %r\n", Status
));
254 EfiReleaseLock (&(Sock
->Lock
));
260 Configure the specific socket Sock using configuration data ConfigData.
262 @param Sock Pointer to the socket to be configured.
263 @param ConfigData Pointer to the configuration data.
265 @retval EFI_SUCCESS The socket is configured successfully.
266 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
267 socket is already configured.
278 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
279 if (EFI_ERROR (Status
)) {
281 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
282 "socket failed with %r", Status
));
284 return EFI_ACCESS_DENIED
;
287 if (SOCK_IS_CONFIGURED (Sock
)) {
288 Status
= EFI_ACCESS_DENIED
;
292 ASSERT (Sock
->State
== SO_CLOSED
);
294 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
297 EfiReleaseLock (&(Sock
->Lock
));
304 Initiate a connection establishment process.
306 @param Sock Pointer to the socket to initiate the initate the
308 @param Token Pointer to the token used for the connection
311 @retval EFI_SUCCESS The connection is initialized successfully.
312 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
313 socket is closed, or the socket is not configured to
314 be an active one, or the token is already in one of
316 @retval EFI_NO_MAPPING The IP address configuration operation is not
318 @retval EFI_NOT_STARTED The socket is not configured.
330 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
331 if (EFI_ERROR (Status
)) {
333 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
334 "socket failed with %r", Status
));
336 return EFI_ACCESS_DENIED
;
339 if (SOCK_IS_NO_MAPPING (Sock
)) {
340 Status
= EFI_NO_MAPPING
;
344 if (SOCK_IS_UNCONFIGURED (Sock
)) {
346 Status
= EFI_NOT_STARTED
;
350 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
352 Status
= EFI_ACCESS_DENIED
;
356 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
358 if (SockTokenExisted (Sock
, Event
)) {
360 Status
= EFI_ACCESS_DENIED
;
364 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
365 SockSetState (Sock
, SO_CONNECTING
);
366 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
369 EfiReleaseLock (&(Sock
->Lock
));
375 Issue a listen token to get an existed connected network instance
376 or wait for a connection if there is none.
378 @param Sock Pointer to the socket to accept connections.
379 @param Token The token to accept a connection.
381 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
382 buffered for further acception.
383 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
384 socket is closed, or the socket is not configured to
385 be a passive one, or the token is already in one of
387 @retval EFI_NO_MAPPING The IP address configuration operation is not
389 @retval EFI_NOT_STARTED The socket is not configured.
390 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
399 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
400 LIST_ENTRY
*ListEntry
;
405 ASSERT (SOCK_STREAM
== Sock
->Type
);
407 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
408 if (EFI_ERROR (Status
)) {
410 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
411 " failed with %r", Status
));
413 return EFI_ACCESS_DENIED
;
416 if (SOCK_IS_NO_MAPPING (Sock
)) {
417 Status
= EFI_NO_MAPPING
;
421 if (SOCK_IS_UNCONFIGURED (Sock
)) {
423 Status
= EFI_NOT_STARTED
;
427 if (!SOCK_IS_LISTENING (Sock
)) {
429 Status
= EFI_ACCESS_DENIED
;
433 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
435 if (SockTokenExisted (Sock
, Event
)) {
437 Status
= EFI_ACCESS_DENIED
;
441 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
444 // Check if a connection has already in this Sock->ConnectionList
446 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
448 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
450 if (SOCK_IS_CONNECTED (Socket
)) {
451 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
452 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
454 RemoveEntryList (ListEntry
);
456 ASSERT (Socket
->Parent
!= NULL
);
458 Socket
->Parent
->ConnCnt
--;
462 "SockAccept: Accept a socket, now conncount is %d",
463 Socket
->Parent
->ConnCnt
)
465 Socket
->Parent
= NULL
;
472 // Buffer this token for latter incoming connection request
474 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
476 Status
= EFI_OUT_OF_RESOURCES
;
480 EfiReleaseLock (&(Sock
->Lock
));
487 Issue a token with data to the socket to send out.
489 @param Sock Pointer to the socket to process the token with
491 @param Token The token with data that needs to send out.
493 @retval EFI_SUCCESS The token is processed successfully.
494 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
495 socket is closed, or the socket is not in a
496 synchronized state , or the token is already in one
497 of this socket's lists.
498 @retval EFI_NO_MAPPING The IP address configuration operation is not
500 @retval EFI_NOT_STARTED The socket is not configured.
501 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
510 SOCK_IO_TOKEN
*SndToken
;
513 EFI_TCP4_TRANSMIT_DATA
*TxData
;
515 SOCK_TOKEN
*SockToken
;
518 ASSERT (SOCK_STREAM
== Sock
->Type
);
520 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
521 if (EFI_ERROR (Status
)) {
523 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
524 " failed with %r", Status
));
526 return EFI_ACCESS_DENIED
;
529 if (SOCK_IS_NO_MAPPING (Sock
)) {
530 Status
= EFI_NO_MAPPING
;
534 SndToken
= (SOCK_IO_TOKEN
*) Token
;
535 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
537 if (SOCK_IS_UNCONFIGURED (Sock
)) {
538 Status
= EFI_NOT_STARTED
;
542 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
544 Status
= EFI_ACCESS_DENIED
;
549 // check if a token is already in the token buffer
551 Event
= SndToken
->Token
.Event
;
553 if (SockTokenExisted (Sock
, Event
)) {
554 Status
= EFI_ACCESS_DENIED
;
558 DataLen
= (UINT32
) TxData
->DataLength
;
561 // process this sending token now or buffer it only?
563 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
565 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
567 SockToken
= SockBufferToken (
574 if (NULL
== SockToken
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 SockToken
= SockBufferToken (
581 &Sock
->ProcessingSndTokenList
,
586 if (NULL
== SockToken
) {
587 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
588 " socket processing SndToken List\n", Status
));
590 Status
= EFI_OUT_OF_RESOURCES
;
594 Status
= SockProcessTcpSndData (Sock
, TxData
);
596 if (EFI_ERROR (Status
)) {
597 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
598 "Snd Data\n", Status
));
600 RemoveEntryList (&(SockToken
->TokenList
));
601 gBS
->FreePool (SockToken
);
606 EfiReleaseLock (&(Sock
->Lock
));
612 Issue a token to get data from the socket.
614 @param Sock Pointer to the socket to get data from.
615 @param Token The token to store the received data from the
618 @retval EFI_SUCCESS The token is processed successfully.
619 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
620 socket is closed, or the socket is not in a
621 synchronized state , or the token is already in one
622 of this socket's lists.
623 @retval EFI_NO_MAPPING The IP address configuration operation is not
625 @retval EFI_NOT_STARTED The socket is not configured.
626 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
627 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
636 SOCK_IO_TOKEN
*RcvToken
;
641 ASSERT (SOCK_STREAM
== Sock
->Type
);
643 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
644 if (EFI_ERROR (Status
)) {
646 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
647 " failed with %r", Status
));
649 return EFI_ACCESS_DENIED
;
652 if (SOCK_IS_NO_MAPPING (Sock
)) {
654 Status
= EFI_NO_MAPPING
;
658 if (SOCK_IS_UNCONFIGURED (Sock
)) {
660 Status
= EFI_NOT_STARTED
;
664 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
666 Status
= EFI_ACCESS_DENIED
;
670 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
673 // check if a token is already in the token buffer of this socket
675 Event
= RcvToken
->Token
.Event
;
676 if (SockTokenExisted (Sock
, Event
)) {
677 Status
= EFI_ACCESS_DENIED
;
681 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
682 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
685 // check whether an error has happened before
687 if (EFI_ABORTED
!= Sock
->SockError
) {
689 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
690 Sock
->SockError
= EFI_ABORTED
;
695 // check whether can not receive and there is no any
696 // data buffered in Sock->RcvBuffer
698 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
700 Status
= EFI_CONNECTION_FIN
;
704 if (RcvdBytes
!= 0) {
705 Status
= SockProcessRcvToken (Sock
, RcvToken
);
707 if (EFI_ERROR (Status
)) {
711 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
714 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
715 Status
= EFI_OUT_OF_RESOURCES
;
720 EfiReleaseLock (&(Sock
->Lock
));
726 Reset the socket and its associated protocol control block.
728 @param Sock Pointer to the socket to be flushed.
730 @retval EFI_SUCCESS The socket is flushed successfully.
731 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
741 ASSERT (SOCK_STREAM
== Sock
->Type
);
743 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
744 if (EFI_ERROR (Status
)) {
746 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
747 " failed with %r", Status
));
749 return EFI_ACCESS_DENIED
;
752 if (!SOCK_IS_CONFIGURED (Sock
)) {
756 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
757 if (EFI_ERROR (Status
)) {
759 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
760 " SOCK_FLUSH with %r", Status
));
765 SOCK_ERROR (Sock
, EFI_ABORTED
);
766 SockConnFlush (Sock
);
767 SockSetState (Sock
, SO_CLOSED
);
769 Sock
->ConfigureState
= SO_UNCONFIGURED
;
772 EfiReleaseLock (&(Sock
->Lock
));
778 Close or abort the socket associated connection.
780 @param Sock Pointer to the socket of the connection to close or
782 @param Token The token for close operation.
783 @param OnAbort TRUE for aborting the connection, FALSE to close it.
785 @retval EFI_SUCCESS The close or abort operation is initialized
787 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
788 socket is closed, or the socket is not in a
789 synchronized state , or the token is already in one
790 of this socket's lists.
791 @retval EFI_NO_MAPPING The IP address configuration operation is not
793 @retval EFI_NOT_STARTED The socket is not configured.
806 ASSERT (SOCK_STREAM
== Sock
->Type
);
808 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
809 if (EFI_ERROR (Status
)) {
810 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
811 " failed with %r", Status
));
813 return EFI_ACCESS_DENIED
;
816 if (SOCK_IS_NO_MAPPING (Sock
)) {
817 Status
= EFI_NO_MAPPING
;
821 if (SOCK_IS_UNCONFIGURED (Sock
)) {
822 Status
= EFI_NOT_STARTED
;
826 if (SOCK_IS_DISCONNECTING (Sock
)) {
827 Status
= EFI_ACCESS_DENIED
;
831 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
833 if (SockTokenExisted (Sock
, Event
)) {
834 Status
= EFI_ACCESS_DENIED
;
838 Sock
->CloseToken
= Token
;
839 SockSetState (Sock
, SO_DISCONNECTING
);
842 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
844 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
848 EfiReleaseLock (&(Sock
->Lock
));
854 Get the mode data of the low layer protocol.
856 @param Sock Pointer to the socket to get mode data from.
857 @param Mode Pointer to the data to store the low layer mode
860 @retval EFI_SUCCESS The mode data is got successfully.
861 @retval EFI_NOT_STARTED The socket is not configured.
870 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
875 Configure the low level protocol to join a multicast group for
876 this socket's connection.
878 @param Sock Pointer to the socket of the connection to join the
879 specific multicast group.
880 @param GroupInfo Pointer to the multicast group info.
882 @retval EFI_SUCCESS The configuration is done successfully.
883 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
884 @retval EFI_NOT_STARTED The socket is not configured.
895 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
897 if (EFI_ERROR (Status
)) {
899 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
900 " failed with %r", Status
));
902 return EFI_ACCESS_DENIED
;
905 if (SOCK_IS_UNCONFIGURED (Sock
)) {
906 Status
= EFI_NOT_STARTED
;
910 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
913 EfiReleaseLock (&(Sock
->Lock
));
919 Add or remove route information in IP route table associated
922 @param Sock Pointer to the socket associated with the IP route
924 @param RouteInfo Pointer to the route information to be processed.
926 @retval EFI_SUCCESS The route table is updated successfully.
927 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
928 @retval EFI_NO_MAPPING The IP address configuration operation is not
930 @retval EFI_NOT_STARTED The socket is not configured.
941 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
942 if (EFI_ERROR (Status
)) {
943 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
944 " failed with %r", Status
));
946 return EFI_ACCESS_DENIED
;
949 if (SOCK_IS_NO_MAPPING (Sock
)) {
950 Status
= EFI_NO_MAPPING
;
954 if (SOCK_IS_UNCONFIGURED (Sock
)) {
955 Status
= EFI_NOT_STARTED
;
959 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
962 EfiReleaseLock (&(Sock
->Lock
));