]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/HttpDxe/HttpImpl.c
CryptoPkg ARM: add ArmSoftFloatLib resolution to CryptoPkg.dsc
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpImpl.c
index 50c061743665b4c1511b5a849dca76dca0833029..0fa437dc327d977767987926fc26519fdd6e7a72 100644 (file)
@@ -2,6 +2,7 @@
   Implementation of EFI_HTTP_PROTOCOL protocol interfaces.\r
 \r
   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
   Implementation of EFI_HTTP_PROTOCOL protocol interfaces.\r
 \r
   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -39,6 +40,7 @@ EFI_HTTP_PROTOCOL  mEfiHttpTemplate = {
                                   This is NULL.\r
                                   HttpConfigData is NULL.\r
                                   HttpConfigData->AccessPoint is NULL.\r
                                   This is NULL.\r
                                   HttpConfigData is NULL.\r
                                   HttpConfigData->AccessPoint is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.\r
   @retval EFI_NOT_STARTED         The HTTP instance is not configured.\r
 \r
 **/\r
   @retval EFI_NOT_STARTED         The HTTP instance is not configured.\r
 \r
 **/\r
@@ -50,6 +52,8 @@ EfiHttpGetModeData (
   )\r
 {\r
   HTTP_PROTOCOL                 *HttpInstance;\r
   )\r
 {\r
   HTTP_PROTOCOL                 *HttpInstance;\r
+  EFI_HTTPv4_ACCESS_POINT       *Http4AccessPoint;\r
+  EFI_HTTPv6_ACCESS_POINT       *Http6AccessPoint;\r
 \r
   if ((This == NULL) || (HttpConfigData == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if ((This == NULL) || (HttpConfigData == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -57,24 +61,38 @@ EfiHttpGetModeData (
   \r
   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
   ASSERT (HttpInstance != NULL);\r
   \r
   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
   ASSERT (HttpInstance != NULL);\r
-\r
+  \r
   if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {\r
     return EFI_NOT_STARTED;\r
   }\r
 \r
   if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {\r
     return EFI_NOT_STARTED;\r
   }\r
 \r
-  if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
   HttpConfigData->HttpVersion        = HttpInstance->HttpVersion;\r
   HttpConfigData->TimeOutMillisec    = HttpInstance->TimeOutMillisec;\r
   HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;\r
 \r
   HttpConfigData->HttpVersion        = HttpInstance->HttpVersion;\r
   HttpConfigData->TimeOutMillisec    = HttpInstance->TimeOutMillisec;\r
   HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;\r
 \r
-  CopyMem (\r
-    HttpConfigData->AccessPoint.IPv4Node,\r
-    &HttpInstance->IPv4Node,\r
-    sizeof (HttpInstance->IPv4Node)\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    Http6AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));\r
+    if (Http6AccessPoint == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (\r
+      Http6AccessPoint,\r
+      &HttpInstance->Ipv6Node,\r
+      sizeof (HttpInstance->Ipv6Node)\r
     );\r
     );\r
+    HttpConfigData->AccessPoint.IPv6Node = Http6AccessPoint;\r
+  } else {\r
+    Http4AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));\r
+    if (Http4AccessPoint == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem (\r
+      Http4AccessPoint,\r
+      &HttpInstance->IPv4Node,\r
+      sizeof (HttpInstance->IPv4Node)\r
+      );\r
+    HttpConfigData->AccessPoint.IPv4Node = Http4AccessPoint;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -119,8 +137,13 @@ EfiHttpConfigure (
 {\r
   HTTP_PROTOCOL                 *HttpInstance;\r
   EFI_STATUS                    Status;\r
 {\r
   HTTP_PROTOCOL                 *HttpInstance;\r
   EFI_STATUS                    Status;\r
-\r
-  if (This == NULL) {\r
+  \r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if (This == NULL || \r
+     (HttpConfigData != NULL && ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||\r
+                                 (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL)))) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -128,18 +151,7 @@ EfiHttpConfigure (
   ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);\r
 \r
   if (HttpConfigData != NULL) {\r
   ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);\r
 \r
   if (HttpConfigData != NULL) {\r
-    //\r
-    // Check input parameters.\r
-    //\r
-    if (HttpConfigData->LocalAddressIsIPv6) {\r
-      if (HttpConfigData->AccessPoint.IPv6Node == NULL) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-    } else {\r
-      if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-    }\r
+\r
     //\r
     // Now configure this HTTP instance.\r
     //\r
     //\r
     // Now configure this HTTP instance.\r
     //\r
@@ -150,33 +162,38 @@ EfiHttpConfigure (
     HttpInstance->HttpVersion        = HttpConfigData->HttpVersion;\r
     HttpInstance->TimeOutMillisec    = HttpConfigData->TimeOutMillisec;\r
     HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;\r
     HttpInstance->HttpVersion        = HttpConfigData->HttpVersion;\r
     HttpInstance->TimeOutMillisec    = HttpConfigData->TimeOutMillisec;\r
     HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;\r
-\r
-    if (HttpConfigData->LocalAddressIsIPv6) {\r
-      return EFI_UNSUPPORTED;\r
+    \r
+    if (HttpConfigData->LocalAddressIsIPv6) { \r
+      CopyMem (\r
+        &HttpInstance->Ipv6Node,\r
+        HttpConfigData->AccessPoint.IPv6Node,\r
+        sizeof (HttpInstance->Ipv6Node)\r
+        );\r
     } else {\r
       CopyMem (\r
         &HttpInstance->IPv4Node,\r
         HttpConfigData->AccessPoint.IPv4Node,\r
         sizeof (HttpInstance->IPv4Node)\r
         );\r
     } else {\r
       CopyMem (\r
         &HttpInstance->IPv4Node,\r
         HttpConfigData->AccessPoint.IPv4Node,\r
         sizeof (HttpInstance->IPv4Node)\r
         );\r
-\r
-      HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
-      return EFI_SUCCESS;\r
     }\r
     }\r
+    //\r
+    // Creat Tcp child\r
+    //\r
+    Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    \r
+    HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
+    return EFI_SUCCESS;\r
 \r
   } else {\r
 \r
   } else {\r
-    if (HttpInstance->LocalAddressIsIPv6) {\r
-      return EFI_UNSUPPORTED;\r
-    } else {\r
-      HttpCleanProtocol (HttpInstance);\r
-      Status = HttpInitProtocol (HttpInstance->Service, HttpInstance);\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-\r
-      HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
-      return EFI_SUCCESS;\r
-    }\r
+    //\r
+    // Reset all the resources related to HttpInsance.\r
+    //\r
+    HttpCleanProtocol (HttpInstance);\r
+    HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
+    return EFI_SUCCESS;\r
   }\r
 }\r
  \r
   }\r
 }\r
  \r
@@ -227,7 +244,6 @@ EfiHttpRequest (
   UINTN                         UrlLen;\r
   CHAR16                        *HostNameStr;\r
   HTTP_TOKEN_WRAP               *Wrap;\r
   UINTN                         UrlLen;\r
   CHAR16                        *HostNameStr;\r
   HTTP_TOKEN_WRAP               *Wrap;\r
-  HTTP_TCP_TOKEN_WRAP           *TcpWrap;\r
   CHAR8                         *FileUrl;\r
   \r
   if ((This == NULL) || (Token == NULL)) {\r
   CHAR8                         *FileUrl;\r
   \r
   if ((This == NULL) || (Token == NULL)) {\r
@@ -264,10 +280,6 @@ EfiHttpRequest (
     return EFI_NOT_STARTED;\r
   }\r
 \r
     return EFI_NOT_STARTED;\r
   }\r
 \r
-  if (HttpInstance->LocalAddressIsIPv6) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
   //\r
   // Check whether the token already existed.\r
   //\r
   //\r
   // Check whether the token already existed.\r
   //\r
@@ -278,7 +290,6 @@ EfiHttpRequest (
   HostName    = NULL;\r
   Wrap        = NULL;\r
   HostNameStr = NULL;\r
   HostName    = NULL;\r
   Wrap        = NULL;\r
   HostNameStr = NULL;\r
-  TcpWrap     = NULL;\r
 \r
   //\r
   // Parse the URI of the remote host.\r
 \r
   //\r
   // Parse the URI of the remote host.\r
@@ -292,7 +303,8 @@ EfiHttpRequest (
     }\r
     FreePool (HttpInstance->Url);\r
     HttpInstance->Url = Url;    \r
     }\r
     FreePool (HttpInstance->Url);\r
     HttpInstance->Url = Url;    \r
-  }  \r
+  } \r
+\r
 \r
   UnicodeStrToAsciiStr (Request->Url, Url);\r
   UrlParser = NULL;\r
 \r
   UnicodeStrToAsciiStr (Request->Url, Url);\r
   UrlParser = NULL;\r
@@ -312,7 +324,11 @@ EfiHttpRequest (
   if (EFI_ERROR (Status)) {\r
     RemotePort = HTTP_DEFAULT_PORT;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     RemotePort = HTTP_DEFAULT_PORT;\r
   }\r
-\r
+  //\r
+  // If Configure is TRUE, it indicates the first time to call Request();\r
+  // If ReConfigure is TRUE, it indicates the request URL is not same\r
+  // with the previous call to Request();\r
+  //\r
   Configure   = TRUE;\r
   ReConfigure = TRUE;  \r
 \r
   Configure   = TRUE;\r
   ReConfigure = TRUE;  \r
 \r
@@ -341,7 +357,7 @@ EfiHttpRequest (
         Wrap->HttpToken    = Token;\r
         Wrap->HttpInstance = HttpInstance;\r
 \r
         Wrap->HttpToken    = Token;\r
         Wrap->HttpInstance = HttpInstance;\r
 \r
-        Status = HttpCreateTcp4TxEvent (Wrap);\r
+        Status = HttpCreateTcpTxEvent (Wrap);\r
         if (EFI_ERROR (Status)) {\r
           goto Error1;\r
         }\r
         if (EFI_ERROR (Status)) {\r
           goto Error1;\r
         }\r
@@ -380,24 +396,35 @@ EfiHttpRequest (
 \r
   if (Configure) {\r
     //\r
 \r
   if (Configure) {\r
     //\r
-    // Parse Url for IPv4 address, if failed, perform DNS resolution.\r
+    // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.\r
     //\r
     //\r
-    Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+    if (!HttpInstance->LocalAddressIsIPv6) {\r
+      Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+    } else {\r
+      Status = HttpUrlGetIp6 (Url, UrlParser, &HttpInstance->RemoteIpv6Addr);\r
+    }\r
+\r
     if (EFI_ERROR (Status)) {\r
     if (EFI_ERROR (Status)) {\r
-      HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16));\r
+      HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));\r
       if (HostNameStr == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Error1;\r
       }\r
       if (HostNameStr == NULL) {\r
         Status = EFI_OUT_OF_RESOURCES;\r
         goto Error1;\r
       }\r
-\r
+      \r
       AsciiStrToUnicodeStr (HostName, HostNameStr);\r
       AsciiStrToUnicodeStr (HostName, HostNameStr);\r
-      Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+      if (!HttpInstance->LocalAddressIsIPv6) {\r
+        Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+      } else {\r
+        Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);\r
+      }\r
+      \r
       FreePool (HostNameStr);\r
       if (EFI_ERROR (Status)) {\r
         goto Error1;\r
       }\r
     }\r
 \r
       FreePool (HostNameStr);\r
       if (EFI_ERROR (Status)) {\r
         goto Error1;\r
       }\r
     }\r
 \r
+\r
     //\r
     // Save the RemotePort and RemoteHost.\r
     //\r
     //\r
     // Save the RemotePort and RemoteHost.\r
     //\r
@@ -411,7 +438,11 @@ EfiHttpRequest (
     //\r
     // The request URL is different from previous calls to Request(), close existing TCP instance.\r
     //\r
     //\r
     // The request URL is different from previous calls to Request(), close existing TCP instance.\r
     //\r
-    ASSERT (HttpInstance->Tcp4 != NULL);\r
+    if (!HttpInstance->LocalAddressIsIPv6) {\r
+      ASSERT (HttpInstance->Tcp4 != NULL);\r
+    } else {\r
+      ASSERT (HttpInstance->Tcp6 != NULL);\r
+    }\r
     HttpCloseConnection (HttpInstance);\r
     EfiHttpCancel (This, NULL);\r
   }\r
     HttpCloseConnection (HttpInstance);\r
     EfiHttpCancel (This, NULL);\r
   }\r
@@ -429,31 +460,21 @@ EfiHttpRequest (
   Wrap->HttpInstance   = HttpInstance;\r
   Wrap->TcpWrap.Method = Request->Method;\r
 \r
   Wrap->HttpInstance   = HttpInstance;\r
   Wrap->TcpWrap.Method = Request->Method;\r
 \r
-  if (Configure) {\r
-    //\r
-    // Configure TCP instance.\r
-    //\r
-    Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error1;\r
-    }\r
-    //\r
-    // Connect TCP.\r
-    //\r
-    Status = HttpConnectTcp4 (HttpInstance);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Error2;\r
-    }\r
-  } else {\r
+  Status = HttpInitTcp (HttpInstance, Wrap, Configure);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error2;\r
+  }  \r
+\r
+  if (!Configure) {\r
     //\r
     // For the new HTTP token, create TX TCP token events.    \r
     //\r
     //\r
     // For the new HTTP token, create TX TCP token events.    \r
     //\r
-    Status = HttpCreateTcp4TxEvent (Wrap);\r
+    Status = HttpCreateTcpTxEvent (Wrap);\r
     if (EFI_ERROR (Status)) {\r
       goto Error1;\r
     }\r
   }\r
     if (EFI_ERROR (Status)) {\r
       goto Error1;\r
     }\r
   }\r
-\r
+  \r
   //\r
   // Create request message.\r
   //\r
   //\r
   // Create request message.\r
   //\r
@@ -486,14 +507,10 @@ EfiHttpRequest (
     goto Error4;\r
   }\r
 \r
     goto Error4;\r
   }\r
 \r
-  if (HostName != NULL) {\r
-    FreePool (HostName);\r
-  }\r
-\r
   //\r
   // Transmit the request message.\r
   //\r
   //\r
   // Transmit the request message.\r
   //\r
-  Status = HttpTransmitTcp4 (\r
+  Status = HttpTransmitTcp (\r
              HttpInstance,\r
              Wrap,\r
              (UINT8*) RequestStr,\r
              HttpInstance,\r
              Wrap,\r
              (UINT8*) RequestStr,\r
@@ -504,7 +521,11 @@ EfiHttpRequest (
   }\r
 \r
   DispatchDpc ();\r
   }\r
 \r
   DispatchDpc ();\r
-\r
+  \r
+  if (HostName != NULL) {\r
+    FreePool (HostName);\r
+  }\r
+  \r
   return EFI_SUCCESS;\r
 \r
 Error5:\r
   return EFI_SUCCESS;\r
 \r
 Error5:\r
@@ -518,15 +539,19 @@ Error4:
 Error3:\r
   HttpCloseConnection (HttpInstance);\r
 \r
 Error3:\r
   HttpCloseConnection (HttpInstance);\r
 \r
-\r
 Error2:\r
 Error2:\r
-  HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
-  if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) {\r
-    gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
-    Wrap->TcpWrap.TxToken.CompletionToken.Event = NULL;\r
+  HttpCloseTcpConnCloseEvent (HttpInstance);\r
+  if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {\r
+    gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+    Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;\r
+  }\r
+  if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {\r
+    gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+    Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;\r
   }\r
 \r
 Error1:\r
   }\r
 \r
 Error1:\r
+\r
   if (HostName != NULL) {\r
     FreePool (HostName);\r
   }\r
   if (HostName != NULL) {\r
     FreePool (HostName);\r
   }\r
@@ -542,7 +567,7 @@ Error1:
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Cancel a TxToken or RxToken. \r
+  Cancel a user's Token. \r
  \r
   @param[in]  Map                The HTTP instance's token queue.\r
   @param[in]  Item               Object container for one HTTP token and token's wrap.\r
  \r
   @param[in]  Map                The HTTP instance's token queue.\r
   @param[in]  Item               Object container for one HTTP token and token's wrap.\r
@@ -563,6 +588,7 @@ HttpCancelTokens (
 \r
   EFI_HTTP_TOKEN            *Token;\r
   HTTP_TOKEN_WRAP           *Wrap;\r
 \r
   EFI_HTTP_TOKEN            *Token;\r
   HTTP_TOKEN_WRAP           *Wrap;\r
+  HTTP_PROTOCOL             *HttpInstance;\r
 \r
   Token = (EFI_HTTP_TOKEN *) Context;\r
 \r
 \r
   Token = (EFI_HTTP_TOKEN *) Context;\r
 \r
@@ -576,24 +602,41 @@ HttpCancelTokens (
 \r
   Wrap = (HTTP_TOKEN_WRAP *) Item->Value;\r
   ASSERT (Wrap != NULL);\r
 \r
   Wrap = (HTTP_TOKEN_WRAP *) Item->Value;\r
   ASSERT (Wrap != NULL);\r
+  HttpInstance = Wrap->HttpInstance;\r
 \r
   //\r
   // Free resources.\r
   //\r
   NetMapRemoveItem (Map, Item, NULL); \r
   \r
 \r
   //\r
   // Free resources.\r
   //\r
   NetMapRemoveItem (Map, Item, NULL); \r
   \r
-  if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {\r
-    gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
-  }\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+    }\r
+    \r
+    if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+    }\r
+    \r
+    if (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+    }\r
 \r
 \r
-  if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
-    gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
-  }\r
+  } else {\r
+    if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+    }\r
+\r
+    if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+    }\r
 \r
 \r
-  if (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
-    FreePool (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+    if (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+    }\r
   }\r
 \r
   }\r
 \r
+\r
   FreePool (Wrap);\r
 \r
   //\r
   FreePool (Wrap);\r
 \r
   //\r
@@ -748,7 +791,7 @@ HttpBodyParserCallback (
   Wrap->HttpInstance->NextMsg = Data;\r
 \r
   //\r
   Wrap->HttpInstance->NextMsg = Data;\r
 \r
   //\r
-  // Free TxToken since already received corrsponding HTTP response.\r
+  // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.\r
   //\r
   FreePool (Wrap);\r
 \r
   //\r
   FreePool (Wrap);\r
 \r
@@ -762,7 +805,7 @@ HttpBodyParserCallback (
 \r
   @retval EFI_SUCCESS             Allocation succeeded.\r
   @retval EFI_OUT_OF_RESOURCES    Failed to complete the opration due to lack of resources.\r
 \r
   @retval EFI_SUCCESS             Allocation succeeded.\r
   @retval EFI_OUT_OF_RESOURCES    Failed to complete the opration due to lack of resources.\r
-  @retval EFI_NOT_READY           Can't find a corresponding TxToken or \r
+  @retval EFI_NOT_READY           Can't find a corresponding Tx4Token/Tx6Token or \r
                                   the EFI_HTTP_UTILITIES_PROTOCOL is not available.\r
 \r
 **/\r
                                   the EFI_HTTP_UTILITIES_PROTOCOL is not available.\r
 \r
 **/\r
@@ -773,12 +816,9 @@ HttpResponseWorker (
 {\r
   EFI_STATUS                    Status;\r
   EFI_HTTP_MESSAGE              *HttpMsg;\r
 {\r
   EFI_STATUS                    Status;\r
   EFI_HTTP_MESSAGE              *HttpMsg;\r
-  EFI_TCP4_IO_TOKEN             *RxToken;\r
-  EFI_TCP4_PROTOCOL             *Tcp4;\r
   CHAR8                         *EndofHeader;\r
   CHAR8                         *HttpHeaders;\r
   UINTN                         SizeofHeaders;\r
   CHAR8                         *EndofHeader;\r
   CHAR8                         *HttpHeaders;\r
   UINTN                         SizeofHeaders;\r
-  CHAR8                         *Buffer;\r
   UINTN                         BufferSize;\r
   UINTN                         StatusCode;\r
   CHAR8                         *Tmp;\r
   UINTN                         BufferSize;\r
   UINTN                         StatusCode;\r
   CHAR8                         *Tmp;\r
@@ -797,23 +837,21 @@ HttpResponseWorker (
   \r
   HttpInstance = Wrap->HttpInstance;\r
   Token = Wrap->HttpToken;\r
   \r
   HttpInstance = Wrap->HttpInstance;\r
   Token = Wrap->HttpToken;\r
-\r
   HttpMsg = Token->Message;\r
 \r
   HttpMsg = Token->Message;\r
 \r
-  Tcp4 = HttpInstance->Tcp4;\r
-  ASSERT (Tcp4 != NULL);\r
-  HttpMsg->Headers = NULL;\r
-  HttpHeaders   = NULL;\r
-  SizeofHeaders = 0;\r
-  Buffer        = NULL;\r
-  BufferSize    = 0;\r
-  EndofHeader   = NULL;\r
+  HttpInstance->EndofHeader = NULL;\r
+  HttpInstance->HttpHeaders = NULL;\r
+  HttpMsg->Headers          = NULL;\r
+  HttpHeaders               = NULL;\r
+  SizeofHeaders             = 0;\r
+  BufferSize                = 0;\r
+  EndofHeader               = NULL;\r
  \r
   if (HttpMsg->Data.Response != NULL) {\r
     //\r
     // Need receive the HTTP headers, prepare buffer.\r
     //\r
  \r
   if (HttpMsg->Data.Response != NULL) {\r
     //\r
     // Need receive the HTTP headers, prepare buffer.\r
     //\r
-    Status = HttpCreateTcp4RxEventForHeader (HttpInstance);\r
+    Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
     if (EFI_ERROR (Status)) {\r
       goto Error;\r
     }\r
     if (EFI_ERROR (Status)) {\r
       goto Error;\r
     }\r
@@ -844,70 +882,17 @@ HttpResponseWorker (
       // Check whether we cached the whole HTTP headers.\r
       //\r
       EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
       // Check whether we cached the whole HTTP headers.\r
       //\r
       EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
-    }\r
-    \r
-    RxToken = &HttpInstance->RxToken;\r
-    RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
-    if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-      goto Error;\r
-    }\r
-\r
-    //\r
-    // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
-    //\r
-    while (EndofHeader == NULL) {   \r
-      HttpInstance->IsRxDone = FALSE;\r
-      RxToken->Packet.RxData->DataLength = DEF_BUF_LEN;\r
-      RxToken->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
-      Status = Tcp4->Receive (Tcp4, RxToken);\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
-        goto Error;\r
-      }\r
-      \r
-      while (!HttpInstance->IsRxDone) {\r
-       Tcp4->Poll (Tcp4);\r
-      }    \r
-\r
-      Status = RxToken->CompletionToken.Status;\r
-      if (EFI_ERROR (Status)) {\r
-        goto Error;\r
-      }\r
+    }   \r
 \r
 \r
-      //\r
-      // Append the response string.\r
-      //\r
-      BufferSize = SizeofHeaders + RxToken->Packet.RxData->FragmentTable[0].FragmentLength;\r
-      Buffer = AllocateZeroPool (BufferSize);\r
-      if (Buffer == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
-        goto Error;\r
-      }\r
-\r
-      if (HttpHeaders != NULL) {\r
-        CopyMem (Buffer, HttpHeaders, SizeofHeaders);\r
-        FreePool (HttpHeaders);\r
-      }\r
-\r
-      CopyMem (\r
-        Buffer + SizeofHeaders,\r
-        RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
-        RxToken->Packet.RxData->FragmentTable[0].FragmentLength\r
-        );\r
-      HttpHeaders   = Buffer;\r
-      SizeofHeaders = BufferSize;\r
+    HttpInstance->EndofHeader = &EndofHeader;\r
+    HttpInstance->HttpHeaders = &HttpHeaders;\r
 \r
 \r
-      //\r
-      // Check whether we received end of HTTP headers.\r
-      //\r
-      EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
-    };\r
+    Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
 \r
 \r
-    //\r
-    // Skip the CRLF after the HTTP headers.\r
-    //\r
-    EndofHeader = EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
+    ASSERT (HttpHeaders != NULL);\r
 \r
     //\r
     // Cache the part of body.\r
 \r
     //\r
     // Cache the part of body.\r
@@ -928,9 +913,6 @@ HttpResponseWorker (
       HttpInstance->CacheLen = BodyLen;\r
     }\r
 \r
       HttpInstance->CacheLen = BodyLen;\r
     }\r
 \r
-    FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
-    RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
-\r
     //\r
     // Search for Status Code.\r
     //\r
     //\r
     // Search for Status Code.\r
     //\r
@@ -998,7 +980,7 @@ HttpResponseWorker (
     }\r
 \r
     //\r
     }\r
 \r
     //\r
-    // The first TxToken not transmitted yet, insert back and return error.\r
+    // The first Tx Token not transmitted yet, insert back and return error.\r
     //\r
     if (!ValueInItem->TcpWrap.IsTxDone) {\r
       goto Error2;\r
     //\r
     if (!ValueInItem->TcpWrap.IsTxDone) {\r
       goto Error2;\r
@@ -1109,16 +1091,8 @@ HttpResponseWorker (
   //\r
   // We still need receive more data when there is no cache data and MsgParser is not NULL;\r
   //\r
   //\r
   // We still need receive more data when there is no cache data and MsgParser is not NULL;\r
   //\r
-  RxToken = &Wrap->TcpWrap.RxToken;\r
-\r
-  RxToken->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
-  RxToken->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
-  RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
-\r
-  RxToken->CompletionToken.Status = EFI_NOT_READY;\r
-  Status = Tcp4->Receive (Tcp4, RxToken);\r
+  Status = HttpTcpReceiveBody (Wrap, HttpMsg);\r
   if (EFI_ERROR (Status)) {\r
   if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
     goto Error;\r
   }\r
 \r
     goto Error;\r
   }\r
 \r
@@ -1131,6 +1105,7 @@ Exit:
   }\r
   Token->Status = Status;\r
   gBS->SignalEvent (Token->Event);\r
   }\r
   Token->Status = Status;\r
   gBS->SignalEvent (Token->Event);\r
+  HttpCloseTcpRxEvent (Wrap);\r
   FreePool (Wrap);\r
   return Status;\r
 \r
   FreePool (Wrap);\r
   return Status;\r
 \r
@@ -1138,28 +1113,7 @@ Error2:
   NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);\r
 \r
 Error:\r
   NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);\r
 \r
 Error:\r
-  if (Wrap != NULL) {\r
-    if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
-      gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
-    }\r
-    RxToken = &Wrap->TcpWrap.RxToken;\r
-    if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
-      FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
-      RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
-    }\r
-    FreePool (Wrap);\r
-  }\r
-\r
-  if (HttpInstance->RxToken.CompletionToken.Event != NULL) {\r
-    gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);\r
-    HttpInstance->RxToken.CompletionToken.Event = NULL;\r
-  }\r
-\r
-  RxToken = &HttpInstance->RxToken;\r
-  if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
-    FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
-    RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
-  }\r
+  HttpTcpTokenCleanup (Wrap);\r
   \r
   if (HttpHeaders != NULL) {\r
     FreePool (HttpHeaders);\r
   \r
   if (HttpHeaders != NULL) {\r
     FreePool (HttpHeaders);\r
@@ -1257,10 +1211,6 @@ EfiHttpResponse (
     return EFI_NOT_STARTED;\r
   }\r
 \r
     return EFI_NOT_STARTED;\r
   }\r
 \r
-  if (HttpInstance->LocalAddressIsIPv6) {\r
-    return EFI_UNSUPPORTED;\r
-  }  \r
-\r
   //\r
   // Check whether the token already existed.\r
   //\r
   //\r
   // Check whether the token already existed.\r
   //\r
@@ -1276,7 +1226,7 @@ EfiHttpResponse (
   Wrap->HttpInstance = HttpInstance;\r
   Wrap->HttpToken    = Token;\r
 \r
   Wrap->HttpInstance = HttpInstance;\r
   Wrap->HttpToken    = Token;\r
 \r
-  Status = HttpCreateTcp4RxEvent (Wrap);\r
+  Status = HttpCreateTcpRxEvent (Wrap);\r
   if (EFI_ERROR (Status)) {\r
     goto Error;\r
   }\r
   if (EFI_ERROR (Status)) {\r
     goto Error;\r
   }\r
@@ -1297,8 +1247,12 @@ EfiHttpResponse (
 \r
 Error:\r
   if (Wrap != NULL) {\r
 \r
 Error:\r
   if (Wrap != NULL) {\r
-    if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
-      gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
+    if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+    }\r
+\r
+    if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
     }\r
     FreePool (Wrap);\r
   }  \r
     }\r
     FreePool (Wrap);\r
   }  \r
@@ -1332,8 +1286,8 @@ EfiHttpPoll (
   IN  EFI_HTTP_PROTOCOL         *This\r
   )\r
 {\r
   IN  EFI_HTTP_PROTOCOL         *This\r
   )\r
 {\r
-  HTTP_PROTOCOL                 *HttpInstance;\r
   EFI_STATUS                    Status;\r
   EFI_STATUS                    Status;\r
+  HTTP_PROTOCOL                 *HttpInstance;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1342,17 +1296,23 @@ EfiHttpPoll (
   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
   ASSERT (HttpInstance != NULL);\r
 \r
   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
   ASSERT (HttpInstance != NULL);\r
 \r
-  if (HttpInstance->LocalAddressIsIPv6) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  if (HttpInstance->Tcp4 == NULL || HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {\r
+  if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {\r
     return EFI_NOT_STARTED;\r
   }\r
     return EFI_NOT_STARTED;\r
   }\r
-\r
-  Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
-\r
+  \r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    if (HttpInstance->Tcp6 == NULL) {\r
+      return EFI_NOT_STARTED;\r
+    }\r
+    Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+  } else {\r
+    if (HttpInstance->Tcp4 == NULL) {\r
+      return EFI_NOT_STARTED;\r
+    }\r
+    Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+  }\r
+  \r
   DispatchDpc ();\r
   DispatchDpc ();\r
-\r
\r
   return Status;\r
 }\r
   return Status;\r
 }\r