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