• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Implementation of the Socket.
3 
4   Copyright (c) 2009 - 2012, 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_INFO,
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   Create a socket with initial data SockInitData.
579 
580   @param[in]  SockInitData          Pointer to the initial data of the socket.
581 
582   @return Pointer to the newly created socket, return NULL when an exception occurs.
583 
584 **/
585 SOCKET *
SockCreate(IN SOCK_INIT_DATA * SockInitData)586 SockCreate (
587   IN SOCK_INIT_DATA *SockInitData
588   )
589 {
590   SOCKET      *Sock;
591   SOCKET      *Parent;
592   EFI_STATUS  Status;
593   EFI_GUID    *TcpProtocolGuid;
594   UINTN       ProtocolLength;
595 
596   ASSERT ((SockInitData != NULL) && (SockInitData->ProtoHandler != NULL));
597   ASSERT (SockInitData->Type == SockStream);
598   ASSERT ((SockInitData->ProtoData != NULL) && (SockInitData->DataSize <= PROTO_RESERVED_LEN));
599 
600   if (SockInitData->IpVersion == IP_VERSION_4) {
601     TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
602     ProtocolLength  = sizeof (EFI_TCP4_PROTOCOL);
603   } else {
604     TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
605     ProtocolLength  = sizeof (EFI_TCP6_PROTOCOL);
606   }
607 
608 
609   Parent = SockInitData->Parent;
610 
611   if ((Parent != NULL) && (Parent->ConnCnt == Parent->BackLog)) {
612     DEBUG (
613       (EFI_D_ERROR,
614       "SockCreate: Socket parent has reached its connection limit with %d ConnCnt and %d BackLog\n",
615       Parent->ConnCnt,
616       Parent->BackLog)
617       );
618 
619     return NULL;
620   }
621 
622   Sock = AllocateZeroPool (sizeof (SOCKET));
623   if (NULL == Sock) {
624 
625     DEBUG ((EFI_D_ERROR, "SockCreate: No resource to create a new socket\n"));
626     return NULL;
627   }
628 
629   InitializeListHead (&Sock->Link);
630   InitializeListHead (&Sock->ConnectionList);
631   InitializeListHead (&Sock->ListenTokenList);
632   InitializeListHead (&Sock->RcvTokenList);
633   InitializeListHead (&Sock->SndTokenList);
634   InitializeListHead (&Sock->ProcessingSndTokenList);
635 
636   EfiInitializeLock (&(Sock->Lock), TPL_CALLBACK);
637 
638   Sock->SndBuffer.DataQueue = NetbufQueAlloc ();
639   if (NULL == Sock->SndBuffer.DataQueue) {
640     DEBUG (
641       (EFI_D_ERROR,
642       "SockCreate: No resource to allocate SndBuffer for new socket\n")
643       );
644 
645     goto OnError;
646   }
647 
648   Sock->RcvBuffer.DataQueue = NetbufQueAlloc ();
649   if (NULL == Sock->RcvBuffer.DataQueue) {
650     DEBUG (
651       (EFI_D_ERROR,
652       "SockCreate: No resource to allocate RcvBuffer for new socket\n")
653       );
654 
655     goto OnError;
656   }
657 
658   Sock->Signature           = SOCK_SIGNATURE;
659 
660   Sock->Parent              = Parent;
661   Sock->BackLog             = SockInitData->BackLog;
662   Sock->ProtoHandler        = SockInitData->ProtoHandler;
663   Sock->SndBuffer.HighWater = SockInitData->SndBufferSize;
664   Sock->RcvBuffer.HighWater = SockInitData->RcvBufferSize;
665   Sock->Type                = SockInitData->Type;
666   Sock->DriverBinding       = SockInitData->DriverBinding;
667   Sock->State               = SockInitData->State;
668   Sock->CreateCallback      = SockInitData->CreateCallback;
669   Sock->DestroyCallback     = SockInitData->DestroyCallback;
670   Sock->Context             = SockInitData->Context;
671 
672   Sock->SockError           = EFI_ABORTED;
673   Sock->SndBuffer.LowWater  = SOCK_BUFF_LOW_WATER;
674   Sock->RcvBuffer.LowWater  = SOCK_BUFF_LOW_WATER;
675 
676   Sock->IpVersion           = SockInitData->IpVersion;
677 
678   //
679   // Install protocol on Sock->SockHandle
680   //
681   CopyMem (&Sock->NetProtocol, SockInitData->Protocol, ProtocolLength);
682 
683   //
684   // copy the protodata into socket
685   //
686   CopyMem (Sock->ProtoReserved, SockInitData->ProtoData, SockInitData->DataSize);
687 
688   Status = gBS->InstallMultipleProtocolInterfaces (
689                   &Sock->SockHandle,
690                   TcpProtocolGuid,
691                   &Sock->NetProtocol,
692                   NULL
693                   );
694 
695   if (EFI_ERROR (Status)) {
696     DEBUG (
697       (EFI_D_ERROR,
698       "SockCreate: Install TCP protocol in socket failed with %r\n",
699       Status)
700       );
701 
702     goto OnError;
703   }
704 
705   if (Parent != NULL) {
706     ASSERT (Parent->BackLog > 0);
707     ASSERT (SOCK_IS_LISTENING (Parent));
708 
709     //
710     // need to add it into Parent->ConnectionList
711     // if the Parent->ConnCnt < Parent->BackLog
712     //
713     Parent->ConnCnt++;
714 
715     DEBUG (
716       (EFI_D_INFO,
717       "SockCreate: Create a new socket and add to parent, now conncnt is %d\n",
718       Parent->ConnCnt)
719       );
720 
721     InsertTailList (&Parent->ConnectionList, &Sock->ConnectionList);
722   }
723 
724   if (Sock->CreateCallback != NULL) {
725     Status = Sock->CreateCallback (Sock, Sock->Context);
726     if (EFI_ERROR (Status)) {
727       goto OnError;
728     }
729   }
730 
731   return Sock;
732 
733 OnError:
734 
735   if (Sock->SockHandle != NULL) {
736     gBS->UninstallMultipleProtocolInterfaces (
737            Sock->SockHandle,
738            TcpProtocolGuid,
739            &Sock->NetProtocol,
740            NULL
741            );
742   }
743 
744   if (NULL != Sock->SndBuffer.DataQueue) {
745     NetbufQueFree (Sock->SndBuffer.DataQueue);
746   }
747 
748   if (NULL != Sock->RcvBuffer.DataQueue) {
749     NetbufQueFree (Sock->RcvBuffer.DataQueue);
750   }
751 
752   FreePool (Sock);
753 
754   return NULL;
755 }
756 
757 /**
758   Destroy a socket.
759 
760   @param[in, out]  Sock                  Pointer to the socket.
761 
762 **/
763 VOID
SockDestroy(IN OUT SOCKET * Sock)764 SockDestroy (
765   IN OUT SOCKET *Sock
766   )
767 {
768   VOID        *SockProtocol;
769   EFI_GUID    *TcpProtocolGuid;
770   EFI_STATUS  Status;
771 
772   ASSERT (SockStream == Sock->Type);
773 
774   if (Sock->DestroyCallback != NULL) {
775     Sock->DestroyCallback (Sock, Sock->Context);
776   }
777 
778   //
779   // Flush the completion token buffered
780   // by sock and rcv, snd buffer
781   //
782   if (!SOCK_IS_UNCONFIGURED (Sock)) {
783 
784     SockConnFlush (Sock);
785     SockSetState (Sock, SO_CLOSED);
786     Sock->ConfigureState = SO_UNCONFIGURED;
787 
788   }
789   //
790   // Destroy the RcvBuffer Queue and SendBuffer Queue
791   //
792   NetbufQueFree (Sock->RcvBuffer.DataQueue);
793   NetbufQueFree (Sock->SndBuffer.DataQueue);
794 
795   //
796   // Remove it from parent connection list if needed
797   //
798   if (Sock->Parent != NULL) {
799 
800     RemoveEntryList (&(Sock->ConnectionList));
801     (Sock->Parent->ConnCnt)--;
802 
803     DEBUG (
804       (EFI_D_WARN,
805       "SockDestroy: Delete a unaccepted socket from parent now conncnt is %d\n",
806       Sock->Parent->ConnCnt)
807       );
808 
809     Sock->Parent = NULL;
810   }
811 
812   //
813   // Set the protocol guid and driver binding handle
814   // in the light of Sock->SockType
815   //
816   if (Sock->IpVersion == IP_VERSION_4) {
817     TcpProtocolGuid = &gEfiTcp4ProtocolGuid;
818   } else {
819     TcpProtocolGuid = &gEfiTcp6ProtocolGuid;
820   }
821 
822   //
823   // Retrieve the protocol installed on this sock
824   //
825   Status = gBS->OpenProtocol (
826                   Sock->SockHandle,
827                   TcpProtocolGuid,
828                   &SockProtocol,
829                   Sock->DriverBinding,
830                   Sock->SockHandle,
831                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
832                   );
833 
834   if (EFI_ERROR (Status)) {
835 
836     DEBUG (
837       (EFI_D_ERROR,
838       "SockDestroy: Open protocol installed on socket failed with %r\n",
839       Status)
840       );
841 
842     goto FreeSock;
843   }
844 
845   //
846   // Uninstall the protocol installed on this sock
847   // in the light of Sock->SockType
848   //
849   gBS->UninstallMultipleProtocolInterfaces (
850         Sock->SockHandle,
851         TcpProtocolGuid,
852         SockProtocol,
853         NULL
854         );
855 
856 FreeSock:
857 
858   FreePool (Sock);
859 }
860 
861 /**
862   Flush the sndBuffer and rcvBuffer of socket.
863 
864   @param[in, out]  Sock                  Pointer to the socket.
865 
866 **/
867 VOID
SockConnFlush(IN OUT SOCKET * Sock)868 SockConnFlush (
869   IN OUT SOCKET *Sock
870   )
871 {
872   SOCKET  *Child;
873 
874   ASSERT (Sock != NULL);
875 
876   //
877   // Clear the flag in this socket
878   //
879   Sock->Flag = 0;
880 
881   //
882   // Flush the SndBuffer and RcvBuffer of Sock
883   //
884   NetbufQueFlush (Sock->SndBuffer.DataQueue);
885   NetbufQueFlush (Sock->RcvBuffer.DataQueue);
886 
887   //
888   // Signal the pending token
889   //
890   if (Sock->ConnectionToken != NULL) {
891     SIGNAL_TOKEN (Sock->ConnectionToken, Sock->SockError);
892     Sock->ConnectionToken = NULL;
893   }
894 
895   if (Sock->CloseToken != NULL) {
896     SIGNAL_TOKEN (Sock->CloseToken, Sock->SockError);
897     Sock->CloseToken = NULL;
898   }
899 
900   SockFlushPendingToken (Sock, &(Sock->ListenTokenList));
901   SockFlushPendingToken (Sock, &(Sock->RcvTokenList));
902   SockFlushPendingToken (Sock, &(Sock->SndTokenList));
903   SockFlushPendingToken (Sock, &(Sock->ProcessingSndTokenList));
904 
905   //
906   // Destroy the pending connection, if it is a listening socket
907   //
908   if (SOCK_IS_LISTENING (Sock)) {
909     while (!IsListEmpty (&Sock->ConnectionList)) {
910       Child = NET_LIST_HEAD (
911                 &Sock->ConnectionList,
912                 SOCKET,
913                 ConnectionList
914                 );
915 
916       SockDestroyChild (Child);
917     }
918 
919     Sock->ConnCnt = 0;
920   }
921 
922 }
923 
924 /**
925   Set the state of the socket.
926 
927   @param[in, out]  Sock                  Pointer to the socket.
928   @param[in]       State                 The new socket state to be set.
929 
930 **/
931 VOID
SockSetState(IN OUT SOCKET * Sock,IN UINT8 State)932 SockSetState (
933   IN OUT SOCKET     *Sock,
934   IN     UINT8      State
935   )
936 {
937   Sock->State = State;
938 }
939 
940 /**
941   Clone a new socket, including its associated protocol control block.
942 
943   @param[in]  Sock                  Pointer to the socket to be cloned.
944 
945   @return Pointer to the newly cloned socket. If NULL, an error condition occurred.
946 
947 **/
948 SOCKET *
SockClone(IN SOCKET * Sock)949 SockClone (
950   IN SOCKET *Sock
951   )
952 {
953   SOCKET          *ClonedSock;
954   SOCK_INIT_DATA  InitData;
955 
956   InitData.BackLog         = Sock->BackLog;
957   InitData.Parent          = Sock;
958   InitData.State           = Sock->State;
959   InitData.ProtoHandler    = Sock->ProtoHandler;
960   InitData.Type            = Sock->Type;
961   InitData.RcvBufferSize   = Sock->RcvBuffer.HighWater;
962   InitData.SndBufferSize   = Sock->SndBuffer.HighWater;
963   InitData.DriverBinding   = Sock->DriverBinding;
964   InitData.IpVersion       = Sock->IpVersion;
965   InitData.Protocol        = &(Sock->NetProtocol);
966   InitData.CreateCallback  = Sock->CreateCallback;
967   InitData.DestroyCallback = Sock->DestroyCallback;
968   InitData.Context         = Sock->Context;
969   InitData.ProtoData       = Sock->ProtoReserved;
970   InitData.DataSize        = sizeof (Sock->ProtoReserved);
971 
972   ClonedSock               = SockCreate (&InitData);
973 
974   if (NULL == ClonedSock) {
975     DEBUG ((EFI_D_ERROR, "SockClone: no resource to create a cloned sock\n"));
976     return NULL;
977   }
978 
979   SockSetState (ClonedSock, SO_CONNECTING);
980   ClonedSock->ConfigureState = Sock->ConfigureState;
981 
982   return ClonedSock;
983 }
984 
985 /**
986   Called by the low layer protocol to indicate the socket a connection is
987   established.
988 
989   This function just changes the socket's state to SO_CONNECTED
990   and signals the token used for connection establishment.
991 
992   @param[in, out]  Sock         Pointer to the socket associated with the
993                                 established connection.
994 
995 **/
996 VOID
SockConnEstablished(IN OUT SOCKET * Sock)997 SockConnEstablished (
998   IN OUT SOCKET *Sock
999   )
1000 {
1001 
1002   ASSERT (SO_CONNECTING == Sock->State);
1003 
1004   SockSetState (Sock, SO_CONNECTED);
1005 
1006   if (NULL == Sock->Parent) {
1007     SockWakeConnToken (Sock);
1008   } else {
1009     SockWakeListenToken (Sock);
1010   }
1011 
1012 }
1013 
1014 /**
1015   Called by the low layer protocol to indicate the connection is closed.
1016 
1017   This function flushes the socket, sets the state to SO_CLOSED, and signals
1018   the close token.
1019 
1020   @param[in, out]  Sock         Pointer to the socket associated with the closed
1021                                 connection.
1022 
1023 **/
1024 VOID
SockConnClosed(IN OUT SOCKET * Sock)1025 SockConnClosed (
1026   IN OUT SOCKET *Sock
1027   )
1028 {
1029   if (Sock->CloseToken != NULL) {
1030     SIGNAL_TOKEN (Sock->CloseToken, EFI_SUCCESS);
1031     Sock->CloseToken = NULL;
1032   }
1033 
1034   SockConnFlush (Sock);
1035   SockSetState (Sock, SO_CLOSED);
1036 
1037   if (Sock->Parent != NULL) {
1038     SockDestroyChild (Sock);
1039   }
1040 
1041 }
1042 
1043 /**
1044   Called by low layer protocol to indicate that some data was sent or processed.
1045 
1046   This function trims the sent data in the socket send buffer, and signals the data
1047   token if proper.
1048 
1049   @param[in, out]  Sock      Pointer to the socket.
1050   @param[in]       Count     The length of the data processed or sent, in bytes.
1051 
1052 **/
1053 VOID
SockDataSent(IN OUT SOCKET * Sock,IN UINT32 Count)1054 SockDataSent (
1055   IN OUT SOCKET     *Sock,
1056   IN     UINT32     Count
1057   )
1058 {
1059   SOCK_TOKEN            *SockToken;
1060   SOCK_COMPLETION_TOKEN *SndToken;
1061 
1062   ASSERT (!IsListEmpty (&Sock->ProcessingSndTokenList));
1063   ASSERT (Count <= (Sock->SndBuffer.DataQueue)->BufSize);
1064 
1065   NetbufQueTrim (Sock->SndBuffer.DataQueue, Count);
1066 
1067   //
1068   // To check if we can signal some snd token in this socket
1069   //
1070   while (Count > 0) {
1071     SockToken = NET_LIST_HEAD (
1072                   &(Sock->ProcessingSndTokenList),
1073                   SOCK_TOKEN,
1074                   TokenList
1075                   );
1076 
1077     SndToken = SockToken->Token;
1078 
1079     if (SockToken->RemainDataLen <= Count) {
1080 
1081       RemoveEntryList (&(SockToken->TokenList));
1082       SIGNAL_TOKEN (SndToken, EFI_SUCCESS);
1083       Count -= SockToken->RemainDataLen;
1084       FreePool (SockToken);
1085     } else {
1086 
1087       SockToken->RemainDataLen -= Count;
1088       Count = 0;
1089     }
1090   }
1091 
1092   //
1093   // to judge if we can process some send token in
1094   // Sock->SndTokenList, if so process those send token
1095   //
1096   SockProcessSndToken (Sock);
1097 }
1098 
1099 /**
1100   Called by the low layer protocol to copy some data in the socket send
1101   buffer starting from the specific offset to a buffer provided by
1102   the caller.
1103 
1104   @param[in]  Sock                  Pointer to the socket.
1105   @param[in]  Offset                The start point of the data to be copied.
1106   @param[in]  Len                   The length of the data to be copied.
1107   @param[out] Dest                  Pointer to the destination to copy the data.
1108 
1109   @return The data size copied.
1110 
1111 **/
1112 UINT32
SockGetDataToSend(IN SOCKET * Sock,IN UINT32 Offset,IN UINT32 Len,OUT UINT8 * Dest)1113 SockGetDataToSend (
1114   IN  SOCKET      *Sock,
1115   IN  UINT32      Offset,
1116   IN  UINT32      Len,
1117   OUT UINT8       *Dest
1118   )
1119 {
1120   ASSERT ((Sock != NULL) && SockStream == Sock->Type);
1121 
1122   return NetbufQueCopy (
1123           Sock->SndBuffer.DataQueue,
1124           Offset,
1125           Len,
1126           Dest
1127           );
1128 }
1129 
1130 /**
1131   Called by the low layer protocol to deliver received data to socket layer.
1132 
1133   This function will append the data to the socket receive buffer, set the
1134   urgent data length, and then check if any receive token can be signaled.
1135 
1136   @param[in, out]  Sock       Pointer to the socket.
1137   @param[in, out]  NetBuffer  Pointer to the buffer that contains the received data.
1138   @param[in]       UrgLen     The length of the urgent data in the received data.
1139 
1140 **/
1141 VOID
SockDataRcvd(IN OUT SOCKET * Sock,IN OUT NET_BUF * NetBuffer,IN UINT32 UrgLen)1142 SockDataRcvd (
1143   IN OUT SOCKET    *Sock,
1144   IN OUT NET_BUF   *NetBuffer,
1145   IN     UINT32    UrgLen
1146   )
1147 {
1148   ASSERT ((Sock != NULL) && (Sock->RcvBuffer.DataQueue != NULL) &&
1149     UrgLen <= NetBuffer->TotalSize);
1150 
1151   NET_GET_REF (NetBuffer);
1152 
1153   ((TCP_RSV_DATA *) (NetBuffer->ProtoData))->UrgLen = UrgLen;
1154 
1155   NetbufQueAppend (Sock->RcvBuffer.DataQueue, NetBuffer);
1156 
1157   SockWakeRcvToken (Sock);
1158 }
1159 
1160 /**
1161   Get the length of the free space of the specific socket buffer.
1162 
1163   @param[in]  Sock              Pointer to the socket.
1164   @param[in]  Which             Flag to indicate which socket buffer to check:
1165                                 either send buffer or receive buffer.
1166 
1167   @return The length of the free space, in bytes.
1168 
1169 **/
1170 UINT32
SockGetFreeSpace(IN SOCKET * Sock,IN UINT32 Which)1171 SockGetFreeSpace (
1172   IN SOCKET  *Sock,
1173   IN UINT32  Which
1174   )
1175 {
1176   UINT32      BufferCC;
1177   SOCK_BUFFER *SockBuffer;
1178 
1179   ASSERT (Sock != NULL && ((SOCK_SND_BUF == Which) || (SOCK_RCV_BUF == Which)));
1180 
1181   if (SOCK_SND_BUF == Which) {
1182     SockBuffer = &(Sock->SndBuffer);
1183   } else {
1184     SockBuffer = &(Sock->RcvBuffer);
1185   }
1186 
1187   BufferCC = (SockBuffer->DataQueue)->BufSize;
1188 
1189   if (BufferCC >= SockBuffer->HighWater) {
1190 
1191     return 0;
1192   }
1193 
1194   return SockBuffer->HighWater - BufferCC;
1195 }
1196 
1197 /**
1198   Called by the low layer protocol to indicate that there will be no more data
1199   from the communication peer.
1200 
1201   This function sets the socket's state to SO_NO_MORE_DATA and signals all queued
1202   IO tokens with the error status EFI_CONNECTION_FIN.
1203 
1204   @param[in, out]  Sock                  Pointer to the socket.
1205 
1206 **/
1207 VOID
SockNoMoreData(IN OUT SOCKET * Sock)1208 SockNoMoreData (
1209   IN OUT SOCKET *Sock
1210   )
1211 {
1212   EFI_STATUS  Err;
1213 
1214   SOCK_NO_MORE_DATA (Sock);
1215 
1216   if (!IsListEmpty (&Sock->RcvTokenList)) {
1217 
1218     ASSERT (0 == GET_RCV_DATASIZE (Sock));
1219 
1220     Err = Sock->SockError;
1221 
1222     SOCK_ERROR (Sock, EFI_CONNECTION_FIN);
1223 
1224     SockFlushPendingToken (Sock, &Sock->RcvTokenList);
1225 
1226     SOCK_ERROR (Sock, Err);
1227 
1228   }
1229 }
1230 
1231