1 /** @file
2   Implementation of the Socket.
3 
4   Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 #include "SockImpl.h"
11 
12 /**
13   Get the first buffer block in the specific socket buffer.
14 
15   @param[in]  Sockbuf               Pointer to the socket buffer.
16 
17   @return Pointer to the first buffer in the queue. NULL if the queue is empty.
18 
19 **/
20 NET_BUF *
SockBufFirst(IN SOCK_BUFFER * Sockbuf)21 SockBufFirst (
22   IN SOCK_BUFFER *Sockbuf
23   )
24 {
25   LIST_ENTRY  *NetbufList;
26 
27   NetbufList = &(Sockbuf->DataQueue->BufList);
28 
29   if (IsListEmpty (NetbufList)) {
30     return NULL;
31   }
32 
33   return NET_LIST_HEAD (NetbufList, NET_BUF, List);
34 }
35 
36 /**
37   Get the next buffer block in the specific socket buffer.
38 
39   @param[in]  Sockbuf     Pointer to the socket buffer.
40   @param[in]  SockEntry   Pointer to the buffer block prior to the required one.
41 
42   @return Pointer to the buffer block next to SockEntry. NULL if SockEntry is
43           the tail or head entry.
44 
45 **/
46 NET_BUF *
SockBufNext(IN SOCK_BUFFER * Sockbuf,IN NET_BUF * SockEntry)47 SockBufNext (
48   IN SOCK_BUFFER *Sockbuf,
49   IN NET_BUF     *SockEntry
50   )
51 {
52   LIST_ENTRY  *NetbufList;
53 
54   NetbufList = &(Sockbuf->DataQueue->BufList);
55 
56   if ((SockEntry->List.ForwardLink == NetbufList) ||
57       (SockEntry->List.BackLink == &SockEntry->List) ||
58       (SockEntry->List.ForwardLink == &SockEntry->List)
59       ) {
60 
61     return NULL;
62   }
63 
64   return NET_LIST_USER_STRUCT (SockEntry->List.ForwardLink, NET_BUF, List);
65 }
66 
67 /**
68   User provided callback function for NetbufFromExt.
69 
70   @param[in] Arg      The Arg parameter forwarded by NetbufFromExt(). Ignored.
71 
72 **/
73 VOID
74 EFIAPI
SockFreeFoo(IN VOID * Arg)75 SockFreeFoo (
76   IN VOID      *Arg
77   )
78 {
79   return;
80 }
81 
82 /**
83   Get the length of the data that can be retrieved from the socket
84   receive buffer.
85 
86   @param[in]  SockBuffer            Pointer to the socket receive buffer.
87   @param[out] IsUrg                 Pointer to a BOOLEAN variable.
88                                     If TRUE the data is OOB.
89   @param[in]  BufLen                The maximum length of the data buffer to
90                                     store the received data in the socket layer.
91 
92   @return The length of the data can be retrieved.
93 
94 **/
95 UINT32
SockTcpDataToRcv(IN SOCK_BUFFER * SockBuffer,OUT BOOLEAN * IsUrg,IN UINT32 BufLen)96 SockTcpDataToRcv (
97   IN  SOCK_BUFFER   *SockBuffer,
98   OUT BOOLEAN       *IsUrg,
99   IN  UINT32        BufLen
100   )
101 {
102   NET_BUF       *RcvBufEntry;
103   UINT32        DataLen;
104   TCP_RSV_DATA  *TcpRsvData;
105   BOOLEAN       Urg;
106 
107   ASSERT ((SockBuffer != NULL) && (IsUrg != NULL) && (BufLen > 0));
108 
109   //
110   // Get the first socket receive buffer
111   //
112   RcvBufEntry = SockBufFirst (SockBuffer);
113   ASSERT (RcvBufEntry != NULL);
114 
115   TcpRsvData  = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
116 
117   //
118   // Check whether the receive data is out of bound. If yes, calculate the maximum
119   // allowed length of the urgent data and output it.
120   //
121   *IsUrg      = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
122 
123   if (*IsUrg && (TcpRsvData->UrgLen < RcvBufEntry->TotalSize)) {
124 
125     DataLen = MIN (TcpRsvData->UrgLen, BufLen);
126 
127     if (DataLen < TcpRsvData->UrgLen) {
128       TcpRsvData->UrgLen = TcpRsvData->UrgLen - DataLen;
129     } else {
130       TcpRsvData->UrgLen = 0;
131     }
132 
133     return DataLen;
134 
135   }
136 
137   //
138   // Process the next socket receive buffer to get the maximum allowed length
139   // of the received data.
140   //
141   DataLen     = RcvBufEntry->TotalSize;
142 
143   RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
144 
145   while ((BufLen > DataLen) && (RcvBufEntry != NULL)) {
146 
147     TcpRsvData  = (TCP_RSV_DATA *) RcvBufEntry->ProtoData;
148 
149     Urg         = (BOOLEAN) ((TcpRsvData->UrgLen > 0) ? TRUE : FALSE);
150 
151     if (*IsUrg != Urg) {
152       break;
153     }
154 
155     if (*IsUrg && TcpRsvData->UrgLen < RcvBufEntry->TotalSize) {
156 
157       if (TcpRsvData->UrgLen + DataLen < BufLen) {
158         TcpRsvData->UrgLen = 0;
159       } else {
160         TcpRsvData->UrgLen = TcpRsvData->UrgLen - (BufLen - DataLen);
161       }
162 
163       return MIN (TcpRsvData->UrgLen + DataLen, BufLen);
164 
165     }
166 
167     DataLen += RcvBufEntry->TotalSize;
168 
169     RcvBufEntry = SockBufNext (SockBuffer, RcvBufEntry);
170   }
171 
172   DataLen = MIN (BufLen, DataLen);
173   return DataLen;
174 }
175 
176 /**
177   Copy data from socket buffer to an application provided receive buffer.
178 
179   @param[in]  Sock        Pointer to the socket.
180   @param[in]  TcpRxData   Pointer to the application provided receive buffer.
181   @param[in]  RcvdBytes   The maximum length of the data can be copied.
182   @param[in]  IsUrg       If TRUE the data is Out of Bound, FALSE the data is normal.
183 
184 **/
185 VOID
SockSetTcpRxData(IN SOCKET * Sock,IN VOID * TcpRxData,IN UINT32 RcvdBytes,IN BOOLEAN IsUrg)186 SockSetTcpRxData (
187   IN SOCKET     *Sock,
188   IN VOID       *TcpRxData,
189   IN UINT32     RcvdBytes,
190   IN BOOLEAN    IsUrg
191   )
192 {
193   UINT32                  Index;
194   UINT32                  CopyBytes;
195   UINT32                  OffSet;
196   EFI_TCP4_RECEIVE_DATA   *RxData;
197   EFI_TCP4_FRAGMENT_DATA  *Fragment;
198 
199   RxData  = (EFI_TCP4_RECEIVE_DATA *) TcpRxData;
200 
201   OffSet  = 0;
202 
203   ASSERT (RxData->DataLength >= RcvdBytes);
204 
205   RxData->DataLength  = RcvdBytes;
206   RxData->UrgentFlag  = IsUrg;
207 
208   //
209   // Copy the CopyBytes data from socket receive buffer to RxData.
210   //
211   for (Index = 0; (Index < RxData->FragmentCount) && (RcvdBytes > 0); Index++) {
212 
213     Fragment  = &RxData->FragmentTable[Index];
214     CopyBytes = MIN ((UINT32) (Fragment->FragmentLength), RcvdBytes);
215 
216     NetbufQueCopy (
217       Sock->RcvBuffer.DataQueue,
218       OffSet,
219       CopyBytes,
220       Fragment->FragmentBuffer
221       );
222 
223     Fragment->FragmentLength = CopyBytes;
224     RcvdBytes -= CopyBytes;
225     OffSet += CopyBytes;
226   }
227 }
228 
229 /**
230   Process the send token.
231 
232   @param[in, out]  Sock                  Pointer to the socket.
233 
234 **/
235 VOID
SockProcessSndToken(IN OUT SOCKET * Sock)236 SockProcessSndToken (
237   IN OUT SOCKET *Sock
238   )
239 {
240   UINT32                  FreeSpace;
241   SOCK_TOKEN              *SockToken;
242   UINT32                  DataLen;
243   SOCK_IO_TOKEN           *SndToken;
244   EFI_TCP4_TRANSMIT_DATA  *TxData;
245   EFI_STATUS              Status;
246 
247   ASSERT ((Sock != NULL) && (SockStream == Sock->Type));
248 
249   FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
250 
251   //
252   // to determine if process a send token using
253   // socket layer flow control policy
254   //
255   while ((FreeSpace >= Sock->SndBuffer.LowWater) && !IsListEmpty (&Sock->SndTokenList)) {
256 
257     SockToken = NET_LIST_HEAD (
258                   &(Sock->SndTokenList),
259                   SOCK_TOKEN,
260                   TokenList
261                   );
262 
263     //
264     // process this token
265     //
266     RemoveEntryList (&(SockToken->TokenList));
267     InsertTailList (
268       &(Sock->ProcessingSndTokenList),
269       &(SockToken->TokenList)
270       );
271 
272     //
273     // Process it in the light of SockType
274     //
275     SndToken  = (SOCK_IO_TOKEN *) SockToken->Token;
276     TxData    = SndToken->Packet.TxData;
277 
278     DataLen   = TxData->DataLength;
279     Status    = SockProcessTcpSndData (Sock, TxData);
280 
281     if (EFI_ERROR (Status)) {
282       goto OnError;
283     }
284 
285     if (DataLen >= FreeSpace) {
286       FreeSpace = 0;
287 
288     } else {
289       FreeSpace -= DataLen;
290 
291     }
292   }
293 
294   return;
295 
296 OnError:
297 
298   RemoveEntryList (&SockToken->TokenList);
299   SIGNAL_TOKEN (SockToken->Token, Status);
300   FreePool (SockToken);
301 }
302 
303 /**
304   Get received data from the socket layer to the receive token.
305 
306   @param[in, out]  Sock       Pointer to the socket.
307   @param[in, out]  RcvToken   Pointer to the application provided receive token.
308 
309   @return The length of data received in this token.
310 
311 **/
312 UINT32
SockProcessRcvToken(IN OUT SOCKET * Sock,IN OUT SOCK_IO_TOKEN * RcvToken)313 SockProcessRcvToken (
314   IN OUT SOCKET        *Sock,
315   IN OUT SOCK_IO_TOKEN *RcvToken
316   )
317 {
318   UINT32                TokenRcvdBytes;
319   EFI_TCP4_RECEIVE_DATA *RxData;
320   BOOLEAN               IsUrg;
321 
322   ASSERT (Sock != NULL);
323 
324   ASSERT (SockStream == Sock->Type);
325 
326   RxData = RcvToken->Packet.RxData;
327 
328   TokenRcvdBytes = SockTcpDataToRcv (
329                      &Sock->RcvBuffer,
330                      &IsUrg,
331                      RxData->DataLength
332                      );
333 
334   //
335   // Copy data from RcvBuffer of socket to user
336   // provided RxData and set the fields in TCP RxData
337   //
338   SockSetTcpRxData (Sock, RxData, TokenRcvdBytes, IsUrg);
339 
340   NetbufQueTrim (Sock->RcvBuffer.DataQueue, TokenRcvdBytes);
341   SIGNAL_TOKEN (&(RcvToken->Token), EFI_SUCCESS);
342 
343   return TokenRcvdBytes;
344 }
345 
346 /**
347   Process the TCP send data, buffer the tcp txdata, and append
348   the buffer to socket send buffer, then try to send it.
349 
350   @param[in]  Sock              Pointer to the socket.
351   @param[in]  TcpTxData         Pointer to the application provided send buffer.
352 
353   @retval EFI_SUCCESS           The operation completed successfully.
354   @retval EFI_OUT_OF_RESOURCES  Failed due to resource limits.
355 
356 **/
357 EFI_STATUS
SockProcessTcpSndData(IN SOCKET * Sock,IN VOID * TcpTxData)358 SockProcessTcpSndData (
359   IN SOCKET   *Sock,
360   IN VOID     *TcpTxData
361   )
362 {
363   NET_BUF                 *SndData;
364   EFI_STATUS              Status;
365   EFI_TCP4_TRANSMIT_DATA  *TxData;
366 
367   TxData = (EFI_TCP4_TRANSMIT_DATA *) TcpTxData;
368 
369   //
370   // transform this TxData into a NET_BUFFER
371   // and insert it into Sock->SndBuffer
372   //
373   SndData = NetbufFromExt (
374               (NET_FRAGMENT *) TxData->FragmentTable,
375               TxData->FragmentCount,
376               0,
377               0,
378               SockFreeFoo,
379               NULL
380               );
381 
382   if (NULL == SndData) {
383     DEBUG (
384       (EFI_D_ERROR,
385       "SockKProcessSndData: Failed to call NetBufferFromExt\n")
386       );
387 
388     return EFI_OUT_OF_RESOURCES;
389   }
390 
391   NetbufQueAppend (Sock->SndBuffer.DataQueue, SndData);
392 
393   //
394   // notify the low layer protocol to handle this send token
395   //
396   if (TxData->Urgent) {
397     Status = Sock->ProtoHandler (Sock, SOCK_SNDURG, NULL);
398 
399     if (EFI_ERROR (Status)) {
400       return Status;
401     }
402   }
403 
404   if (TxData->Push) {
405     Status = Sock->ProtoHandler (Sock, SOCK_SNDPUSH, NULL);
406 
407     if (EFI_ERROR (Status)) {
408       return Status;
409     }
410   }
411 
412   //
413   // low layer protocol should really handle the sending
414   // process when catching SOCK_SND request
415   //
416   Status = Sock->ProtoHandler (Sock, SOCK_SND, NULL);
417 
418   if (EFI_ERROR (Status)) {
419     return Status;
420   }
421 
422   return EFI_SUCCESS;
423 }
424 
425 /**
426   Flush the tokens in the specific token list.
427 
428   @param[in]       Sock                  Pointer to the socket.
429   @param[in, out]  PendingTokenList      Pointer to the token list to be flushed.
430 
431 **/
432 VOID
SockFlushPendingToken(IN SOCKET * Sock,IN OUT LIST_ENTRY * PendingTokenList)433 SockFlushPendingToken (
434   IN     SOCKET         *Sock,
435   IN OUT LIST_ENTRY     *PendingTokenList
436   )
437 {
438   SOCK_TOKEN            *SockToken;
439   SOCK_COMPLETION_TOKEN *Token;
440 
441   ASSERT ((Sock != NULL) && (PendingTokenList != NULL));
442 
443   while (!IsListEmpty (PendingTokenList)) {
444     SockToken = NET_LIST_HEAD (
445                   PendingTokenList,
446                   SOCK_TOKEN,
447                   TokenList
448                   );
449 
450     Token = SockToken->Token;
451     SIGNAL_TOKEN (Token, Sock->SockError);
452 
453     RemoveEntryList (&(SockToken->TokenList));
454     FreePool (SockToken);
455   }
456 }
457 
458 /**
459   Wake up the connection token while the connection is successfully established,
460   then try to process any pending send token.
461 
462   @param[in, out]  Sock                  Pointer to the socket.
463 
464 **/
465 VOID
SockWakeConnToken(IN OUT SOCKET * Sock)466 SockWakeConnToken (
467   IN OUT SOCKET *Sock
468   )
469 {
470   ASSERT (Sock->ConnectionToken != NULL);
471 
472   SIGNAL_TOKEN (Sock->ConnectionToken, EFI_SUCCESS);
473   Sock->ConnectionToken = NULL;
474 
475   //
476   // check to see if some pending send token existed?
477   //
478   SockProcessSndToken (Sock);
479 }
480 
481 /**
482   Wake up the listen token while the connection is established successfully.
483 
484   @param[in, out]  Sock                  Pointer to the socket.
485 
486 **/
487 VOID
SockWakeListenToken(IN OUT SOCKET * Sock)488 SockWakeListenToken (
489   IN OUT SOCKET *Sock
490   )
491 {
492   SOCKET                *Parent;
493   SOCK_TOKEN            *SockToken;
494   EFI_TCP4_LISTEN_TOKEN *ListenToken;
495 
496   Parent = Sock->Parent;
497 
498   ASSERT ((Parent != NULL) && SOCK_IS_LISTENING (Parent) && SOCK_IS_CONNECTED (Sock));
499 
500   if (!IsListEmpty (&Parent->ListenTokenList)) {
501     SockToken = NET_LIST_HEAD (
502                   &Parent->ListenTokenList,
503                   SOCK_TOKEN,
504                   TokenList
505                   );
506 
507     ListenToken                 = (EFI_TCP4_LISTEN_TOKEN *) SockToken->Token;
508     ListenToken->NewChildHandle = Sock->SockHandle;
509 
510     SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
511 
512     RemoveEntryList (&SockToken->TokenList);
513     FreePool (SockToken);
514 
515     RemoveEntryList (&Sock->ConnectionList);
516 
517     Parent->ConnCnt--;
518     DEBUG (
519       (EFI_D_NET,
520       "SockWakeListenToken: accept a socket, now conncnt is %d",
521       Parent->ConnCnt)
522       );
523 
524     Sock->Parent = NULL;
525   }
526 }
527 
528 /**
529   Wake up the receive token while some data is received.
530 
531   @param[in, out]  Sock                  Pointer to the socket.
532 
533 **/
534 VOID
SockWakeRcvToken(IN OUT SOCKET * Sock)535 SockWakeRcvToken (
536   IN OUT SOCKET *Sock
537   )
538 {
539   UINT32        RcvdBytes;
540   UINT32        TokenRcvdBytes;
541   SOCK_TOKEN    *SockToken;
542   SOCK_IO_TOKEN *RcvToken;
543 
544   ASSERT (Sock->RcvBuffer.DataQueue != NULL);
545 
546   RcvdBytes = (Sock->RcvBuffer.DataQueue)->BufSize;
547 
548   ASSERT (RcvdBytes > 0);
549 
550   while (RcvdBytes > 0 && !IsListEmpty (&Sock->RcvTokenList)) {
551 
552     SockToken = NET_LIST_HEAD (
553                   &Sock->RcvTokenList,
554                   SOCK_TOKEN,
555                   TokenList
556                   );
557 
558     RcvToken        = (SOCK_IO_TOKEN *) SockToken->Token;
559     TokenRcvdBytes  = SockProcessRcvToken (Sock, RcvToken);
560 
561     if (0 == TokenRcvdBytes) {
562       return ;
563     }
564 
565     RemoveEntryList (&(SockToken->TokenList));
566     FreePool (SockToken);
567     RcvdBytes -= TokenRcvdBytes;
568   }
569 }
570 
571 /**
572   Cancel the tokens in the specific token list.
573 
574   @param[in]       Token                 Pointer to the Token. If NULL, all tokens
575                                          in SpecifiedTokenList will be canceled.
576   @param[in, out]  SpecifiedTokenList    Pointer to the token list to be checked.
577 
578   @retval EFI_SUCCESS          Cancel the tokens in the specific token listsuccessfully.
579   @retval EFI_NOT_FOUND        The Token is not found in SpecifiedTokenList.
580 
581 **/
582 EFI_STATUS
SockCancelToken(IN SOCK_COMPLETION_TOKEN * Token,IN OUT LIST_ENTRY * SpecifiedTokenList)583 SockCancelToken (
584   IN     SOCK_COMPLETION_TOKEN  *Token,
585   IN OUT LIST_ENTRY             *SpecifiedTokenList
586   )
587 {
588   EFI_STATUS     Status;
589   LIST_ENTRY     *Entry;
590   SOCK_TOKEN     *SockToken;
591 
592   Status    = EFI_SUCCESS;
593   Entry     = NULL;
594   SockToken = NULL;
595 
596   if (IsListEmpty (SpecifiedTokenList) && Token != NULL) {
597     return EFI_NOT_FOUND;
598   }
599 
600   //
601   // Iterate through the SpecifiedTokenList.
602   //
603   Entry = SpecifiedTokenList->ForwardLink;
604   while (Entry != SpecifiedTokenList) {
605     SockToken = NET_LIST_USER_STRUCT (Entry, SOCK_TOKEN, TokenList);
606 
607     if (Token == NULL) {
608       SIGNAL_TOKEN (SockToken->Token, EFI_ABORTED);
609       RemoveEntryList (&SockToken->TokenList);
610       FreePool (SockToken);
611 
612       Entry = SpecifiedTokenList->ForwardLink;
613       Status = EFI_SUCCESS;
614     } else {
615       if (Token == (VOID *) SockToken->Token) {
616         SIGNAL_TOKEN (Token, EFI_ABORTED);
617         RemoveEntryList (&(SockToken->TokenList));
618         FreePool (SockToken);
619 
620         return EFI_SUCCESS;
621       }
622 
623       Status = EFI_NOT_FOUND;
624 
625       Entry = Entry->ForwardLink;
626     }
627   }
628 
629   ASSERT (IsListEmpty (SpecifiedTokenList) || Token != NULL);
630 
631   return Status;
632 }
633 
634 /**
635   Create a socket with initial data SockInitData.
636 
637   @param[in]  SockInitData          Pointer to the initial data of the socket.
638 
639   @return Pointer to the newly created socket, return NULL when an exception occurs.
640 
641 **/
642 SOCKET *
SockCreate(IN SOCK_INIT_DATA * SockInitData)643 SockCreate (
644   IN SOCK_INIT_DATA *SockInitData
645   )
646 {
647   SOCKET      *Sock;
648   SOCKET      *Parent;
649   EFI_STATUS  Status;
650   EFI_GUID    *TcpProtocolGuid;
651   UINTN       ProtocolLength;
652 
653   ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL));
654   ASSERT (SockInitData->Type == SockStream);
655   ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
656 
657   if (SockInitData->IpVersion == IP_VERSION_4) {
658     TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
659     ProtocolLength  = sizeof (EFI_TCP4_PROTOCOL);
660   } else {
661     TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
662     ProtocolLength  = sizeof (EFI_TCP6_PROTOCOL);
663   }
664 
665 
666   Parent = SockInitData->Parent;
667 
668   if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {
669     DEBUG (
670       (EFI_D_ERROR,
671       "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n",
672       Parent->ConnCnt,
673       Parent->BackLog)
674       );
675 
676     return NULL;
677   }
678 
679   Sock = AllocateZeroPool (sizeof (SOCKET));
680   if (NULL == Sock) {
681 
682     DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));
683     return NULL;
684   }
685 
686   InitializeListHead (&Sock->Link);
687   InitializeListHead (&Sock->ConnectionList);
688   InitializeListHead (&Sock->ListenTokenList);
689   InitializeListHead (&Sock->RcvTokenList);
690   InitializeListHead (&Sock->SndTokenList);
691   InitializeListHead (&Sock->ProcessingSndTokenList);
692 
693   EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);
694 
695   Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
696   if (NULL == Sock->SndBuffer.DataQueue) {
697     DEBUG (
698       (EFI_D_ERROR,
699       "SockCreate: No resource to allocate SndBuffer for new socket\n")
700       );
701 
702     goto OnError;
703   }
704 
705   Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
706   if (NULL == Sock->RcvBuffer.DataQueue) {
707     DEBUG (
708       (EFI_D_ERROR,
709       "SockCreate: No resource to allocate RcvBuffer for new socket\n")
710       );
711 
712     goto OnError;
713   }
714 
715   Sock->Signature           = SOCK_SIGNATURE;
716 
717   Sock->Parent              = Parent;
718   Sock->BackLog             = SockInitData->BackLog;
719   Sock->ProtoHandler        = SockInitData->ProtoHandler;
720   Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
721   Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
722   Sock->Type                = SockInitData->Type;
723   Sock->DriverBinding       = SockInitData->DriverBinding;
724   Sock->State               = SockInitData->State;
725   Sock->CreateCallback      = SockInitData->CreateCallback;
726   Sock->DestroyCallback     = SockInitData->DestroyCallback;
727   Sock->Context             = SockInitData->Context;
728 
729   Sock->SockError           = EFI_ABORTED;
730   Sock->SndBuffer.LowWater  = SOCK_BUFF_LOW_WATER;
731   Sock->RcvBuffer.LowWater  = SOCK_BUFF_LOW_WATER;
732 
733   Sock->IpVersion           = SockInitData->IpVersion;
734 
735   //
736   // Install protocol on Sock->SockHandle
737   //
738   CopyMem (&Sock->NetProtocol, SockInitData->Protocol, ProtocolLength);
739 
740   //
741   // copy the protodata into socket
742   //
743   CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
744 
745   Status = gBS->InstallMultipleProtocolInterfaces (
746                   &Sock->SockHandle,
747                   TcpProtocolGuid,
748                   &Sock->NetProtocol,
749                   NULL
750                   );
751 
752   if (EFI_ERROR (Status)) {
753     DEBUG (
754       (EFI_D_ERROR,
755       "SockCreate: Install TCP protocol in socket failed with %r\n",
756       Status)
757       );
758 
759     goto OnError;
760   }
761 
762   if (Parent != NULL) {
763     ASSERT (Parent->BackLog > 0);
764     ASSERT (SOCK_IS_LISTENING (Parent));
765 
766     //
767     // need to add it into Parent->ConnectionList
768     // if the Parent->ConnCnt < Parent->BackLog
769     //
770     Parent->ConnCnt++;
771 
772     DEBUG (
773       (EFI_D_NET,
774       "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
775       Parent->ConnCnt)
776       );
777 
778     InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);
779   }
780 
781   if (Sock->CreateCallback != NULL) {
782     Status = Sock->CreateCallback (Sock, Sock->Context);
783     if (EFI_ERROR (Status)) {
784       goto OnError;
785     }
786   }
787 
788   return Sock;
789 
790 OnError:
791 
792   if (Sock->SockHandle != NULL) {
793     gBS->UninstallMultipleProtocolInterfaces (
794            Sock->SockHandle,
795            TcpProtocolGuid,
796            &Sock->NetProtocol,
797            NULL
798            );
799   }
800 
801   if (NULL != Sock->SndBuffer.DataQueue) {
802     NetbufQueFree (Sock->SndBuffer.DataQueue);
803   }
804 
805   if (NULL != Sock->RcvBuffer.DataQueue) {
806     NetbufQueFree (Sock->RcvBuffer.DataQueue);
807   }
808 
809   FreePool (Sock);
810 
811   return NULL;
812 }
813 
814 /**
815   Destroy a socket.
816 
817   @param[in, out]  Sock                  Pointer to the socket.
818 
819 **/
820 VOID
SockDestroy(IN OUT SOCKET * Sock)821 SockDestroy (
822   IN OUT SOCKET *Sock
823   )
824 {
825   ASSERT (SockStream == Sock->Type);
826 
827   //
828   // Flush the completion token buffered
829   // by sock and rcv, snd buffer
830   //
831   if (!SOCK_IS_UNCONFIGURED (Sock)) {
832 
833     SockConnFlush (Sock);
834     SockSetState (Sock, SO_CLOSED);
835     Sock->ConfigureState = SO_UNCONFIGURED;
836 
837   }
838   //
839   // Destroy the RcvBuffer Queue and SendBuffer Queue
840   //
841   NetbufQueFree (Sock->RcvBuffer.DataQueue);
842   NetbufQueFree (Sock->SndBuffer.DataQueue);
843 
844   //
845   // Remove it from parent connection list if needed
846   //
847   if (Sock->Parent != NULL) {
848 
849     RemoveEntryList (&(Sock->ConnectionList));
850     (Sock->Parent->ConnCnt)--;
851 
852     DEBUG (
853       (EFI_D_WARN,
854       "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n",
855       Sock->Parent->ConnCnt)
856       );
857 
858     Sock->Parent = NULL;
859   }
860 
861   FreePool (Sock);
862 }
863 
864 /**
865   Flush the sndBuffer and rcvBuffer of socket.
866 
867   @param[in, out]  Sock                  Pointer to the socket.
868 
869 **/
870 VOID
SockConnFlush(IN OUT SOCKET * Sock)871 SockConnFlush (
872   IN OUT SOCKET *Sock
873   )
874 {
875   SOCKET  *Child;
876 
877   ASSERT (Sock != NULL);
878 
879   //
880   // Clear the flag in this socket
881   //
882   Sock->Flag = 0;
883 
884   //
885   // Flush the SndBuffer and RcvBuffer of Sock
886   //
887   NetbufQueFlush (Sock->SndBuffer.DataQueue);
888   NetbufQueFlush (Sock->RcvBuffer.DataQueue);
889 
890   //
891   // Signal the pending token
892   //
893   if (Sock->ConnectionToken != NULL) {
894     SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
895     Sock->ConnectionToken = NULL;
896   }
897 
898   if (Sock->CloseToken != NULL) {
899     SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
900     Sock->CloseToken = NULL;
901   }
902 
903   SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
904   SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
905   SockFlushPendingToken (Sock, &(Sock->SndTokenList));
906   SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
907 
908   //
909   // Destroy the pending connection, if it is a listening socket
910   //
911   if (SOCK_IS_LISTENING (Sock)) {
912     while (!IsListEmpty (&Sock->ConnectionList)) {
913       Child = NET_LIST_HEAD (
914                 &Sock->ConnectionList,
915                 SOCKET,
916                 ConnectionList
917                 );
918 
919       SockDestroyChild (Child);
920     }
921 
922     Sock->ConnCnt = 0;
923   }
924 
925 }
926 
927 /**
928   Set the state of the socket.
929 
930   @param[in, out]  Sock                  Pointer to the socket.
931   @param[in]       State                 The new socket state to be set.
932 
933 **/
934 VOID
SockSetState(IN OUT SOCKET * Sock,IN UINT8 State)935 SockSetState (
936   IN OUT SOCKET     *Sock,
937   IN     UINT8      State
938   )
939 {
940   Sock->State = State;
941 }
942 
943 /**
944   Clone a new socket, including its associated protocol control block.
945 
946   @param[in]  Sock                  Pointer to the socket to be cloned.
947 
948   @return Pointer to the newly cloned socket. If NULL, an error condition occurred.
949 
950 **/
951 SOCKET *
SockClone(IN SOCKET * Sock)952 SockClone (
953   IN SOCKET *Sock
954   )
955 {
956   SOCKET          *ClonedSock;
957   SOCK_INIT_DATA  InitData;
958 
959   InitData.BackLog         = Sock->BackLog;
960   InitData.Parent          = Sock;
961   InitData.State           = Sock->State;
962   InitData.ProtoHandler    = Sock->ProtoHandler;
963   InitData.Type            = Sock->Type;
964   InitData.RcvBufferSize   = Sock->RcvBuffer.HighWater;
965   InitData.SndBufferSize   = Sock->SndBuffer.HighWater;
966   InitData.DriverBinding   = Sock->DriverBinding;
967   InitData.IpVersion       = Sock->IpVersion;
968   InitData.Protocol        = &(Sock->NetProtocol);
969   InitData.CreateCallback  = Sock->CreateCallback;
970   InitData.DestroyCallback = Sock->DestroyCallback;
971   InitData.Context         = Sock->Context;
972   InitData.ProtoData       = Sock->ProtoReserved;
973   InitData.DataSize        = sizeof (Sock->ProtoReserved);
974 
975   ClonedSock               = SockCreate (&InitData);
976 
977   if (NULL == ClonedSock) {
978     DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));
979     return NULL;
980   }
981 
982   SockSetState (ClonedSock, SO_CONNECTING);
983   ClonedSock->ConfigureState = Sock->ConfigureState;
984 
985   return ClonedSock;
986 }
987 
988 /**
989   Called by the low layer protocol to indicate the socket a connection is
990   established.
991 
992   This function just changes the socket's state to SO_CONNECTED
993   and signals the token used for connection establishment.
994 
995   @param[in, out]  Sock         Pointer to the socket associated with the
996                                 established connection.
997 
998 **/
999 VOID
SockConnEstablished(IN OUT SOCKET * Sock)1000 SockConnEstablished (
1001   IN OUT SOCKET *Sock
1002   )
1003 {
1004 
1005   ASSERT (SO_CONNECTING == Sock->State);
1006 
1007   SockSetState (Sock, SO_CONNECTED);
1008 
1009   if (NULL == Sock->Parent) {
1010     SockWakeConnToken (Sock);
1011   } else {
1012     SockWakeListenToken (Sock);
1013   }
1014 
1015 }
1016 
1017 /**
1018   Called by the low layer protocol to indicate the connection is closed.
1019 
1020   This function flushes the socket, sets the state to SO_CLOSED, and signals
1021   the close token.
1022 
1023   @param[in, out]  Sock         Pointer to the socket associated with the closed
1024                                 connection.
1025 
1026 **/
1027 VOID
SockConnClosed(IN OUT SOCKET * Sock)1028 SockConnClosed (
1029   IN OUT SOCKET *Sock
1030   )
1031 {
1032   if (Sock->CloseToken != NULL) {
1033     SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
1034     Sock->CloseToken = NULL;
1035   }
1036 
1037   SockConnFlush (Sock);
1038   SockSetState (Sock, SO_CLOSED);
1039 
1040   if (Sock->Parent != NULL) {
1041     SockDestroyChild (Sock);
1042   }
1043 
1044 }
1045 
1046 /**
1047   Called by low layer protocol to indicate that some data was sent or processed.
1048 
1049   This function trims the sent data in the socket send buffer, and signals the data
1050   token if proper.
1051 
1052   @param[in, out]  Sock      Pointer to the socket.
1053   @param[in]       Count     The length of the data processed or sent, in bytes.
1054 
1055 **/
1056 VOID
SockDataSent(IN OUT SOCKET * Sock,IN UINT32 Count)1057 SockDataSent (
1058   IN OUT SOCKET     *Sock,
1059   IN     UINT32     Count
1060   )
1061 {
1062   SOCK_TOKEN            *SockToken;
1063   SOCK_COMPLETION_TOKEN *SndToken;
1064 
1065   ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList));
1066   ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
1067 
1068   NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
1069 
1070   //
1071   // To check if we can signal some snd token in this socket
1072   //
1073   while (Count > 0) {
1074     SockToken = NET_LIST_HEAD (
1075                   &(Sock->ProcessingSndTokenList),
1076                   SOCK_TOKEN,
1077                   TokenList
1078                   );
1079 
1080     SndToken = SockToken->Token;
1081 
1082     if (SockToken->RemainDataLen <= Count) {
1083 
1084       RemoveEntryList (&(SockToken->TokenList));
1085       SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
1086       Count -= SockToken->RemainDataLen;
1087       FreePool (SockToken);
1088     } else {
1089 
1090       SockToken->RemainDataLen -= Count;
1091       Count = 0;
1092     }
1093   }
1094 
1095   //
1096   // to judge if we can process some send token in
1097   // Sock->SndTokenList, if so process those send token
1098   //
1099   SockProcessSndToken (Sock);
1100 }
1101 
1102 /**
1103   Called by the low layer protocol to copy some data in the socket send
1104   buffer starting from the specific offset to a buffer provided by
1105   the caller.
1106 
1107   @param[in]  Sock                  Pointer to the socket.
1108   @param[in]  Offset                The start point of the data to be copied.
1109   @param[in]  Len                   The length of the data to be copied.
1110   @param[out] Dest                  Pointer to the destination to copy the data.
1111 
1112   @return The data size copied.
1113 
1114 **/
1115 UINT32
SockGetDataToSend(IN SOCKET * Sock,IN UINT32 Offset,IN UINT32 Len,OUT UINT8 * Dest)1116 SockGetDataToSend (
1117   IN  SOCKET      *Sock,
1118   IN  UINT32      Offset,
1119   IN  UINT32      Len,
1120   OUT UINT8       *Dest
1121   )
1122 {
1123   ASSERT ((Sock != NULL) && SockStream == Sock->Type);
1124 
1125   return NetbufQueCopy (
1126           Sock->SndBuffer.DataQueue,
1127           Offset,
1128           Len,
1129           Dest
1130           );
1131 }
1132 
1133 /**
1134   Called by the low layer protocol to deliver received data to socket layer.
1135 
1136   This function will append the data to the socket receive buffer, set the
1137   urgent data length, and then check if any receive token can be signaled.
1138 
1139   @param[in, out]  Sock       Pointer to the socket.
1140   @param[in, out]  NetBuffer  Pointer to the buffer that contains the received data.
1141   @param[in]       UrgLen     The length of the urgent data in the received data.
1142 
1143 **/
1144 VOID
SockDataRcvd(IN OUT SOCKET * Sock,IN OUT NET_BUF * NetBuffer,IN UINT32 UrgLen)1145 SockDataRcvd (
1146   IN OUT SOCKET    *Sock,
1147   IN OUT NET_BUF   *NetBuffer,
1148   IN     UINT32    UrgLen
1149   )
1150 {
1151   ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) &&
1152     UrgLen <= NetBuffer->TotalSize);
1153 
1154   NET_GET_REF (NetBuffer);
1155 
1156   ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
1157 
1158   NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
1159 
1160   SockWakeRcvToken (Sock);
1161 }
1162 
1163 /**
1164   Get the length of the free space of the specific socket buffer.
1165 
1166   @param[in]  Sock              Pointer to the socket.
1167   @param[in]  Which             Flag to indicate which socket buffer to check:
1168                                 either send buffer or receive buffer.
1169 
1170   @return The length of the free space, in bytes.
1171 
1172 **/
1173 UINT32
SockGetFreeSpace(IN SOCKET * Sock,IN UINT32 Which)1174 SockGetFreeSpace (
1175   IN SOCKET  *Sock,
1176   IN UINT32  Which
1177   )
1178 {
1179   UINT32      BufferCC;
1180   SOCK_BUFFER *SockBuffer;
1181 
1182   ASSERT (Sock != NULL && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
1183 
1184   if (SOCK_SND_BUF == Which) {
1185     SockBuffer = &(Sock->SndBuffer);
1186   } else {
1187     SockBuffer = &(Sock->RcvBuffer);
1188   }
1189 
1190   BufferCC = (SockBuffer->DataQueue)->BufSize;
1191 
1192   if (BufferCC >= SockBuffer->HighWater) {
1193 
1194     return 0;
1195   }
1196 
1197   return SockBuffer->HighWater - BufferCC;
1198 }
1199 
1200 /**
1201   Called by the low layer protocol to indicate that there will be no more data
1202   from the communication peer.
1203 
1204   This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
1205   IO tokens with the error status EFI_CONNECTION_FIN.
1206 
1207   @param[in, out]  Sock                  Pointer to the socket.
1208 
1209 **/
1210 VOID
SockNoMoreData(IN OUT SOCKET * Sock)1211 SockNoMoreData (
1212   IN OUT SOCKET *Sock
1213   )
1214 {
1215   EFI_STATUS  Err;
1216 
1217   SOCK_NO_MORE_DATA (Sock);
1218 
1219   if (!IsListEmpty (&Sock->RcvTokenList)) {
1220 
1221     ASSERT (0 == GET_RCV_DATASIZE (Sock));
1222 
1223     Err = Sock->SockError;
1224 
1225     SOCK_ERROR (Sock, EFI_CONNECTION_FIN);
1226 
1227     SockFlushPendingToken (Sock, &Sock->RcvTokenList);
1228 
1229     SOCK_ERROR (Sock, Err);
1230 
1231   }
1232 }
1233 
1234