3 Copyright (c) 2005 - 2006, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
21 #include "SockImpl.h"
\r
26 IN SOCK_BUFFER *SockBuffer,
\r
33 SockProcessSndToken (
\r
47 Get the length of the data that can be retrieved from the socket
\r
50 @param SockBuffer Pointer to the socket receive buffer.
\r
51 @param IsUrg Pointer to a BOOLEAN variable. If TRUE the data is
\r
53 @param BufLen The maximum length of the data buffer to store the
\r
54 received data in socket layer.
\r
56 @return The length of the data can be retreived.
\r
62 IN SOCK_BUFFER *SockBuffer,
\r
67 NET_BUF *RcvBufEntry;
\r
69 TCP_RSV_DATA *TcpRsvData;
\r
72 ASSERT (SockBuffer && IsUrg && (BufLen > 0));
\r
74 RcvBufEntry = SockBufFirst (SockBuffer);
\r
75 ASSERT (RcvBufEntry);
\r
77 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
\r
79 *IsUrg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
\r
81 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
\r
83 DataLen = MIN (TcpRsvData->UrgLen, BufLen);
\r
85 if (DataLen < TcpRsvData->UrgLen) {
\r
86 TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen;
\r
88 TcpRsvData->UrgLen = 0;
\r
95 DataLen = RcvBufEntry->TotalSize;
\r
97 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
\r
99 while ((BufLen > DataLen) && (RcvBufEntry != NULL)) {
\r
101 TcpRsvData = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
\r
103 Urg = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
\r
105 if (*IsUrg != Urg) {
\r
109 if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
\r
111 if (TcpRsvData->UrgLen + DataLen < BufLen) {
\r
112 TcpRsvData->UrgLen = 0;
\r
114 TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen);
\r
117 return MIN (TcpRsvData->UrgLen + DataLen, BufLen);
\r
121 DataLen += RcvBufEntry->TotalSize;
\r
123 RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
\r
126 DataLen = MIN (BufLen, DataLen);
\r
132 Copy data from socket buffer to application provided receive buffer.
\r
134 @param Sock Pointer to the socket.
\r
135 @param TcpRxData Pointer to the application provided receive buffer.
\r
136 @param RcvdBytes The maximum length of the data can be copied.
\r
137 @param IsOOB If TURE the data is OOB, else the data is normal.
\r
145 IN VOID *TcpRxData,
\r
146 IN UINT32 RcvdBytes,
\r
153 EFI_TCP4_RECEIVE_DATA *RxData;
\r
154 EFI_TCP4_FRAGMENT_DATA *Fragment;
\r
156 RxData = (EFI_TCP4_RECEIVE_DATA *) TcpRxData;
\r
160 ASSERT (RxData->DataLength >= RcvdBytes);
\r
162 RxData->DataLength = RcvdBytes;
\r
163 RxData->UrgentFlag = IsOOB;
\r
165 for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) {
\r
167 Fragment = &RxData->FragmentTable[Index];
\r
168 CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes);
\r
171 Sock->RcvBuffer.DataQueue,
\r
174 Fragment->FragmentBuffer
\r
177 Fragment->FragmentLength = CopyBytes;
\r
178 RcvdBytes -= CopyBytes;
\r
179 OffSet += CopyBytes;
\r
185 Get received data from the socket layer to the receive token.
\r
187 @param Sock Pointer to the socket.
\r
188 @param RcvToken Pointer to the application provided receive token.
\r
190 @return The length of data received in this token.
\r
194 SockProcessRcvToken (
\r
196 IN SOCK_IO_TOKEN *RcvToken
\r
199 UINT32 TokenRcvdBytes;
\r
200 EFI_TCP4_RECEIVE_DATA *RxData;
\r
205 ASSERT (SOCK_STREAM == Sock->Type);
\r
207 RxData = RcvToken->Packet.RxData;
\r
209 TokenRcvdBytes = SockTcpDataToRcv (
\r
212 (UINT32) RxData->DataLength
\r
216 // Copy data from RcvBuffer of socket to user
\r
217 // provided RxData and set the fields in TCP RxData
\r
219 SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg);
\r
221 SOCK_TRIM_RCV_BUFF (Sock, TokenRcvdBytes);
\r
222 SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS);
\r
224 return TokenRcvdBytes;
\r
229 Process the TCP send data, buffer the tcp txdata and append
\r
230 the buffer to socket send buffer,then try to send it.
\r
232 @param Sock Pointer to the socket.
\r
233 @param TcpTxData Pointer to the tcp txdata.
\r
235 @retval EFI_SUCCESS The operation is completed successfully.
\r
236 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
\r
240 SockProcessTcpSndData (
\r
247 EFI_TCP4_TRANSMIT_DATA *TxData;
\r
249 TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData;
\r
252 // transform this TxData into a NET_BUFFER
\r
253 // and insert it into Sock->SndBuffer
\r
255 SndData = NetbufFromExt (
\r
256 (NET_FRAGMENT *) TxData->FragmentTable,
\r
257 (UINT32) TxData->FragmentCount,
\r
264 if (NULL == SndData) {
\r
265 SOCK_DEBUG_ERROR (("SockKProcessSndData: Failed to"
\r
266 " call NetBufferFromExt\n"));
\r
268 return EFI_OUT_OF_RESOURCES;
\r
271 NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData);
\r
274 // notify the low layer protocol to handle this send token
\r
276 if (TxData->Urgent) {
\r
277 Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL);
\r
279 if (EFI_ERROR (Status)) {
\r
284 if (TxData->Push) {
\r
285 Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL);
\r
287 if (EFI_ERROR (Status)) {
\r
293 // low layer protocol should really handle the sending
\r
294 // process when catching SOCK_SND request
\r
296 Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL);
\r
298 if (EFI_ERROR (Status)) {
\r
302 return EFI_SUCCESS;
\r
307 Flush the tokens in the specific token list.
\r
309 @param Sock Pointer to the socket.
\r
310 @param PendingTokenList Pointer to the token list to be flushed.
\r
317 SockFlushPendingToken (
\r
319 IN NET_LIST_ENTRY *PendingTokenList
\r
322 SOCK_TOKEN *SockToken;
\r
323 SOCK_COMPLETION_TOKEN *Token;
\r
325 ASSERT (Sock && PendingTokenList);
\r
327 while (!NetListIsEmpty (PendingTokenList)) {
\r
328 SockToken = NET_LIST_HEAD (
\r
334 Token = SockToken->Token;
\r
335 SIGNAL_TOKEN (Token, Sock->SockError);
\r
337 NetListRemoveEntry (&(SockToken->TokenList));
\r
338 NetFreePool (SockToken);
\r
344 Wake up the connection token while the connection is
\r
345 successfully established, then try to process any
\r
346 pending send token.
\r
348 @param Sock Pointer to the socket.
\r
355 SockWakeConnToken (
\r
359 ASSERT (Sock->ConnectionToken != NULL);
\r
361 SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS);
\r
362 Sock->ConnectionToken = NULL;
\r
365 // check to see if some pending send token existed?
\r
367 SockProcessSndToken (Sock);
\r
373 Wake up the listen token while the connection is
\r
374 established successfully.
\r
376 @param Sock Pointer to the socket.
\r
383 SockWakeListenToken (
\r
388 SOCK_TOKEN *SockToken;
\r
389 EFI_TCP4_LISTEN_TOKEN *ListenToken;
\r
391 Parent = Sock->Parent;
\r
393 ASSERT (Parent && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock));
\r
395 if (!NetListIsEmpty (&Parent->ListenTokenList)) {
\r
396 SockToken = NET_LIST_HEAD (
\r
397 &Parent->ListenTokenList,
\r
402 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token;
\r
403 ListenToken->NewChildHandle = Sock->SockHandle;
\r
405 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
\r
407 NetListRemoveEntry (&SockToken->TokenList);
\r
408 NetFreePool (SockToken);
\r
410 NetListRemoveEntry (&Sock->ConnectionList);
\r
413 SOCK_DEBUG_WARN (("SockWakeListenToken: accept a socket,"
\r
414 "now conncnt is %d", Parent->ConnCnt));
\r
416 Sock->Parent = NULL;
\r
422 Wake up the receive token while some data is received.
\r
424 @param Sock Pointer to the socket.
\r
436 UINT32 TokenRcvdBytes;
\r
437 SOCK_TOKEN *SockToken;
\r
438 SOCK_IO_TOKEN *RcvToken;
\r
440 ASSERT (Sock->RcvBuffer.DataQueue);
\r
442 RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;
\r
444 ASSERT (RcvdBytes > 0);
\r
446 while (RcvdBytes > 0 && !NetListIsEmpty (&Sock->RcvTokenList)) {
\r
448 SockToken = NET_LIST_HEAD (
\r
449 &Sock->RcvTokenList,
\r
454 RcvToken = (SOCK_IO_TOKEN *) SockToken->Token;
\r
455 TokenRcvdBytes = SockProcessRcvToken (Sock, RcvToken);
\r
457 if (0 == TokenRcvdBytes) {
\r
461 NetListRemoveEntry (&(SockToken->TokenList));
\r
462 NetFreePool (SockToken);
\r
463 RcvdBytes -= TokenRcvdBytes;
\r
469 Process the send token.
\r
471 @param Sock Pointer to the socket.
\r
478 SockProcessSndToken (
\r
483 SOCK_TOKEN *SockToken;
\r
485 SOCK_IO_TOKEN *SndToken;
\r
486 EFI_TCP4_TRANSMIT_DATA *TxData;
\r
489 ASSERT (Sock && (SOCK_STREAM == Sock->Type));
\r
491 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
\r
494 // to determine if process a send token using
\r
495 // socket layer flow control policy
\r
497 while ((FreeSpace >= Sock->SndBuffer.LowWater) &&
\r
498 !NetListIsEmpty (&Sock->SndTokenList)) {
\r
500 SockToken = NET_LIST_HEAD (
\r
501 &(Sock->SndTokenList),
\r
507 // process this token
\r
509 NetListRemoveEntry (&(SockToken->TokenList));
\r
510 NetListInsertTail (
\r
511 &(Sock->ProcessingSndTokenList),
\r
512 &(SockToken->TokenList)
\r
516 // Proceess it in the light of SockType
\r
518 SndToken = (SOCK_IO_TOKEN *) SockToken->Token;
\r
519 TxData = SndToken->Packet.TxData;
\r
521 DataLen = (UINT32) TxData->DataLength;
\r
522 Status = SockProcessTcpSndData (Sock, TxData);
\r
524 if (EFI_ERROR (Status)) {
\r
528 if (DataLen >= FreeSpace) {
\r
532 FreeSpace -= DataLen;
\r
541 NetListRemoveEntry (&SockToken->TokenList);
\r
542 SIGNAL_TOKEN (SockToken->Token, Status);
\r
543 NetFreePool (SockToken);
\r
548 Create a socket with initial data SockInitData.
\r
550 @param SockInitData Pointer to the initial data of the socket.
\r
552 @return Pointer to the newly created socket.
\r
557 IN SOCK_INIT_DATA *SockInitData
\r
564 ASSERT (SockInitData && SockInitData->ProtoHandler);
\r
565 ASSERT (SockInitData->Type == SOCK_STREAM);
\r
566 ASSERT (SockInitData->ProtoData && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
\r
568 Parent = SockInitData->Parent;
\r
570 if (Parent && (Parent->ConnCnt == Parent->BackLog)) {
\r
572 ("SockCreate: Socket parent has "
\r
573 "reached its connection limit with %d ConnCnt and %d BackLog\n",
\r
581 Sock = NetAllocateZeroPool (sizeof (SOCKET));
\r
582 if (NULL == Sock) {
\r
584 SOCK_DEBUG_ERROR (("SockCreate: No resource to create a new socket\n"));
\r
588 NetListInit (&Sock->Link);
\r
589 NetListInit (&Sock->ConnectionList);
\r
590 NetListInit (&Sock->ListenTokenList);
\r
591 NetListInit (&Sock->RcvTokenList);
\r
592 NetListInit (&Sock->SndTokenList);
\r
593 NetListInit (&Sock->ProcessingSndTokenList);
\r
595 NET_LOCK_INIT (&(Sock->Lock));
\r
597 Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
\r
598 if (NULL == Sock->SndBuffer.DataQueue) {
\r
599 SOCK_DEBUG_ERROR (("SockCreate: No resource to allocate"
\r
600 " SndBuffer for new socket\n"));
\r
605 Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
\r
606 if (NULL == Sock->RcvBuffer.DataQueue) {
\r
607 SOCK_DEBUG_ERROR (("SockCreate: No resource to allocate "
\r
608 "RcvBuffer for new socket\n"));
\r
613 Sock->Signature = SOCK_SIGNATURE;
\r
615 Sock->Parent = Parent;
\r
616 Sock->BackLog = SockInitData->BackLog;
\r
617 Sock->ProtoHandler = SockInitData->ProtoHandler;
\r
618 Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
\r
619 Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
\r
620 Sock->Type = SockInitData->Type;
\r
621 Sock->DriverBinding = SockInitData->DriverBinding;
\r
622 Sock->State = SockInitData->State;
\r
623 Sock->CreateCallback = SockInitData->CreateCallback;
\r
624 Sock->DestroyCallback = SockInitData->DestroyCallback;
\r
625 Sock->Context = SockInitData->Context;
\r
627 Sock->SockError = EFI_ABORTED;
\r
628 Sock->SndBuffer.LowWater = SOCK_BUFF_LOW_WATER;
\r
629 Sock->RcvBuffer.LowWater = SOCK_BUFF_LOW_WATER;
\r
632 // Install protocol on Sock->SockHandle
\r
635 &(Sock->NetProtocol.TcpProtocol),
\r
636 SockInitData->Protocol,
\r
637 sizeof (EFI_TCP4_PROTOCOL)
\r
641 // copy the protodata into socket
\r
643 NetCopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
\r
645 Status = gBS->InstallMultipleProtocolInterfaces (
\r
647 &gEfiTcp4ProtocolGuid,
\r
648 &(Sock->NetProtocol.TcpProtocol),
\r
652 if (EFI_ERROR (Status)) {
\r
653 SOCK_DEBUG_ERROR (("SockCreate: Install TCP protocol in "
\r
654 "socket failed with %r\n", Status));
\r
659 if (Parent != NULL) {
\r
660 ASSERT (Parent->BackLog > 0);
\r
661 ASSERT (SOCK_IS_LISTENING (Parent));
\r
664 // need to add it into Parent->ConnectionList
\r
665 // if the Parent->ConnCnt < Parent->BackLog
\r
669 SOCK_DEBUG_WARN (("SockCreate: Create a new socket and"
\r
670 "add to parent, now conncnt is %d\n", Parent->ConnCnt));
\r
672 NetListInsertTail (&Parent->ConnectionList, &Sock->ConnectionList);
\r
675 if (Sock->CreateCallback != NULL) {
\r
676 Status = Sock->CreateCallback (Sock, Sock->Context);
\r
677 if (EFI_ERROR (Status)) {
\r
686 if (Sock->SockHandle != NULL) {
\r
687 gBS->UninstallMultipleProtocolInterfaces (
\r
689 &gEfiTcp4ProtocolGuid,
\r
690 &(Sock->NetProtocol.TcpProtocol),
\r
695 if (NULL != Sock->SndBuffer.DataQueue) {
\r
696 NetbufQueFree (Sock->SndBuffer.DataQueue);
\r
699 if (NULL != Sock->RcvBuffer.DataQueue) {
\r
700 NetbufQueFree (Sock->RcvBuffer.DataQueue);
\r
703 NetFreePool (Sock);
\r
712 @param Sock Pointer to the socket.
\r
722 VOID *SockProtocol;
\r
723 EFI_GUID *ProtocolGuid;
\r
726 ASSERT (SOCK_STREAM == Sock->Type);
\r
728 if (Sock->DestroyCallback != NULL) {
\r
729 Sock->DestroyCallback (Sock, Sock->Context);
\r
733 // Flush the completion token buffered
\r
734 // by sock and rcv, snd buffer
\r
736 if (!SOCK_IS_UNCONFIGURED (Sock)) {
\r
738 SockConnFlush (Sock);
\r
739 SockSetState (Sock, SO_CLOSED);
\r
740 Sock->ConfigureState = SO_UNCONFIGURED;
\r
744 // Destory the RcvBuffer Queue and SendBuffer Queue
\r
746 NetbufQueFree (Sock->RcvBuffer.DataQueue);
\r
747 NetbufQueFree (Sock->SndBuffer.DataQueue);
\r
750 // Remove it from parent connection list if needed
\r
752 if (Sock->Parent) {
\r
754 NetListRemoveEntry (&(Sock->ConnectionList));
\r
755 (Sock->Parent->ConnCnt)--;
\r
757 SOCK_DEBUG_WARN (("SockDestory: Delete a unaccepted socket from parent"
\r
758 "now conncnt is %d\n", Sock->Parent->ConnCnt));
\r
760 Sock->Parent = NULL;
\r
764 // Set the protocol guid and driver binding handle
\r
765 // in the light of Sock->SockType
\r
767 ProtocolGuid = &gEfiTcp4ProtocolGuid;
\r
770 // Retrieve the protocol installed on this sock
\r
772 Status = gBS->OpenProtocol (
\r
776 Sock->DriverBinding,
\r
778 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
781 if (EFI_ERROR (Status)) {
\r
783 SOCK_DEBUG_ERROR (("SockDestroy: Open protocol installed "
\r
784 "on socket failed with %r\n", Status));
\r
790 // Uninstall the protocol installed on this sock
\r
791 // in the light of Sock->SockType
\r
793 gBS->UninstallMultipleProtocolInterfaces (
\r
801 NetFreePool (Sock);
\r
809 @param Sock Pointer to the socket.
\r
824 // Clear the flag in this socket
\r
829 // Flush the SndBuffer and RcvBuffer of Sock
\r
831 NetbufQueFlush (Sock->SndBuffer.DataQueue);
\r
832 NetbufQueFlush (Sock->RcvBuffer.DataQueue);
\r
835 // Signal the pending token
\r
837 if (Sock->ConnectionToken != NULL) {
\r
838 SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
\r
839 Sock->ConnectionToken = NULL;
\r
842 if (Sock->CloseToken != NULL) {
\r
843 SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
\r
844 Sock->CloseToken = NULL;
\r
847 SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
\r
848 SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
\r
849 SockFlushPendingToken (Sock, &(Sock->SndTokenList));
\r
850 SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
\r
853 // Destroy the pending connection, if it is a listening socket
\r
855 if (SOCK_IS_LISTENING (Sock)) {
\r
856 while (!NetListIsEmpty (&Sock->ConnectionList)) {
\r
857 Child = NET_LIST_HEAD (
\r
858 &Sock->ConnectionList,
\r
863 SockDestroyChild (Child);
\r
874 Set the state of the socket.
\r
876 @param Sock Pointer to the socket.
\r
877 @param State The new state to be set.
\r
885 IN SOCK_STATE State
\r
888 Sock->State = State;
\r
893 Clone a new socket including its associated protocol control block.
\r
895 @param Sock Pointer to the socket to be cloned.
\r
897 @retval * Pointer to the newly cloned socket. If NULL, error
\r
898 condition occurred.
\r
906 SOCKET *ClonedSock;
\r
907 SOCK_INIT_DATA InitData;
\r
909 InitData.BackLog = Sock->BackLog;
\r
910 InitData.Parent = Sock;
\r
911 InitData.State = Sock->State;
\r
912 InitData.ProtoHandler = Sock->ProtoHandler;
\r
913 InitData.Type = Sock->Type;
\r
914 InitData.RcvBufferSize = Sock->RcvBuffer.HighWater;
\r
915 InitData.SndBufferSize = Sock->SndBuffer.HighWater;
\r
916 InitData.DriverBinding = Sock->DriverBinding;
\r
917 InitData.Protocol = &(Sock->NetProtocol);
\r
918 InitData.CreateCallback = Sock->CreateCallback;
\r
919 InitData.DestroyCallback = Sock->DestroyCallback;
\r
920 InitData.Context = Sock->Context;
\r
921 InitData.ProtoData = Sock->ProtoReserved;
\r
922 InitData.DataSize = sizeof (Sock->ProtoReserved);
\r
924 ClonedSock = SockCreate (&InitData);
\r
926 if (NULL == ClonedSock) {
\r
927 SOCK_DEBUG_ERROR (("SockClone: no resource to create a cloned sock\n"));
\r
931 SockSetState (ClonedSock, SO_CONNECTING);
\r
932 ClonedSock->ConfigureState = Sock->ConfigureState;
\r
939 Called by the low layer protocol to indicate the socket
\r
940 a connection is established. This function just changes
\r
941 the socket's state to SO_CONNECTED and signals the token
\r
942 used for connection establishment.
\r
944 @param Sock Pointer to the socket associated with the
\r
945 established connection.
\r
951 SockConnEstablished (
\r
956 ASSERT (SO_CONNECTING == Sock->State);
\r
958 SockSetState (Sock, SO_CONNECTED);
\r
960 if (NULL == Sock->Parent) {
\r
961 SockWakeConnToken (Sock);
\r
963 SockWakeListenToken (Sock);
\r
971 Called by the low layer protocol to indicate the connection
\r
972 is closed. This function flushes the socket, sets the state
\r
973 to SO_CLOSED and signals the close token.
\r
975 @param Sock Pointer to the socket associated with the closed
\r
986 if (Sock->CloseToken) {
\r
987 SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
\r
988 Sock->CloseToken = NULL;
\r
991 SockConnFlush (Sock);
\r
992 SockSetState (Sock, SO_CLOSED);
\r
994 if (Sock->Parent != NULL) {
\r
995 SockDestroyChild (Sock);
\r
1002 Called by low layer protocol to indicate that some
\r
1003 data is sent or processed. This function trims the
\r
1004 sent data in the socket send buffer, signals the
\r
1005 data token if proper
\r
1007 @param Sock Pointer to the socket.
\r
1008 @param Count The length of the data processed or sent, in bytes.
\r
1019 SOCK_TOKEN *SockToken;
\r
1020 SOCK_COMPLETION_TOKEN *SndToken;
\r
1022 ASSERT (!NetListIsEmpty (&Sock->ProcessingSndTokenList));
\r
1023 ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
\r
1025 NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
\r
1028 // To check if we can signal some snd token in this socket
\r
1030 while (Count > 0) {
\r
1031 SockToken = NET_LIST_HEAD (
\r
1032 &(Sock->ProcessingSndTokenList),
\r
1037 SndToken = SockToken->Token;
\r
1039 if (SockToken->RemainDataLen <= Count) {
\r
1041 NetListRemoveEntry (&(SockToken->TokenList));
\r
1042 SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
\r
1043 Count -= SockToken->RemainDataLen;
\r
1044 NetFreePool (SockToken);
\r
1047 SockToken->RemainDataLen -= Count;
\r
1053 // to judge if we can process some send token in
\r
1054 // Sock->SndTokenList, if so process those send token
\r
1056 SockProcessSndToken (Sock);
\r
1062 Called by the low layer protocol to copy some data in socket send
\r
1063 buffer starting from the specific offset to a buffer provided by
\r
1066 @param Sock Pointer to the socket.
\r
1067 @param Offset The start point of the data to be copied.
\r
1068 @param Len The length of the data to be copied.
\r
1069 @param Dest Pointer to the destination to copy the data.
\r
1071 @return The data size copied.
\r
1075 SockGetDataToSend (
\r
1082 ASSERT (Sock && SOCK_STREAM == Sock->Type);
\r
1084 return NetbufQueCopy (
\r
1085 Sock->SndBuffer.DataQueue,
\r
1094 Called by the low layer protocol to deliver received data
\r
1095 to socket layer. This function will append the data to the
\r
1096 socket receive buffer, set ther urgent data length and then
\r
1097 check if any receive token can be signaled.
\r
1099 @param Sock Pointer to the socket.
\r
1100 @param NetBuffer Pointer to the buffer that contains the received
\r
1102 @param UrgLen The length of the urgent data in the received data.
\r
1110 IN NET_BUF *NetBuffer,
\r
1114 ASSERT (Sock && Sock->RcvBuffer.DataQueue &&
\r
1115 UrgLen <= NetBuffer->TotalSize);
\r
1117 NET_GET_REF (NetBuffer);
\r
1119 ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
\r
1121 NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
\r
1123 SockWakeRcvToken (Sock);
\r
1129 Get the length of the free space of the specific socket buffer.
\r
1131 @param Sock Pointer to the socket.
\r
1132 @param Which Flag to indicate which socket buffer to check,
\r
1133 either send buffer or receive buffer.
\r
1135 @return The length of the free space, in bytes.
\r
1139 SockGetFreeSpace (
\r
1145 SOCK_BUFFER *SockBuffer;
\r
1147 ASSERT (Sock && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
\r
1149 if (SOCK_SND_BUF == Which) {
\r
1150 SockBuffer = &(Sock->SndBuffer);
\r
1152 SockBuffer = &(Sock->RcvBuffer);
\r
1155 BufferCC = (SockBuffer->DataQueue)->BufSize;
\r
1157 if (BufferCC >= SockBuffer->HighWater) {
\r
1162 return SockBuffer->HighWater - BufferCC;
\r
1167 Signal the receive token with the specific error or
\r
1168 set socket error code after error is received.
\r
1170 @param Sock Pointer to the socket.
\r
1171 @param Error The error code received.
\r
1179 IN EFI_STATUS Error
\r
1182 SOCK_TOKEN *SockToken;
\r
1184 if (!NetListIsEmpty (&Sock->RcvTokenList)) {
\r
1186 SockToken = NET_LIST_HEAD (
\r
1187 &Sock->RcvTokenList,
\r
1192 NetListRemoveEntry (&SockToken->TokenList);
\r
1194 SIGNAL_TOKEN (SockToken->Token, Error);
\r
1196 NetFreePool (SockToken);
\r
1199 SOCK_ERROR (Sock, Error);
\r
1205 Called by the low layer protocol to indicate that there
\r
1206 will be no more data from the communication peer. This
\r
1207 function set the socket's state to SO_NO_MORE_DATA and
\r
1208 signal all queued IO tokens with the error status
\r
1209 EFI_CONNECTION_FIN.
\r
1211 @param Sock Pointer to the socket.
\r
1223 SOCK_NO_MORE_DATA (Sock);
\r
1225 if (!NetListIsEmpty (&Sock->RcvTokenList)) {
\r
1227 ASSERT (0 == GET_RCV_DATASIZE (Sock));
\r
1229 Err = Sock->SockError;
\r
1231 SOCK_ERROR (Sock, EFI_CONNECTION_FIN);
\r
1233 SockFlushPendingToken (Sock, &Sock->RcvTokenList);
\r
1235 SOCK_ERROR (Sock, Err);
\r
1243 Get the first buffer block in the specific socket buffer.
\r
1245 @param Sockbuf Pointer to the socket buffer.
\r
1247 @return Pointer to the first buffer in the queue. NULL if the queue is empty.
\r
1252 IN SOCK_BUFFER *Sockbuf
\r
1255 NET_LIST_ENTRY *NetbufList;
\r
1257 NetbufList = &(Sockbuf->DataQueue->BufList);
\r
1259 if (NetListIsEmpty (NetbufList)) {
\r
1263 return NET_LIST_HEAD (NetbufList, NET_BUF, List);
\r
1268 Get the next buffer block in the specific socket buffer.
\r
1270 @param Sockbuf Pointer to the socket buffer.
\r
1271 @param SockEntry Pointer to the buffer block prior to the required
\r
1274 @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is the tail or head entry.
\r
1279 IN SOCK_BUFFER *Sockbuf,
\r
1280 IN NET_BUF *SockEntry
\r
1283 NET_LIST_ENTRY *NetbufList;
\r
1285 NetbufList = &(Sockbuf->DataQueue->BufList);
\r
1287 if ((SockEntry->List.ForwardLink == NetbufList) ||
\r
1288 (SockEntry->List.BackLink == &SockEntry->List) ||
\r
1289 (SockEntry->List.ForwardLink == &SockEntry->List)
\r
1295 return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List);
\r