2 Implementation of the Socket.
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Get the first buffer block in the specific socket buffer.
21 @param[in] Sockbuf Pointer to the socket buffer.
23 @return Pointer to the first buffer in the queue. NULL if the queue is empty.
28 IN SOCK_BUFFER
*Sockbuf
31 LIST_ENTRY
*NetbufList
;
33 NetbufList
= &(Sockbuf
->DataQueue
->BufList
);
35 if (IsListEmpty (NetbufList
)) {
39 return NET_LIST_HEAD (NetbufList
, NET_BUF
, List
);
43 Get the next buffer block in the specific socket buffer.
45 @param[in] Sockbuf Pointer to the socket buffer.
46 @param[in] SockEntry Pointer to the buffer block prior to the required one.
48 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is
49 the tail or head entry.
54 IN SOCK_BUFFER
*Sockbuf
,
58 LIST_ENTRY
*NetbufList
;
60 NetbufList
= &(Sockbuf
->DataQueue
->BufList
);
62 if ((SockEntry
->List
.ForwardLink
== NetbufList
) ||
63 (SockEntry
->List
.BackLink
== &SockEntry
->List
) ||
64 (SockEntry
->List
.ForwardLink
== &SockEntry
->List
)
70 return NET_LIST_USER_STRUCT (SockEntry
->List
.ForwardLink
, NET_BUF
, List
);
74 User provided callback function for NetbufFromExt.
76 @param[in] Event The Event this notify function registered to, ignored.
89 Get the length of the data that can be retrieved from the socket
92 @param[in] SockBuffer Pointer to the socket receive buffer.
93 @param[out] IsUrg Pointer to a BOOLEAN variable.
94 If TRUE the data is OOB.
95 @param[in] BufLen The maximum length of the data buffer to
96 store the received data in the socket layer.
98 @return The length of the data can be retreived.
103 IN SOCK_BUFFER
*SockBuffer
,
108 NET_BUF
*RcvBufEntry
;
110 TCP_RSV_DATA
*TcpRsvData
;
113 ASSERT ((SockBuffer
!= NULL
) && (IsUrg
!= NULL
) && (BufLen
> 0));
116 // Get the first socket receive buffer
118 RcvBufEntry
= SockBufFirst (SockBuffer
);
119 ASSERT (RcvBufEntry
!= NULL
);
121 TcpRsvData
= (TCP_RSV_DATA
*) RcvBufEntry
->ProtoData
;
124 // Check whether the receive data is out of bound. If yes, calculate the maximum
125 // allowed length of the urgent data and output it.
127 *IsUrg
= (BOOLEAN
) ((TcpRsvData
->UrgLen
> 0) ? TRUE
: FALSE
);
129 if (*IsUrg
&& (TcpRsvData
->UrgLen
< RcvBufEntry
->TotalSize
)) {
131 DataLen
= MIN (TcpRsvData
->UrgLen
, BufLen
);
133 if (DataLen
< TcpRsvData
->UrgLen
) {
134 TcpRsvData
->UrgLen
= TcpRsvData
->UrgLen
- DataLen
;
136 TcpRsvData
->UrgLen
= 0;
144 // Process the next socket receive buffer to get the maximum allowed length
145 // of the received data.
147 DataLen
= RcvBufEntry
->TotalSize
;
149 RcvBufEntry
= SockBufNext (SockBuffer
, RcvBufEntry
);
151 while ((BufLen
> DataLen
) && (RcvBufEntry
!= NULL
)) {
153 TcpRsvData
= (TCP_RSV_DATA
*) RcvBufEntry
->ProtoData
;
155 Urg
= (BOOLEAN
) ((TcpRsvData
->UrgLen
> 0) ? TRUE
: FALSE
);
161 if (*IsUrg
&& TcpRsvData
->UrgLen
< RcvBufEntry
->TotalSize
) {
163 if (TcpRsvData
->UrgLen
+ DataLen
< BufLen
) {
164 TcpRsvData
->UrgLen
= 0;
166 TcpRsvData
->UrgLen
= TcpRsvData
->UrgLen
- (BufLen
- DataLen
);
169 return MIN (TcpRsvData
->UrgLen
+ DataLen
, BufLen
);
173 DataLen
+= RcvBufEntry
->TotalSize
;
175 RcvBufEntry
= SockBufNext (SockBuffer
, RcvBufEntry
);
178 DataLen
= MIN (BufLen
, DataLen
);
183 Copy data from socket buffer to an application provided receive buffer.
185 @param[in] Sock Pointer to the socket.
186 @param[in] TcpRxData Pointer to the application provided receive buffer.
187 @param[in] RcvdBytes The maximum length of the data can be copied.
188 @param[in] IsUrg If TRUE the data is Out of Bound, FALSE the data is normal.
202 EFI_TCP4_RECEIVE_DATA
*RxData
;
203 EFI_TCP4_FRAGMENT_DATA
*Fragment
;
205 RxData
= (EFI_TCP4_RECEIVE_DATA
*) TcpRxData
;
209 ASSERT (RxData
->DataLength
>= RcvdBytes
);
211 RxData
->DataLength
= RcvdBytes
;
212 RxData
->UrgentFlag
= IsUrg
;
215 // Copy the CopyBytes data from socket receive buffer to RxData.
217 for (Index
= 0; (Index
< RxData
->FragmentCount
) && (RcvdBytes
> 0); Index
++) {
219 Fragment
= &RxData
->FragmentTable
[Index
];
220 CopyBytes
= MIN ((UINT32
) (Fragment
->FragmentLength
), RcvdBytes
);
223 Sock
->RcvBuffer
.DataQueue
,
226 Fragment
->FragmentBuffer
229 Fragment
->FragmentLength
= CopyBytes
;
230 RcvdBytes
-= CopyBytes
;
236 Process the send token.
238 @param[in, out] Sock Pointer to the socket.
242 SockProcessSndToken (
247 SOCK_TOKEN
*SockToken
;
249 SOCK_IO_TOKEN
*SndToken
;
250 EFI_TCP4_TRANSMIT_DATA
*TxData
;
253 ASSERT ((Sock
!= NULL
) && (SockStream
== Sock
->Type
));
255 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
258 // to determine if process a send token using
259 // socket layer flow control policy
261 while ((FreeSpace
>= Sock
->SndBuffer
.LowWater
) && !IsListEmpty (&Sock
->SndTokenList
)) {
263 SockToken
= NET_LIST_HEAD (
264 &(Sock
->SndTokenList
),
270 // process this token
272 RemoveEntryList (&(SockToken
->TokenList
));
274 &(Sock
->ProcessingSndTokenList
),
275 &(SockToken
->TokenList
)
279 // Proceess it in the light of SockType
281 SndToken
= (SOCK_IO_TOKEN
*) SockToken
->Token
;
282 TxData
= SndToken
->Packet
.TxData
;
284 DataLen
= TxData
->DataLength
;
285 Status
= SockProcessTcpSndData (Sock
, TxData
);
287 if (EFI_ERROR (Status
)) {
291 if (DataLen
>= FreeSpace
) {
295 FreeSpace
-= DataLen
;
304 RemoveEntryList (&SockToken
->TokenList
);
305 SIGNAL_TOKEN (SockToken
->Token
, Status
);
306 FreePool (SockToken
);
310 Get received data from the socket layer to the receive token.
312 @param[in, out] Sock Pointer to the socket.
313 @param[in, out] RcvToken Pointer to the application provided receive token.
315 @return The length of data received in this token.
319 SockProcessRcvToken (
321 IN OUT SOCK_IO_TOKEN
*RcvToken
324 UINT32 TokenRcvdBytes
;
325 EFI_TCP4_RECEIVE_DATA
*RxData
;
328 ASSERT (Sock
!= NULL
);
330 ASSERT (SockStream
== Sock
->Type
);
332 RxData
= RcvToken
->Packet
.RxData
;
334 TokenRcvdBytes
= SockTcpDataToRcv (
341 // Copy data from RcvBuffer of socket to user
342 // provided RxData and set the fields in TCP RxData
344 SockSetTcpRxData (Sock
, RxData
, TokenRcvdBytes
, IsUrg
);
346 NetbufQueTrim (Sock
->RcvBuffer
.DataQueue
, TokenRcvdBytes
);
347 SIGNAL_TOKEN (&(RcvToken
->Token
), EFI_SUCCESS
);
349 return TokenRcvdBytes
;
353 Process the TCP send data, buffer the tcp txdata, and append
354 the buffer to socket send buffer, then try to send it.
356 @param[in] Sock Pointer to the socket.
357 @param[in] TcpTxData Pointer to the application provided send buffer.
359 @retval EFI_SUCCESS The operation completed successfully.
360 @retval EFI_OUT_OF_RESOURCES Failed due to resource limits.
364 SockProcessTcpSndData (
371 EFI_TCP4_TRANSMIT_DATA
*TxData
;
373 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) TcpTxData
;
376 // transform this TxData into a NET_BUFFER
377 // and insert it into Sock->SndBuffer
379 SndData
= NetbufFromExt (
380 (NET_FRAGMENT
*) TxData
->FragmentTable
,
381 TxData
->FragmentCount
,
388 if (NULL
== SndData
) {
391 "SockKProcessSndData: Failed to call NetBufferFromExt\n")
394 return EFI_OUT_OF_RESOURCES
;
397 NetbufQueAppend (Sock
->SndBuffer
.DataQueue
, SndData
);
400 // notify the low layer protocol to handle this send token
402 if (TxData
->Urgent
) {
403 Status
= Sock
->ProtoHandler (Sock
, SOCK_SNDURG
, NULL
);
405 if (EFI_ERROR (Status
)) {
411 Status
= Sock
->ProtoHandler (Sock
, SOCK_SNDPUSH
, NULL
);
413 if (EFI_ERROR (Status
)) {
419 // low layer protocol should really handle the sending
420 // process when catching SOCK_SND request
422 Status
= Sock
->ProtoHandler (Sock
, SOCK_SND
, NULL
);
424 if (EFI_ERROR (Status
)) {
432 Flush the tokens in the specific token list.
434 @param[in] Sock Pointer to the socket.
435 @param[in, out] PendingTokenList Pointer to the token list to be flushed.
439 SockFlushPendingToken (
441 IN OUT LIST_ENTRY
*PendingTokenList
444 SOCK_TOKEN
*SockToken
;
445 SOCK_COMPLETION_TOKEN
*Token
;
447 ASSERT ((Sock
!= NULL
) && (PendingTokenList
!= NULL
));
449 while (!IsListEmpty (PendingTokenList
)) {
450 SockToken
= NET_LIST_HEAD (
456 Token
= SockToken
->Token
;
457 SIGNAL_TOKEN (Token
, Sock
->SockError
);
459 RemoveEntryList (&(SockToken
->TokenList
));
460 FreePool (SockToken
);
465 Wake up the connection token while the connection is successfully established,
466 then try to process any pending send token.
468 @param[in, out] Sock Pointer to the socket.
476 ASSERT (Sock
->ConnectionToken
!= NULL
);
478 SIGNAL_TOKEN (Sock
->ConnectionToken
, EFI_SUCCESS
);
479 Sock
->ConnectionToken
= NULL
;
482 // check to see if some pending send token existed?
484 SockProcessSndToken (Sock
);
488 Wake up the listen token while the connection is established successfully.
490 @param[in, out] Sock Pointer to the socket.
494 SockWakeListenToken (
499 SOCK_TOKEN
*SockToken
;
500 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
502 Parent
= Sock
->Parent
;
504 ASSERT ((Parent
!= NULL
) && SOCK_IS_LISTENING (Parent
) && SOCK_IS_CONNECTED (Sock
));
506 if (!IsListEmpty (&Parent
->ListenTokenList
)) {
507 SockToken
= NET_LIST_HEAD (
508 &Parent
->ListenTokenList
,
513 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) SockToken
->Token
;
514 ListenToken
->NewChildHandle
= Sock
->SockHandle
;
516 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
518 RemoveEntryList (&SockToken
->TokenList
);
519 FreePool (SockToken
);
521 RemoveEntryList (&Sock
->ConnectionList
);
526 "SockWakeListenToken: accept a socket, now conncnt is %d",
535 Wake up the receive token while some data is received.
537 @param[in, out] Sock Pointer to the socket.
546 UINT32 TokenRcvdBytes
;
547 SOCK_TOKEN
*SockToken
;
548 SOCK_IO_TOKEN
*RcvToken
;
550 ASSERT (Sock
->RcvBuffer
.DataQueue
!= NULL
);
552 RcvdBytes
= (Sock
->RcvBuffer
.DataQueue
)->BufSize
;
554 ASSERT (RcvdBytes
> 0);
556 while (RcvdBytes
> 0 && !IsListEmpty (&Sock
->RcvTokenList
)) {
558 SockToken
= NET_LIST_HEAD (
564 RcvToken
= (SOCK_IO_TOKEN
*) SockToken
->Token
;
565 TokenRcvdBytes
= SockProcessRcvToken (Sock
, RcvToken
);
567 if (0 == TokenRcvdBytes
) {
571 RemoveEntryList (&(SockToken
->TokenList
));
572 FreePool (SockToken
);
573 RcvdBytes
-= TokenRcvdBytes
;
578 Cancel the tokens in the specific token list.
580 @param[in] Token Pointer to the Token. If NULL, all tokens
581 in SpecifiedTokenList will be canceled.
582 @param[in, out] SpecifiedTokenList Pointer to the token list to be checked.
584 @retval EFI_SUCCESS Cancel the tokens in the specific token listsuccessfully.
585 @retval EFI_NOT_FOUND The Token is not found in SpecifiedTokenList.
590 IN SOCK_COMPLETION_TOKEN
*Token
,
591 IN OUT LIST_ENTRY
*SpecifiedTokenList
596 SOCK_TOKEN
*SockToken
;
598 Status
= EFI_SUCCESS
;
602 if (IsListEmpty (SpecifiedTokenList
) && Token
!= NULL
) {
603 return EFI_NOT_FOUND
;
607 // Iterate through the SpecifiedTokenList.
609 Entry
= SpecifiedTokenList
->ForwardLink
;
610 while (Entry
!= SpecifiedTokenList
) {
611 SockToken
= NET_LIST_USER_STRUCT (Entry
, SOCK_TOKEN
, TokenList
);
614 SIGNAL_TOKEN (SockToken
->Token
, EFI_ABORTED
);
615 RemoveEntryList (&SockToken
->TokenList
);
616 FreePool (SockToken
);
618 Entry
= SpecifiedTokenList
->ForwardLink
;
619 Status
= EFI_SUCCESS
;
621 if (Token
== (VOID
*) SockToken
->Token
) {
622 SIGNAL_TOKEN (Token
, EFI_ABORTED
);
623 RemoveEntryList (&(SockToken
->TokenList
));
624 FreePool (SockToken
);
629 Status
= EFI_NOT_FOUND
;
631 Entry
= Entry
->ForwardLink
;
635 ASSERT (IsListEmpty (SpecifiedTokenList
) || Token
!= NULL
);
641 Create a socket with initial data SockInitData.
643 @param[in] SockInitData Pointer to the initial data of the socket.
645 @return Pointer to the newly created socket, return NULL when an exception occurs.
650 IN SOCK_INIT_DATA
*SockInitData
656 EFI_GUID
*TcpProtocolGuid
;
657 UINTN ProtocolLength
;
659 ASSERT ((SockInitData
!= NULL
) && (SockInitData
->ProtoHandler
!= NULL
));
660 ASSERT (SockInitData
->Type
== SockStream
);
661 ASSERT ((SockInitData
->ProtoData
!= NULL
) && (SockInitData
->DataSize
<= PROTO_RESERVED_LEN
));
663 if (SockInitData
->IpVersion
== IP_VERSION_4
) {
664 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
665 ProtocolLength
= sizeof (EFI_TCP4_PROTOCOL
);
667 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
668 ProtocolLength
= sizeof (EFI_TCP6_PROTOCOL
);
672 Parent
= SockInitData
->Parent
;
674 if ((Parent
!= NULL
) && (Parent
->ConnCnt
== Parent
->BackLog
)) {
677 "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n",
685 Sock
= AllocateZeroPool (sizeof (SOCKET
));
688 DEBUG ((EFI_D_ERROR
, "SockCreate: No resource to create a new socket\n"));
692 InitializeListHead (&Sock
->Link
);
693 InitializeListHead (&Sock
->ConnectionList
);
694 InitializeListHead (&Sock
->ListenTokenList
);
695 InitializeListHead (&Sock
->RcvTokenList
);
696 InitializeListHead (&Sock
->SndTokenList
);
697 InitializeListHead (&Sock
->ProcessingSndTokenList
);
699 EfiInitializeLock (&(Sock
->Lock
), TPL_CALLBACK
);
701 Sock
->SndBuffer
.DataQueue
= NetbufQueAlloc ();
702 if (NULL
== Sock
->SndBuffer
.DataQueue
) {
705 "SockCreate: No resource to allocate SndBuffer for new socket\n")
711 Sock
->RcvBuffer
.DataQueue
= NetbufQueAlloc ();
712 if (NULL
== Sock
->RcvBuffer
.DataQueue
) {
715 "SockCreate: No resource to allocate RcvBuffer for new socket\n")
721 Sock
->Signature
= SOCK_SIGNATURE
;
723 Sock
->Parent
= Parent
;
724 Sock
->BackLog
= SockInitData
->BackLog
;
725 Sock
->ProtoHandler
= SockInitData
->ProtoHandler
;
726 Sock
->SndBuffer
.HighWater
= SockInitData
->SndBufferSize
;
727 Sock
->RcvBuffer
.HighWater
= SockInitData
->RcvBufferSize
;
728 Sock
->Type
= SockInitData
->Type
;
729 Sock
->DriverBinding
= SockInitData
->DriverBinding
;
730 Sock
->State
= SockInitData
->State
;
731 Sock
->CreateCallback
= SockInitData
->CreateCallback
;
732 Sock
->DestroyCallback
= SockInitData
->DestroyCallback
;
733 Sock
->Context
= SockInitData
->Context
;
735 Sock
->SockError
= EFI_ABORTED
;
736 Sock
->SndBuffer
.LowWater
= SOCK_BUFF_LOW_WATER
;
737 Sock
->RcvBuffer
.LowWater
= SOCK_BUFF_LOW_WATER
;
739 Sock
->IpVersion
= SockInitData
->IpVersion
;
742 // Install protocol on Sock->SockHandle
744 CopyMem (&Sock
->NetProtocol
, SockInitData
->Protocol
, ProtocolLength
);
747 // copy the protodata into socket
749 CopyMem (Sock
->ProtoReserved
, SockInitData
->ProtoData
, SockInitData
->DataSize
);
751 Status
= gBS
->InstallMultipleProtocolInterfaces (
758 if (EFI_ERROR (Status
)) {
761 "SockCreate: Install TCP protocol in socket failed with %r\n",
768 if (Parent
!= NULL
) {
769 ASSERT (Parent
->BackLog
> 0);
770 ASSERT (SOCK_IS_LISTENING (Parent
));
773 // need to add it into Parent->ConnectionList
774 // if the Parent->ConnCnt < Parent->BackLog
780 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
784 InsertTailList (&Parent
->ConnectionList
, &Sock
->ConnectionList
);
787 if (Sock
->CreateCallback
!= NULL
) {
788 Status
= Sock
->CreateCallback (Sock
, Sock
->Context
);
789 if (EFI_ERROR (Status
)) {
798 if (Sock
->SockHandle
!= NULL
) {
799 gBS
->UninstallMultipleProtocolInterfaces (
807 if (NULL
!= Sock
->SndBuffer
.DataQueue
) {
808 NetbufQueFree (Sock
->SndBuffer
.DataQueue
);
811 if (NULL
!= Sock
->RcvBuffer
.DataQueue
) {
812 NetbufQueFree (Sock
->RcvBuffer
.DataQueue
);
823 @param[in, out] Sock Pointer to the socket.
832 EFI_GUID
*TcpProtocolGuid
;
835 ASSERT (SockStream
== Sock
->Type
);
837 if (Sock
->DestroyCallback
!= NULL
) {
838 Sock
->DestroyCallback (Sock
, Sock
->Context
);
842 // Flush the completion token buffered
843 // by sock and rcv, snd buffer
845 if (!SOCK_IS_UNCONFIGURED (Sock
)) {
847 SockConnFlush (Sock
);
848 SockSetState (Sock
, SO_CLOSED
);
849 Sock
->ConfigureState
= SO_UNCONFIGURED
;
853 // Destroy the RcvBuffer Queue and SendBuffer Queue
855 NetbufQueFree (Sock
->RcvBuffer
.DataQueue
);
856 NetbufQueFree (Sock
->SndBuffer
.DataQueue
);
859 // Remove it from parent connection list if needed
861 if (Sock
->Parent
!= NULL
) {
863 RemoveEntryList (&(Sock
->ConnectionList
));
864 (Sock
->Parent
->ConnCnt
)--;
868 "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n",
869 Sock
->Parent
->ConnCnt
)
876 // Set the protocol guid and driver binding handle
877 // in the light of Sock->SockType
879 if (Sock
->IpVersion
== IP_VERSION_4
) {
880 TcpProtocolGuid
= &gEfiTcp4ProtocolGuid
;
882 TcpProtocolGuid
= &gEfiTcp6ProtocolGuid
;
886 // Retrieve the protocol installed on this sock
888 Status
= gBS
->OpenProtocol (
894 EFI_OPEN_PROTOCOL_GET_PROTOCOL
897 if (EFI_ERROR (Status
)) {
901 "SockDestroy: Open protocol installed on socket failed with %r\n",
909 // Uninstall the protocol installed on this sock
910 // in the light of Sock->SockType
912 gBS
->UninstallMultipleProtocolInterfaces (
925 Flush the sndBuffer and rcvBuffer of socket.
927 @param[in, out] Sock Pointer to the socket.
937 ASSERT (Sock
!= NULL
);
940 // Clear the flag in this socket
945 // Flush the SndBuffer and RcvBuffer of Sock
947 NetbufQueFlush (Sock
->SndBuffer
.DataQueue
);
948 NetbufQueFlush (Sock
->RcvBuffer
.DataQueue
);
951 // Signal the pending token
953 if (Sock
->ConnectionToken
!= NULL
) {
954 SIGNAL_TOKEN (Sock
->ConnectionToken
, Sock
->SockError
);
955 Sock
->ConnectionToken
= NULL
;
958 if (Sock
->CloseToken
!= NULL
) {
959 SIGNAL_TOKEN (Sock
->CloseToken
, Sock
->SockError
);
960 Sock
->CloseToken
= NULL
;
963 SockFlushPendingToken (Sock
, &(Sock
->ListenTokenList
));
964 SockFlushPendingToken (Sock
, &(Sock
->RcvTokenList
));
965 SockFlushPendingToken (Sock
, &(Sock
->SndTokenList
));
966 SockFlushPendingToken (Sock
, &(Sock
->ProcessingSndTokenList
));
969 // Destroy the pending connection, if it is a listening socket
971 if (SOCK_IS_LISTENING (Sock
)) {
972 while (!IsListEmpty (&Sock
->ConnectionList
)) {
973 Child
= NET_LIST_HEAD (
974 &Sock
->ConnectionList
,
979 SockDestroyChild (Child
);
988 Set the state of the socket.
990 @param[in, out] Sock Pointer to the socket.
991 @param[in] State The new socket state to be set.
1000 Sock
->State
= State
;
1004 Clone a new socket, including its associated protocol control block.
1006 @param[in] Sock Pointer to the socket to be cloned.
1008 @return Pointer to the newly cloned socket. If NULL, an error condition occurred.
1017 SOCK_INIT_DATA InitData
;
1019 InitData
.BackLog
= Sock
->BackLog
;
1020 InitData
.Parent
= Sock
;
1021 InitData
.State
= Sock
->State
;
1022 InitData
.ProtoHandler
= Sock
->ProtoHandler
;
1023 InitData
.Type
= Sock
->Type
;
1024 InitData
.RcvBufferSize
= Sock
->RcvBuffer
.HighWater
;
1025 InitData
.SndBufferSize
= Sock
->SndBuffer
.HighWater
;
1026 InitData
.DriverBinding
= Sock
->DriverBinding
;
1027 InitData
.IpVersion
= Sock
->IpVersion
;
1028 InitData
.Protocol
= &(Sock
->NetProtocol
);
1029 InitData
.CreateCallback
= Sock
->CreateCallback
;
1030 InitData
.DestroyCallback
= Sock
->DestroyCallback
;
1031 InitData
.Context
= Sock
->Context
;
1032 InitData
.ProtoData
= Sock
->ProtoReserved
;
1033 InitData
.DataSize
= sizeof (Sock
->ProtoReserved
);
1035 ClonedSock
= SockCreate (&InitData
);
1037 if (NULL
== ClonedSock
) {
1038 DEBUG ((EFI_D_ERROR
, "SockClone: no resource to create a cloned sock\n"));
1042 SockSetState (ClonedSock
, SO_CONNECTING
);
1043 ClonedSock
->ConfigureState
= Sock
->ConfigureState
;
1049 Called by the low layer protocol to indicate the socket a connection is
1052 This function just changes the socket's state to SO_CONNECTED
1053 and signals the token used for connection establishment.
1055 @param[in, out] Sock Pointer to the socket associated with the
1056 established connection.
1060 SockConnEstablished (
1065 ASSERT (SO_CONNECTING
== Sock
->State
);
1067 SockSetState (Sock
, SO_CONNECTED
);
1069 if (NULL
== Sock
->Parent
) {
1070 SockWakeConnToken (Sock
);
1072 SockWakeListenToken (Sock
);
1078 Called by the low layer protocol to indicate the connection is closed.
1080 This function flushes the socket, sets the state to SO_CLOSED, and signals
1083 @param[in, out] Sock Pointer to the socket associated with the closed
1092 if (Sock
->CloseToken
!= NULL
) {
1093 SIGNAL_TOKEN (Sock
->CloseToken
, EFI_SUCCESS
);
1094 Sock
->CloseToken
= NULL
;
1097 SockConnFlush (Sock
);
1098 SockSetState (Sock
, SO_CLOSED
);
1100 if (Sock
->Parent
!= NULL
) {
1101 SockDestroyChild (Sock
);
1107 Called by low layer protocol to indicate that some data was sent or processed.
1109 This function trims the sent data in the socket send buffer, and signals the data
1112 @param[in, out] Sock Pointer to the socket.
1113 @param[in] Count The length of the data processed or sent, in bytes.
1118 IN OUT SOCKET
*Sock
,
1122 SOCK_TOKEN
*SockToken
;
1123 SOCK_COMPLETION_TOKEN
*SndToken
;
1125 ASSERT (!IsListEmpty (&Sock
->ProcessingSndTokenList
));
1126 ASSERT (Count
<= (Sock
->SndBuffer
.DataQueue
)->BufSize
);
1128 NetbufQueTrim (Sock
->SndBuffer
.DataQueue
, Count
);
1131 // To check if we can signal some snd token in this socket
1134 SockToken
= NET_LIST_HEAD (
1135 &(Sock
->ProcessingSndTokenList
),
1140 SndToken
= SockToken
->Token
;
1142 if (SockToken
->RemainDataLen
<= Count
) {
1144 RemoveEntryList (&(SockToken
->TokenList
));
1145 SIGNAL_TOKEN (SndToken
, EFI_SUCCESS
);
1146 Count
-= SockToken
->RemainDataLen
;
1147 FreePool (SockToken
);
1150 SockToken
->RemainDataLen
-= Count
;
1156 // to judge if we can process some send token in
1157 // Sock->SndTokenList, if so process those send token
1159 SockProcessSndToken (Sock
);
1163 Called by the low layer protocol to copy some data in the socket send
1164 buffer starting from the specific offset to a buffer provided by
1167 @param[in] Sock Pointer to the socket.
1168 @param[in] Offset The start point of the data to be copied.
1169 @param[in] Len The length of the data to be copied.
1170 @param[out] Dest Pointer to the destination to copy the data.
1172 @return The data size copied.
1183 ASSERT ((Sock
!= NULL
) && SockStream
== Sock
->Type
);
1185 return NetbufQueCopy (
1186 Sock
->SndBuffer
.DataQueue
,
1194 Called by the low layer protocol to deliver received data to socket layer.
1196 This function will append the data to the socket receive buffer, set the
1197 urgent data length, and then check if any receive token can be signaled.
1199 @param[in, out] Sock Pointer to the socket.
1200 @param[in, out] NetBuffer Pointer to the buffer that contains the received data.
1201 @param[in] UrgLen The length of the urgent data in the received data.
1206 IN OUT SOCKET
*Sock
,
1207 IN OUT NET_BUF
*NetBuffer
,
1211 ASSERT ((Sock
!= NULL
) && (Sock
->RcvBuffer
.DataQueue
!= NULL
) &&
1212 UrgLen
<= NetBuffer
->TotalSize
);
1214 NET_GET_REF (NetBuffer
);
1216 ((TCP_RSV_DATA
*) (NetBuffer
->ProtoData
))->UrgLen
= UrgLen
;
1218 NetbufQueAppend (Sock
->RcvBuffer
.DataQueue
, NetBuffer
);
1220 SockWakeRcvToken (Sock
);
1224 Get the length of the free space of the specific socket buffer.
1226 @param[in] Sock Pointer to the socket.
1227 @param[in] Which Flag to indicate which socket buffer to check:
1228 either send buffer or receive buffer.
1230 @return The length of the free space, in bytes.
1240 SOCK_BUFFER
*SockBuffer
;
1242 ASSERT (Sock
!= NULL
&& ((SOCK_SND_BUF
== Which
) || (SOCK_RCV_BUF
== Which
)));
1244 if (SOCK_SND_BUF
== Which
) {
1245 SockBuffer
= &(Sock
->SndBuffer
);
1247 SockBuffer
= &(Sock
->RcvBuffer
);
1250 BufferCC
= (SockBuffer
->DataQueue
)->BufSize
;
1252 if (BufferCC
>= SockBuffer
->HighWater
) {
1257 return SockBuffer
->HighWater
- BufferCC
;
1261 Called by the low layer protocol to indicate that there will be no more data
1262 from the communication peer.
1264 This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
1265 IO tokens with the error status EFI_CONNECTION_FIN.
1267 @param[in, out] Sock Pointer to the socket.
1277 SOCK_NO_MORE_DATA (Sock
);
1279 if (!IsListEmpty (&Sock
->RcvTokenList
)) {
1281 ASSERT (0 == GET_RCV_DATASIZE (Sock
));
1283 Err
= Sock
->SockError
;
1285 SOCK_ERROR (Sock
, EFI_CONNECTION_FIN
);
1287 SockFlushPendingToken (Sock
, &Sock
->RcvTokenList
);
1289 SOCK_ERROR (Sock
, Err
);