]>
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.
208 @param ProtoData Pointer to the protocol specific data.
209 @param Len Length of the protocol specific data.
211 @return Pointer to the newly created socket. If NULL, error condition occured.
216 IN SOCK_INIT_DATA
*SockInitData
223 // create a new socket
225 Sock
= SockCreate (SockInitData
);
228 DEBUG ((EFI_D_ERROR
, "SockCreateChild: No resource to "
229 "create a new socket\n"));
234 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
235 if (EFI_ERROR (Status
)) {
237 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Get the lock to "
238 "access socket failed with %r\n", Status
));
244 // inform the protocol layer to attach the socket
245 // with a new protocol control block
247 Status
= Sock
->ProtoHandler (Sock
, SOCK_ATTACH
, NULL
);
248 if (EFI_ERROR (Status
)) {
250 DEBUG ((EFI_D_ERROR
, "SockCreateChild: Protocol failed to"
251 " attach a socket with %r\n", Status
));
257 EfiReleaseLock (&(Sock
->Lock
));
263 Configure the specific socket Sock using configuration data
266 @param Sock Pointer to the socket to be configured.
267 @param ConfigData Pointer to the configuration data.
269 @retval EFI_SUCCESS The socket is configured successfully.
270 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
271 socket is already configured.
282 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
283 if (EFI_ERROR (Status
)) {
285 DEBUG ((EFI_D_ERROR
, "SockConfigure: Get the access for "
286 "socket failed with %r", Status
));
288 return EFI_ACCESS_DENIED
;
291 if (SOCK_IS_CONFIGURED (Sock
)) {
292 Status
= EFI_ACCESS_DENIED
;
296 ASSERT (Sock
->State
== SO_CLOSED
);
298 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONFIGURE
, ConfigData
);
301 EfiReleaseLock (&(Sock
->Lock
));
308 Initiate a connection establishment process.
310 @param Sock Pointer to the socket to initiate the initate the
312 @param Token Pointer to the token used for the connection
315 @retval EFI_SUCCESS The connection is initialized successfully.
316 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
317 socket is closed, or the socket is not configured to
318 be an active one, or the token is already in one of
320 @retval EFI_NO_MAPPING The IP address configuration operation is not
322 @retval EFI_NOT_STARTED The socket is not configured.
334 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
335 if (EFI_ERROR (Status
)) {
337 DEBUG ((EFI_D_ERROR
, "SockConnect: Get the access for "
338 "socket failed with %r", Status
));
340 return EFI_ACCESS_DENIED
;
343 if (SOCK_IS_NO_MAPPING (Sock
)) {
344 Status
= EFI_NO_MAPPING
;
348 if (SOCK_IS_UNCONFIGURED (Sock
)) {
350 Status
= EFI_NOT_STARTED
;
354 if (!SOCK_IS_CLOSED (Sock
) || !SOCK_IS_CONFIGURED_ACTIVE (Sock
)) {
356 Status
= EFI_ACCESS_DENIED
;
360 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
362 if (SockTokenExisted (Sock
, Event
)) {
364 Status
= EFI_ACCESS_DENIED
;
368 Sock
->ConnectionToken
= (SOCK_COMPLETION_TOKEN
*) Token
;
369 SockSetState (Sock
, SO_CONNECTING
);
370 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONNECT
, NULL
);
373 EfiReleaseLock (&(Sock
->Lock
));
379 Issue a listen token to get an existed connected network instance
380 or wait for a connection if there is none.
382 @param Sock Pointer to the socket to accept connections.
383 @param Token The token to accept a connection.
385 @retval EFI_SUCCESS Either a connection is accpeted or the Token is
386 buffered for further acception.
387 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
388 socket is closed, or the socket is not configured to
389 be a passive one, or the token is already in one of
391 @retval EFI_NO_MAPPING The IP address configuration operation is not
393 @retval EFI_NOT_STARTED The socket is not configured.
394 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
403 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
404 LIST_ENTRY
*ListEntry
;
409 ASSERT (SOCK_STREAM
== Sock
->Type
);
411 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
412 if (EFI_ERROR (Status
)) {
414 DEBUG ((EFI_D_ERROR
, "SockAccept: Get the access for socket"
415 " failed with %r", Status
));
417 return EFI_ACCESS_DENIED
;
420 if (SOCK_IS_NO_MAPPING (Sock
)) {
421 Status
= EFI_NO_MAPPING
;
425 if (SOCK_IS_UNCONFIGURED (Sock
)) {
427 Status
= EFI_NOT_STARTED
;
431 if (!SOCK_IS_LISTENING (Sock
)) {
433 Status
= EFI_ACCESS_DENIED
;
437 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
439 if (SockTokenExisted (Sock
, Event
)) {
441 Status
= EFI_ACCESS_DENIED
;
445 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) Token
;
448 // Check if a connection has already in this Sock->ConnectionList
450 NET_LIST_FOR_EACH (ListEntry
, &Sock
->ConnectionList
) {
452 Socket
= NET_LIST_USER_STRUCT (ListEntry
, SOCKET
, ConnectionList
);
454 if (SOCK_IS_CONNECTED (Socket
)) {
455 ListenToken
->NewChildHandle
= Socket
->SockHandle
;
456 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
458 RemoveEntryList (ListEntry
);
460 ASSERT (Socket
->Parent
);
462 Socket
->Parent
->ConnCnt
--;
466 "SockAccept: Accept a socket, now conncount is %d",
467 Socket
->Parent
->ConnCnt
)
469 Socket
->Parent
= NULL
;
476 // Buffer this token for latter incoming connection request
478 if (NULL
== SockBufferToken (Sock
, &(Sock
->ListenTokenList
), Token
, 0)) {
480 Status
= EFI_OUT_OF_RESOURCES
;
484 EfiReleaseLock (&(Sock
->Lock
));
491 Issue a token with data to the socket to send out.
493 @param Sock Pointer to the socket to process the token with
495 @param Token The token with data that needs to send out.
497 @retval EFI_SUCCESS The token is processed successfully.
498 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
499 socket is closed, or the socket is not in a
500 synchronized state , or the token is already in one
501 of this socket's lists.
502 @retval EFI_NO_MAPPING The IP address configuration operation is not
504 @retval EFI_NOT_STARTED The socket is not configured.
505 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
514 SOCK_IO_TOKEN
*SndToken
;
517 EFI_TCP4_TRANSMIT_DATA
*TxData
;
519 SOCK_TOKEN
*SockToken
;
522 ASSERT (SOCK_STREAM
== Sock
->Type
);
524 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
525 if (EFI_ERROR (Status
)) {
527 DEBUG ((EFI_D_ERROR
, "SockSend: Get the access for socket"
528 " failed with %r", Status
));
530 return EFI_ACCESS_DENIED
;
533 if (SOCK_IS_NO_MAPPING (Sock
)) {
534 Status
= EFI_NO_MAPPING
;
538 SndToken
= (SOCK_IO_TOKEN
*) Token
;
539 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) SndToken
->Packet
.TxData
;
541 if (SOCK_IS_UNCONFIGURED (Sock
)) {
542 Status
= EFI_NOT_STARTED
;
546 if (!(SOCK_IS_CONNECTING (Sock
) || SOCK_IS_CONNECTED (Sock
))) {
548 Status
= EFI_ACCESS_DENIED
;
553 // check if a token is already in the token buffer
555 Event
= SndToken
->Token
.Event
;
557 if (SockTokenExisted (Sock
, Event
)) {
558 Status
= EFI_ACCESS_DENIED
;
562 DataLen
= (UINT32
) TxData
->DataLength
;
565 // process this sending token now or buffer it only?
567 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
569 if ((FreeSpace
< Sock
->SndBuffer
.LowWater
) || !SOCK_IS_CONNECTED (Sock
)) {
571 SockToken
= SockBufferToken (
578 if (NULL
== SockToken
) {
579 Status
= EFI_OUT_OF_RESOURCES
;
583 SockToken
= SockBufferToken (
585 &Sock
->ProcessingSndTokenList
,
590 if (NULL
== SockToken
) {
591 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to buffer IO token into"
592 " socket processing SndToken List\n", Status
));
594 Status
= EFI_OUT_OF_RESOURCES
;
598 Status
= SockProcessTcpSndData (Sock
, TxData
);
600 if (EFI_ERROR (Status
)) {
601 DEBUG ((EFI_D_ERROR
, "SockSend: Failed to process "
602 "Snd Data\n", Status
));
604 RemoveEntryList (&(SockToken
->TokenList
));
605 gBS
->FreePool (SockToken
);
610 EfiReleaseLock (&(Sock
->Lock
));
616 Issue a token to get data from the socket.
618 @param Sock Pointer to the socket to get data from.
619 @param Token The token to store the received data from the
622 @retval EFI_SUCCESS The token is processed successfully.
623 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
624 socket is closed, or the socket is not in a
625 synchronized state , or the token is already in one
626 of this socket's lists.
627 @retval EFI_NO_MAPPING The IP address configuration operation is not
629 @retval EFI_NOT_STARTED The socket is not configured.
630 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
631 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
640 SOCK_IO_TOKEN
*RcvToken
;
645 ASSERT (SOCK_STREAM
== Sock
->Type
);
647 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
648 if (EFI_ERROR (Status
)) {
650 DEBUG ((EFI_D_ERROR
, "SockRcv: Get the access for socket"
651 " failed with %r", Status
));
653 return EFI_ACCESS_DENIED
;
656 if (SOCK_IS_NO_MAPPING (Sock
)) {
658 Status
= EFI_NO_MAPPING
;
662 if (SOCK_IS_UNCONFIGURED (Sock
)) {
664 Status
= EFI_NOT_STARTED
;
668 if (!(SOCK_IS_CONNECTED (Sock
) || SOCK_IS_CONNECTING (Sock
))) {
670 Status
= EFI_ACCESS_DENIED
;
674 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
677 // check if a token is already in the token buffer of this socket
679 Event
= RcvToken
->Token
.Event
;
680 if (SockTokenExisted (Sock
, Event
)) {
681 Status
= EFI_ACCESS_DENIED
;
685 RcvToken
= (SOCK_IO_TOKEN
*) Token
;
686 RcvdBytes
= GET_RCV_DATASIZE (Sock
);
689 // check whether an error has happened before
691 if (EFI_ABORTED
!= Sock
->SockError
) {
693 SIGNAL_TOKEN (&(RcvToken
->Token
), Sock
->SockError
);
694 Sock
->SockError
= EFI_ABORTED
;
699 // check whether can not receive and there is no any
700 // data buffered in Sock->RcvBuffer
702 if (SOCK_IS_NO_MORE_DATA (Sock
) && (0 == RcvdBytes
)) {
704 Status
= EFI_CONNECTION_FIN
;
708 if (RcvdBytes
!= 0) {
709 Status
= SockProcessRcvToken (Sock
, RcvToken
);
711 if (EFI_ERROR (Status
)) {
715 Status
= Sock
->ProtoHandler (Sock
, SOCK_CONSUMED
, NULL
);
718 if (NULL
== SockBufferToken (Sock
, &Sock
->RcvTokenList
, RcvToken
, 0)) {
719 Status
= EFI_OUT_OF_RESOURCES
;
724 EfiReleaseLock (&(Sock
->Lock
));
730 Reset the socket and its associated protocol control block.
732 @param Sock Pointer to the socket to be flushed.
734 @retval EFI_SUCCESS The socket is flushed successfully.
735 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
745 ASSERT (SOCK_STREAM
== Sock
->Type
);
747 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
748 if (EFI_ERROR (Status
)) {
750 DEBUG ((EFI_D_ERROR
, "SockFlush: Get the access for socket"
751 " failed with %r", Status
));
753 return EFI_ACCESS_DENIED
;
756 if (!SOCK_IS_CONFIGURED (Sock
)) {
760 Status
= Sock
->ProtoHandler (Sock
, SOCK_FLUSH
, NULL
);
761 if (EFI_ERROR (Status
)) {
763 DEBUG ((EFI_D_ERROR
, "SockFlush: Protocol failed handling"
764 " SOCK_FLUSH with %r", Status
));
769 SOCK_ERROR (Sock
, EFI_ABORTED
);
770 SockConnFlush (Sock
);
771 SockSetState (Sock
, SO_CLOSED
);
773 Sock
->ConfigureState
= SO_UNCONFIGURED
;
776 EfiReleaseLock (&(Sock
->Lock
));
782 Close or abort the socket associated connection.
784 @param Sock Pointer to the socket of the connection to close or
786 @param Token The token for close operation.
787 @param OnAbort TRUE for aborting the connection, FALSE to close it.
789 @retval EFI_SUCCESS The close or abort operation is initialized
791 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
792 socket is closed, or the socket is not in a
793 synchronized state , or the token is already in one
794 of this socket's lists.
795 @retval EFI_NO_MAPPING The IP address configuration operation is not
797 @retval EFI_NOT_STARTED The socket is not configured.
810 ASSERT (SOCK_STREAM
== Sock
->Type
);
812 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
813 if (EFI_ERROR (Status
)) {
814 DEBUG ((EFI_D_ERROR
, "SockClose: Get the access for socket"
815 " failed with %r", Status
));
817 return EFI_ACCESS_DENIED
;
820 if (SOCK_IS_NO_MAPPING (Sock
)) {
821 Status
= EFI_NO_MAPPING
;
825 if (SOCK_IS_UNCONFIGURED (Sock
)) {
826 Status
= EFI_NOT_STARTED
;
830 if (SOCK_IS_DISCONNECTING (Sock
)) {
831 Status
= EFI_ACCESS_DENIED
;
835 Event
= ((SOCK_COMPLETION_TOKEN
*) Token
)->Event
;
837 if (SockTokenExisted (Sock
, Event
)) {
838 Status
= EFI_ACCESS_DENIED
;
842 Sock
->CloseToken
= Token
;
843 SockSetState (Sock
, SO_DISCONNECTING
);
846 Status
= Sock
->ProtoHandler (Sock
, SOCK_ABORT
, NULL
);
848 Status
= Sock
->ProtoHandler (Sock
, SOCK_CLOSE
, NULL
);
852 EfiReleaseLock (&(Sock
->Lock
));
858 Get the mode data of the low layer protocol.
860 @param Sock Pointer to the socket to get mode data from.
861 @param Mode Pointer to the data to store the low layer mode
864 @retval EFI_SUCCESS The mode data is got successfully.
865 @retval EFI_NOT_STARTED The socket is not configured.
874 return Sock
->ProtoHandler (Sock
, SOCK_MODE
, Mode
);
879 Configure the low level protocol to join a multicast group for
880 this socket's connection.
882 @param Sock Pointer to the socket of the connection to join the
883 specific multicast group.
884 @param GroupInfo Pointer to the multicast group info.
886 @retval EFI_SUCCESS The configuration is done successfully.
887 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
888 @retval EFI_NOT_STARTED The socket is not configured.
899 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
901 if (EFI_ERROR (Status
)) {
903 DEBUG ((EFI_D_ERROR
, "SockGroup: Get the access for socket"
904 " failed with %r", Status
));
906 return EFI_ACCESS_DENIED
;
909 if (SOCK_IS_UNCONFIGURED (Sock
)) {
910 Status
= EFI_NOT_STARTED
;
914 Status
= Sock
->ProtoHandler (Sock
, SOCK_GROUP
, GroupInfo
);
917 EfiReleaseLock (&(Sock
->Lock
));
923 Add or remove route information in IP route table associated
926 @param Sock Pointer to the socket associated with the IP route
928 @param RouteInfo Pointer to the route information to be processed.
930 @retval EFI_SUCCESS The route table is updated successfully.
931 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
932 @retval EFI_NO_MAPPING The IP address configuration operation is not
934 @retval EFI_NOT_STARTED The socket is not configured.
945 Status
= EfiAcquireLockOrFail (&(Sock
->Lock
));
946 if (EFI_ERROR (Status
)) {
947 DEBUG ((EFI_D_ERROR
, "SockRoute: Get the access for socket"
948 " failed with %r", Status
));
950 return EFI_ACCESS_DENIED
;
953 if (SOCK_IS_NO_MAPPING (Sock
)) {
954 Status
= EFI_NO_MAPPING
;
958 if (SOCK_IS_UNCONFIGURED (Sock
)) {
959 Status
= EFI_NOT_STARTED
;
963 Status
= Sock
->ProtoHandler (Sock
, SOCK_ROUTE
, RouteInfo
);
966 EfiReleaseLock (&(Sock
->Lock
));