]> git.proxmox.com Git - mirror_edk2.git/commitdiff
NetworkPkg: Avoid the indefinite wait case in HttpDxe
authorJiaxin Wu <jiaxin.wu@intel.com>
Tue, 26 Apr 2016 08:46:33 +0000 (16:46 +0800)
committerJiaxin Wu <jiaxin.wu@intel.com>
Thu, 28 Apr 2016 08:27:42 +0000 (16:27 +0800)
Need the timer check to avoid the indefinite wait case
in HttpDxe driver
A.HTTP receive Header process in HttpTcpReceiveHeader();
B.HTTP receive Body process in HttpTcpReceiveBody();

Cc: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Cc: El-Haj-Mahmoud Samer <samer.el-haj-mahmoud@hpe.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
Reviewed-by: Hegde Nagaraj P <nagaraj-p.hegde@hpe.com>
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
NetworkPkg/HttpDxe/HttpImpl.c
NetworkPkg/HttpDxe/HttpProto.c
NetworkPkg/HttpDxe/HttpProto.h

index 553b79cca01aeb35805398e7168fe70c6920a638..7a236f40e020e5da0e2f408c4784f3c6fd9cb047 100644 (file)
@@ -176,6 +176,7 @@ EfiHttpConfigure (
         sizeof (HttpInstance->IPv4Node)\r
         );\r
     }\r
+    \r
     //\r
     // Creat Tcp child\r
     //\r
@@ -897,7 +898,35 @@ HttpResponseWorker (
     HttpInstance->EndofHeader = &EndofHeader;\r
     HttpInstance->HttpHeaders = &HttpHeaders;\r
 \r
-    Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);\r
+\r
+    if (HttpInstance->TimeoutEvent == NULL) {\r
+      //\r
+      // Create TimeoutEvent for response\r
+      //\r
+      Status = gBS->CreateEvent (\r
+                      EVT_TIMER,\r
+                      TPL_CALLBACK,\r
+                      NULL,\r
+                      NULL,\r
+                      &HttpInstance->TimeoutEvent\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        goto Error;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Start the timer, and wait Timeout seconds to receive the header packet.\r
+    //\r
+    Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+\r
+    Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize, HttpInstance->TimeoutEvent);\r
+\r
+    gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
+\r
     if (EFI_ERROR (Status)) {\r
       goto Error;\r
     }\r
@@ -1098,10 +1127,37 @@ HttpResponseWorker (
 \r
   ASSERT (HttpInstance->MsgParser != NULL);\r
 \r
+  if (HttpInstance->TimeoutEvent == NULL) {\r
+    //\r
+    // Create TimeoutEvent for response\r
+    //\r
+    Status = gBS->CreateEvent (\r
+                    EVT_TIMER,\r
+                    TPL_CALLBACK,\r
+                    NULL,\r
+                    NULL,\r
+                    &HttpInstance->TimeoutEvent\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Start the timer, and wait Timeout seconds to receive the body packet.\r
+  //\r
+  Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
   //\r
   // We still need receive more data when there is no cache data and MsgParser is not NULL;\r
   //\r
-  Status = HttpTcpReceiveBody (Wrap, HttpMsg);\r
+  Status = HttpTcpReceiveBody (Wrap, HttpMsg, HttpInstance->TimeoutEvent);\r
+\r
+  gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
+\r
   if (EFI_ERROR (Status)) {\r
     goto Error;\r
   }\r
index 9b3c774ae21d53feb2987b6e53f8d33617d881b4..06f3bb686061c8c62310fe99dc07c8b07dfd31cf 100644 (file)
@@ -815,6 +815,11 @@ HttpCleanProtocol (
   \r
   HttpCloseTcpConnCloseEvent (HttpInstance);\r
 \r
+  if (HttpInstance->TimeoutEvent != NULL) {\r
+    gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
+    HttpInstance->TimeoutEvent = NULL;\r
+  }\r
+\r
   if (HttpInstance->CacheBody != NULL) {\r
     FreePool (HttpInstance->CacheBody);\r
     HttpInstance->CacheBody = NULL;\r
@@ -1541,6 +1546,7 @@ HttpTcpReceive (
   @param[in]       HttpInstance     The HTTP instance private data.\r
   @param[in, out]  SizeofHeaders    The HTTP header length.\r
   @param[in, out]  BufferSize       The size of buffer to cacahe the header message.\r
+  @param[in]       Timeout          The time to wait for receiving the header packet.\r
   \r
   @retval EFI_SUCCESS               The HTTP header is received.                          \r
   @retval Others                    Other errors as indicated.\r
@@ -1550,7 +1556,8 @@ EFI_STATUS
 HttpTcpReceiveHeader (\r
   IN  HTTP_PROTOCOL         *HttpInstance,\r
   IN  OUT UINTN             *SizeofHeaders,\r
-  IN  OUT UINTN             *BufferSize\r
+  IN  OUT UINTN             *BufferSize,\r
+  IN  EFI_EVENT             Timeout\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
@@ -1599,9 +1606,14 @@ HttpTcpReceiveHeader (
         return Status;\r
       }\r
       \r
-      while (!HttpInstance->IsRxDone) {\r
-       Tcp4->Poll (Tcp4);\r
-      }    \r
+      while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+        Tcp4->Poll (Tcp4);\r
+      }\r
+\r
+      if (!HttpInstance->IsRxDone) {\r
+        gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
+        Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
+      }\r
   \r
       Status = Rx4Token->CompletionToken.Status;\r
       if (EFI_ERROR (Status)) {\r
@@ -1660,9 +1672,14 @@ HttpTcpReceiveHeader (
         return Status;\r
       }\r
       \r
-      while (!HttpInstance->IsRxDone) {\r
-       Tcp6->Poll (Tcp6);\r
-      }    \r
+      while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+        Tcp6->Poll (Tcp6);\r
+      }\r
+\r
+      if (!HttpInstance->IsRxDone) {\r
+        gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
+        Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
+      }\r
   \r
       Status = Rx6Token->CompletionToken.Status;\r
       if (EFI_ERROR (Status)) {\r
@@ -1715,6 +1732,7 @@ HttpTcpReceiveHeader (
 \r
   @param[in]  Wrap               The HTTP token's wrap data.\r
   @param[in]  HttpMsg            The HTTP message data.\r
+  @param[in]  Timeout            The time to wait for receiving the body packet.\r
 \r
   @retval EFI_SUCCESS            The HTTP body is received.                          \r
   @retval Others                 Other error as indicated.\r
@@ -1723,7 +1741,8 @@ HttpTcpReceiveHeader (
 EFI_STATUS\r
 HttpTcpReceiveBody (\r
   IN  HTTP_TOKEN_WRAP       *Wrap,\r
-  IN  EFI_HTTP_MESSAGE      *HttpMsg\r
+  IN  EFI_HTTP_MESSAGE      *HttpMsg,\r
+  IN  EFI_EVENT             Timeout\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -1738,7 +1757,6 @@ HttpTcpReceiveBody (
   Tcp6 = HttpInstance->Tcp6;\r
   Rx4Token       = NULL;\r
   Rx6Token       = NULL;\r
-\r
   \r
   if (HttpInstance->LocalAddressIsIPv6) {\r
     ASSERT (Tcp6 != NULL);\r
@@ -1758,7 +1776,17 @@ HttpTcpReceiveBody (
       DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
       return Status;\r
     }\r
-      \r
+\r
+    while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+      Tcp6->Poll (Tcp6);\r
+    }\r
+\r
+    if (!Wrap->TcpWrap.IsRxDone) {\r
+      gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
+      Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
+      Wrap->HttpToken->Status = Rx6Token->CompletionToken.Status;\r
+      gBS->SignalEvent (Wrap->HttpToken->Event);\r
+    }\r
   } else {\r
     Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
     Rx4Token->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
@@ -1771,6 +1799,17 @@ HttpTcpReceiveBody (
       DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
       return Status;\r
     }\r
+\r
+    while (!Wrap->TcpWrap.IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+      Tcp4->Poll (Tcp4);\r
+    }\r
+\r
+    if (!Wrap->TcpWrap.IsRxDone) {\r
+      gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
+      Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
+      Wrap->HttpToken->Status = Rx4Token->CompletionToken.Status;\r
+      gBS->SignalEvent (Wrap->HttpToken->Event);\r
+    }\r
   }\r
 \r
   return EFI_SUCCESS;\r
index 7b4b343b2a2e84964a67bc1667c2be1cadd5c01e..8b47fe00f69edf466bae71f86da2c2a39fd902bd 100644 (file)
@@ -47,6 +47,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define HTTP_BUFFER_SIZE_DEAULT      65535\r
 #define HTTP_MAX_SYN_BACK_LOG        5\r
 #define HTTP_CONNECTION_TIMEOUT      60\r
+#define HTTP_RESPONSE_TIMEOUT        5\r
 #define HTTP_DATA_RETRIES            12\r
 #define HTTP_FIN_TIMEOUT             2\r
 #define HTTP_KEEP_ALIVE_PROBES       6\r
@@ -93,6 +94,8 @@ typedef struct _HTTP_PROTOCOL {
 \r
   UINTN                         StatusCode;\r
 \r
+  EFI_EVENT                     TimeoutEvent;\r
+\r
   EFI_HANDLE                    Tcp4ChildHandle;\r
   EFI_TCP4_PROTOCOL             *Tcp4;\r
   EFI_TCP4_CONFIG_DATA          Tcp4CfgData;\r
@@ -116,9 +119,7 @@ typedef struct _HTTP_PROTOCOL {
   EFI_TCP6_CLOSE_TOKEN          Tcp6CloseToken;\r
   BOOLEAN                       IsTcp6CloseDone;\r
   EFI_IPv6_ADDRESS              RemoteIpv6Addr;\r
-\r
-\r
-  \r
\r
   //\r
   // Rx4Token or Rx6Token used for receiving HTTP header.\r
   //\r
@@ -504,6 +505,7 @@ HttpTcpReceive (
   @param[in]       HttpInstance    The HTTP instance private data.\r
   @param[in, out]  SizeofHeaders   The HTTP header length.\r
   @param[in, out]  BufferSize      The size of buffer to cacahe the header message.\r
+  @param[in]       Timeout         The time to wait for receiving the header packet.\r
 \r
   @retval EFI_SUCCESS              The HTTP header is received.                          \r
   @retval Others                   Other errors as indicated.\r
@@ -513,7 +515,8 @@ EFI_STATUS
 HttpTcpReceiveHeader (\r
   IN  HTTP_PROTOCOL         *HttpInstance,\r
   IN  OUT UINTN             *SizeofHeaders,\r
-  IN  OUT UINTN             *BufferSize\r
+  IN  OUT UINTN             *BufferSize,\r
+  IN  EFI_EVENT             Timeout\r
   );\r
 \r
 /**\r
@@ -521,6 +524,7 @@ HttpTcpReceiveHeader (
 \r
   @param[in]  Wrap               The HTTP token's wrap data.\r
   @param[in]  HttpMsg            The HTTP message data.\r
+  @param[in]  Timeout            The time to wait for receiving the body packet.\r
 \r
   @retval EFI_SUCCESS            The HTTP body is received.                          \r
   @retval Others                 Other error as indicated.\r
@@ -529,7 +533,8 @@ HttpTcpReceiveHeader (
 EFI_STATUS\r
 HttpTcpReceiveBody (\r
   IN  HTTP_TOKEN_WRAP       *Wrap,\r
-  IN  EFI_HTTP_MESSAGE      *HttpMsg\r
+  IN  EFI_HTTP_MESSAGE      *HttpMsg,\r
+  IN  EFI_EVENT             Timeout\r
   );\r
 \r
 /**\r