/** @file\r
Implementation of EFI_HTTP_PROTOCOL protocol interfaces.\r
\r
- Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
This is NULL.\r
HttpConfigData is NULL.\r
- HttpConfigData->AccessPoint is NULL.\r
- @retval EFI_NOT_STARTED The HTTP instance is not configured.\r
+ HttpInstance->LocalAddressIsIPv6 is FALSE and\r
+ HttpConfigData->IPv4Node is NULL.\r
+ HttpInstance->LocalAddressIsIPv6 is TRUE and\r
+ HttpConfigData->IPv6Node is NULL.\r
+ @retval EFI_NOT_STARTED This EFI HTTP Protocol instance has not been started.\r
\r
**/\r
EFI_STATUS\r
{\r
HTTP_PROTOCOL *HttpInstance;\r
\r
+ //\r
+ // Check input parameters.\r
+ //\r
if ((This == NULL) || (HttpConfigData == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
- \r
+\r
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
ASSERT (HttpInstance != NULL);\r
\r
- if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {\r
- return EFI_NOT_STARTED;\r
+ if ((HttpInstance->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||\r
+ (!HttpInstance->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
}\r
\r
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
+ if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {\r
+ return EFI_NOT_STARTED;\r
}\r
\r
HttpConfigData->HttpVersion = HttpInstance->HttpVersion;\r
HttpConfigData->TimeOutMillisec = HttpInstance->TimeOutMillisec;\r
HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;\r
\r
- CopyMem (\r
- HttpConfigData->AccessPoint.IPv4Node,\r
- &HttpInstance->IPv4Node,\r
- sizeof (HttpInstance->IPv4Node)\r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ CopyMem (\r
+ HttpConfigData->AccessPoint.IPv6Node,\r
+ &HttpInstance->Ipv6Node,\r
+ sizeof (HttpInstance->Ipv6Node)\r
);\r
+ } else {\r
+ CopyMem (\r
+ HttpConfigData->AccessPoint.IPv4Node,\r
+ &HttpInstance->IPv4Node,\r
+ sizeof (HttpInstance->IPv4Node)\r
+ );\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
connections with remote hosts, canceling all asynchronous tokens, and flush request\r
and response buffers without informing the appropriate hosts.\r
\r
- Except for GetModeData() and Configure(), No other EFI HTTP function can be executed\r
- by this instance until the Configure() function is executed and returns successfully.\r
+ No other EFI HTTP function can be executed by this instance until the Configure()\r
+ function is executed and returns successfully.\r
\r
@param[in] This Pointer to EFI_HTTP_PROTOCOL instance.\r
@param[in] HttpConfigData Pointer to the configure data to configure the instance.\r
@retval EFI_SUCCESS Operation succeeded.\r
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
This is NULL.\r
+ HttpConfigData is NULL.\r
HttpConfigData->LocalAddressIsIPv6 is FALSE and\r
HttpConfigData->IPv4Node is NULL.\r
HttpConfigData->LocalAddressIsIPv6 is TRUE and\r
{\r
HTTP_PROTOCOL *HttpInstance;\r
EFI_STATUS Status;\r
-\r
- if (This == NULL) {\r
+ \r
+ //\r
+ // Check input parameters.\r
+ //\r
+ if (This == NULL ||\r
+ HttpConfigData == NULL ||\r
+ ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||\r
+ (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL))) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);\r
\r
if (HttpConfigData != NULL) {\r
- //\r
- // Check input parameters.\r
- //\r
- if (HttpConfigData->LocalAddressIsIPv6) {\r
- if (HttpConfigData->AccessPoint.IPv6Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
+\r
//\r
// Now configure this HTTP instance.\r
//\r
HttpInstance->HttpVersion = HttpConfigData->HttpVersion;\r
HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;\r
HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;\r
-\r
- if (HttpConfigData->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
+ \r
+ if (HttpConfigData->LocalAddressIsIPv6) { \r
+ CopyMem (\r
+ &HttpInstance->Ipv6Node,\r
+ HttpConfigData->AccessPoint.IPv6Node,\r
+ sizeof (HttpInstance->Ipv6Node)\r
+ );\r
} else {\r
CopyMem (\r
&HttpInstance->IPv4Node,\r
HttpConfigData->AccessPoint.IPv4Node,\r
sizeof (HttpInstance->IPv4Node)\r
);\r
-\r
- HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
- return EFI_SUCCESS;\r
}\r
+ //\r
+ // Creat Tcp child\r
+ //\r
+ Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
+ return EFI_SUCCESS;\r
\r
} else {\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- } else {\r
- HttpCleanProtocol (HttpInstance);\r
- Status = HttpInitProtocol (HttpInstance->Service, HttpInstance);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
- return EFI_SUCCESS;\r
- }\r
+ //\r
+ // Reset all the resources related to HttpInsance.\r
+ //\r
+ HttpCleanProtocol (HttpInstance);\r
+ HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
implementation.\r
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
This is NULL.\r
+ Token is NULL.\r
Token->Message is NULL.\r
Token->Message->Body is not NULL,\r
Token->Message->BodyLength is non-zero, and\r
UINTN UrlLen;\r
CHAR16 *HostNameStr;\r
HTTP_TOKEN_WRAP *Wrap;\r
- HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
CHAR8 *FileUrl;\r
\r
if ((This == NULL) || (Token == NULL)) {\r
return EFI_NOT_STARTED;\r
}\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
//\r
// Check whether the token already existed.\r
//\r
HostName = NULL;\r
Wrap = NULL;\r
HostNameStr = NULL;\r
- TcpWrap = NULL;\r
\r
//\r
// Parse the URI of the remote host.\r
}\r
FreePool (HttpInstance->Url);\r
HttpInstance->Url = Url; \r
- } \r
+ } \r
+\r
\r
UnicodeStrToAsciiStr (Request->Url, Url);\r
UrlParser = NULL;\r
if (EFI_ERROR (Status)) {\r
RemotePort = HTTP_DEFAULT_PORT;\r
}\r
-\r
+ //\r
+ // If Configure is TRUE, it indicates the first time to call Request();\r
+ // If ReConfigure is TRUE, it indicates the request URL is not same\r
+ // with the previous call to Request();\r
+ //\r
Configure = TRUE;\r
ReConfigure = TRUE; \r
\r
Wrap->HttpToken = Token;\r
Wrap->HttpInstance = HttpInstance;\r
\r
- Status = HttpCreateTcp4TxEvent (Wrap);\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
\r
if (Configure) {\r
//\r
- // Parse Url for IPv4 address, if failed, perform DNS resolution.\r
+ // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.\r
//\r
- Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+ } else {\r
+ Status = HttpUrlGetIp6 (Url, UrlParser, &HttpInstance->RemoteIpv6Addr);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
- HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16));\r
+ HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));\r
if (HostNameStr == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Error1;\r
}\r
-\r
+ \r
AsciiStrToUnicodeStr (HostName, HostNameStr);\r
- Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+ } else {\r
+ Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);\r
+ }\r
+ \r
FreePool (HostNameStr);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
}\r
\r
+\r
//\r
// Save the RemotePort and RemoteHost.\r
//\r
//\r
// The request URL is different from previous calls to Request(), close existing TCP instance.\r
//\r
- ASSERT (HttpInstance->Tcp4 != NULL);\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ ASSERT (HttpInstance->Tcp4 != NULL);\r
+ } else {\r
+ ASSERT (HttpInstance->Tcp6 != NULL);\r
+ }\r
HttpCloseConnection (HttpInstance);\r
EfiHttpCancel (This, NULL);\r
}\r
Wrap->HttpInstance = HttpInstance;\r
Wrap->TcpWrap.Method = Request->Method;\r
\r
- if (Configure) {\r
- //\r
- // Configure TCP instance.\r
- //\r
- Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
- if (EFI_ERROR (Status)) {\r
- goto Error1;\r
- }\r
- //\r
- // Connect TCP.\r
- //\r
- Status = HttpConnectTcp4 (HttpInstance);\r
- if (EFI_ERROR (Status)) {\r
- goto Error2;\r
- }\r
- } else {\r
+ Status = HttpInitTcp (HttpInstance, Wrap, Configure);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error2;\r
+ } \r
+\r
+ if (!Configure) {\r
//\r
// For the new HTTP token, create TX TCP token events. \r
//\r
- Status = HttpCreateTcp4TxEvent (Wrap);\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
}\r
-\r
+ \r
//\r
// Create request message.\r
//\r
goto Error3;\r
}\r
}\r
- RequestStr = HttpGenRequestString (HttpInstance, HttpMsg, FileUrl);\r
- if (RequestStr == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
+\r
+ Status = HttpGenRequestString (HttpMsg, FileUrl, &RequestStr);\r
+\r
+ if (EFI_ERROR (Status)) {\r
goto Error3;\r
}\r
\r
goto Error4;\r
}\r
\r
- if (HostName != NULL) {\r
- FreePool (HostName);\r
- }\r
-\r
//\r
// Transmit the request message.\r
//\r
- Status = HttpTransmitTcp4 (\r
+ Status = HttpTransmitTcp (\r
HttpInstance,\r
Wrap,\r
(UINT8*) RequestStr,\r
}\r
\r
DispatchDpc ();\r
-\r
+ \r
+ if (HostName != NULL) {\r
+ FreePool (HostName);\r
+ }\r
+ \r
return EFI_SUCCESS;\r
\r
Error5:\r
Error3:\r
HttpCloseConnection (HttpInstance);\r
\r
-\r
Error2:\r
- HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
- if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) {\r
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
- Wrap->TcpWrap.TxToken.CompletionToken.Event = NULL;\r
+ HttpCloseTcpConnCloseEvent (HttpInstance);\r
+ if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+ Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;\r
+ }\r
+ if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+ Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;\r
}\r
\r
Error1:\r
+\r
if (HostName != NULL) {\r
FreePool (HostName);\r
}\r
}\r
\r
/**\r
- Cancel a TxToken or RxToken. \r
+ Cancel a user's Token. \r
\r
@param[in] Map The HTTP instance's token queue.\r
@param[in] Item Object container for one HTTP token and token's wrap.\r
\r
EFI_HTTP_TOKEN *Token;\r
HTTP_TOKEN_WRAP *Wrap;\r
+ HTTP_PROTOCOL *HttpInstance;\r
\r
Token = (EFI_HTTP_TOKEN *) Context;\r
\r
\r
Wrap = (HTTP_TOKEN_WRAP *) Item->Value;\r
ASSERT (Wrap != NULL);\r
+ HttpInstance = Wrap->HttpInstance;\r
\r
//\r
// Free resources.\r
//\r
NetMapRemoveItem (Map, Item, NULL); \r
\r
- if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
- }\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+ }\r
+ \r
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ }\r
+ \r
+ if (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- }\r
+ } else {\r
+ if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+ }\r
+\r
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+ }\r
\r
- if (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ if (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
}\r
\r
+\r
FreePool (Wrap);\r
\r
//\r
@retval EFI_SUCCESS Request and Response queues are successfully flushed.\r
@retval EFI_INVALID_PARAMETER This is NULL.\r
@retval EFI_NOT_STARTED This instance hasn't been configured.\r
- @retval EFI_NO_MAPPING When using the default address, configuration (DHCP,\r
- BOOTP, RARP, etc.) hasn't finished yet.\r
@retval EFI_NOT_FOUND The asynchronous request or response token is not\r
found.\r
@retval EFI_UNSUPPORTED The implementation does not support this function.\r
)\r
{\r
HTTP_TOKEN_WRAP *Wrap;\r
+ UINTN BodyLength;\r
+ CHAR8 *Body;\r
\r
if (EventType != BodyParseEventOnComplete) {\r
return EFI_SUCCESS;\r
}\r
\r
Wrap = (HTTP_TOKEN_WRAP *) Context;\r
- Wrap->HttpInstance->NextMsg = Data;\r
+ Body = Wrap->HttpToken->Message->Body;\r
+ BodyLength = Wrap->HttpToken->Message->BodyLength;\r
+ if (Data < Body + BodyLength) {\r
+ Wrap->HttpInstance->NextMsg = Data;\r
+ } else {\r
+ Wrap->HttpInstance->NextMsg = NULL;\r
+ }\r
+ \r
\r
//\r
- // Free TxToken since already received corrsponding HTTP response.\r
+ // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.\r
//\r
FreePool (Wrap);\r
\r
\r
@retval EFI_SUCCESS Allocation succeeded.\r
@retval EFI_OUT_OF_RESOURCES Failed to complete the opration due to lack of resources.\r
- @retval EFI_NOT_READY Can't find a corresponding TxToken or \r
+ @retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6Token or \r
the EFI_HTTP_UTILITIES_PROTOCOL is not available.\r
\r
**/\r
{\r
EFI_STATUS Status;\r
EFI_HTTP_MESSAGE *HttpMsg;\r
- EFI_TCP4_IO_TOKEN *RxToken;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
CHAR8 *EndofHeader;\r
CHAR8 *HttpHeaders;\r
UINTN SizeofHeaders;\r
- CHAR8 *Buffer;\r
UINTN BufferSize;\r
UINTN StatusCode;\r
CHAR8 *Tmp;\r
\r
HttpInstance = Wrap->HttpInstance;\r
Token = Wrap->HttpToken;\r
-\r
HttpMsg = Token->Message;\r
\r
- Tcp4 = HttpInstance->Tcp4;\r
- ASSERT (Tcp4 != NULL);\r
- HttpMsg->Headers = NULL;\r
- HttpHeaders = NULL;\r
- SizeofHeaders = 0;\r
- Buffer = NULL;\r
- BufferSize = 0;\r
- EndofHeader = NULL;\r
+ HttpInstance->EndofHeader = NULL;\r
+ HttpInstance->HttpHeaders = NULL;\r
+ HttpMsg->Headers = NULL;\r
+ HttpHeaders = NULL;\r
+ SizeofHeaders = 0;\r
+ BufferSize = 0;\r
+ EndofHeader = NULL;\r
\r
if (HttpMsg->Data.Response != NULL) {\r
//\r
// Need receive the HTTP headers, prepare buffer.\r
//\r
- Status = HttpCreateTcp4RxEventForHeader (HttpInstance);\r
+ Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
// Check whether we cached the whole HTTP headers.\r
//\r
EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
- }\r
- \r
- RxToken = &HttpInstance->RxToken;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
+ } \r
\r
- //\r
- // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
- //\r
- while (EndofHeader == NULL) { \r
- HttpInstance->IsRxDone = FALSE;\r
- RxToken->Packet.RxData->DataLength = DEF_BUF_LEN;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
- Status = Tcp4->Receive (Tcp4, RxToken);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
- goto Error;\r
- }\r
- \r
- while (!HttpInstance->IsRxDone) {\r
- Tcp4->Poll (Tcp4);\r
- } \r
-\r
- Status = RxToken->CompletionToken.Status;\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
+ HttpInstance->EndofHeader = &EndofHeader;\r
+ HttpInstance->HttpHeaders = &HttpHeaders;\r
\r
- //\r
- // Append the response string.\r
- //\r
- BufferSize = SizeofHeaders + RxToken->Packet.RxData->FragmentTable[0].FragmentLength;\r
- Buffer = AllocateZeroPool (BufferSize);\r
- if (Buffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- if (HttpHeaders != NULL) {\r
- CopyMem (Buffer, HttpHeaders, SizeofHeaders);\r
- FreePool (HttpHeaders);\r
- }\r
-\r
- CopyMem (\r
- Buffer + SizeofHeaders,\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength\r
- );\r
- HttpHeaders = Buffer;\r
- SizeofHeaders = BufferSize;\r
-\r
- //\r
- // Check whether we received end of HTTP headers.\r
- //\r
- EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
- };\r
+ Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
\r
- //\r
- // Skip the CRLF after the HTTP headers.\r
- //\r
- EndofHeader = EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
+ ASSERT (HttpHeaders != NULL);\r
\r
//\r
// Cache the part of body.\r
HttpInstance->CacheLen = BodyLen;\r
}\r
\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
-\r
//\r
// Search for Status Code.\r
//\r
HttpHeaders = NULL;\r
\r
HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode);\r
-\r
+ HttpInstance->StatusCode = StatusCode;\r
//\r
// Init message-body parser by header information. \r
//\r
}\r
\r
//\r
- // The first TxToken not transmitted yet, insert back and return error.\r
+ // The first Tx Token not transmitted yet, insert back and return error.\r
//\r
if (!ValueInItem->TcpWrap.IsTxDone) {\r
goto Error2;\r
//\r
// We still need receive more data when there is no cache data and MsgParser is not NULL;\r
//\r
- RxToken = &Wrap->TcpWrap.RxToken;\r
-\r
- RxToken->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
-\r
- RxToken->CompletionToken.Status = EFI_NOT_READY;\r
- Status = Tcp4->Receive (Tcp4, RxToken);\r
+ Status = HttpTcpReceiveBody (Wrap, HttpMsg);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
goto Error;\r
}\r
\r
if (Item != NULL) {\r
NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);\r
}\r
- Token->Status = Status;\r
+\r
+ if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) {\r
+ Token->Status = EFI_HTTP_ERROR;\r
+ } else {\r
+ Token->Status = Status;\r
+ }\r
+\r
gBS->SignalEvent (Token->Event);\r
+ HttpCloseTcpRxEvent (Wrap);\r
FreePool (Wrap);\r
return Status;\r
\r
NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);\r
\r
Error:\r
- if (Wrap != NULL) {\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- }\r
- RxToken = &Wrap->TcpWrap.RxToken;\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
- }\r
- FreePool (Wrap);\r
- }\r
-\r
- if (HttpInstance->RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);\r
- HttpInstance->RxToken.CompletionToken.Event = NULL;\r
- }\r
-\r
- RxToken = &HttpInstance->RxToken;\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
- }\r
+ HttpTcpTokenCleanup (Wrap);\r
\r
if (HttpHeaders != NULL) {\r
FreePool (HttpHeaders);\r
HttpInstance->CacheBody = NULL;\r
}\r
\r
- Token->Status = Status;\r
+ if (HttpInstance->StatusCode >= HTTP_ERROR_OR_NOT_SUPPORT_STATUS_CODE) {\r
+ Token->Status = EFI_HTTP_ERROR;\r
+ } else {\r
+ Token->Status = Status;\r
+ }\r
+\r
gBS->SignalEvent (Token->Event);\r
\r
return Status; \r
\r
/**\r
The Response() function queues an HTTP response to this HTTP instance, similar to\r
- Receive() function in the EFI TCP driver. When the HTTP request is sent successfully,\r
+ Receive() function in the EFI TCP driver. When the HTTP response is received successfully,\r
or if there is an error, Status in token will be updated and Event will be signaled.\r
\r
The HTTP driver will queue a receive token to the underlying TCP instance. When data\r
return EFI_NOT_STARTED;\r
}\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- } \r
-\r
//\r
// Check whether the token already existed.\r
//\r
Wrap->HttpInstance = HttpInstance;\r
Wrap->HttpToken = Token;\r
\r
- Status = HttpCreateTcp4RxEvent (Wrap);\r
+ Status = HttpCreateTcpRxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
\r
Error:\r
if (Wrap != NULL) {\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ }\r
+\r
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
}\r
FreePool (Wrap);\r
} \r
IN EFI_HTTP_PROTOCOL *This\r
)\r
{\r
- HTTP_PROTOCOL *HttpInstance;\r
EFI_STATUS Status;\r
+ HTTP_PROTOCOL *HttpInstance;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
ASSERT (HttpInstance != NULL);\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (HttpInstance->Tcp4 == NULL || HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {\r
+ if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {\r
return EFI_NOT_STARTED;\r
}\r
-\r
- Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
-\r
+ \r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ if (HttpInstance->Tcp6 == NULL) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+ Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+ } else {\r
+ if (HttpInstance->Tcp4 == NULL) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+ Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+ }\r
+ \r
DispatchDpc ();\r
-\r
+ \r
return Status;\r
}\r