]>
git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
2 Interface function of the Socket.
4 Copyright (c) 2005 - 2006, Intel Corporation<BR>
5 All rights reserved. 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 Destory 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
->IsDestroyed
) {
155 Sock
->IsDestroyed
= 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
->IsDestroyed
= 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 if (EFI_ERROR (Status
)) {
242 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
243 " attach a socket with %r\n", Status
));
249 EfiReleaseLock (&(Sock
->Lock
));
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 (SOCK_STREAM
== 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 (SOCK_STREAM
== 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 gBS
->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 (SOCK_STREAM
== 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 Status
= SockProcessRcvToken (Sock
, RcvToken
);
702 if (EFI_ERROR (Status
)) {
706 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
709 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
710 Status
= EFI_OUT_OF_RESOURCES
;
715 EfiReleaseLock (&(Sock
->Lock
));
721 Reset the socket and its associated protocol control block.
723 @param Sock Pointer to the socket to be flushed.
725 @retval EFI_SUCCESS The socket is flushed successfully.
726 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
736 ASSERT (SOCK_STREAM
== Sock
->Type
);
738 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
739 if (EFI_ERROR (Status
)) {
741 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
742 " failed with %r", Status
));
744 return EFI_ACCESS_DENIED
;
747 if (!SOCK_IS_CONFIGURED (Sock
)) {
751 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
752 if (EFI_ERROR (Status
)) {
754 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
755 " SOCK_FLUSH with %r", Status
));
760 SOCK_ERROR (Sock
, EFI_ABORTED
);
761 SockConnFlush (Sock
);
762 SockSetState (Sock
, SO_CLOSED
);
764 Sock
->ConfigureState
= SO_UNCONFIGURED
;
767 EfiReleaseLock (&(Sock
->Lock
));
773 Close or abort the socket associated connection.
775 @param Sock Pointer to the socket of the connection to close or
777 @param Token The token for close operation.
778 @param OnAbort TRUE for aborting the connection, FALSE to close it.
780 @retval EFI_SUCCESS The close or abort operation is initialized
782 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
783 socket is closed, or the socket is not in a
784 synchronized state , or the token is already in one
785 of this socket's lists.
786 @retval EFI_NO_MAPPING The IP address configuration operation is not
788 @retval EFI_NOT_STARTED The socket is not configured.
801 ASSERT (SOCK_STREAM
== Sock
->Type
);
803 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
804 if (EFI_ERROR (Status
)) {
805 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
806 " failed with %r", Status
));
808 return EFI_ACCESS_DENIED
;
811 if (SOCK_IS_NO_MAPPING (Sock
)) {
812 Status
= EFI_NO_MAPPING
;
816 if (SOCK_IS_UNCONFIGURED (Sock
)) {
817 Status
= EFI_NOT_STARTED
;
821 if (SOCK_IS_DISCONNECTING (Sock
)) {
822 Status
= EFI_ACCESS_DENIED
;
826 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
828 if (SockTokenExisted (Sock
, Event
)) {
829 Status
= EFI_ACCESS_DENIED
;
833 Sock
->CloseToken
= Token
;
834 SockSetState (Sock
, SO_DISCONNECTING
);
837 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
839 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
843 EfiReleaseLock (&(Sock
->Lock
));
849 Get the mode data of the low layer protocol.
851 @param Sock Pointer to the socket to get mode data from.
852 @param Mode Pointer to the data to store the low layer mode
855 @retval EFI_SUCCESS The mode data is got successfully.
856 @retval EFI_NOT_STARTED The socket is not configured.
865 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
870 Configure the low level protocol to join a multicast group for
871 this socket's connection.
873 @param Sock Pointer to the socket of the connection to join the
874 specific multicast group.
875 @param GroupInfo Pointer to the multicast group info.
877 @retval EFI_SUCCESS The configuration is done successfully.
878 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
879 @retval EFI_NOT_STARTED The socket is not configured.
890 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
892 if (EFI_ERROR (Status
)) {
894 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
895 " failed with %r", Status
));
897 return EFI_ACCESS_DENIED
;
900 if (SOCK_IS_UNCONFIGURED (Sock
)) {
901 Status
= EFI_NOT_STARTED
;
905 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
908 EfiReleaseLock (&(Sock
->Lock
));
914 Add or remove route information in IP route table associated
917 @param Sock Pointer to the socket associated with the IP route
919 @param RouteInfo Pointer to the route information to be processed.
921 @retval EFI_SUCCESS The route table is updated successfully.
922 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
923 @retval EFI_NO_MAPPING The IP address configuration operation is not
925 @retval EFI_NOT_STARTED The socket is not configured.
936 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
937 if (EFI_ERROR (Status
)) {
938 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
939 " failed with %r", Status
));
941 return EFI_ACCESS_DENIED
;
944 if (SOCK_IS_NO_MAPPING (Sock
)) {
945 Status
= EFI_NO_MAPPING
;
949 if (SOCK_IS_UNCONFIGURED (Sock
)) {
950 Status
= EFI_NOT_STARTED
;
954 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
957 EfiReleaseLock (&(Sock
->Lock
));