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