Home | History | Annotate | Download | only in TcpDxe
      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 *
     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 *
     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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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 *
    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
    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
    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
    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 *
   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
   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
   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
   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
   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
   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
   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
   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