147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/** @file
247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Implementation of EFI_HTTP_PROTOCOL protocol interfaces.
347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5c5a693cea60823e0a3df5a3e92604e4e8936c84aSamer El-Haj-Mahmoud  (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  This program and the accompanying materials
847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  are licensed and made available under the terms and conditions of the BSD License
947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  which accompanies this distribution.  The full text of the license may be found at
1047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  http://opensource.org/licenses/bsd-license.php.
1147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
1247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
1547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
1647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
1747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting#include "HttpDriver.h"
1847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
1947f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_HTTP_PROTOCOL  mEfiHttpTemplate = {
2047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpGetModeData,
2147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpConfigure,
2247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpRequest,
2347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpCancel,
2447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpResponse,
2547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpPoll
2647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting};
2747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
2847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
2947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Returns the operational parameters for the current HTTP child instance.
3047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
3147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The GetModeData() function is used to read the current mode data (operational
3247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  parameters) for this HTTP protocol instance.
3347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
3447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
3547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[out] HttpConfigData      Point to buffer for operational parameters of this
3647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HTTP instance.
3747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
3847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Operation succeeded.
3947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
4047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  This is NULL.
4147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData is NULL.
4247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData->AccessPoint is NULL.
431b96428d92c01383dc437717db679f57cf70d980Zhang Lubo  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
4447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_STARTED         The HTTP instance is not configured.
4547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
4647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
4747f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
4847f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
4947f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpGetModeData (
5047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This,
5147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  OUT EFI_HTTP_CONFIG_DATA      *HttpConfigData
5247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
5347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
5447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
55b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  EFI_HTTPv4_ACCESS_POINT       *Http4AccessPoint;
56b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  EFI_HTTPv6_ACCESS_POINT       *Http6AccessPoint;
5747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
5847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((This == NULL) || (HttpConfigData == NULL)) {
5947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
6047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
6147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
6247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
6347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL);
64b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
6547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
6647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_NOT_STARTED;
6747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
6847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
6947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpConfigData->HttpVersion        = HttpInstance->HttpVersion;
7047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpConfigData->TimeOutMillisec    = HttpInstance->TimeOutMillisec;
7147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;
7247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
73b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (HttpInstance->LocalAddressIsIPv6) {
74b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Http6AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
751b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    if (Http6AccessPoint == NULL) {
761b96428d92c01383dc437717db679f57cf70d980Zhang Lubo      return EFI_OUT_OF_RESOURCES;
771b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    }
78b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    CopyMem (
79b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      Http6AccessPoint,
80b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      &HttpInstance->Ipv6Node,
81b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      sizeof (HttpInstance->Ipv6Node)
8247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    );
83b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpConfigData->AccessPoint.IPv6Node = Http6AccessPoint;
84b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  } else {
85b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Http4AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
861b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    if (Http4AccessPoint == NULL) {
871b96428d92c01383dc437717db679f57cf70d980Zhang Lubo      return EFI_OUT_OF_RESOURCES;
881b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    }
89b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    CopyMem (
90b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      Http4AccessPoint,
91b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      &HttpInstance->IPv4Node,
92b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      sizeof (HttpInstance->IPv4Node)
93b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      );
94b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpConfigData->AccessPoint.IPv4Node = Http4AccessPoint;
95b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  }
9647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
9747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return EFI_SUCCESS;
9847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
9947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
10047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
10147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Initialize or brutally reset the operational parameters for this EFI HTTP instance.
10247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
10347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The Configure() function does the following:
10447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  When HttpConfigData is not NULL Initialize this EFI HTTP instance by configuring
10547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  timeout, local address, port, etc.
10647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  When HttpConfigData is NULL, reset this EFI HTTP instance by closing all active
10747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  connections with remote hosts, canceling all asynchronous tokens, and flush request
10847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  and response buffers without informing the appropriate hosts.
10947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
11047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Except for GetModeData() and Configure(), No other EFI HTTP function can be executed
11147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  by this instance until the Configure() function is executed and returns successfully.
11247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
11347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
11447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  HttpConfigData      Pointer to the configure data to configure the instance.
11547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
11647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Operation succeeded.
11747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
11847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  This is NULL.
11947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData->LocalAddressIsIPv6 is FALSE and
12047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData->IPv4Node is NULL.
12147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData->LocalAddressIsIPv6 is TRUE and
12247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  HttpConfigData->IPv6Node is NULL.
12347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_ALREADY_STARTED     Reinitialize this HTTP instance without calling
12447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Configure() with NULL to reset it.
12547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
12647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources when
12747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  executing Configure().
12847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_UNSUPPORTED         One or more options in HttpConfigData are not supported
12947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  in the implementation.
13047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
13147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
13247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
13347f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpConfigure (
13447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This,
13547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_CONFIG_DATA      *HttpConfigData
13647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
13747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
13847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
13947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_STATUS                    Status;
140b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
141b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  //
142b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  // Check input parameters.
143b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  //
144b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (This == NULL ||
145b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo     (HttpConfigData != NULL && ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||
146b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo                                 (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL)))) {
14747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
14847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
14947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
15047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
15147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);
15247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
15347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpConfigData != NULL) {
154b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
15547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
15647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Now configure this HTTP instance.
15747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
15847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (HttpInstance->State != HTTP_STATE_UNCONFIGED) {
15947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      return EFI_ALREADY_STARTED;
16047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
16147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
16247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->HttpVersion        = HttpConfigData->HttpVersion;
16347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->TimeOutMillisec    = HttpConfigData->TimeOutMillisec;
16447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
165b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
166b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (HttpConfigData->LocalAddressIsIPv6) {
167b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      CopyMem (
168b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        &HttpInstance->Ipv6Node,
169b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        HttpConfigData->AccessPoint.IPv6Node,
170b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        sizeof (HttpInstance->Ipv6Node)
171b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        );
17247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    } else {
17347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      CopyMem (
17447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        &HttpInstance->IPv4Node,
17547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpConfigData->AccessPoint.IPv4Node,
17647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        sizeof (HttpInstance->IPv4Node)
17747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        );
17847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
179b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    //
180b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    // Creat Tcp child
181b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    //
182b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);
183b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (EFI_ERROR (Status)) {
184b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      return Status;
185b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
186b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
187b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;
188b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    return EFI_SUCCESS;
18947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
19047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  } else {
191b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    //
192b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    // Reset all the resources related to HttpInsance.
193b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    //
194b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpCleanProtocol (HttpInstance);
195b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpInstance->State = HTTP_STATE_UNCONFIGED;
196b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    return EFI_SUCCESS;
19747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
19847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
19947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
20047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
20147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
20247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The Request() function queues an HTTP request to this HTTP instance.
20347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
20447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Similar to Transmit() function in the EFI TCP driver. When the HTTP request is sent
20547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  successfully, or if there is an error, Status in token will be updated and Event will
20647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  be signaled.
20747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
20847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
20947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Token               Pointer to storage containing HTTP request token.
21047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
21147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Outgoing data was processed.
21247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
21347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
21447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_TIMEOUT             Data was dropped out of the transmit or receive queue.
21547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
21647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_UNSUPPORTED         The HTTP method is not supported in current
21747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  implementation.
21847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
21947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  This is NULL.
22047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message is NULL.
22147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->Body is not NULL,
22247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->BodyLength is non-zero, and
22347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->Data is NULL, but a previous call to
22447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Request()has not been completed successfully.
22547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
22647f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
22747f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
22847f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpRequest (
22947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This,
23047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_TOKEN            *Token
23147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
23247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
23347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_MESSAGE              *HttpMsg;
23447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_REQUEST_DATA         *Request;
23547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  VOID                          *UrlParser;
23647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_STATUS                    Status;
23747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *HostName;
23847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINT16                        RemotePort;
23947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
24047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BOOLEAN                       Configure;
24147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BOOLEAN                       ReConfigure;
24247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *RequestStr;
24347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *Url;
24451b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan  UINTN                         UrlLen;
24547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR16                        *HostNameStr;
24647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_TOKEN_WRAP               *Wrap;
247b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin  CHAR8                         *FileUrl;
248b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin
24947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((This == NULL) || (Token == NULL)) {
25047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
25147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
25247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
25347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpMsg = Token->Message;
25447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((HttpMsg == NULL) || (HttpMsg->Headers == NULL)) {
25547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
25647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
25747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
25847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
25947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Current implementation does not support POST/PUT method.
26047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // If future version supports these two methods, Request could be NULL for a special case that to send large amounts
26147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // of data. For this case, the implementation need check whether previous call to Request() has been completed or not.
26247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
26347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
26447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Request = HttpMsg->Data.Request;
26547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((Request == NULL) || (Request->Url == NULL)) {
26647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
26747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
26847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
26947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
27047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Only support GET and HEAD method in current implementation.
27147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
27247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((Request->Method != HttpMethodGet) && (Request->Method != HttpMethodHead)) {
27347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_UNSUPPORTED;
27447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
27547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
27647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
27747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL);
27847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
27947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
28047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_NOT_STARTED;
28147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
28247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
28347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
28447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Check whether the token already existed.
28547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
28647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) {
28747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_ACCESS_DENIED;
28847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
28947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
29047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HostName    = NULL;
29147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap        = NULL;
29247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HostNameStr = NULL;
29347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
29447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
29547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Parse the URI of the remote host.
29647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
2977ef0690f7c116e8760b5556e8c91d5902deee255Fu Siyuan  Url = HttpInstance->Url;
29851b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan  UrlLen = StrLen (Request->Url) + 1;
29951b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan  if (UrlLen > HTTP_URL_BUFFER_LEN) {
30051b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan    Url = AllocateZeroPool (UrlLen);
30151b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan    if (Url == NULL) {
30251b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan      return EFI_OUT_OF_RESOURCES;
30351b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan    }
30451b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan    FreePool (HttpInstance->Url);
30551b0450e002431b7cb902220c513ddaf589f3600Fu Siyuan    HttpInstance->Url = Url;
306b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  }
307b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
30847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
30947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UnicodeStrToAsciiStr (Request->Url, Url);
31047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UrlParser = NULL;
31147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser);
31247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
31347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error1;
31447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
31547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
31647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  RequestStr = NULL;
31747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HostName   = NULL;
31847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status     = HttpUrlGetHostName (Url, UrlParser, &HostName);
31947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
32047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error1;
32147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
32247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
32347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
32447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
32547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    RemotePort = HTTP_DEFAULT_PORT;
32647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
327a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  //
328a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  // If Configure is TRUE, it indicates the first time to call Request();
329a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  // If ReConfigure is TRUE, it indicates the request URL is not same
330a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  // with the previous call to Request();
331a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  //
33247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Configure   = TRUE;
33347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ReConfigure = TRUE;
33447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
335a8706acb0ee847c1521bd8db71c144fd24480e0bFu Siyuan  if (HttpInstance->RemoteHost == NULL) {
33647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
33747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Request() is called the first time.
33847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
33947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    ReConfigure = FALSE;
34047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  } else {
34147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if ((HttpInstance->RemotePort == RemotePort) &&
34247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) {
34347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
34447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // Host Name and port number of the request URL are the same with previous call to Request().
34547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // Check whether previous TCP packet sent out.
34647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
34747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) {
34847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
34947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        // Wrap the HTTP token in HTTP_TOKEN_WRAP
35047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
35147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
35247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        if (Wrap == NULL) {
35347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          Status = EFI_OUT_OF_RESOURCES;
35447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          goto Error1;
35547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        }
35647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
35747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Wrap->HttpToken    = Token;
35847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Wrap->HttpInstance = HttpInstance;
35947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
360b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        Status = HttpCreateTcpTxEvent (Wrap);
36147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        if (EFI_ERROR (Status)) {
36247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          goto Error1;
36347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        }
36447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
36547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
36647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        if (EFI_ERROR (Status)) {
36747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          goto Error1;
36847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        }
36947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
37047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Wrap->TcpWrap.Method = Request->Method;
37147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
37247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        FreePool (HostName);
37347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
37447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
37547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        // Queue the HTTP token and return.
37647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
37747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        return EFI_SUCCESS;
37847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      } else {
37947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
38047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        // Use existing TCP instance to transmit the packet.
38147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
38247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Configure   = FALSE;
38347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        ReConfigure = FALSE;
38447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
38547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    } else {
38647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
38747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // Need close existing TCP instance and create a new TCP instance for data transmit.
38847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
38947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpInstance->RemoteHost != NULL) {
39047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        FreePool (HttpInstance->RemoteHost);
39147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpInstance->RemoteHost = NULL;
392a8706acb0ee847c1521bd8db71c144fd24480e0bFu Siyuan        HttpInstance->RemotePort = 0;
39347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
39447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
39547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
39647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
39747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Configure) {
39847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
399b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.
40047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
401b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (!HttpInstance->LocalAddressIsIPv6) {
402b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);
403b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    } else {
404ac4588532d17a2f3cac3e7dde7c85ed59dab319bZhang Lubo      Status = HttpUrlGetIp6 (Url, UrlParser, &HttpInstance->RemoteIpv6Addr);
405b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
406b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
40747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (EFI_ERROR (Status)) {
408b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));
40947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HostNameStr == NULL) {
41047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Status = EFI_OUT_OF_RESOURCES;
41147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        goto Error1;
41247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
413b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
41447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      AsciiStrToUnicodeStr (HostName, HostNameStr);
415b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      if (!HttpInstance->LocalAddressIsIPv6) {
416b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);
417b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      } else {
418b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo        Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);
419b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      }
420b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
42147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      FreePool (HostNameStr);
42247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (EFI_ERROR (Status)) {
42347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        goto Error1;
42447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
42547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
42647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
427b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
42847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
42947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Save the RemotePort and RemoteHost.
43047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
43147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    ASSERT (HttpInstance->RemoteHost == NULL);
43247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->RemotePort = RemotePort;
43347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->RemoteHost = HostName;
43447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HostName = NULL;
43547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
43647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
43747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (ReConfigure) {
43847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
43947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // The request URL is different from previous calls to Request(), close existing TCP instance.
44047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
441a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo    if (!HttpInstance->LocalAddressIsIPv6) {
442a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo      ASSERT (HttpInstance->Tcp4 != NULL);
443a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo    } else {
444a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo      ASSERT (HttpInstance->Tcp6 != NULL);
445a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo    }
44647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpCloseConnection (HttpInstance);
44747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    EfiHttpCancel (This, NULL);
44847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
44947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
45047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
45147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Wrap the HTTP token in HTTP_TOKEN_WRAP
45247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
45347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
45447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Wrap == NULL) {
45547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Status = EFI_OUT_OF_RESOURCES;
45647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error1;
45747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
45847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
45947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap->HttpToken      = Token;
46047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap->HttpInstance   = HttpInstance;
46147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap->TcpWrap.Method = Request->Method;
46247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
463a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  Status = HttpInitTcp (HttpInstance, Wrap, Configure);
464a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  if (EFI_ERROR (Status)) {
465a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo    goto Error2;
466a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  }
467b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
468a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo  if (!Configure) {
46947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
47047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // For the new HTTP token, create TX TCP token events.
47147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
472b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpCreateTcpTxEvent (Wrap);
47347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (EFI_ERROR (Status)) {
47447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error1;
47547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
47647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
477a2e619821a791de5cd65cd2c757de0a8aa7f138cZhang Lubo
47847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
47947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Create request message.
48047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
481b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin  FileUrl = Url;
482b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin  if (*FileUrl != '/') {
483b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    //
484b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    // Convert the absolute-URI to the absolute-path
485b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    //
486b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    while (*FileUrl != ':') {
487b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      FileUrl++;
488b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    }
489b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    if ((*(FileUrl+1) == '/') && (*(FileUrl+2) == '/')) {
490b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      FileUrl += 3;
491b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      while (*FileUrl != '/') {
492b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin        FileUrl++;
493b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      }
494b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    } else {
495b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      Status = EFI_INVALID_PARAMETER;
496b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin      goto Error3;
497b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin    }
498b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin  }
499b199d9418820b873d0e05190fe5dc947a6f72b14Gary Ching-Pang Lin  RequestStr = HttpGenRequestString (HttpInstance, HttpMsg, FileUrl);
50047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (RequestStr == NULL) {
50147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Status = EFI_OUT_OF_RESOURCES;
50247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error3;
50347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
50447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
50547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
50647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
50747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error4;
50847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
50947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
51047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
51147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Transmit the request message.
51247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
513b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  Status = HttpTransmitTcp (
51447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting             HttpInstance,
51547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting             Wrap,
51647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting             (UINT8*) RequestStr,
51747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting             AsciiStrLen (RequestStr)
51847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting             );
51947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
52047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error5;
52147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
52247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
52349c9f74cc1bd967ea042bcfc948c849207fa71bfFu Siyuan  DispatchDpc ();
524b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
525cdf8c32ec169db14d4824c659159e2b6b6bed540Nagaraj Hegde  if (HostName != NULL) {
526cdf8c32ec169db14d4824c659159e2b6b6bed540Nagaraj Hegde    FreePool (HostName);
527cdf8c32ec169db14d4824c659159e2b6b6bed540Nagaraj Hegde  }
528b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
52947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return EFI_SUCCESS;
53047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
53147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError5:
53247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    NetMapRemoveTail (&HttpInstance->TxTokens, NULL);
53347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
53447f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError4:
53547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (RequestStr != NULL) {
53647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (RequestStr);
53747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
53847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
53947f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError3:
54047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpCloseConnection (HttpInstance);
54147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
54247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError2:
543b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpCloseTcpConnCloseEvent (HttpInstance);
544b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {
545b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
546b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;
547b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  }
548b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {
549b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
550b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;
55147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
55247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
55347f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError1:
554b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
55547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HostName != NULL) {
55647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HostName);
55747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
55847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Wrap != NULL) {
55947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (Wrap);
56047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
56147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (UrlParser!= NULL) {
56247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpUrlFreeParser (UrlParser);
56347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
56447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
56547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return Status;
56647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
56747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
56847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
56947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
570b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  Cancel a user's Token.
57147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
57247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Map                The HTTP instance's token queue.
57347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Item               Object container for one HTTP token and token's wrap.
57447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Context            The user's token to cancel.
57547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
57647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS            Continue to check the next Item.
57747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_ABORTED            The user's Token (Token != NULL) is cancelled.
57847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
57947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
58047f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
58147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
58247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingHttpCancelTokens (
58347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN NET_MAP                *Map,
58447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN NET_MAP_ITEM           *Item,
58547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN VOID                   *Context
58647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
58747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
58847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
58947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_TOKEN            *Token;
59047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_TOKEN_WRAP           *Wrap;
591b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HTTP_PROTOCOL             *HttpInstance;
59247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
59347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Token = (EFI_HTTP_TOKEN *) Context;
59447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
59547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
59647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Return EFI_SUCCESS to check the next item in the map if
59747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // this one doesn't match.
59847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
59947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((Token != NULL) && (Token != Item->Key)) {
60047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_SUCCESS;
60147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
60247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
60347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap = (HTTP_TOKEN_WRAP *) Item->Value;
60447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (Wrap != NULL);
605b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpInstance = Wrap->HttpInstance;
60647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
60747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
60847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Free resources.
60947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
61047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  NetMapRemoveItem (Map, Item, NULL);
61147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
612b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (!HttpInstance->LocalAddressIsIPv6) {
613b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {
614b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
615b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
616b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
617b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
618b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
619b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
620b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
621b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
622b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      FreePool (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer);
623b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
62447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
625b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  } else {
626b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {
627b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);
628b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
629b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
630b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
631b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
632b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
63347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
634b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
635b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      FreePool (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer);
636b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
63747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
63847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
639b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
64047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  FreePool (Wrap);
64147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
64247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
64347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // If only one item is to be cancel, return EFI_ABORTED to stop
64447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // iterating the map any more.
64547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
64647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Token != NULL) {
64747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_ABORTED;
64847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
64947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
65047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return EFI_SUCCESS;
65147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
65247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
65347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
65447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Cancel the user's receive/transmit request. It is the worker function of
65547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EfiHttpCancel API. If a matching token is found, it will call HttpCancelTokens to cancel the
65647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  token.
65747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
65847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  HttpInstance       Pointer to HTTP_PROTOCOL structure.
65947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Token              The token to cancel. If NULL, all token will be
66047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                 cancelled.
66147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
66247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS            The token is cancelled.
66347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_FOUND          The asynchronous request or response token is not found.
66447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval Others                 Other error as indicated.
66547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
66647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
66747f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
66847f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingHttpCancel (
66947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  HTTP_PROTOCOL             *HttpInstance,
67047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_TOKEN            *Token
67147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
67247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
67347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_STATUS                    Status;
67447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
67547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
67647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // First check the tokens queued by EfiHttpRequest().
67747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
67847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = NetMapIterate (&HttpInstance->TxTokens, HttpCancelTokens, Token);
67947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
68047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (Token != NULL) {
68147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (Status == EFI_ABORTED) {
68247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        return EFI_SUCCESS;
68347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
68447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    } else {
68547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      return Status;
68647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
68747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
68847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
68947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
69047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Then check the tokens queued by EfiHttpResponse().
69147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
69247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = NetMapIterate (&HttpInstance->RxTokens, HttpCancelTokens, Token);
69347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
69447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (Token != NULL) {
69547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (Status == EFI_ABORTED) {
69647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        return EFI_SUCCESS;
69747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      } else {
69847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        return EFI_NOT_FOUND;
69947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
70047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    } else {
70147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      return Status;
70247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
70347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
70447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
70547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return EFI_SUCCESS;
70647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
70747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
70847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
70947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
71047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Abort an asynchronous HTTP request or response token.
71147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
71247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The Cancel() function aborts a pending HTTP request or response transaction. If
71347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Token is not NULL and the token is in transmit or receive queues when it is being
71447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  cancelled, its Token->Status will be set to EFI_ABORTED and then Token->Event will
71547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  be signaled. If the token is not in one of the queues, which usually means that the
71647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  asynchronous operation has completed, EFI_NOT_FOUND is returned. If Token is NULL,
71747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  all asynchronous tokens issued by Request() or Response() will be aborted.
71847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
71947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
72047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Token               Point to storage containing HTTP request or response
72147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  token.
72247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
72347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Request and Response queues are successfully flushed.
72447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   This is NULL.
72547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_STARTED         This instance hasn't been configured.
72647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NO_MAPPING          When using the default address, configuration (DHCP,
72747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  BOOTP, RARP, etc.) hasn't finished yet.
72847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_FOUND           The asynchronous request or response token is not
72947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  found.
73047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_UNSUPPORTED         The implementation does not support this function.
73147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
73247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
73347f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
73447f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
73547f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpCancel (
73647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This,
73747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_TOKEN            *Token
73847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
73947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
74047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
74147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
74247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (This == NULL) {
74347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
74447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
74547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
74647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
74747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL);
74847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
74947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
75047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_NOT_STARTED;
75147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
75247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
75347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return HttpCancel (HttpInstance, Token);
75447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
75547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
75647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
75747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
75847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  A callback function to intercept events during message parser.
75947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
76047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  This function will be invoked during HttpParseMessageBody() with various events type. An error
76147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return status of the callback function will cause the HttpParseMessageBody() aborted.
76247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
76347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]    EventType          Event type of this callback call.
76447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]    Data               A pointer to data buffer.
76547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]    Length             Length in bytes of the Data.
76647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]    Context            Callback context set by HttpInitMsgParser().
76747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
76847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS              Continue to parser the message body.
76947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
77047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
77147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
77247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
77347f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingHttpBodyParserCallback (
77447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN HTTP_BODY_PARSE_EVENT      EventType,
77547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN CHAR8                      *Data,
77647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN UINTN                      Length,
77747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN VOID                       *Context
77847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
77947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
78047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_TOKEN_WRAP               *Wrap;
7815ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  UINTN                         BodyLength;
7825ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  CHAR8                         *Body;
78347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
78447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EventType != BodyParseEventOnComplete) {
78547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_SUCCESS;
78647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
78747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
78847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Data == NULL || Length != 0 || Context == NULL) {
78947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_SUCCESS;
79047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
79147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
79247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap = (HTTP_TOKEN_WRAP *) Context;
7935ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  Body = Wrap->HttpToken->Message->Body;
7945ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  BodyLength = Wrap->HttpToken->Message->BodyLength;
7955ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  if (Data < Body + BodyLength) {
7965ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo    Wrap->HttpInstance->NextMsg = Data;
7975ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  } else {
7985ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo    Wrap->HttpInstance->NextMsg = NULL;
7995ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo  }
8005ba9f065a5cd401330281763fae1135961cfd8c4Zhang Lubo
80147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
80247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
803b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.
80447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
80547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  FreePool (Wrap);
80647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
80747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return EFI_SUCCESS;
80847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
80947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
81047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
81147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The work function of EfiHttpResponse().
81247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
81347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Wrap                Pointer to HTTP token's wrap data.
81447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
81547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Allocation succeeded.
81647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_OUT_OF_RESOURCES    Failed to complete the opration due to lack of resources.
817b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  @retval EFI_NOT_READY           Can't find a corresponding Tx4Token/Tx6Token or
8185ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                                  the EFI_HTTP_UTILITIES_PROTOCOL is not available.
81947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
82047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
82147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
82247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingHttpResponseWorker (
82347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  HTTP_TOKEN_WRAP           *Wrap
82447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
82547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
82647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_STATUS                    Status;
82747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_MESSAGE              *HttpMsg;
82847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *EndofHeader;
82947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *HttpHeaders;
83047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINTN                         SizeofHeaders;
83147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINTN                         BufferSize;
83247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINTN                         StatusCode;
83347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *Tmp;
83447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *HeaderTmp;
83547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  CHAR8                         *StatusCodeStr;
83647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINTN                         BodyLen;
83747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
83847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_TOKEN                *Token;
83947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  NET_MAP_ITEM                  *Item;
84047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_TOKEN_WRAP               *ValueInItem;
84147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  UINTN                         HdrLen;
84247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
8433fd7bd08f438130f9fcbcc1ab4392dea1a859c14fanwang  if (Wrap == NULL || Wrap->HttpInstance == NULL) {
8443fd7bd08f438130f9fcbcc1ab4392dea1a859c14fanwang    return EFI_INVALID_PARAMETER;
8453fd7bd08f438130f9fcbcc1ab4392dea1a859c14fanwang  }
8463fd7bd08f438130f9fcbcc1ab4392dea1a859c14fanwang
84747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = Wrap->HttpInstance;
84847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Token = Wrap->HttpToken;
84947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpMsg = Token->Message;
85047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
851b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpInstance->EndofHeader = NULL;
852b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpInstance->HttpHeaders = NULL;
853b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpMsg->Headers          = NULL;
854b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpHeaders               = NULL;
855b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  SizeofHeaders             = 0;
856b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  BufferSize                = 0;
857b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  EndofHeader               = NULL;
85847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
85947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpMsg->Data.Response != NULL) {
86047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
86147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Need receive the HTTP headers, prepare buffer.
86247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
863b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpCreateTcpRxEventForHeader (HttpInstance);
86447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (EFI_ERROR (Status)) {
86547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
86647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
86747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
86847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
86947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Check whether we have cached header from previous call.
87047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
87147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if ((HttpInstance->CacheBody != NULL) && (HttpInstance->NextMsg != NULL)) {
87247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
87347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // The data is stored at [NextMsg, CacheBody + CacheLen].
87447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
87547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HdrLen = HttpInstance->CacheBody + HttpInstance->CacheLen - HttpInstance->NextMsg;
87647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpHeaders = AllocateZeroPool (HdrLen);
87747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpHeaders == NULL) {
87847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Status = EFI_OUT_OF_RESOURCES;
87947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        goto Error;
88047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
88147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
88247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      CopyMem (HttpHeaders, HttpInstance->NextMsg, HdrLen);
88347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      FreePool (HttpInstance->CacheBody);
88447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpInstance->CacheBody   = NULL;
88547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpInstance->NextMsg     = NULL;
88647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpInstance->CacheOffset = 0;
88747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      SizeofHeaders = HdrLen;
88847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      BufferSize = HttpInstance->CacheLen;
88947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
89047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
89147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // Check whether we cached the whole HTTP headers.
89247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
89347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR);
894b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
89547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
896b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpInstance->EndofHeader = &EndofHeader;
897b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    HttpInstance->HttpHeaders = &HttpHeaders;
89847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
899b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);
900b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (EFI_ERROR (Status)) {
901b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      goto Error;
902b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
90347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
9041b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    ASSERT (HttpHeaders != NULL);
9051b96428d92c01383dc437717db679f57cf70d980Zhang Lubo
90647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
90747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Cache the part of body.
90847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
90947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    BodyLen = BufferSize - (EndofHeader - HttpHeaders);
91047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (BodyLen > 0) {
91147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpInstance->CacheBody != NULL) {
91247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        FreePool (HttpInstance->CacheBody);
91347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
91447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
91547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpInstance->CacheBody = AllocateZeroPool (BodyLen);
91647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpInstance->CacheBody == NULL) {
91747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        Status = EFI_OUT_OF_RESOURCES;
91847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        goto Error;
91947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
92047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
92147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      CopyMem (HttpInstance->CacheBody, EndofHeader, BodyLen);
92247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpInstance->CacheLen = BodyLen;
92347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
92447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
92547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
92647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Search for Status Code.
92747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
92847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    StatusCodeStr = HttpHeaders + AsciiStrLen (HTTP_VERSION_STR) + 1;
92947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (StatusCodeStr == NULL) {
93047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
93147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
93247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
93347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    StatusCode = AsciiStrDecimalToUintn (StatusCodeStr);
93447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
93547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
93647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Remove the first line of HTTP message, e.g. "HTTP/1.1 200 OK\r\n".
93747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
93847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Tmp = AsciiStrStr (HttpHeaders, HTTP_CRLF_STR);
93947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (Tmp == NULL) {
94047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
94147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
94247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
94347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Tmp = Tmp + AsciiStrLen (HTTP_CRLF_STR);
94447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    SizeofHeaders = SizeofHeaders - (Tmp - HttpHeaders);
94547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HeaderTmp = AllocateZeroPool (SizeofHeaders);
94647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (HeaderTmp == NULL) {
94747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
94847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
94947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
95047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    CopyMem (HeaderTmp, Tmp, SizeofHeaders);
95147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HttpHeaders);
95247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpHeaders = HeaderTmp;
9535ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu
9545ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    //
9555ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
9565ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    //
9575ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    if (mHttpUtilities == NULL) {
9585ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu      Status = EFI_NOT_READY;
9595ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu      goto Error;
9605ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    }
9615ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu
96247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
96347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Parse the HTTP header into array of key/value pairs.
96447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
9655ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu    Status = mHttpUtilities->Parse (
9665ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               mHttpUtilities,
9675ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               HttpHeaders,
9685ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               SizeofHeaders,
9695ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               &HttpMsg->Headers,
9705ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               &HttpMsg->HeaderCount
9715ca29abe529794c1c2a2663378b0719e902c1077Jiaxin Wu                               );
97247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (EFI_ERROR (Status)) {
97347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
97447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
97547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
97647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HttpHeaders);
97747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpHeaders = NULL;
97847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
97947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode);
98047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
98147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
98247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Init message-body parser by header information.
98347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
98447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Status = EFI_NOT_READY;
98547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    ValueInItem = NULL;
98647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    NetMapRemoveHead (&HttpInstance->TxTokens, (VOID**) &ValueInItem);
98747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (ValueInItem == NULL)  {
98847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error;
98947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
99047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
99147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
992b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    // The first Tx Token not transmitted yet, insert back and return error.
99347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
99447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (!ValueInItem->TcpWrap.IsTxDone) {
99547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error2;
99647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
99747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
99847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    Status = HttpInitMsgParser (
99947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               ValueInItem->TcpWrap.Method,
100047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               HttpMsg->Data.Response->StatusCode,
100147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               HttpMsg->HeaderCount,
100247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               HttpMsg->Headers,
100347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               HttpBodyParserCallback,
100447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               (VOID *) ValueInItem,
100547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               &HttpInstance->MsgParser
100647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting               );
100747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (EFI_ERROR (Status)) {
100847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Error2;
100947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
101047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
101147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
101247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Check whether we received a complete HTTP message.
101347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
101447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (HttpInstance->CacheBody != NULL) {
101547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
101647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (EFI_ERROR (Status)) {
101747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        goto Error2;
101847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
101947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
102047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
102147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
102247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        // Free the MsgParse since we already have a full HTTP message.
102347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
102447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpFreeMsgParser (HttpInstance->MsgParser);
102547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpInstance->MsgParser = NULL;
102647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
102747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
102847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
102947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if ((HttpMsg->Body == NULL) || (HttpMsg->BodyLength == 0)) {
103047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      Status = EFI_SUCCESS;
103147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Exit;
103247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
103347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
103447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
103547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
103647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Receive the response body.
103747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
103847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BodyLen = 0;
103947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
104047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
104147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // First check whether we cached some data.
104247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
104347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->CacheBody != NULL) {
104447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
104547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    // Calculate the length of the cached data.
104647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    //
104747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (HttpInstance->NextMsg != NULL) {
104847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
104947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // We have a cached HTTP message which includes a part of HTTP header of next message.
105047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
105147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      BodyLen = HttpInstance->NextMsg - (HttpInstance->CacheBody + HttpInstance->CacheOffset);
105247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    } else {
105347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      BodyLen = HttpInstance->CacheLen - HttpInstance->CacheOffset;
105447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
105547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
105647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (BodyLen > 0) {
105747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
105847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // We have some cached data. Just copy the data and return.
105947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
106047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      if (HttpMsg->BodyLength < BodyLen) {
106147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, HttpMsg->BodyLength);
106247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpInstance->CacheOffset = HttpInstance->CacheOffset + HttpMsg->BodyLength;
106347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      } else {
106447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
106547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        // Copy all cached data out.
106647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        //
106747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        CopyMem (HttpMsg->Body, HttpInstance->CacheBody + HttpInstance->CacheOffset, BodyLen);
106847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpInstance->CacheOffset = BodyLen + HttpInstance->CacheOffset;
106947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        HttpMsg->BodyLength = BodyLen;
107047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
107147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        if (HttpInstance->NextMsg == NULL) {
107247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          //
107347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          // There is no HTTP header of next message. Just free the cache buffer.
107447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          //
107547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          FreePool (HttpInstance->CacheBody);
107647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          HttpInstance->CacheBody   = NULL;
107747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          HttpInstance->NextMsg     = NULL;
107847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting          HttpInstance->CacheOffset = 0;
107947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting        }
108047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      }
108147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
108247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // Return since we aready received required data.
108347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
108447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      Status = EFI_SUCCESS;
108547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Exit;
108647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
108747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
108847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    if (BodyLen == 0 && HttpInstance->MsgParser == NULL) {
108947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
109047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      // We received a complete HTTP message, and we don't have more data to return to caller.
109147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      //
109247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      HttpMsg->BodyLength = 0;
109347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      Status = EFI_SUCCESS;
109447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting      goto Exit;
109547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
109647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
109747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
109847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance->MsgParser != NULL);
109947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
110047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
110147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // We still need receive more data when there is no cache data and MsgParser is not NULL;
110247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
1103b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  Status = HttpTcpReceiveBody (Wrap, HttpMsg);
110447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
110547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error;
110647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
110747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
110847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return Status;
110947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
111047f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingExit:
111147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap->HttpToken);
111247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Item != NULL) {
111347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);
111447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
111547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Token->Status = Status;
111647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  gBS->SignalEvent (Token->Event);
1117b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpCloseTcpRxEvent (Wrap);
111847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  FreePool (Wrap);
111947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return Status;
112047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
112147f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError2:
112247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);
112347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
112447f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError:
1125b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HttpTcpTokenCleanup (Wrap);
112647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
112747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpHeaders != NULL) {
112847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HttpHeaders);
112947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
113047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
113147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpMsg->Headers != NULL) {
113247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HttpMsg->Headers);
113347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
113447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
113547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->CacheBody != NULL) {
113647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (HttpInstance->CacheBody);
113747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    HttpInstance->CacheBody = NULL;
113847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
113947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
114047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Token->Status = Status;
114147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  gBS->SignalEvent (Token->Event);
114247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
114347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return Status;
114447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
114547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
114647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
114747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
114847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
114947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The Response() function queues an HTTP response to this HTTP instance, similar to
115047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Receive() function in the EFI TCP driver. When the HTTP request is sent successfully,
115147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  or if there is an error, Status in token will be updated and Event will be signaled.
115247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
115347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The HTTP driver will queue a receive token to the underlying TCP instance. When data
115447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  is received in the underlying TCP instance, the data will be parsed and Token will
115547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  be populated with the response data. If the data received from the remote host
115647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  contains an incomplete or invalid HTTP header, the HTTP driver will continue waiting
115747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  (asynchronously) for more data to be sent from the remote host before signaling
115847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Event in Token.
115947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
116047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  It is the responsibility of the caller to allocate a buffer for Body and specify the
116147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  size in BodyLength. If the remote host provides a response that contains a content
116247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  body, up to BodyLength bytes will be copied from the receive buffer into Body and
116347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BodyLength will be updated with the amount of bytes received and copied to Body. This
116447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  allows the client to download a large file in chunks instead of into one contiguous
116547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  block of memory. Similar to HTTP request, if Body is not NULL and BodyLength is
116647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  non-zero and all other fields are NULL or 0, the HTTP driver will queue a receive
116747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  token to underlying TCP instance. If data arrives in the receive buffer, up to
116847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BodyLength bytes of data will be copied to Body. The HTTP driver will then update
116947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  BodyLength with the amount of bytes received and copied to Body.
117047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
117147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  If the HTTP driver does not have an open underlying TCP connection with the host
117247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  specified in the response URL, Request() will return EFI_ACCESS_DENIED. This is
117347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  consistent with RFC 2616 recommendation that HTTP clients should attempt to maintain
117447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  an open TCP connection between client and host.
117547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
117647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
117747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  Token               Pointer to storage containing HTTP response token.
117847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
117947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Allocation succeeded.
118047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been
118147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  initialized.
118247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
118347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  This is NULL.
118447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token is NULL.
118547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->Headers is NULL.
118647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message is NULL.
118747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->Body is not NULL,
118847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->BodyLength is non-zero, and
118947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Token->Message->Data is NULL, but a previous call to
119047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  Response() has not been completed successfully.
119147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resources.
119247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_ACCESS_DENIED       An open TCP connection is not present with the host
119347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting                                  specified by response URL.
119447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
119547f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
119647f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
119747f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpResponse (
119847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This,
119947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_TOKEN            *Token
120047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
120147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
120247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_STATUS                    Status;
120347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  EFI_HTTP_MESSAGE              *HttpMsg;
120447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_PROTOCOL                 *HttpInstance;
120547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HTTP_TOKEN_WRAP               *Wrap;
120647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
120747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if ((This == NULL) || (Token == NULL)) {
120847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
120947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
121047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
121147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpMsg = Token->Message;
121247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpMsg == NULL) {
121347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
121447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
121547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
121647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
121747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL);
121847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
121947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
122047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_NOT_STARTED;
122147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
122247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
122347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
122447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // Check whether the token already existed.
122547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
122647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (NetMapIterate (&HttpInstance->RxTokens, HttpTokenExist, Token))) {
122747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_ACCESS_DENIED;
122847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
122947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
123047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
123147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Wrap == NULL) {
123247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_OUT_OF_RESOURCES;
123347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
123447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
123547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap->HttpInstance = HttpInstance;
123647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Wrap->HttpToken    = Token;
123747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
1238b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  Status = HttpCreateTcpRxEvent (Wrap);
123947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
124047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error;
124147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
124247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
124347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  Status = NetMapInsertTail (&HttpInstance->RxTokens, Token, Wrap);
124447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (EFI_ERROR (Status)) {
124547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    goto Error;
124647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
124747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
124847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
124947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  // If already have pending RxTokens, return directly.
125047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  //
125147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (NetMapGetCount (&HttpInstance->RxTokens) > 1) {
125247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_SUCCESS;
125347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
125447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
125547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return HttpResponseWorker (Wrap);
125647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
125747f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingError:
125847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (Wrap != NULL) {
1259b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {
1260b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);
1261b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    }
1262b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
1263b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {
1264b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo      gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);
126547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    }
126647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    FreePool (Wrap);
126747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
126847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
126947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  return Status;
127047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
127147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
127247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting/**
127347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  The Poll() function can be used by network drivers and applications to increase the
127447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  rate that data packets are moved between the communication devices and the transmit
127547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  and receive queues.
127647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
127747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  In some systems, the periodic timer event in the managed network driver may not poll
127847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  the underlying communications device fast enough to transmit and/or receive all data
127947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  packets without missing incoming packets or dropping outgoing packets. Drivers and
128047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  applications that are experiencing packet loss should try calling the Poll() function
128147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  more often.
128247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
128347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @param[in]  This                Pointer to EFI_HTTP_PROTOCOL instance.
128447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
128547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_SUCCESS             Incoming or outgoing data was processed.
128647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_DEVICE_ERROR        An unexpected system or network error occurred.
128747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_INVALID_PARAMETER   This is NULL.
128847f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_READY           No incoming or outgoing data is processed.
128947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  @retval EFI_NOT_STARTED         This EFI HTTP Protocol instance has not been started.
129047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
129147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting**/
129247f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFI_STATUS
129347f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEFIAPI
129447f51a064fbb3d3226304380674b2bec3cb33ba1Ye TingEfiHttpPoll (
129547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  IN  EFI_HTTP_PROTOCOL         *This
129647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  )
129747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting{
129849c9f74cc1bd967ea042bcfc948c849207fa71bfFu Siyuan  EFI_STATUS                    Status;
1299b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  HTTP_PROTOCOL                 *HttpInstance;
130047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
130147f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  if (This == NULL) {
130247f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_INVALID_PARAMETER;
130347f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
130447f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
130547f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
130647f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  ASSERT (HttpInstance != NULL);
130747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting
13081b96428d92c01383dc437717db679f57cf70d980Zhang Lubo  if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {
130947f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting    return EFI_NOT_STARTED;
131047f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting  }
1311b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
1312b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  if (HttpInstance->LocalAddressIsIPv6) {
13131b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    if (HttpInstance->Tcp6 == NULL) {
13141b96428d92c01383dc437717db679f57cf70d980Zhang Lubo      return EFI_NOT_STARTED;
13151b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    }
1316b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
1317b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  } else {
13181b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    if (HttpInstance->Tcp4 == NULL) {
13191b96428d92c01383dc437717db679f57cf70d980Zhang Lubo      return EFI_NOT_STARTED;
13201b96428d92c01383dc437717db679f57cf70d980Zhang Lubo    }
1321b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo    Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
1322b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo  }
1323b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
132449c9f74cc1bd967ea042bcfc948c849207fa71bfFu Siyuan  DispatchDpc ();
1325b659408b933f40765960e877de3e1f8ceaab52cbZhang Lubo
132649c9f74cc1bd967ea042bcfc948c849207fa71bfFu Siyuan  return Status;
132747f51a064fbb3d3226304380674b2bec3cb33ba1Ye Ting}
1328