]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/HttpDxe/HttpImpl.c
NetworkPkg:Enable Http Boot over Ipv6 stack
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpImpl.c
index f1e3e5341136b28b5a0ee962041deb806af254a2..c527da08723ece2c4878f64c357ef20e4462998d 100644 (file)
@@ -51,6 +51,8 @@ EfiHttpGetModeData (
   )\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
@@ -58,24 +60,32 @@ EfiHttpGetModeData (
   \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 (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
-  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
+    CopyMem (\r
+      Http6AccessPoint,\r
+      &HttpInstance->Ipv6Node,\r
+      sizeof (HttpInstance->Ipv6Node)\r
     );\r
+    HttpConfigData->AccessPoint.IPv6Node = Http6AccessPoint;\r
+  } else {\r
+    Http4AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));\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
@@ -120,8 +130,13 @@ EfiHttpConfigure (
 {\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
@@ -129,18 +144,7 @@ EfiHttpConfigure (
   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
@@ -151,33 +155,38 @@ EfiHttpConfigure (
     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
-\r
-      HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
-      return EFI_SUCCESS;\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
-    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
@@ -264,10 +273,6 @@ EfiHttpRequest (
     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
@@ -291,7 +296,8 @@ EfiHttpRequest (
     }\r
     FreePool (HttpInstance->Url);\r
     HttpInstance->Url = Url;    \r
-  }  \r
+  } \r
+\r
 \r
   UnicodeStrToAsciiStr (Request->Url, Url);\r
   UrlParser = NULL;\r
@@ -340,7 +346,7 @@ EfiHttpRequest (
         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
@@ -379,24 +385,35 @@ EfiHttpRequest (
 \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
-    Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+    if (!HttpInstance->LocalAddressIsIPv6) {\r
+      Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+    } else {\r
+      Status = NetLibAsciiStrToIp6 (HostName, &HttpInstance->RemoteIpv6Addr);\r
+    }\r
+\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
-\r
+      \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
+\r
     //\r
     // Save the RemotePort and RemoteHost.\r
     //\r
@@ -410,7 +427,7 @@ EfiHttpRequest (
     //\r
     // The request URL is different from previous calls to Request(), close existing TCP instance.\r
     //\r
-    ASSERT (HttpInstance->Tcp4 != NULL);\r
+    ASSERT (HttpInstance->Tcp4 != NULL &&HttpInstance->Tcp6 != NULL);\r
     HttpCloseConnection (HttpInstance);\r
     EfiHttpCancel (This, NULL);\r
   }\r
@@ -429,25 +446,16 @@ EfiHttpRequest (
   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
+    Status = HttpInitTcp (HttpInstance, Wrap);\r
     if (EFI_ERROR (Status)) {\r
       goto Error2;\r
     }\r
+\r
   } else {\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
@@ -488,7 +496,7 @@ EfiHttpRequest (
   //\r
   // Transmit the request message.\r
   //\r
-  Status = HttpTransmitTcp4 (\r
+  Status = HttpTransmitTcp (\r
              HttpInstance,\r
              Wrap,\r
              (UINT8*) RequestStr,\r
@@ -499,11 +507,11 @@ EfiHttpRequest (
   }\r
 \r
   DispatchDpc ();\r
-\r
+  \r
   if (HostName != NULL) {\r
     FreePool (HostName);\r
   }\r
-\r
+  \r
   return EFI_SUCCESS;\r
 \r
 Error5:\r
@@ -517,15 +525,19 @@ Error4:
 Error3:\r
   HttpCloseConnection (HttpInstance);\r
 \r
-\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
   if (HostName != NULL) {\r
     FreePool (HostName);\r
   }\r
@@ -541,7 +553,7 @@ Error1:
 }\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
@@ -562,6 +574,7 @@ HttpCancelTokens (
 \r
   EFI_HTTP_TOKEN            *Token;\r
   HTTP_TOKEN_WRAP           *Wrap;\r
+  HTTP_PROTOCOL             *HttpInstance;\r
 \r
   Token = (EFI_HTTP_TOKEN *) Context;\r
 \r
@@ -575,24 +588,41 @@ HttpCancelTokens (
 \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
-  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
-  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
-  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
   FreePool (Wrap);\r
 \r
   //\r
@@ -747,7 +777,7 @@ HttpBodyParserCallback (
   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
@@ -761,7 +791,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
-  @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
@@ -772,12 +802,9 @@ HttpResponseWorker (
 {\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                         *Buffer;\r
   UINTN                         BufferSize;\r
   UINTN                         StatusCode;\r
   CHAR8                         *Tmp;\r
@@ -796,23 +823,21 @@ HttpResponseWorker (
   \r
   HttpInstance = Wrap->HttpInstance;\r
   Token = Wrap->HttpToken;\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
-    Status = HttpCreateTcp4RxEventForHeader (HttpInstance);\r
+    Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
     if (EFI_ERROR (Status)) {\r
       goto Error;\r
     }\r
@@ -843,70 +868,15 @@ HttpResponseWorker (
       // 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
-      // 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
+    }   \r
 \r
-      //\r
-      // Check whether we received end of HTTP headers.\r
-      //\r
-      EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
-    };\r
+    HttpInstance->EndofHeader = &EndofHeader;\r
+    HttpInstance->HttpHeaders = &HttpHeaders;\r
 \r
-    //\r
-    // Skip the CRLF after the HTTP headers.\r
-    //\r
-    EndofHeader = EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
+    Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Error;\r
+    }\r
 \r
     //\r
     // Cache the part of body.\r
@@ -927,9 +897,6 @@ HttpResponseWorker (
       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
@@ -997,7 +964,7 @@ HttpResponseWorker (
     }\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
@@ -1108,16 +1075,8 @@ HttpResponseWorker (
   //\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
-    DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
     goto Error;\r
   }\r
 \r
@@ -1130,18 +1089,7 @@ Exit:
   }\r
   Token->Status = Status;\r
   gBS->SignalEvent (Token->Event);\r
-\r
-  if (Wrap != NULL) {\r
-    if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
-      gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
-    }\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
+  HttpCloseTcpRxEvent (Wrap);\r
   FreePool (Wrap);\r
   return Status;\r
 \r
@@ -1149,28 +1097,7 @@ Error2:
   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
@@ -1268,10 +1195,6 @@ EfiHttpResponse (
     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
@@ -1287,7 +1210,7 @@ EfiHttpResponse (
   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
@@ -1308,8 +1231,12 @@ EfiHttpResponse (
 \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
@@ -1343,8 +1270,8 @@ EfiHttpPoll (
   IN  EFI_HTTP_PROTOCOL         *This\r
   )\r
 {\r
-  HTTP_PROTOCOL                 *HttpInstance;\r
   EFI_STATUS                    Status;\r
+  HTTP_PROTOCOL                 *HttpInstance;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -1353,17 +1280,18 @@ EfiHttpPoll (
   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 || (HttpInstance->Tcp4 == NULL && \r
+                                                          HttpInstance->Tcp6 == NULL)) {\r
     return EFI_NOT_STARTED;\r
   }\r
-\r
-  Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
-\r
+  \r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+  } else {\r
+    Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+  }\r
+  \r
   DispatchDpc ();\r
-\r
\r
   return Status;\r
 }\r