2 Implementation of the Socket.
4 Copyright (c) 2005 - 2009, 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.
18 Get the length of the data that can be retrieved from the socket
21 @param SockBuffer Pointer to the socket receive buffer.
22 @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is
24 @param BufLen The maximum length of the data buffer to store the
25 received data in socket layer.
27 @return The length of the data can be retreived.
32 IN SOCK_BUFFER
*SockBuffer
,
38 Process the send token.
40 @param Sock Pointer to the socket.
49 Supporting function for both SockImpl and SockInterface.
51 @param Event The Event this notify function registered to, ignored.
64 Get the length of the data that can be retrieved from the socket
67 @param SockBuffer Pointer to the socket receive buffer.
68 @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is
70 @param BufLen The maximum length of the data buffer to store the
71 received data in socket layer.
73 @return The length of the data can be retreived.
78 IN SOCK_BUFFER
*SockBuffer
,
85 TCP_RSV_DATA
*TcpRsvData
;
87 ASSERT ((SockBuffer
!= NULL
) && (IsUrg
!= NULL
) && (BufLen
> 0));
89 RcvBufEntry
= SockBufFirst (SockBuffer
);
90 ASSERT (RcvBufEntry
!= NULL
);
92 TcpRsvData
= (TCP_RSV_DATA
*) RcvBufEntry
->ProtoData
;
94 *IsUrg
= (BOOLEAN
) ((TcpRsvData
->UrgLen
> 0) ? TRUE
: FALSE
);
96 if (*IsUrg
&& TcpRsvData
->UrgLen
< RcvBufEntry
->TotalSize
) {
98 DataLen
= MIN (TcpRsvData
->UrgLen
, BufLen
);
100 if (DataLen
< TcpRsvData
->UrgLen
) {
101 TcpRsvData
->UrgLen
= TcpRsvData
->UrgLen
- DataLen
;
103 TcpRsvData
->UrgLen
= 0;
110 DataLen
= RcvBufEntry
->TotalSize
;
112 RcvBufEntry
= SockBufNext (SockBuffer
, RcvBufEntry
);
114 while ((BufLen
> DataLen
) && (RcvBufEntry
!= NULL
)) {
116 TcpRsvData
= (TCP_RSV_DATA
*) RcvBufEntry
->ProtoData
;
118 Urg
= (BOOLEAN
) ((TcpRsvData
->UrgLen
> 0) ? TRUE
: FALSE
);
124 if (*IsUrg
&& TcpRsvData
->UrgLen
< RcvBufEntry
->TotalSize
) {
126 if (TcpRsvData
->UrgLen
+ DataLen
< BufLen
) {
127 TcpRsvData
->UrgLen
= 0;
129 TcpRsvData
->UrgLen
= TcpRsvData
->UrgLen
- (BufLen
- DataLen
);
132 return MIN (TcpRsvData
->UrgLen
+ DataLen
, BufLen
);
136 DataLen
+= RcvBufEntry
->TotalSize
;
138 RcvBufEntry
= SockBufNext (SockBuffer
, RcvBufEntry
);
141 DataLen
= MIN (BufLen
, DataLen
);
147 Copy data from socket buffer to application provided receive buffer.
149 @param Sock Pointer to the socket.
150 @param TcpRxData Pointer to the application provided receive buffer.
151 @param RcvdBytes The maximum length of the data can be copied.
152 @param IsOOB If TURE the data is OOB, FALSE the data is normal.
166 EFI_TCP4_RECEIVE_DATA
*RxData
;
167 EFI_TCP4_FRAGMENT_DATA
*Fragment
;
169 RxData
= (EFI_TCP4_RECEIVE_DATA
*) TcpRxData
;
173 ASSERT (RxData
->DataLength
>= RcvdBytes
);
175 RxData
->DataLength
= RcvdBytes
;
176 RxData
->UrgentFlag
= IsOOB
;
178 for (Index
= 0; (Index
< RxData
->FragmentCount
) && (RcvdBytes
> 0); Index
++) {
180 Fragment
= &RxData
->FragmentTable
[Index
];
181 CopyBytes
= MIN ((UINT32
) (Fragment
->FragmentLength
), RcvdBytes
);
184 Sock
->RcvBuffer
.DataQueue
,
187 Fragment
->FragmentBuffer
190 Fragment
->FragmentLength
= CopyBytes
;
191 RcvdBytes
-= CopyBytes
;
198 Get received data from the socket layer to the receive token.
200 @param Sock Pointer to the socket.
201 @param RcvToken Pointer to the application provided receive token.
203 @return The length of data received in this token.
207 SockProcessRcvToken (
209 IN OUT SOCK_IO_TOKEN
*RcvToken
212 UINT32 TokenRcvdBytes
;
213 EFI_TCP4_RECEIVE_DATA
*RxData
;
216 ASSERT (Sock
!= NULL
);
218 ASSERT (SockStream
== Sock
->Type
);
220 RxData
= RcvToken
->Packet
.RxData
;
222 TokenRcvdBytes
= SockTcpDataToRcv (
225 (UINT32
) RxData
->DataLength
229 // Copy data from RcvBuffer of socket to user
230 // provided RxData and set the fields in TCP RxData
232 SockSetTcpRxData (Sock
, RxData
, TokenRcvdBytes
, IsUrg
);
234 NetbufQueTrim (Sock
->RcvBuffer
.DataQueue
, TokenRcvdBytes
);
235 SIGNAL_TOKEN (&(RcvToken
->Token
), EFI_SUCCESS
);
237 return TokenRcvdBytes
;
242 Process the TCP send data, buffer the tcp txdata and append
243 the buffer to socket send buffer,then try to send it.
245 @param Sock Pointer to the socket.
246 @param TcpTxData Pointer to the application provided send buffer.
248 @retval EFI_SUCCESS The operation is completed successfully.
249 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
253 SockProcessTcpSndData (
260 EFI_TCP4_TRANSMIT_DATA
*TxData
;
262 TxData
= (EFI_TCP4_TRANSMIT_DATA
*) TcpTxData
;
265 // transform this TxData into a NET_BUFFER
266 // and insert it into Sock->SndBuffer
268 SndData
= NetbufFromExt (
269 (NET_FRAGMENT
*) TxData
->FragmentTable
,
270 (UINT32
) TxData
->FragmentCount
,
277 if (NULL
== SndData
) {
278 DEBUG ((EFI_D_ERROR
, "SockKProcessSndData: Failed to"
279 " call NetBufferFromExt\n"));
281 return EFI_OUT_OF_RESOURCES
;
284 NetbufQueAppend (Sock
->SndBuffer
.DataQueue
, SndData
);
287 // notify the low layer protocol to handle this send token
289 if (TxData
->Urgent
) {
290 Status
= Sock
->ProtoHandler (Sock
, SOCK_SNDURG
, NULL
);
292 if (EFI_ERROR (Status
)) {
298 Status
= Sock
->ProtoHandler (Sock
, SOCK_SNDPUSH
, NULL
);
300 if (EFI_ERROR (Status
)) {
306 // low layer protocol should really handle the sending
307 // process when catching SOCK_SND request
309 Status
= Sock
->ProtoHandler (Sock
, SOCK_SND
, NULL
);
311 if (EFI_ERROR (Status
)) {
320 Flush the tokens in the specific token list.
322 @param Sock Pointer to the socket.
323 @param PendingTokenList Pointer to the token list to be flushed.
327 SockFlushPendingToken (
329 IN LIST_ENTRY
*PendingTokenList
332 SOCK_TOKEN
*SockToken
;
333 SOCK_COMPLETION_TOKEN
*Token
;
335 ASSERT ((Sock
!= NULL
) && (PendingTokenList
!= NULL
));
337 while (!IsListEmpty (PendingTokenList
)) {
338 SockToken
= NET_LIST_HEAD (
344 Token
= SockToken
->Token
;
345 SIGNAL_TOKEN (Token
, Sock
->SockError
);
347 RemoveEntryList (&(SockToken
->TokenList
));
348 gBS
->FreePool (SockToken
);
354 Wake up the connection token while the connection is successfully established,
355 then try to process any pending send token.
357 @param Sock Pointer to the socket.
365 ASSERT (Sock
->ConnectionToken
!= NULL
);
367 SIGNAL_TOKEN (Sock
->ConnectionToken
, EFI_SUCCESS
);
368 Sock
->ConnectionToken
= NULL
;
371 // check to see if some pending send token existed?
373 SockProcessSndToken (Sock
);
379 Wake up the listen token while the connection is established successfully.
381 @param Sock Pointer to the socket.
385 SockWakeListenToken (
390 SOCK_TOKEN
*SockToken
;
391 EFI_TCP4_LISTEN_TOKEN
*ListenToken
;
393 Parent
= Sock
->Parent
;
395 ASSERT ((Parent
!= NULL
) && SOCK_IS_LISTENING (Parent
) && SOCK_IS_CONNECTED (Sock
));
397 if (!IsListEmpty (&Parent
->ListenTokenList
)) {
398 SockToken
= NET_LIST_HEAD (
399 &Parent
->ListenTokenList
,
404 ListenToken
= (EFI_TCP4_LISTEN_TOKEN
*) SockToken
->Token
;
405 ListenToken
->NewChildHandle
= Sock
->SockHandle
;
407 SIGNAL_TOKEN (&(ListenToken
->CompletionToken
), EFI_SUCCESS
);
409 RemoveEntryList (&SockToken
->TokenList
);
410 gBS
->FreePool (SockToken
);
412 RemoveEntryList (&Sock
->ConnectionList
);
415 DEBUG ((EFI_D_INFO
, "SockWakeListenToken: accept a socket, now conncnt is %d", Parent
->ConnCnt
));
423 Wake up the receive token while some data is received.
425 @param Sock Pointer to the socket.
434 UINT32 TokenRcvdBytes
;
435 SOCK_TOKEN
*SockToken
;
436 SOCK_IO_TOKEN
*RcvToken
;
438 ASSERT (Sock
->RcvBuffer
.DataQueue
!= NULL
);
440 RcvdBytes
= (Sock
->RcvBuffer
.DataQueue
)->BufSize
;
442 ASSERT (RcvdBytes
> 0);
444 while (RcvdBytes
> 0 && !IsListEmpty (&Sock
->RcvTokenList
)) {
446 SockToken
= NET_LIST_HEAD (
452 RcvToken
= (SOCK_IO_TOKEN
*) SockToken
->Token
;
453 TokenRcvdBytes
= SockProcessRcvToken (Sock
, RcvToken
);
455 if (0 == TokenRcvdBytes
) {
459 RemoveEntryList (&(SockToken
->TokenList
));
460 gBS
->FreePool (SockToken
);
461 RcvdBytes
-= TokenRcvdBytes
;
467 Process the send token.
469 @param Sock Pointer to the socket.
473 SockProcessSndToken (
478 SOCK_TOKEN
*SockToken
;
480 SOCK_IO_TOKEN
*SndToken
;
481 EFI_TCP4_TRANSMIT_DATA
*TxData
;
484 ASSERT ((Sock
!= NULL
) && (SockStream
== Sock
->Type
));
486 FreeSpace
= SockGetFreeSpace (Sock
, SOCK_SND_BUF
);
489 // to determine if process a send token using
490 // socket layer flow control policy
492 while ((FreeSpace
>= Sock
->SndBuffer
.LowWater
) &&
493 !IsListEmpty (&Sock
->SndTokenList
)) {
495 SockToken
= NET_LIST_HEAD (
496 &(Sock
->SndTokenList
),
502 // process this token
504 RemoveEntryList (&(SockToken
->TokenList
));
506 &(Sock
->ProcessingSndTokenList
),
507 &(SockToken
->TokenList
)
511 // Proceess it in the light of SockType
513 SndToken
= (SOCK_IO_TOKEN
*) SockToken
->Token
;
514 TxData
= SndToken
->Packet
.TxData
;
516 DataLen
= (UINT32
) TxData
->DataLength
;
517 Status
= SockProcessTcpSndData (Sock
, TxData
);
519 if (EFI_ERROR (Status
)) {
523 if (DataLen
>= FreeSpace
) {
527 FreeSpace
-= DataLen
;
536 RemoveEntryList (&SockToken
->TokenList
);
537 SIGNAL_TOKEN (SockToken
->Token
, Status
);
538 gBS
->FreePool (SockToken
);
543 Create a socket with initial data SockInitData.
545 @param SockInitData Pointer to the initial data of the socket.
547 @return Pointer to the newly created socket, return NULL when exception occured.
552 IN SOCK_INIT_DATA
*SockInitData
559 ASSERT ((SockInitData
!= NULL
) && (SockInitData
->ProtoHandler
!= NULL
));
560 ASSERT (SockInitData
->Type
== SockStream
);
561 ASSERT ((SockInitData
->ProtoData
!= NULL
) && (SockInitData
->DataSize
<= PROTO_RESERVED_LEN
));
563 Parent
= SockInitData
->Parent
;
565 if ((Parent
!= NULL
) && (Parent
->ConnCnt
== Parent
->BackLog
)) {
568 "SockCreate: Socket parent has "
569 "reached its connection limit with %d ConnCnt and %d BackLog\n",
577 Sock
= AllocateZeroPool (sizeof (SOCKET
));
580 DEBUG ((EFI_D_ERROR
, "SockCreate: No resource to create a new socket\n"));
584 InitializeListHead (&Sock
->Link
);
585 InitializeListHead (&Sock
->ConnectionList
);
586 InitializeListHead (&Sock
->ListenTokenList
);
587 InitializeListHead (&Sock
->RcvTokenList
);
588 InitializeListHead (&Sock
->SndTokenList
);
589 InitializeListHead (&Sock
->ProcessingSndTokenList
);
591 EfiInitializeLock (&(Sock
->Lock
), TPL_CALLBACK
);
593 Sock
->SndBuffer
.DataQueue
= NetbufQueAlloc ();
594 if (NULL
== Sock
->SndBuffer
.DataQueue
) {
595 DEBUG ((EFI_D_ERROR
, "SockCreate: No resource to allocate"
596 " SndBuffer for new socket\n"));
601 Sock
->RcvBuffer
.DataQueue
= NetbufQueAlloc ();
602 if (NULL
== Sock
->RcvBuffer
.DataQueue
) {
603 DEBUG ((EFI_D_ERROR
, "SockCreate: No resource to allocate "
604 "RcvBuffer for new socket\n"));
609 Sock
->Signature
= SOCK_SIGNATURE
;
611 Sock
->Parent
= Parent
;
612 Sock
->BackLog
= SockInitData
->BackLog
;
613 Sock
->ProtoHandler
= SockInitData
->ProtoHandler
;
614 Sock
->SndBuffer
.HighWater
= SockInitData
->SndBufferSize
;
615 Sock
->RcvBuffer
.HighWater
= SockInitData
->RcvBufferSize
;
616 Sock
->Type
= SockInitData
->Type
;
617 Sock
->DriverBinding
= SockInitData
->DriverBinding
;
618 Sock
->State
= SockInitData
->State
;
619 Sock
->CreateCallback
= SockInitData
->CreateCallback
;
620 Sock
->DestroyCallback
= SockInitData
->DestroyCallback
;
621 Sock
->Context
= SockInitData
->Context
;
623 Sock
->SockError
= EFI_ABORTED
;
624 Sock
->SndBuffer
.LowWater
= SOCK_BUFF_LOW_WATER
;
625 Sock
->RcvBuffer
.LowWater
= SOCK_BUFF_LOW_WATER
;
628 // Install protocol on Sock->SockHandle
631 &(Sock
->NetProtocol
.TcpProtocol
),
632 SockInitData
->Protocol
,
633 sizeof (EFI_TCP4_PROTOCOL
)
637 // copy the protodata into socket
639 CopyMem (Sock
->ProtoReserved
, SockInitData
->ProtoData
, SockInitData
->DataSize
);
641 Status
= gBS
->InstallMultipleProtocolInterfaces (
643 &gEfiTcp4ProtocolGuid
,
644 &(Sock
->NetProtocol
.TcpProtocol
),
648 if (EFI_ERROR (Status
)) {
649 DEBUG ((EFI_D_ERROR
, "SockCreate: Install TCP protocol in "
650 "socket failed with %r\n", Status
));
655 if (Parent
!= NULL
) {
656 ASSERT (Parent
->BackLog
> 0);
657 ASSERT (SOCK_IS_LISTENING (Parent
));
660 // need to add it into Parent->ConnectionList
661 // if the Parent->ConnCnt < Parent->BackLog
667 "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
671 InsertTailList (&Parent
->ConnectionList
, &Sock
->ConnectionList
);
674 if (Sock
->CreateCallback
!= NULL
) {
675 Status
= Sock
->CreateCallback (Sock
, Sock
->Context
);
676 if (EFI_ERROR (Status
)) {
685 if (Sock
->SockHandle
!= NULL
) {
686 gBS
->UninstallMultipleProtocolInterfaces (
688 &gEfiTcp4ProtocolGuid
,
689 &(Sock
->NetProtocol
.TcpProtocol
),
694 if (NULL
!= Sock
->SndBuffer
.DataQueue
) {
695 NetbufQueFree (Sock
->SndBuffer
.DataQueue
);
698 if (NULL
!= Sock
->RcvBuffer
.DataQueue
) {
699 NetbufQueFree (Sock
->RcvBuffer
.DataQueue
);
702 gBS
->FreePool (Sock
);
711 @param Sock Pointer to the socket.
720 EFI_GUID
*ProtocolGuid
;
723 ASSERT (SockStream
== Sock
->Type
);
725 if (Sock
->DestroyCallback
!= NULL
) {
726 Sock
->DestroyCallback (Sock
, Sock
->Context
);
730 // Flush the completion token buffered
731 // by sock and rcv, snd buffer
733 if (!SOCK_IS_UNCONFIGURED (Sock
)) {
735 SockConnFlush (Sock
);
736 SockSetState (Sock
, SO_CLOSED
);
737 Sock
->ConfigureState
= SO_UNCONFIGURED
;
741 // Destory the RcvBuffer Queue and SendBuffer Queue
743 NetbufQueFree (Sock
->RcvBuffer
.DataQueue
);
744 NetbufQueFree (Sock
->SndBuffer
.DataQueue
);
747 // Remove it from parent connection list if needed
749 if (Sock
->Parent
!= NULL
) {
751 RemoveEntryList (&(Sock
->ConnectionList
));
752 (Sock
->Parent
->ConnCnt
)--;
756 "SockDestory: Delete a unaccepted socket from parent"
757 "now conncnt is %d\n",
758 Sock
->Parent
->ConnCnt
)
765 // Set the protocol guid and driver binding handle
766 // in the light of Sock->SockType
768 ProtocolGuid
= &gEfiTcp4ProtocolGuid
;
771 // Retrieve the protocol installed on this sock
773 Status
= gBS
->OpenProtocol (
779 EFI_OPEN_PROTOCOL_GET_PROTOCOL
782 if (EFI_ERROR (Status
)) {
784 DEBUG ((EFI_D_ERROR
, "SockDestroy: Open protocol installed "
785 "on socket failed with %r\n", Status
));
791 // Uninstall the protocol installed on this sock
792 // in the light of Sock->SockType
794 gBS
->UninstallMultipleProtocolInterfaces (
802 gBS
->FreePool (Sock
);
808 Flush the sndBuffer and rcvBuffer of socket.
810 @param Sock Pointer to the socket.
820 ASSERT (Sock
!= NULL
);
823 // Clear the flag in this socket
828 // Flush the SndBuffer and RcvBuffer of Sock
830 NetbufQueFlush (Sock
->SndBuffer
.DataQueue
);
831 NetbufQueFlush (Sock
->RcvBuffer
.DataQueue
);
834 // Signal the pending token
836 if (Sock
->ConnectionToken
!= NULL
) {
837 SIGNAL_TOKEN (Sock
->ConnectionToken
, Sock
->SockError
);
838 Sock
->ConnectionToken
= NULL
;
841 if (Sock
->CloseToken
!= NULL
) {
842 SIGNAL_TOKEN (Sock
->CloseToken
, Sock
->SockError
);
843 Sock
->CloseToken
= NULL
;
846 SockFlushPendingToken (Sock
, &(Sock
->ListenTokenList
));
847 SockFlushPendingToken (Sock
, &(Sock
->RcvTokenList
));
848 SockFlushPendingToken (Sock
, &(Sock
->SndTokenList
));
849 SockFlushPendingToken (Sock
, &(Sock
->ProcessingSndTokenList
));
852 // Destroy the pending connection, if it is a listening socket
854 if (SOCK_IS_LISTENING (Sock
)) {
855 while (!IsListEmpty (&Sock
->ConnectionList
)) {
856 Child
= NET_LIST_HEAD (
857 &Sock
->ConnectionList
,
862 SockDestroyChild (Child
);
873 Set the state of the socket.
875 @param Sock Pointer to the socket.
876 @param State The new socket state to be set.
890 Clone a new socket including its associated protocol control block.
892 @param Sock Pointer to the socket to be cloned.
894 @return Pointer to the newly cloned socket. If NULL, error condition occurred.
903 SOCK_INIT_DATA InitData
;
905 InitData
.BackLog
= Sock
->BackLog
;
906 InitData
.Parent
= Sock
;
907 InitData
.State
= Sock
->State
;
908 InitData
.ProtoHandler
= Sock
->ProtoHandler
;
909 InitData
.Type
= Sock
->Type
;
910 InitData
.RcvBufferSize
= Sock
->RcvBuffer
.HighWater
;
911 InitData
.SndBufferSize
= Sock
->SndBuffer
.HighWater
;
912 InitData
.DriverBinding
= Sock
->DriverBinding
;
913 InitData
.Protocol
= &(Sock
->NetProtocol
);
914 InitData
.CreateCallback
= Sock
->CreateCallback
;
915 InitData
.DestroyCallback
= Sock
->DestroyCallback
;
916 InitData
.Context
= Sock
->Context
;
917 InitData
.ProtoData
= Sock
->ProtoReserved
;
918 InitData
.DataSize
= sizeof (Sock
->ProtoReserved
);
920 ClonedSock
= SockCreate (&InitData
);
922 if (NULL
== ClonedSock
) {
923 DEBUG ((EFI_D_ERROR
, "SockClone: no resource to create a cloned sock\n"));
927 SockSetState (ClonedSock
, SO_CONNECTING
);
928 ClonedSock
->ConfigureState
= Sock
->ConfigureState
;
935 Called by the low layer protocol to indicate the socket a connection is
938 This function just changes the socket's state to SO_CONNECTED
939 and signals the token used for connection establishment.
941 @param Sock Pointer to the socket associated with the
942 established connection.
945 SockConnEstablished (
950 ASSERT (SO_CONNECTING
== Sock
->State
);
952 SockSetState (Sock
, SO_CONNECTED
);
954 if (NULL
== Sock
->Parent
) {
955 SockWakeConnToken (Sock
);
957 SockWakeListenToken (Sock
);
965 Called by the low layer protocol to indicate the connection is closed.
967 This function flushes the socket, sets the state to SO_CLOSED and signals
970 @param Sock Pointer to the socket associated with the closed
979 if (Sock
->CloseToken
!= NULL
) {
980 SIGNAL_TOKEN (Sock
->CloseToken
, EFI_SUCCESS
);
981 Sock
->CloseToken
= NULL
;
984 SockConnFlush (Sock
);
985 SockSetState (Sock
, SO_CLOSED
);
987 if (Sock
->Parent
!= NULL
) {
988 SockDestroyChild (Sock
);
995 Called by low layer protocol to indicate that some data is sent or processed.
997 This function trims the sent data in the socket send buffer, signals the data
1000 @param Sock Pointer to the socket.
1001 @param Count The length of the data processed or sent, in bytes.
1010 SOCK_TOKEN
*SockToken
;
1011 SOCK_COMPLETION_TOKEN
*SndToken
;
1013 ASSERT (!IsListEmpty (&Sock
->ProcessingSndTokenList
));
1014 ASSERT (Count
<= (Sock
->SndBuffer
.DataQueue
)->BufSize
);
1016 NetbufQueTrim (Sock
->SndBuffer
.DataQueue
, Count
);
1019 // To check if we can signal some snd token in this socket
1022 SockToken
= NET_LIST_HEAD (
1023 &(Sock
->ProcessingSndTokenList
),
1028 SndToken
= SockToken
->Token
;
1030 if (SockToken
->RemainDataLen
<= Count
) {
1032 RemoveEntryList (&(SockToken
->TokenList
));
1033 SIGNAL_TOKEN (SndToken
, EFI_SUCCESS
);
1034 Count
-= SockToken
->RemainDataLen
;
1035 gBS
->FreePool (SockToken
);
1038 SockToken
->RemainDataLen
-= Count
;
1044 // to judge if we can process some send token in
1045 // Sock->SndTokenList, if so process those send token
1047 SockProcessSndToken (Sock
);
1053 Called by the low layer protocol to copy some data in socket send
1054 buffer starting from the specific offset to a buffer provided by
1057 @param Sock Pointer to the socket.
1058 @param Offset The start point of the data to be copied.
1059 @param Len The length of the data to be copied.
1060 @param Dest Pointer to the destination to copy the data.
1062 @return The data size copied.
1073 ASSERT ((Sock
!= NULL
) && SockStream
== Sock
->Type
);
1075 return NetbufQueCopy (
1076 Sock
->SndBuffer
.DataQueue
,
1085 Called by the low layer protocol to deliver received data to socket layer.
1087 This function will append the data to the socket receive buffer, set ther
1088 urgent data length and then check if any receive token can be signaled.
1090 @param Sock Pointer to the socket.
1091 @param NetBuffer Pointer to the buffer that contains the received
1093 @param UrgLen The length of the urgent data in the received data.
1099 IN OUT NET_BUF
*NetBuffer
,
1103 ASSERT ((Sock
!= NULL
) && (Sock
->RcvBuffer
.DataQueue
!= NULL
) &&
1104 UrgLen
<= NetBuffer
->TotalSize
);
1106 NET_GET_REF (NetBuffer
);
1108 ((TCP_RSV_DATA
*) (NetBuffer
->ProtoData
))->UrgLen
= UrgLen
;
1110 NetbufQueAppend (Sock
->RcvBuffer
.DataQueue
, NetBuffer
);
1112 SockWakeRcvToken (Sock
);
1118 Get the length of the free space of the specific socket buffer.
1120 @param Sock Pointer to the socket.
1121 @param Which Flag to indicate which socket buffer to check,
1122 either send buffer or receive buffer.
1124 @return The length of the free space, in bytes.
1134 SOCK_BUFFER
*SockBuffer
;
1136 ASSERT ((Sock
!= NULL
) && ((SOCK_SND_BUF
== Which
) || (SOCK_RCV_BUF
== Which
)));
1138 if (SOCK_SND_BUF
== Which
) {
1139 SockBuffer
= &(Sock
->SndBuffer
);
1141 SockBuffer
= &(Sock
->RcvBuffer
);
1144 BufferCC
= (SockBuffer
->DataQueue
)->BufSize
;
1146 if (BufferCC
>= SockBuffer
->HighWater
) {
1151 return SockBuffer
->HighWater
- BufferCC
;
1156 Signal the receive token with the specific error or
1157 set socket error code after error is received.
1159 @param Sock Pointer to the socket.
1160 @param Error The error code received.
1165 IN OUT SOCKET
*Sock
,
1169 SOCK_TOKEN
*SockToken
;
1171 if (!IsListEmpty (&Sock
->RcvTokenList
)) {
1173 SockToken
= NET_LIST_HEAD (
1174 &Sock
->RcvTokenList
,
1179 RemoveEntryList (&SockToken
->TokenList
);
1181 SIGNAL_TOKEN (SockToken
->Token
, Error
);
1183 gBS
->FreePool (SockToken
);
1186 SOCK_ERROR (Sock
, Error
);
1192 Called by the low layer protocol to indicate that there will be no more data
1193 from the communication peer.
1195 This function set the socket's state to SO_NO_MORE_DATA and signal all queued
1196 IO tokens with the error status EFI_CONNECTION_FIN.
1198 @param Sock Pointer to the socket.
1208 SOCK_NO_MORE_DATA (Sock
);
1210 if (!IsListEmpty (&Sock
->RcvTokenList
)) {
1212 ASSERT (0 == GET_RCV_DATASIZE (Sock
));
1214 Err
= Sock
->SockError
;
1216 SOCK_ERROR (Sock
, EFI_CONNECTION_FIN
);
1218 SockFlushPendingToken (Sock
, &Sock
->RcvTokenList
);
1220 SOCK_ERROR (Sock
, Err
);
1228 Get the first buffer block in the specific socket buffer.
1230 @param Sockbuf Pointer to the socket buffer.
1232 @return Pointer to the first buffer in the queue. NULL if the queue is empty.
1237 IN SOCK_BUFFER
*Sockbuf
1240 LIST_ENTRY
*NetbufList
;
1242 NetbufList
= &(Sockbuf
->DataQueue
->BufList
);
1244 if (IsListEmpty (NetbufList
)) {
1248 return NET_LIST_HEAD (NetbufList
, NET_BUF
, List
);
1253 Get the next buffer block in the specific socket buffer.
1255 @param Sockbuf Pointer to the socket buffer.
1256 @param SockEntry Pointer to the buffer block prior to the required
1259 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is
1260 the tail or head entry.
1265 IN SOCK_BUFFER
*Sockbuf
,
1266 IN NET_BUF
*SockEntry
1269 LIST_ENTRY
*NetbufList
;
1271 NetbufList
= &(Sockbuf
->DataQueue
->BufList
);
1273 if ((SockEntry
->List
.ForwardLink
== NetbufList
) ||
1274 (SockEntry
->List
.BackLink
== &SockEntry
->List
) ||
1275 (SockEntry
->List
.ForwardLink
== &SockEntry
->List
)) {
1280 return NET_LIST_USER_STRUCT (SockEntry
->List
.ForwardLink
, NET_BUF
, List
);