]> git.proxmox.com Git - mirror_edk2.git/blobdiff - StdLib/EfiSocketLib/Socket.c
Eliminate duplicated file GUID.
[mirror_edk2.git] / StdLib / EfiSocketLib / Socket.c
index 1805fa629ce1f052252b7dce32f5800ad5de0dae..49c288d90a4a8d92152f8c5e049bba7a38ce1498 100644 (file)
@@ -1259,7 +1259,10 @@ EslSocketBind (
       //\r
       //  Verify that at least one network connection was found\r
       //\r
-      if ( NULL == pSocket->pPortList ) {\r
+      if ( NULL != pSocket->pPortList ) {\r
+        Status = EFI_SUCCESS;\r
+      }\r
+      else {\r
         if ( EADDRNOTAVAIL == pSocket->errno ) {\r
           DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
                     "ERROR - Socket address is not available!\r\n" ));\r
@@ -1333,27 +1336,40 @@ EslSocketBindTest (
   pConfigData = (VOID *)pBuffer;\r
 \r
   //\r
-  //  Attempt to use this configuration\r
+  //  Validate that the port is connected\r
   //\r
-  Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );\r
+  Status = pPort->pSocket->pApi->pfnVerifyLocalIpAddress ( pPort, pBuffer );\r
   if ( EFI_ERROR ( Status )) {\r
     DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
-              "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",\r
+              "WARNING - Port 0x%08x invalid IP address: %r\r\n",\r
               pPort,\r
               Status ));\r
     pPort->pSocket->errno = ErrnoValue;\r
   }\r
   else {\r
     //\r
-    //  Reset the port\r
+    //  Attempt to use this configuration\r
     //\r
-    Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );\r
+    Status = pPort->pfnConfigure ( pPort->pProtocol.v, pConfigData );\r
     if ( EFI_ERROR ( Status )) {\r
-      DEBUG (( DEBUG_ERROR | DEBUG_BIND,\r
-                "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",\r
+      DEBUG (( DEBUG_WARN | DEBUG_BIND,\r
+                "WARNING - Port 0x%08x failed configuration, Status: %r\r\n",\r
                 pPort,\r
                 Status ));\r
-      ASSERT ( EFI_SUCCESS == Status );\r
+      pPort->pSocket->errno = ErrnoValue;\r
+    }\r
+    else {\r
+      //\r
+      //  Reset the port\r
+      //\r
+      Status = pPort->pfnConfigure ( pPort->pProtocol.v, NULL );\r
+      if ( EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_BIND,\r
+                  "ERROR - Port 0x%08x failed configuration reset, Status: %r\r\n",\r
+                  pPort,\r
+                  Status ));\r
+        ASSERT ( EFI_SUCCESS == Status );\r
+      }\r
     }\r
   }\r
 \r
@@ -1787,6 +1803,11 @@ EslSocketConnect (
         break;\r
 \r
       case SOCKET_STATE_CONNECTING:\r
+        //\r
+        //  Poll the network adapter\r
+        //\r
+        EslSocketRxPoll ( pSocket );\r
+\r
         //\r
         //  Poll for connection completion\r
         //\r
@@ -1804,15 +1825,7 @@ EslSocketConnect (
           //  Set the next state if connected\r
           //\r
           if ( EFI_NOT_READY != Status ) {\r
-            if ( !EFI_ERROR ( Status )) {\r
-              pSocket->State = SOCKET_STATE_CONNECTED;\r
-\r
-              //\r
-              //  Start the receive operations\r
-              //\r
-              EslSocketRxStart ( pSocket->pPortList );\r
-            }\r
-            else {\r
+            if ( EFI_ERROR ( Status )) {\r
               pSocket->State = SOCKET_STATE_BOUND;\r
             }\r
           }\r
@@ -1821,10 +1834,9 @@ EslSocketConnect (
 \r
       case SOCKET_STATE_CONNECTED:\r
         //\r
-        //  Already connected\r
+        //  Connected\r
         //\r
-        pSocket->errno = EISCONN;\r
-        Status = EFI_ALREADY_STARTED;\r
+        Status = EFI_SUCCESS;\r
         break;\r
       }\r
 \r
@@ -1942,6 +1954,168 @@ EslSocketCopyFragmentedBuffer (
 }\r
 \r
 \r
+/**\r
+  Free the socket.\r
+\r
+  This routine frees the socket structure and handle resources.\r
+\r
+  The ::close routine calls EslServiceFreeProtocol which then calls\r
+  this routine to free the socket context structure and close the\r
+  handle.\r
+\r
+  @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+  \r
+  @param [out] pErrno         Address to receive the errno value upon completion.\r
+\r
+  @retval EFI_SUCCESS   The socket resources were returned successfully.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketFree (\r
+  IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+  IN int * pErrno\r
+  )\r
+{\r
+  EFI_HANDLE ChildHandle;\r
+  int errno;\r
+  ESL_LAYER * pLayer;\r
+  ESL_SOCKET * pSocket;\r
+  ESL_SOCKET * pSocketPrevious;\r
+  EFI_STATUS Status;\r
+  EFI_TPL TplPrevious;\r
+\r
+  DBG_ENTER ( );\r
+\r
+  //\r
+  //  Assume failure\r
+  //\r
+  errno = EIO;\r
+  pSocket = NULL;\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  //\r
+  //  Validate the socket\r
+  //\r
+  pLayer = &mEslLayer;\r
+  if ( NULL != pSocketProtocol ) {\r
+    pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+    //\r
+    //  Synchronize with the socket layer\r
+    //\r
+    RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+    //\r
+    //  Walk the socket list\r
+    //\r
+    pSocketPrevious = pLayer->pSocketList;\r
+    if ( NULL != pSocketPrevious ) {\r
+      if ( pSocket == pSocketPrevious ) {\r
+        //\r
+        //  Remove the socket from the head of the list\r
+        //\r
+        pLayer->pSocketList = pSocket->pNext;\r
+      }\r
+      else {\r
+        //\r
+        //  Find the socket in the middle of the list\r
+        //\r
+        while (( NULL != pSocketPrevious )\r
+          && ( pSocket != pSocketPrevious->pNext )) {\r
+          //\r
+          //  Set the next socket\r
+          //\r
+          pSocketPrevious = pSocketPrevious->pNext;\r
+        }\r
+        if ( NULL != pSocketPrevious ) {\r
+          //\r
+          //  Remove the socket from the middle of the list\r
+          //\r
+          pSocketPrevious = pSocket->pNext;\r
+        }\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                "ERROR - Socket list is empty!\r\n" ));\r
+    }\r
+\r
+    //\r
+    //  Release the socket layer synchronization\r
+    //\r
+    RESTORE_TPL ( TplPrevious );\r
+\r
+    //\r
+    //  Determine if the socket was found\r
+    //\r
+    if ( NULL != pSocketPrevious ) {\r
+      pSocket->pNext = NULL;\r
+\r
+      //\r
+      //  Remove the socket protocol\r
+      //\r
+      ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
+      Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                ChildHandle,\r
+                &gEfiSocketProtocolGuid,\r
+                &pSocket->SocketProtocol,\r
+                NULL );\r
+      if ( !EFI_ERROR ( Status )) {\r
+        DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
+                    "Removed:   gEfiSocketProtocolGuid from 0x%08x\r\n",\r
+                    ChildHandle ));\r
+\r
+        //\r
+        //  Free the socket structure\r
+        //\r
+        Status = gBS->FreePool ( pSocket );\r
+        if ( !EFI_ERROR ( Status )) {\r
+          DEBUG (( DEBUG_POOL,\r
+                    "0x%08x: Free pSocket, %d bytes\r\n",\r
+                    pSocket,\r
+                    sizeof ( *pSocket )));\r
+          errno = 0;\r
+        }\r
+        else {\r
+          DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+                    "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
+                    pSocket,\r
+                    Status ));\r
+        }\r
+      }\r
+      else {\r
+        DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
+                    "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
+                    ChildHandle,\r
+                    Status ));\r
+      }\r
+    }\r
+    else {\r
+      DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+                "ERROR - The socket was not in the socket list!\r\n" ));\r
+      Status = EFI_NOT_FOUND;\r
+    }\r
+  }\r
+  else {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));\r
+  }\r
+\r
+  //\r
+  //  Return the errno value if possible\r
+  //\r
+  if ( NULL != pErrno ) {\r
+    *pErrno = errno;\r
+  }\r
+\r
+  //\r
+  //  Return the operation status\r
+  //\r
+  DBG_EXIT_STATUS ( Status );\r
+  return Status;\r
+}\r
+\r
+\r
 /**\r
   Get the local address.\r
 \r
@@ -1993,70 +2167,60 @@ EslSocketGetLocalAddress (
     //\r
     //  Verify the socket state\r
     //\r
-    Status = EslSocketIsConfigured ( pSocket );\r
-    if ( !EFI_ERROR ( Status )) {\r
+    EslSocketIsConfigured ( pSocket );\r
+    if ( pSocket->bAddressSet ) {\r
       //\r
       //  Verify the address buffer and length address\r
       //\r
       if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
         //\r
-        //  Verify the socket state\r
+        //  Verify the API\r
         //\r
-        if (( SOCKET_STATE_CONNECTED == pSocket->State )\r
-          || ( SOCKET_STATE_LISTENING == pSocket->State )) {\r
+        if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
+          Status = EFI_UNSUPPORTED;\r
+          pSocket->errno = ENOTSUP;\r
+        }\r
+        else {\r
           //\r
-          //  Verify the API\r
+          //  Synchronize with the socket layer\r
           //\r
-          if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
-            Status = EFI_UNSUPPORTED;\r
-            pSocket->errno = ENOTSUP;\r
-          }\r
-          else {\r
-            //\r
-            //  Synchronize with the socket layer\r
-            //\r
-            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
+          //\r
+          //  Verify that there is just a single connection\r
+          //\r
+          pPort = pSocket->pPortList;\r
+          if ( NULL != pPort ) {\r
             //\r
-            //  Verify that there is just a single connection\r
+            //  Verify the address length\r
             //\r
-            pPort = pSocket->pPortList;\r
-            if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
+            LengthInBytes = pSocket->pApi->AddressLength;\r
+            if (( LengthInBytes <= *pAddressLength ) \r
+              && ( 255 >= LengthInBytes )) {\r
               //\r
-              //  Verify the address length\r
+              //  Return the local address and address length\r
               //\r
-              LengthInBytes = pSocket->pApi->AddressLength;\r
-              if (( LengthInBytes <= *pAddressLength ) \r
-                && ( 255 >= LengthInBytes )) {\r
-                //\r
-                //  Return the local address and address length\r
-                //\r
-                ZeroMem ( pAddress, LengthInBytes );\r
-                pAddress->sa_len = (uint8_t)LengthInBytes;\r
-                *pAddressLength = pAddress->sa_len;\r
-                pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
-                pSocket->errno = 0;\r
-                Status = EFI_SUCCESS;\r
-              }\r
-              else {\r
-                pSocket->errno = EINVAL;\r
-                Status = EFI_INVALID_PARAMETER;\r
-              }\r
+              ZeroMem ( pAddress, LengthInBytes );\r
+              pAddress->sa_len = (uint8_t)LengthInBytes;\r
+              *pAddressLength = pAddress->sa_len;\r
+              pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
+              pSocket->errno = 0;\r
+              Status = EFI_SUCCESS;\r
             }\r
             else {\r
-              pSocket->errno = ENOTCONN;\r
-              Status = EFI_NOT_STARTED;\r
+              pSocket->errno = EINVAL;\r
+              Status = EFI_INVALID_PARAMETER;\r
             }\r
-            \r
-            //\r
-            //  Release the socket layer synchronization\r
-            //\r
-            RESTORE_TPL ( TplPrevious );\r
           }\r
-        }\r
-        else {\r
-          pSocket->errno = ENOTCONN;\r
-          Status = EFI_NOT_STARTED;\r
+          else {\r
+            pSocket->errno = ENOTCONN;\r
+            Status = EFI_NOT_STARTED;\r
+          }\r
+          \r
+          //\r
+          //  Release the socket layer synchronization\r
+          //\r
+          RESTORE_TPL ( TplPrevious );\r
         }\r
       }\r
       else {\r
@@ -2064,6 +2228,13 @@ EslSocketGetLocalAddress (
         Status = EFI_INVALID_PARAMETER;\r
       }\r
     }\r
+    else {\r
+      //\r
+      //  Address not set\r
+      //\r
+      Status = EFI_NOT_STARTED;\r
+      pSocket->errno = EADDRNOTAVAIL;\r
+    }\r
   }\r
   \r
   //\r
@@ -2567,7 +2738,7 @@ EslSocketListen (
         //  Create the event for SocketAccept completion\r
         //\r
         Status = gBS->CreateEvent ( 0,\r
-                                    TplPrevious,\r
+                                    TPL_SOCKETS,\r
                                     NULL,\r
                                     NULL,\r
                                     &pSocket->WaitAccept );\r
@@ -2808,6 +2979,14 @@ EslSocketOptionGet (
         LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
         break;\r
 \r
+      case SO_REUSEADDR:\r
+        //\r
+        //  Return the address reuse flag\r
+        //\r
+        pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+        LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+        break;\r
+      \r
       case SO_SNDBUF:\r
         //\r
         //  Return the maximum transmit buffer size\r
@@ -3032,6 +3211,14 @@ EslSocketOptionSet (
           LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
           break;\r
 \r
+        case SO_REUSEADDR:\r
+          //\r
+          //  Return the address reuse flag\r
+          //\r
+          pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+          LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+          break;\r
+\r
         case SO_SNDBUF:\r
           //\r
           //  Send buffer size\r
@@ -3175,7 +3362,7 @@ EslSocketPacketFree (
   DBG_ENTER ( );\r
 \r
   //\r
-  //  Allocate a packet structure\r
+  //  Free a packet structure\r
   //\r
   LengthInBytes = pPacket->PacketSize;\r
   Status = gBS->FreePool ( pPacket );\r
@@ -4945,7 +5132,7 @@ EslSocketRxPoll (
   <ul>\r
     <li>::EslIp4Receive to restart the receive engine to release flow control.</li>\r
     <li>::EslIp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
-    <li>::EslIp4SocketIsConfigured to start the recevie engine for the new socket.</li>\r
+    <li>::EslIp4SocketIsConfigured to start the receive engine for the new socket.</li>\r
     <li>::EslTcp4ListenComplete to start the recevie engine for the new socket.</li>\r
     <li>::EslTcp4Receive to restart the receive engine to release flow control.</li>\r
     <li>::EslTcp4RxComplete to continue the operation of the receive engine if flow control is not being applied.</li>\r
@@ -5741,10 +5928,24 @@ EslSocketTxStart (
       *ppActive = pIo;\r
     }\r
     else {\r
+      //\r
+      //  Display the transmit error\r
+      //\r
+      DEBUG (( DEBUG_TX | DEBUG_INFO,\r
+                "0x%08x, 0x%08x: pIo, pPacket transmit failure: %r\r\n",\r
+                pIo,\r
+                pPacket,\r
+                Status ));\r
       if ( EFI_SUCCESS == pSocket->TxError ) {\r
         pSocket->TxError = Status;\r
       }\r
 \r
+      //\r
+      //  Free the IO structure\r
+      //\r
+      pIo->pNext = *ppFree;\r
+      *ppFree = pIo;\r
+\r
       //\r
       //  Discard the transmit buffer\r
       //\r