]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
dd359823b4a50c49b52ed02c5f35cc57ef0dd908
3 Copyright (c) 2005 - 2006, Intel Corporation<BR>
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<BR>
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.
19 Check whether the Event is in the List.
21 @param List Pointer to the token list to be searched.
22 @param Event The event to be checked.
24 @retval TRUE The specific Event exists in the List.
25 @retval False The specific Event is not in the List.
29 SockTokenExistedInList (
34 LIST_ENTRY
*ListEntry
;
35 SOCK_TOKEN
*SockToken
;
37 NET_LIST_FOR_EACH (ListEntry
, List
) {
38 SockToken
= NET_LIST_USER_STRUCT (
44 if (Event
== SockToken
->Token
->Event
) {
54 Call SockTokenExistedInList() to check whether the Event is
55 in the related socket's lists.
57 @param Sock Pointer to the instance's socket.
58 @param Event The event to be checked.
60 @return The specific Event exists in one of socket's lists or not.
70 if (SockTokenExistedInList (&Sock
->SndTokenList
, Event
) ||
71 SockTokenExistedInList (&Sock
->ProcessingSndTokenList
, Event
) ||
72 SockTokenExistedInList (&Sock
->RcvTokenList
, Event
) ||
73 SockTokenExistedInList (&Sock
->ListenTokenList
, Event
)) {
78 if ((Sock
->ConnectionToken
!= NULL
) &&
79 (Sock
->ConnectionToken
->Event
== Event
)) {
84 if ((Sock
->CloseToken
!= NULL
) && (Sock
->CloseToken
->Event
== Event
)) {
93 Buffer a token into the specific list of socket Sock.
95 @param Sock Pointer to the instance's socket.
96 @param List Pointer to the list to store the token.
97 @param Token Pointer to the token to be buffered.
98 @param DataLen The data length of the buffer contained in Token.
100 @return Pointer to the token that wraps Token. If NULL, error condition occurred.
111 SOCK_TOKEN
*SockToken
;
113 SockToken
= AllocatePool (sizeof (SOCK_TOKEN
));
114 if (NULL
== SockToken
) {
116 DEBUG ((EFI_D_ERROR
, "SockBufferIOToken: No Memory "
117 "to allocate SockToken\n"));
122 SockToken
->Sock
= Sock
;
123 SockToken
->Token
= (SOCK_COMPLETION_TOKEN
*) Token
;
124 SockToken
->RemainDataLen
= DataLen
;
125 InsertTailList (List
, &SockToken
->TokenList
);
132 Destory the socket Sock and its associated protocol control block.
134 @param Sock The socket to be destroyed.
136 @retval EFI_SUCCESS The socket Sock is destroyed successfully.
137 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
147 ASSERT ((Sock
!= NULL
) && (Sock
->ProtoHandler
!= NULL
));
149 if (Sock
->IsDestroyed
) {
153 Sock
->IsDestroyed
= TRUE
;
155 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
156 if (EFI_ERROR (Status
)) {
158 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Get the lock to "
159 "access socket failed with %r\n", Status
));
161 return EFI_ACCESS_DENIED
;
165 // force protocol layer to detach the PCB
167 Status
= Sock
->ProtoHandler (Sock
, SOCK_DETACH
, NULL
);
169 if (EFI_ERROR (Status
)) {
171 DEBUG ((EFI_D_ERROR
, "SockDestroyChild: Protocol detach socket"
172 " failed with %r\n", Status
));
174 Sock
->IsDestroyed
= FALSE
;
175 } else if (SOCK_IS_CONFIGURED (Sock
)) {
177 SockConnFlush (Sock
);
178 SockSetState (Sock
, SO_CLOSED
);
180 Sock
->ConfigureState
= SO_UNCONFIGURED
;
183 EfiReleaseLock (&(Sock
->Lock
));
185 if (EFI_ERROR (Status
)) {
195 Create a socket and its associated protocol control block
196 with the intial data SockInitData and protocol specific
199 @param SockInitData Inital data to setting the socket.
201 @return Pointer to the newly created socket. If NULL, error condition occured.
206 IN SOCK_INIT_DATA
*SockInitData
213 // create a new socket
215 Sock
= SockCreate (SockInitData
);
218 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
219 "create a new socket\n"));
224 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
225 if (EFI_ERROR (Status
)) {
227 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
228 "access socket failed with %r\n", Status
));
234 // inform the protocol layer to attach the socket
235 // with a new protocol control block
237 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
238 if (EFI_ERROR (Status
)) {
240 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
241 " attach a socket with %r\n", Status
));
247 EfiReleaseLock (&(Sock
->Lock
));
253 Configure the specific socket Sock using configuration data ConfigData.
255 @param Sock Pointer to the socket to be configured.
256 @param ConfigData Pointer to the configuration data.
258 @retval EFI_SUCCESS The socket is configured successfully.
259 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
260 socket is already configured.
271 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
272 if (EFI_ERROR (Status
)) {
274 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
275 "socket failed with %r", Status
));
277 return EFI_ACCESS_DENIED
;
280 if (SOCK_IS_CONFIGURED (Sock
)) {
281 Status
= EFI_ACCESS_DENIED
;
285 ASSERT (Sock
->State
== SO_CLOSED
);
287 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
290 EfiReleaseLock (&(Sock
->Lock
));
297 Initiate a connection establishment process.
299 @param Sock Pointer to the socket to initiate the initate the
301 @param Token Pointer to the token used for the connection
304 @retval EFI_SUCCESS The connection is initialized successfully.
305 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
306 socket is closed, or the socket is not configured to
307 be an active one, or the token is already in one of
309 @retval EFI_NO_MAPPING The IP address configuration operation is not
311 @retval EFI_NOT_STARTED The socket is not configured.
323 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
324 if (EFI_ERROR (Status
)) {
326 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
327 "socket failed with %r", Status
));
329 return EFI_ACCESS_DENIED
;
332 if (SOCK_IS_NO_MAPPING (Sock
)) {
333 Status
= EFI_NO_MAPPING
;
337 if (SOCK_IS_UNCONFIGURED (Sock
)) {
339 Status
= EFI_NOT_STARTED
;
343 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
345 Status
= EFI_ACCESS_DENIED
;
349 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
351 if (SockTokenExisted (Sock
, Event
)) {
353 Status
= EFI_ACCESS_DENIED
;
357 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
358 SockSetState (Sock
, SO_CONNECTING
);
359 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
362 EfiReleaseLock (&(Sock
->Lock
));
368 Issue a listen token to get an existed connected network instance
369 or wait for a connection if there is none.
371 @param Sock Pointer to the socket to accept connections.
372 @param Token The token to accept a connection.
374 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
375 buffered for further acception.
376 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
377 socket is closed, or the socket is not configured to
378 be a passive one, or the token is already in one of
380 @retval EFI_NO_MAPPING The IP address configuration operation is not
382 @retval EFI_NOT_STARTED The socket is not configured.
383 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
392 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
393 LIST_ENTRY
*ListEntry
;
398 ASSERT (SOCK_STREAM
== Sock
->Type
);
400 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
401 if (EFI_ERROR (Status
)) {
403 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
404 " failed with %r", Status
));
406 return EFI_ACCESS_DENIED
;
409 if (SOCK_IS_NO_MAPPING (Sock
)) {
410 Status
= EFI_NO_MAPPING
;
414 if (SOCK_IS_UNCONFIGURED (Sock
)) {
416 Status
= EFI_NOT_STARTED
;
420 if (!SOCK_IS_LISTENING (Sock
)) {
422 Status
= EFI_ACCESS_DENIED
;
426 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
428 if (SockTokenExisted (Sock
, Event
)) {
430 Status
= EFI_ACCESS_DENIED
;
434 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
437 // Check if a connection has already in this Sock->ConnectionList
439 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
441 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
443 if (SOCK_IS_CONNECTED (Socket
)) {
444 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
445 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
447 RemoveEntryList (ListEntry
);
449 ASSERT (Socket
->Parent
!= NULL
);
451 Socket
->Parent
->ConnCnt
--;
455 "SockAccept: Accept a socket, now conncount is %d",
456 Socket
->Parent
->ConnCnt
)
458 Socket
->Parent
= NULL
;
465 // Buffer this token for latter incoming connection request
467 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
469 Status
= EFI_OUT_OF_RESOURCES
;
473 EfiReleaseLock (&(Sock
->Lock
));
480 Issue a token with data to the socket to send out.
482 @param Sock Pointer to the socket to process the token with
484 @param Token The token with data that needs to send out.
486 @retval EFI_SUCCESS The token is processed successfully.
487 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
488 socket is closed, or the socket is not in a
489 synchronized state , or the token is already in one
490 of this socket's lists.
491 @retval EFI_NO_MAPPING The IP address configuration operation is not
493 @retval EFI_NOT_STARTED The socket is not configured.
494 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
503 SOCK_IO_TOKEN
*SndToken
;
506 EFI_TCP4_TRANSMIT_DATA
*TxData
;
508 SOCK_TOKEN
*SockToken
;
511 ASSERT (SOCK_STREAM
== Sock
->Type
);
513 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
514 if (EFI_ERROR (Status
)) {
516 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
517 " failed with %r", Status
));
519 return EFI_ACCESS_DENIED
;
522 if (SOCK_IS_NO_MAPPING (Sock
)) {
523 Status
= EFI_NO_MAPPING
;
527 SndToken
= (SOCK_IO_TOKEN
*) Token
;
528 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
530 if (SOCK_IS_UNCONFIGURED (Sock
)) {
531 Status
= EFI_NOT_STARTED
;
535 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
537 Status
= EFI_ACCESS_DENIED
;
542 // check if a token is already in the token buffer
544 Event
= SndToken
->Token
.Event
;
546 if (SockTokenExisted (Sock
, Event
)) {
547 Status
= EFI_ACCESS_DENIED
;
551 DataLen
= (UINT32
) TxData
->DataLength
;
554 // process this sending token now or buffer it only?
556 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
558 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
560 SockToken
= SockBufferToken (
567 if (NULL
== SockToken
) {
568 Status
= EFI_OUT_OF_RESOURCES
;
572 SockToken
= SockBufferToken (
574 &Sock
->ProcessingSndTokenList
,
579 if (NULL
== SockToken
) {
580 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
581 " socket processing SndToken List\n", Status
));
583 Status
= EFI_OUT_OF_RESOURCES
;
587 Status
= SockProcessTcpSndData (Sock
, TxData
);
589 if (EFI_ERROR (Status
)) {
590 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
591 "Snd Data\n", Status
));
593 RemoveEntryList (&(SockToken
->TokenList
));
594 gBS
->FreePool (SockToken
);
599 EfiReleaseLock (&(Sock
->Lock
));
605 Issue a token to get data from the socket.
607 @param Sock Pointer to the socket to get data from.
608 @param Token The token to store the received data from the
611 @retval EFI_SUCCESS The token is processed successfully.
612 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
613 socket is closed, or the socket is not in a
614 synchronized state , or the token is already in one
615 of this socket's lists.
616 @retval EFI_NO_MAPPING The IP address configuration operation is not
618 @retval EFI_NOT_STARTED The socket is not configured.
619 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
620 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
629 SOCK_IO_TOKEN
*RcvToken
;
634 ASSERT (SOCK_STREAM
== Sock
->Type
);
636 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
637 if (EFI_ERROR (Status
)) {
639 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
640 " failed with %r", Status
));
642 return EFI_ACCESS_DENIED
;
645 if (SOCK_IS_NO_MAPPING (Sock
)) {
647 Status
= EFI_NO_MAPPING
;
651 if (SOCK_IS_UNCONFIGURED (Sock
)) {
653 Status
= EFI_NOT_STARTED
;
657 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
659 Status
= EFI_ACCESS_DENIED
;
663 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
666 // check if a token is already in the token buffer of this socket
668 Event
= RcvToken
->Token
.Event
;
669 if (SockTokenExisted (Sock
, Event
)) {
670 Status
= EFI_ACCESS_DENIED
;
674 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
675 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
678 // check whether an error has happened before
680 if (EFI_ABORTED
!= Sock
->SockError
) {
682 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
683 Sock
->SockError
= EFI_ABORTED
;
688 // check whether can not receive and there is no any
689 // data buffered in Sock->RcvBuffer
691 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
693 Status
= EFI_CONNECTION_FIN
;
697 if (RcvdBytes
!= 0) {
698 Status
= SockProcessRcvToken (Sock
, RcvToken
);
700 if (EFI_ERROR (Status
)) {
704 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
707 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
708 Status
= EFI_OUT_OF_RESOURCES
;
713 EfiReleaseLock (&(Sock
->Lock
));
719 Reset the socket and its associated protocol control block.
721 @param Sock Pointer to the socket to be flushed.
723 @retval EFI_SUCCESS The socket is flushed successfully.
724 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
734 ASSERT (SOCK_STREAM
== Sock
->Type
);
736 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
737 if (EFI_ERROR (Status
)) {
739 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
740 " failed with %r", Status
));
742 return EFI_ACCESS_DENIED
;
745 if (!SOCK_IS_CONFIGURED (Sock
)) {
749 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
750 if (EFI_ERROR (Status
)) {
752 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
753 " SOCK_FLUSH with %r", Status
));
758 SOCK_ERROR (Sock
, EFI_ABORTED
);
759 SockConnFlush (Sock
);
760 SockSetState (Sock
, SO_CLOSED
);
762 Sock
->ConfigureState
= SO_UNCONFIGURED
;
765 EfiReleaseLock (&(Sock
->Lock
));
771 Close or abort the socket associated connection.
773 @param Sock Pointer to the socket of the connection to close or
775 @param Token The token for close operation.
776 @param OnAbort TRUE for aborting the connection, FALSE to close it.
778 @retval EFI_SUCCESS The close or abort operation is initialized
780 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
781 socket is closed, or the socket is not in a
782 synchronized state , or the token is already in one
783 of this socket's lists.
784 @retval EFI_NO_MAPPING The IP address configuration operation is not
786 @retval EFI_NOT_STARTED The socket is not configured.
799 ASSERT (SOCK_STREAM
== Sock
->Type
);
801 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
802 if (EFI_ERROR (Status
)) {
803 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
804 " failed with %r", Status
));
806 return EFI_ACCESS_DENIED
;
809 if (SOCK_IS_NO_MAPPING (Sock
)) {
810 Status
= EFI_NO_MAPPING
;
814 if (SOCK_IS_UNCONFIGURED (Sock
)) {
815 Status
= EFI_NOT_STARTED
;
819 if (SOCK_IS_DISCONNECTING (Sock
)) {
820 Status
= EFI_ACCESS_DENIED
;
824 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
826 if (SockTokenExisted (Sock
, Event
)) {
827 Status
= EFI_ACCESS_DENIED
;
831 Sock
->CloseToken
= Token
;
832 SockSetState (Sock
, SO_DISCONNECTING
);
835 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
837 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
841 EfiReleaseLock (&(Sock
->Lock
));
847 Get the mode data of the low layer protocol.
849 @param Sock Pointer to the socket to get mode data from.
850 @param Mode Pointer to the data to store the low layer mode
853 @retval EFI_SUCCESS The mode data is got successfully.
854 @retval EFI_NOT_STARTED The socket is not configured.
863 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
868 Configure the low level protocol to join a multicast group for
869 this socket's connection.
871 @param Sock Pointer to the socket of the connection to join the
872 specific multicast group.
873 @param GroupInfo Pointer to the multicast group info.
875 @retval EFI_SUCCESS The configuration is done successfully.
876 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
877 @retval EFI_NOT_STARTED The socket is not configured.
888 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
890 if (EFI_ERROR (Status
)) {
892 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
893 " failed with %r", Status
));
895 return EFI_ACCESS_DENIED
;
898 if (SOCK_IS_UNCONFIGURED (Sock
)) {
899 Status
= EFI_NOT_STARTED
;
903 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
906 EfiReleaseLock (&(Sock
->Lock
));
912 Add or remove route information in IP route table associated
915 @param Sock Pointer to the socket associated with the IP route
917 @param RouteInfo Pointer to the route information to be processed.
919 @retval EFI_SUCCESS The route table is updated successfully.
920 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
921 @retval EFI_NO_MAPPING The IP address configuration operation is not
923 @retval EFI_NOT_STARTED The socket is not configured.
934 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
935 if (EFI_ERROR (Status
)) {
936 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
937 " failed with %r", Status
));
939 return EFI_ACCESS_DENIED
;
942 if (SOCK_IS_NO_MAPPING (Sock
)) {
943 Status
= EFI_NO_MAPPING
;
947 if (SOCK_IS_UNCONFIGURED (Sock
)) {
948 Status
= EFI_NOT_STARTED
;
952 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
955 EfiReleaseLock (&(Sock
->Lock
));