mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 16:44:10 +02:00
NetworkPkg:HttpDxe: Code changes to support HTTP PUT/POST operations
Code changes enables HttpDxe to handle PUT/POST operations. EfiHttpRequest assumes "Request" and "HttpMsg->Headers" can never be NULL. Also, HttpResponseWorker assumes HTTP Reponse will contain headers. We could have response which could contain only a string (HTTP 100 Continue) and no headers. Code changes tries to do-away from these assumptions, which would enable HttpDxe to support PUT/POST operations. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hegde, Nagaraj P nagaraj-p.hegde@hpe.com Reviewed-By: Wu Jiaxin <jiaxin.wu@intel.com> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
This commit is contained in:
parent
bfba88bc68
commit
d8293d3141
@ -2,6 +2,7 @@
|
|||||||
The driver binding and service binding protocol for HttpDxe driver.
|
The driver binding and service binding protocol for HttpDxe driver.
|
||||||
|
|
||||||
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
|
||||||
|
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
|
||||||
|
|
||||||
This program and the accompanying materials
|
This program and the accompanying materials
|
||||||
are licensed and made available under the terms and conditions of the BSD License
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
@ -939,6 +940,8 @@ HttpServiceBindingCreateChild (
|
|||||||
|
|
||||||
HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
|
HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
|
||||||
HttpInstance->Service = HttpService;
|
HttpInstance->Service = HttpService;
|
||||||
|
HttpInstance->Method = HttpMethodMax;
|
||||||
|
|
||||||
CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
|
CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
|
||||||
NetMapInit (&HttpInstance->TxTokens);
|
NetMapInit (&HttpInstance->TxTokens);
|
||||||
NetMapInit (&HttpInstance->RxTokens);
|
NetMapInit (&HttpInstance->RxTokens);
|
||||||
|
@ -249,150 +249,184 @@ EfiHttpRequest (
|
|||||||
CHAR8 *FileUrl;
|
CHAR8 *FileUrl;
|
||||||
UINTN RequestMsgSize;
|
UINTN RequestMsgSize;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initializations
|
||||||
|
//
|
||||||
|
Url = NULL;
|
||||||
|
HostName = NULL;
|
||||||
|
RequestMsg = NULL;
|
||||||
|
HostNameStr = NULL;
|
||||||
|
Wrap = NULL;
|
||||||
|
FileUrl = NULL;
|
||||||
|
|
||||||
if ((This == NULL) || (Token == NULL)) {
|
if ((This == NULL) || (Token == NULL)) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpMsg = Token->Message;
|
HttpMsg = Token->Message;
|
||||||
if ((HttpMsg == NULL) || (HttpMsg->Headers == NULL)) {
|
if (HttpMsg == NULL) {
|
||||||
return EFI_INVALID_PARAMETER;
|
return EFI_INVALID_PARAMETER;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Current implementation does not support POST/PUT method.
|
|
||||||
// If future version supports these two methods, Request could be NULL for a special case that to send large amounts
|
|
||||||
// of data. For this case, the implementation need check whether previous call to Request() has been completed or not.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
Request = HttpMsg->Data.Request;
|
Request = HttpMsg->Data.Request;
|
||||||
if ((Request == NULL) || (Request->Url == NULL)) {
|
|
||||||
return EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Only support GET and HEAD method in current implementation.
|
// Only support GET, HEAD, PUT and POST method in current implementation.
|
||||||
//
|
//
|
||||||
if ((Request->Method != HttpMethodGet) && (Request->Method != HttpMethodHead)) {
|
if ((Request != NULL) && (Request->Method != HttpMethodGet) &&
|
||||||
|
(Request->Method != HttpMethodHead) && (Request->Method != HttpMethodPut) && (Request->Method != HttpMethodPost)) {
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
|
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
|
||||||
ASSERT (HttpInstance != NULL);
|
ASSERT (HttpInstance != NULL);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Capture the method into HttpInstance.
|
||||||
|
//
|
||||||
|
if (Request != NULL) {
|
||||||
|
HttpInstance->Method = Request->Method;
|
||||||
|
}
|
||||||
|
|
||||||
if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
|
if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {
|
||||||
return EFI_NOT_STARTED;
|
return EFI_NOT_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
if (Request == NULL) {
|
||||||
// Check whether the token already existed.
|
//
|
||||||
//
|
// Request would be NULL only for PUT/POST operation (in the current implementation)
|
||||||
if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) {
|
//
|
||||||
return EFI_ACCESS_DENIED;
|
if ((HttpInstance->Method != HttpMethodPut) && (HttpInstance->Method != HttpMethodPost)) {
|
||||||
}
|
return EFI_INVALID_PARAMETER;
|
||||||
|
|
||||||
HostName = NULL;
|
|
||||||
Wrap = NULL;
|
|
||||||
HostNameStr = NULL;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parse the URI of the remote host.
|
|
||||||
//
|
|
||||||
Url = HttpInstance->Url;
|
|
||||||
UrlLen = StrLen (Request->Url) + 1;
|
|
||||||
if (UrlLen > HTTP_URL_BUFFER_LEN) {
|
|
||||||
Url = AllocateZeroPool (UrlLen);
|
|
||||||
if (Url == NULL) {
|
|
||||||
return EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
}
|
||||||
FreePool (HttpInstance->Url);
|
|
||||||
HttpInstance->Url = Url;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UnicodeStrToAsciiStr (Request->Url, Url);
|
|
||||||
UrlParser = NULL;
|
|
||||||
Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error1;
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestMsg = NULL;
|
|
||||||
HostName = NULL;
|
|
||||||
Status = HttpUrlGetHostName (Url, UrlParser, &HostName);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
RemotePort = HTTP_DEFAULT_PORT;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// If Configure is TRUE, it indicates the first time to call Request();
|
|
||||||
// If ReConfigure is TRUE, it indicates the request URL is not same
|
|
||||||
// with the previous call to Request();
|
|
||||||
//
|
|
||||||
Configure = TRUE;
|
|
||||||
ReConfigure = TRUE;
|
|
||||||
|
|
||||||
if (HttpInstance->RemoteHost == NULL) {
|
|
||||||
//
|
//
|
||||||
// Request() is called the first time.
|
// For PUT/POST, we need to have the TCP already configured. Bail out if it is not!
|
||||||
//
|
//
|
||||||
|
if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We need to have the Message Body for sending the HTTP message across in these cases.
|
||||||
|
//
|
||||||
|
if (HttpMsg->Body == NULL || HttpMsg->BodyLength == 0) {
|
||||||
|
return EFI_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Use existing TCP instance to transmit the packet.
|
||||||
|
//
|
||||||
|
Configure = FALSE;
|
||||||
ReConfigure = FALSE;
|
ReConfigure = FALSE;
|
||||||
} else {
|
} else {
|
||||||
if ((HttpInstance->RemotePort == RemotePort) &&
|
//
|
||||||
|
// Check whether the token already existed.
|
||||||
|
//
|
||||||
|
if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTokenExist, Token))) {
|
||||||
|
return EFI_ACCESS_DENIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the URI of the remote host.
|
||||||
|
//
|
||||||
|
Url = HttpInstance->Url;
|
||||||
|
UrlLen = StrLen (Request->Url) + 1;
|
||||||
|
if (UrlLen > HTTP_URL_BUFFER_LEN) {
|
||||||
|
Url = AllocateZeroPool (UrlLen);
|
||||||
|
if (Url == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
FreePool (HttpInstance->Url);
|
||||||
|
HttpInstance->Url = Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UnicodeStrToAsciiStr (Request->Url, Url);
|
||||||
|
UrlParser = NULL;
|
||||||
|
Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error1;
|
||||||
|
}
|
||||||
|
|
||||||
|
HostName = NULL;
|
||||||
|
Status = HttpUrlGetHostName (Url, UrlParser, &HostName);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
RemotePort = HTTP_DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// If Configure is TRUE, it indicates the first time to call Request();
|
||||||
|
// If ReConfigure is TRUE, it indicates the request URL is not same
|
||||||
|
// with the previous call to Request();
|
||||||
|
//
|
||||||
|
Configure = TRUE;
|
||||||
|
ReConfigure = TRUE;
|
||||||
|
|
||||||
|
if (HttpInstance->RemoteHost == NULL) {
|
||||||
|
//
|
||||||
|
// Request() is called the first time.
|
||||||
|
//
|
||||||
|
ReConfigure = FALSE;
|
||||||
|
} else {
|
||||||
|
if ((HttpInstance->RemotePort == RemotePort) &&
|
||||||
(AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) {
|
(AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) {
|
||||||
//
|
|
||||||
// Host Name and port number of the request URL are the same with previous call to Request().
|
|
||||||
// Check whether previous TCP packet sent out.
|
|
||||||
//
|
|
||||||
if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) {
|
|
||||||
//
|
//
|
||||||
// Wrap the HTTP token in HTTP_TOKEN_WRAP
|
// Host Name and port number of the request URL are the same with previous call to Request().
|
||||||
|
// Check whether previous TCP packet sent out.
|
||||||
//
|
//
|
||||||
Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
|
|
||||||
if (Wrap == NULL) {
|
if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens, HttpTcpNotReady, NULL))) {
|
||||||
Status = EFI_OUT_OF_RESOURCES;
|
//
|
||||||
goto Error1;
|
// Wrap the HTTP token in HTTP_TOKEN_WRAP
|
||||||
|
//
|
||||||
|
Wrap = AllocateZeroPool (sizeof (HTTP_TOKEN_WRAP));
|
||||||
|
if (Wrap == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Error1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wrap->HttpToken = Token;
|
||||||
|
Wrap->HttpInstance = HttpInstance;
|
||||||
|
|
||||||
|
Status = HttpCreateTcpTxEvent (Wrap);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Wrap->TcpWrap.Method = Request->Method;
|
||||||
|
|
||||||
|
FreePool (HostName);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Queue the HTTP token and return.
|
||||||
|
//
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Use existing TCP instance to transmit the packet.
|
||||||
|
//
|
||||||
|
Configure = FALSE;
|
||||||
|
ReConfigure = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Wrap->HttpToken = Token;
|
|
||||||
Wrap->HttpInstance = HttpInstance;
|
|
||||||
|
|
||||||
Status = HttpCreateTcpTxEvent (Wrap);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Wrap->TcpWrap.Method = Request->Method;
|
|
||||||
|
|
||||||
FreePool (HostName);
|
|
||||||
|
|
||||||
//
|
|
||||||
// Queue the HTTP token and return.
|
|
||||||
//
|
|
||||||
return EFI_SUCCESS;
|
|
||||||
} else {
|
} else {
|
||||||
//
|
//
|
||||||
// Use existing TCP instance to transmit the packet.
|
// Need close existing TCP instance and create a new TCP instance for data transmit.
|
||||||
//
|
//
|
||||||
Configure = FALSE;
|
if (HttpInstance->RemoteHost != NULL) {
|
||||||
ReConfigure = FALSE;
|
FreePool (HttpInstance->RemoteHost);
|
||||||
}
|
HttpInstance->RemoteHost = NULL;
|
||||||
} else {
|
HttpInstance->RemotePort = 0;
|
||||||
//
|
}
|
||||||
// Need close existing TCP instance and create a new TCP instance for data transmit.
|
|
||||||
//
|
|
||||||
if (HttpInstance->RemoteHost != NULL) {
|
|
||||||
FreePool (HttpInstance->RemoteHost);
|
|
||||||
HttpInstance->RemoteHost = NULL;
|
|
||||||
HttpInstance->RemotePort = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -461,7 +495,9 @@ EfiHttpRequest (
|
|||||||
|
|
||||||
Wrap->HttpToken = Token;
|
Wrap->HttpToken = Token;
|
||||||
Wrap->HttpInstance = HttpInstance;
|
Wrap->HttpInstance = HttpInstance;
|
||||||
Wrap->TcpWrap.Method = Request->Method;
|
if (Request != NULL) {
|
||||||
|
Wrap->TcpWrap.Method = Request->Method;
|
||||||
|
}
|
||||||
|
|
||||||
Status = HttpInitTcp (HttpInstance, Wrap, Configure);
|
Status = HttpInitTcp (HttpInstance, Wrap, Configure);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
@ -482,7 +518,7 @@ EfiHttpRequest (
|
|||||||
// Create request message.
|
// Create request message.
|
||||||
//
|
//
|
||||||
FileUrl = Url;
|
FileUrl = Url;
|
||||||
if (*FileUrl != '/') {
|
if (Url != NULL && *FileUrl != '/') {
|
||||||
//
|
//
|
||||||
// Convert the absolute-URI to the absolute-path
|
// Convert the absolute-URI to the absolute-path
|
||||||
//
|
//
|
||||||
@ -506,9 +542,17 @@ EfiHttpRequest (
|
|||||||
goto Error3;
|
goto Error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
|
//
|
||||||
if (EFI_ERROR (Status)) {
|
// Every request we insert a TxToken and a response call would remove the TxToken.
|
||||||
goto Error4;
|
// In cases of PUT/POST, after an initial request-response pair, we would do a
|
||||||
|
// continuous request without a response call. So, in such cases, where Request
|
||||||
|
// structure is NULL, we would not insert a TxToken.
|
||||||
|
//
|
||||||
|
if (Request != NULL) {
|
||||||
|
Status = NetMapInsertTail (&HttpInstance->TxTokens, Token, Wrap);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -533,7 +577,13 @@ EfiHttpRequest (
|
|||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
|
|
||||||
Error5:
|
Error5:
|
||||||
NetMapRemoveTail (&HttpInstance->TxTokens, NULL);
|
//
|
||||||
|
// We would have inserted a TxToken only if Request structure is not NULL.
|
||||||
|
// Hence check before we do a remove in this error case.
|
||||||
|
//
|
||||||
|
if (Request != NULL) {
|
||||||
|
NetMapRemoveTail (&HttpInstance->TxTokens, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
Error4:
|
Error4:
|
||||||
if (RequestMsg != NULL) {
|
if (RequestMsg != NULL) {
|
||||||
@ -970,89 +1020,114 @@ HttpResponseWorker (
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// We could have response with just a HTTP message and no headers. For Example,
|
||||||
|
// "100 Continue". In such cases, we would not want to unnecessarily call a Parse
|
||||||
|
// method. A "\r\n" following Tmp string again would indicate an end. Compare and
|
||||||
|
// set SizeofHeaders to 0.
|
||||||
|
//
|
||||||
Tmp = Tmp + AsciiStrLen (HTTP_CRLF_STR);
|
Tmp = Tmp + AsciiStrLen (HTTP_CRLF_STR);
|
||||||
SizeofHeaders = SizeofHeaders - (Tmp - HttpHeaders);
|
if (CompareMem (Tmp, HTTP_CRLF_STR, AsciiStrLen (HTTP_CRLF_STR)) == 0) {
|
||||||
HeaderTmp = AllocateZeroPool (SizeofHeaders);
|
SizeofHeaders = 0;
|
||||||
if (HeaderTmp == NULL) {
|
} else {
|
||||||
goto Error;
|
SizeofHeaders = SizeofHeaders - (Tmp - HttpHeaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyMem (HeaderTmp, Tmp, SizeofHeaders);
|
|
||||||
FreePool (HttpHeaders);
|
|
||||||
HttpHeaders = HeaderTmp;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
|
|
||||||
//
|
|
||||||
if (mHttpUtilities == NULL) {
|
|
||||||
Status = EFI_NOT_READY;
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Parse the HTTP header into array of key/value pairs.
|
|
||||||
//
|
|
||||||
Status = mHttpUtilities->Parse (
|
|
||||||
mHttpUtilities,
|
|
||||||
HttpHeaders,
|
|
||||||
SizeofHeaders,
|
|
||||||
&HttpMsg->Headers,
|
|
||||||
&HttpMsg->HeaderCount
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
FreePool (HttpHeaders);
|
|
||||||
HttpHeaders = NULL;
|
|
||||||
|
|
||||||
HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode);
|
HttpMsg->Data.Response->StatusCode = HttpMappingToStatusCode (StatusCode);
|
||||||
HttpInstance->StatusCode = StatusCode;
|
HttpInstance->StatusCode = StatusCode;
|
||||||
//
|
|
||||||
// Init message-body parser by header information.
|
|
||||||
//
|
|
||||||
Status = EFI_NOT_READY;
|
Status = EFI_NOT_READY;
|
||||||
ValueInItem = NULL;
|
ValueInItem = NULL;
|
||||||
NetMapRemoveHead (&HttpInstance->TxTokens, (VOID**) &ValueInItem);
|
|
||||||
if (ValueInItem == NULL) {
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// The first Tx Token not transmitted yet, insert back and return error.
|
// In cases of PUT/POST, after an initial request-response pair, we would do a
|
||||||
|
// continuous request without a response call. So, we would not do an insert of
|
||||||
|
// TxToken. After we have sent the complete file, we will call a response to get
|
||||||
|
// a final response from server. In such a case, we would not have any TxTokens.
|
||||||
|
// Hence, check that case before doing a NetMapRemoveHead.
|
||||||
//
|
//
|
||||||
if (!ValueInItem->TcpWrap.IsTxDone) {
|
if (!NetMapIsEmpty (&HttpInstance->TxTokens)) {
|
||||||
goto Error2;
|
NetMapRemoveHead (&HttpInstance->TxTokens, (VOID**) &ValueInItem);
|
||||||
|
if (ValueInItem == NULL) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// The first Tx Token not transmitted yet, insert back and return error.
|
||||||
|
//
|
||||||
|
if (!ValueInItem->TcpWrap.IsTxDone) {
|
||||||
|
goto Error2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = HttpInitMsgParser (
|
if (SizeofHeaders != 0) {
|
||||||
ValueInItem->TcpWrap.Method,
|
HeaderTmp = AllocateZeroPool (SizeofHeaders);
|
||||||
HttpMsg->Data.Response->StatusCode,
|
if (HeaderTmp == NULL) {
|
||||||
HttpMsg->HeaderCount,
|
goto Error;
|
||||||
HttpMsg->Headers,
|
}
|
||||||
HttpBodyParserCallback,
|
|
||||||
(VOID *) ValueInItem,
|
|
||||||
&HttpInstance->MsgParser
|
|
||||||
);
|
|
||||||
if (EFI_ERROR (Status)) {
|
|
||||||
goto Error2;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
CopyMem (HeaderTmp, Tmp, SizeofHeaders);
|
||||||
// Check whether we received a complete HTTP message.
|
FreePool (HttpHeaders);
|
||||||
//
|
HttpHeaders = HeaderTmp;
|
||||||
if (HttpInstance->CacheBody != NULL) {
|
|
||||||
Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
|
//
|
||||||
|
// Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.
|
||||||
|
//
|
||||||
|
if (mHttpUtilities == NULL) {
|
||||||
|
Status = EFI_NOT_READY;
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Parse the HTTP header into array of key/value pairs.
|
||||||
|
//
|
||||||
|
Status = mHttpUtilities->Parse (
|
||||||
|
mHttpUtilities,
|
||||||
|
HttpHeaders,
|
||||||
|
SizeofHeaders,
|
||||||
|
&HttpMsg->Headers,
|
||||||
|
&HttpMsg->HeaderCount
|
||||||
|
);
|
||||||
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
|
||||||
|
FreePool (HttpHeaders);
|
||||||
|
HttpHeaders = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init message-body parser by header information.
|
||||||
|
//
|
||||||
|
Status = HttpInitMsgParser (
|
||||||
|
HttpInstance->Method,
|
||||||
|
HttpMsg->Data.Response->StatusCode,
|
||||||
|
HttpMsg->HeaderCount,
|
||||||
|
HttpMsg->Headers,
|
||||||
|
HttpBodyParserCallback,
|
||||||
|
(VOID *) ValueInItem,
|
||||||
|
&HttpInstance->MsgParser
|
||||||
|
);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
goto Error2;
|
goto Error2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
|
//
|
||||||
//
|
// Check whether we received a complete HTTP message.
|
||||||
// Free the MsgParse since we already have a full HTTP message.
|
//
|
||||||
//
|
if (HttpInstance->CacheBody != NULL) {
|
||||||
HttpFreeMsgParser (HttpInstance->MsgParser);
|
Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
|
||||||
HttpInstance->MsgParser = NULL;
|
if (EFI_ERROR (Status)) {
|
||||||
|
goto Error2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
|
||||||
|
//
|
||||||
|
// Free the MsgParse since we already have a full HTTP message.
|
||||||
|
//
|
||||||
|
HttpFreeMsgParser (HttpInstance->MsgParser);
|
||||||
|
HttpInstance->MsgParser = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ typedef struct _HTTP_PROTOCOL {
|
|||||||
LIST_ENTRY Link; // Link to all HTTP instance from the service.
|
LIST_ENTRY Link; // Link to all HTTP instance from the service.
|
||||||
BOOLEAN InDestroy;
|
BOOLEAN InDestroy;
|
||||||
INTN State;
|
INTN State;
|
||||||
|
EFI_HTTP_METHOD Method;
|
||||||
|
|
||||||
UINTN StatusCode;
|
UINTN StatusCode;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user