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