Better handle transmit errors
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Aug 2011 18:19:45 +0000 (18:19 +0000)
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 8 Aug 2011 18:19:45 +0000 (18:19 +0000)
Return 0 receive bytes when socket is closed

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12099 6f19259b-4bc3-4df7-8a09-765794883524

StdLib/EfiSocketLib/Socket.c
StdLib/EfiSocketLib/Tcp4.c

index bad888c..ebbc8df 100644 (file)
@@ -2525,91 +2525,18 @@ EslSocketReceive (
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
-    //  Verify the socket state\r
+    //  Return the transmit error if necessary\r
     //\r
-    if ( !pSocket->bConfigured ) {\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-      //\r
-      //  Validate the local address\r
-      //\r
-      switch ( pSocket->Domain ) {\r
-      default:\r
-        DEBUG (( DEBUG_RX,\r
-                  "ERROR - Invalid socket address family: %d\r\n",\r
-                  pSocket->Domain ));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-        break;\r
-\r
-      case AF_INET:\r
-        //\r
-        //  Determine the connection point within the network stack\r
-        //\r
-        switch ( pSocket->Type ) {\r
-        default:\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket type: %d\r\n",\r
-                    pSocket->Type));\r
-          Status = EFI_INVALID_PARAMETER;\r
-          break;\r
-\r
-        case SOCK_STREAM:\r
-        case SOCK_SEQPACKET:\r
-          //\r
-          //  Verify the port state\r
-          //\r
-          Status = EslTcpSocketIsConfigured4 ( pSocket );\r
-          break;\r
-\r
-        case SOCK_DGRAM:\r
-          //\r
-          //  Verify the port state\r
-          //\r
-          Status = EslUdpSocketIsConfigured4 ( pSocket );\r
-          break;\r
-        }\r
-        break;\r
-      }\r
-\r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-\r
-      //\r
-      //  Set errno if a failure occurs\r
-      //\r
-      if ( EFI_ERROR ( Status )) {\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-      }\r
+    if ( EFI_SUCCESS != pSocket->TxError ) {\r
+      pSocket->errno = EIO;\r
+      Status = pSocket->TxError;\r
+      pSocket->TxError = EFI_SUCCESS;\r
     }\r
-    if ( !EFI_ERROR ( Status )) {\r
+    else {\r
       //\r
-      //  Validate the buffer length\r
+      //  Verify the socket state\r
       //\r
-      if (( NULL == pDataLength )\r
-        && ( 0 > pDataLength )\r
-        && ( NULL == pBuffer )) {\r
-        if ( NULL == pDataLength ) {\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - pDataLength is NULL!\r\n" ));\r
-        }\r
-        else if ( NULL == pBuffer ) {\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - pBuffer is NULL!\r\n" ));\r
-        }\r
-        else {\r
-          DEBUG (( DEBUG_RX,\r
-                    "ERROR - Data length < 0!\r\n" ));\r
-        }\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EFAULT;\r
-      }\r
-      else{\r
+      if ( !pSocket->bConfigured ) {\r
         //\r
         //  Synchronize with the socket layer\r
         //\r
@@ -2637,28 +2564,21 @@ EslSocketReceive (
                       "ERROR - Invalid socket type: %d\r\n",\r
                       pSocket->Type));\r
             Status = EFI_INVALID_PARAMETER;\r
-            pSocket->errno = EADDRNOTAVAIL;\r
             break;\r
 \r
           case SOCK_STREAM:\r
           case SOCK_SEQPACKET:\r
-            Status = EslTcpReceive4 ( pSocket,\r
-                                      Flags,\r
-                                      BufferLength,\r
-                                      pBuffer,\r
-                                      pDataLength,\r
-                                      pAddress,\r
-                                      pAddressLength );\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslTcpSocketIsConfigured4 ( pSocket );\r
             break;\r
 \r
           case SOCK_DGRAM:\r
-            Status = EslUdpReceive4 ( pSocket,\r
-                                      Flags,\r
-                                      BufferLength,\r
-                                      pBuffer,\r
-                                      pDataLength,\r
-                                      pAddress,\r
-                                      pAddressLength);\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslUdpSocketIsConfigured4 ( pSocket );\r
             break;\r
           }\r
           break;\r
@@ -2668,6 +2588,96 @@ EslSocketReceive (
         //  Release the socket layer synchronization\r
         //\r
         RESTORE_TPL ( TplPrevious );\r
+\r
+        //\r
+        //  Set errno if a failure occurs\r
+        //\r
+        if ( EFI_ERROR ( Status )) {\r
+          pSocket->errno = EADDRNOTAVAIL;\r
+        }\r
+      }\r
+      if ( !EFI_ERROR ( Status )) {\r
+        //\r
+        //  Validate the buffer length\r
+        //\r
+        if (( NULL == pDataLength )\r
+          && ( 0 > pDataLength )\r
+          && ( NULL == pBuffer )) {\r
+          if ( NULL == pDataLength ) {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - pDataLength is NULL!\r\n" ));\r
+          }\r
+          else if ( NULL == pBuffer ) {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - pBuffer is NULL!\r\n" ));\r
+          }\r
+          else {\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Data length < 0!\r\n" ));\r
+          }\r
+          Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EFAULT;\r
+        }\r
+        else{\r
+          //\r
+          //  Synchronize with the socket layer\r
+          //\r
+          RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+          //\r
+          //  Validate the local address\r
+          //\r
+          switch ( pSocket->Domain ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket address family: %d\r\n",\r
+                      pSocket->Domain ));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            pSocket->errno = EADDRNOTAVAIL;\r
+            break;\r
+\r
+          case AF_INET:\r
+            //\r
+            //  Determine the connection point within the network stack\r
+            //\r
+            switch ( pSocket->Type ) {\r
+            default:\r
+              DEBUG (( DEBUG_RX,\r
+                        "ERROR - Invalid socket type: %d\r\n",\r
+                        pSocket->Type));\r
+              Status = EFI_INVALID_PARAMETER;\r
+              pSocket->errno = EADDRNOTAVAIL;\r
+              break;\r
+\r
+            case SOCK_STREAM:\r
+            case SOCK_SEQPACKET:\r
+              Status = EslTcpReceive4 ( pSocket,\r
+                                        Flags,\r
+                                        BufferLength,\r
+                                        pBuffer,\r
+                                        pDataLength,\r
+                                        pAddress,\r
+                                        pAddressLength );\r
+              break;\r
+\r
+            case SOCK_DGRAM:\r
+              Status = EslUdpReceive4 ( pSocket,\r
+                                        Flags,\r
+                                        BufferLength,\r
+                                        pBuffer,\r
+                                        pDataLength,\r
+                                        pAddress,\r
+                                        pAddressLength);\r
+              break;\r
+            }\r
+            break;\r
+          }\r
+\r
+          //\r
+          //  Release the socket layer synchronization\r
+          //\r
+          RESTORE_TPL ( TplPrevious );\r
+        }\r
       }\r
     }\r
   }\r
@@ -2895,171 +2905,181 @@ EslSocketTransmit (
     pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
 \r
     //\r
-    //  Verify the socket state\r
+    //  Return the transmit error if necessary\r
     //\r
-    if ( !pSocket->bConfigured ) {\r
-      //\r
-      //  Synchronize with the socket layer\r
-      //\r
-      RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-    \r
+    if ( EFI_SUCCESS != pSocket->TxError ) {\r
+      pSocket->errno = EIO;\r
+      Status = pSocket->TxError;\r
+      pSocket->TxError = EFI_SUCCESS;\r
+    }\r
+    else {\r
       //\r
-      //  Validate the local address\r
+      //  Verify the socket state\r
       //\r
-      switch ( pSocket->Domain ) {\r
-      default:\r
-        DEBUG (( DEBUG_RX,\r
-                  "ERROR - Invalid socket address family: %d\r\n",\r
-                  pSocket->Domain ));\r
-        Status = EFI_INVALID_PARAMETER;\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-        break;\r
-    \r
-      case AF_INET:\r
+      if ( !pSocket->bConfigured ) {\r
+        //\r
+        //  Synchronize with the socket layer\r
+        //\r
+        RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
         //\r
-        //  Determine the connection point within the network stack\r
+        //  Validate the local address\r
         //\r
-        switch ( pSocket->Type ) {\r
+        switch ( pSocket->Domain ) {\r
         default:\r
           DEBUG (( DEBUG_RX,\r
-                    "ERROR - Invalid socket type: %d\r\n",\r
-                    pSocket->Type));\r
+                    "ERROR - Invalid socket address family: %d\r\n",\r
+                    pSocket->Domain ));\r
           Status = EFI_INVALID_PARAMETER;\r
+          pSocket->errno = EADDRNOTAVAIL;\r
           break;\r
-    \r
-        case SOCK_STREAM:\r
-        case SOCK_SEQPACKET:\r
-          //\r
-          //  Verify the port state\r
-          //\r
-          Status = EslTcpSocketIsConfigured4 ( pSocket );\r
-          break;\r
-    \r
-        case SOCK_DGRAM:\r
+\r
+        case AF_INET:\r
           //\r
-          //  Verify the port state\r
+          //  Determine the connection point within the network stack\r
           //\r
-          Status = EslUdpSocketIsConfigured4 ( pSocket );\r
+          switch ( pSocket->Type ) {\r
+          default:\r
+            DEBUG (( DEBUG_RX,\r
+                      "ERROR - Invalid socket type: %d\r\n",\r
+                      pSocket->Type));\r
+            Status = EFI_INVALID_PARAMETER;\r
+            break;\r
+\r
+          case SOCK_STREAM:\r
+          case SOCK_SEQPACKET:\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslTcpSocketIsConfigured4 ( pSocket );\r
+            break;\r
+\r
+          case SOCK_DGRAM:\r
+            //\r
+            //  Verify the port state\r
+            //\r
+            Status = EslUdpSocketIsConfigured4 ( pSocket );\r
+            break;\r
+          }\r
           break;\r
         }\r
-        break;\r
-      }\r
-    \r
-      //\r
-      //  Release the socket layer synchronization\r
-      //\r
-      RESTORE_TPL ( TplPrevious );\r
-    \r
-      //\r
-      //  Set errno if a failure occurs\r
-      //\r
-      if ( EFI_ERROR ( Status )) {\r
-        pSocket->errno = EADDRNOTAVAIL;\r
-      }\r
-    }\r
-    if ( !EFI_ERROR ( Status )) {\r
-      //\r
-      //  Verify that transmit is still allowed\r
-      //\r
-      if ( !pSocket->bTxDisable ) {\r
+\r
         //\r
-        //  Validate the buffer length\r
+        //  Release the socket layer synchronization\r
         //\r
-        if (( NULL == pDataLength )\r
-          && ( 0 > pDataLength )\r
-          && ( NULL == pBuffer )) {\r
-          if ( NULL == pDataLength ) {\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - pDataLength is NULL!\r\n" ));\r
-          }\r
-          else if ( NULL == pBuffer ) {\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - pBuffer is NULL!\r\n" ));\r
-          }\r
-          else {\r
-            DEBUG (( DEBUG_RX,\r
-                      "ERROR - Data length < 0!\r\n" ));\r
-          }\r
-          Status = EFI_INVALID_PARAMETER;\r
-          pSocket->errno = EFAULT;\r
+        RESTORE_TPL ( TplPrevious );\r
+\r
+        //\r
+        //  Set errno if a failure occurs\r
+        //\r
+        if ( EFI_ERROR ( Status )) {\r
+          pSocket->errno = EADDRNOTAVAIL;\r
         }\r
-        else {\r
+      }\r
+      if ( !EFI_ERROR ( Status )) {\r
+        //\r
+        //  Verify that transmit is still allowed\r
+        //\r
+        if ( !pSocket->bTxDisable ) {\r
           //\r
-          //  Validate the remote network address\r
+          //  Validate the buffer length\r
           //\r
-          if (( NULL != pAddress )\r
-            && ( AddressLength < pAddress->sa_len )) {\r
-            DEBUG (( DEBUG_TX,\r
-                      "ERROR - Invalid sin_len field in address\r\n" ));\r
+          if (( NULL == pDataLength )\r
+            && ( 0 > pDataLength )\r
+            && ( NULL == pBuffer )) {\r
+            if ( NULL == pDataLength ) {\r
+              DEBUG (( DEBUG_RX,\r
+                        "ERROR - pDataLength is NULL!\r\n" ));\r
+            }\r
+            else if ( NULL == pBuffer ) {\r
+              DEBUG (( DEBUG_RX,\r
+                        "ERROR - pBuffer is NULL!\r\n" ));\r
+            }\r
+            else {\r
+              DEBUG (( DEBUG_RX,\r
+                        "ERROR - Data length < 0!\r\n" ));\r
+            }\r
             Status = EFI_INVALID_PARAMETER;\r
             pSocket->errno = EFAULT;\r
           }\r
           else {\r
             //\r
-            //  Synchronize with the socket layer\r
-            //\r
-            RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
-\r
-            //\r
-            //  Validate the local address\r
+            //  Validate the remote network address\r
             //\r
-            switch ( pSocket->Domain ) {\r
-            default:\r
-              DEBUG (( DEBUG_RX,\r
-                        "ERROR - Invalid socket address family: %d\r\n",\r
-                        pSocket->Domain ));\r
+            if (( NULL != pAddress )\r
+              && ( AddressLength < pAddress->sa_len )) {\r
+              DEBUG (( DEBUG_TX,\r
+                        "ERROR - Invalid sin_len field in address\r\n" ));\r
               Status = EFI_INVALID_PARAMETER;\r
-              pSocket->errno = EADDRNOTAVAIL;\r
-              break;\r
+              pSocket->errno = EFAULT;\r
+            }\r
+            else {\r
+              //\r
+              //  Synchronize with the socket layer\r
+              //\r
+              RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
 \r
-            case AF_INET:\r
               //\r
-              //  Determine the connection point within the network stack\r
+              //  Validate the local address\r
               //\r
-              switch ( pSocket->Type ) {\r
+              switch ( pSocket->Domain ) {\r
               default:\r
                 DEBUG (( DEBUG_RX,\r
-                          "ERROR - Invalid socket type: %d\r\n",\r
-                          pSocket->Type));\r
+                          "ERROR - Invalid socket address family: %d\r\n",\r
+                          pSocket->Domain ));\r
                 Status = EFI_INVALID_PARAMETER;\r
                 pSocket->errno = EADDRNOTAVAIL;\r
                 break;\r
 \r
-              case SOCK_STREAM:\r
-              case SOCK_SEQPACKET:\r
-                Status = EslTcpTxBuffer4 ( pSocket,\r
-                                           Flags,\r
-                                           BufferLength,\r
-                                           pBuffer,\r
-                                           pDataLength );\r
-                break;\r
-\r
-              case SOCK_DGRAM:\r
-                Status = EslUdpTxBuffer4 ( pSocket,\r
-                                           Flags,\r
-                                           BufferLength,\r
-                                           pBuffer,\r
-                                           pDataLength,\r
-                                           pAddress,\r
-                                           AddressLength );\r
+              case AF_INET:\r
+                //\r
+                //  Determine the connection point within the network stack\r
+                //\r
+                switch ( pSocket->Type ) {\r
+                default:\r
+                  DEBUG (( DEBUG_RX,\r
+                            "ERROR - Invalid socket type: %d\r\n",\r
+                            pSocket->Type));\r
+                  Status = EFI_INVALID_PARAMETER;\r
+                  pSocket->errno = EADDRNOTAVAIL;\r
+                  break;\r
+\r
+                case SOCK_STREAM:\r
+                case SOCK_SEQPACKET:\r
+                  Status = EslTcpTxBuffer4 ( pSocket,\r
+                                             Flags,\r
+                                             BufferLength,\r
+                                             pBuffer,\r
+                                             pDataLength );\r
+                  break;\r
+\r
+                case SOCK_DGRAM:\r
+                  Status = EslUdpTxBuffer4 ( pSocket,\r
+                                             Flags,\r
+                                             BufferLength,\r
+                                             pBuffer,\r
+                                             pDataLength,\r
+                                             pAddress,\r
+                                             AddressLength );\r
+                  break;\r
+                }\r
                 break;\r
               }\r
-              break;\r
-            }\r
 \r
-            //\r
-            //  Release the socket layer synchronization\r
-            //\r
-            RESTORE_TPL ( TplPrevious );\r
+              //\r
+              //  Release the socket layer synchronization\r
+              //\r
+              RESTORE_TPL ( TplPrevious );\r
+            }\r
           }\r
         }\r
-      }\r
-      else {\r
-        //\r
-        //  The transmitter was shutdown\r
-        //\r
-        pSocket->errno = EPIPE;\r
-        Status = EFI_NOT_STARTED;\r
+        else {\r
+          //\r
+          //  The transmitter was shutdown\r
+          //\r
+          pSocket->errno = EPIPE;\r
+          Status = EFI_NOT_STARTED;\r
+        }\r
       }\r
     }\r
   }\r
index 2840dd7..b489608 100644 (file)
@@ -2448,13 +2448,21 @@ EslTcpReceive4 (
           && ( NULL == pSocket->pRxPacketListHead )\r
           && ( NULL == pSocket->pRxOobPacketListHead )) {\r
           Status = pSocket->RxError;\r
+          pSocket->RxError = EFI_SUCCESS;\r
           switch ( Status ) {\r
           default:\r
             pSocket->errno = EIO;\r
             break;\r
           \r
           case EFI_CONNECTION_FIN:\r
-            pSocket->errno = ESHUTDOWN;\r
+            //\r
+            //  Continue to return zero bytes received when the\r
+            //  peer has successfully closed the connection\r
+            //\r
+            pSocket->RxError = EFI_CONNECTION_FIN;\r
+            *pDataLength = 0;\r
+            pSocket->errno = 0;\r
+            Status = EFI_SUCCESS;\r
             break;\r
 \r
           case EFI_CONNECTION_REFUSED:\r
@@ -2481,7 +2489,6 @@ EslTcpReceive4 (
             pSocket->errno = ENOPROTOOPT;\r
             break;\r
           }\r
-          pSocket->RxError = EFI_SUCCESS;\r
         }\r
         else {\r
           Status = EFI_NOT_READY;\r