NetworkPkg/HttpBootDxe: Add proxy connect flow to *GetBootFile()
- Add HTTP CONNECT flow to connect to Proxy Server - Provide Proxy URL to HTTP GET/HEAD Requests Implementation based on UEFI Specification v2.11 - Section 24.7.10 to use HTTP CONNECT method to connect to Proxy Server and use it to forward the HEAD/GET request to Endpoint Server's BootURI. - Section 29.6.6 to use EFI_HTTP_CONNECT_REQUEST_DATA structure for HttpMethodConnect usage in EFI_HTTP_PROTOCOL.Request() Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
This commit is contained in:
committed by
mergify[bot]
parent
884585818f
commit
80c04eb46f
@@ -664,52 +664,63 @@ HttpBootFreeCache (
|
||||
IN HTTP_BOOT_CACHE_CONTENT *Cache
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *NextEntry;
|
||||
HTTP_BOOT_ENTITY_DATA *EntityData;
|
||||
UINTN Index;
|
||||
LIST_ENTRY *Entry;
|
||||
LIST_ENTRY *NextEntry;
|
||||
HTTP_BOOT_ENTITY_DATA *EntityData;
|
||||
EFI_HTTP_CONNECT_REQUEST_DATA *ConnRequestData;
|
||||
|
||||
if (Cache != NULL) {
|
||||
//
|
||||
// Free the request data
|
||||
//
|
||||
if (Cache->RequestData != NULL) {
|
||||
if (Cache->RequestData->Url != NULL) {
|
||||
FreePool (Cache->RequestData->Url);
|
||||
}
|
||||
|
||||
FreePool (Cache->RequestData);
|
||||
}
|
||||
|
||||
//
|
||||
// Free the response header
|
||||
//
|
||||
if (Cache->ResponseData != NULL) {
|
||||
if (Cache->ResponseData->Headers != NULL) {
|
||||
for (Index = 0; Index < Cache->ResponseData->HeaderCount; Index++) {
|
||||
FreePool (Cache->ResponseData->Headers[Index].FieldName);
|
||||
FreePool (Cache->ResponseData->Headers[Index].FieldValue);
|
||||
}
|
||||
|
||||
FreePool (Cache->ResponseData->Headers);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Free the response body
|
||||
//
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Cache->EntityDataList) {
|
||||
EntityData = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_ENTITY_DATA, Link);
|
||||
if (EntityData->Block != NULL) {
|
||||
FreePool (EntityData->Block);
|
||||
}
|
||||
|
||||
RemoveEntryList (&EntityData->Link);
|
||||
FreePool (EntityData);
|
||||
}
|
||||
|
||||
FreePool (Cache);
|
||||
if (Cache == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Free the request data
|
||||
//
|
||||
if (Cache->RequestData != NULL) {
|
||||
if (Cache->RequestData->Url != NULL) {
|
||||
FreePool (Cache->RequestData->Url);
|
||||
}
|
||||
|
||||
if (Cache->RequestData->Method == HttpMethodConnect) {
|
||||
ConnRequestData = (EFI_HTTP_CONNECT_REQUEST_DATA *)Cache->RequestData;
|
||||
|
||||
if (ConnRequestData->ProxyUrl != NULL) {
|
||||
FreePool (ConnRequestData->ProxyUrl);
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (Cache->RequestData);
|
||||
}
|
||||
|
||||
//
|
||||
// Free the response header
|
||||
//
|
||||
if (Cache->ResponseData != NULL) {
|
||||
if (Cache->ResponseData->Headers != NULL) {
|
||||
for (Index = 0; Index < Cache->ResponseData->HeaderCount; Index++) {
|
||||
FreePool (Cache->ResponseData->Headers[Index].FieldName);
|
||||
FreePool (Cache->ResponseData->Headers[Index].FieldValue);
|
||||
}
|
||||
|
||||
FreePool (Cache->ResponseData->Headers);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Free the response body
|
||||
//
|
||||
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Cache->EntityDataList) {
|
||||
EntityData = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_ENTITY_DATA, Link);
|
||||
if (EntityData->Block != NULL) {
|
||||
FreePool (EntityData->Block);
|
||||
}
|
||||
|
||||
RemoveEntryList (&EntityData->Link);
|
||||
FreePool (EntityData);
|
||||
}
|
||||
|
||||
FreePool (Cache);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -901,6 +912,182 @@ HttpBootGetBootFileCallback (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function establishes a connection through a proxy server
|
||||
|
||||
@param[in] Private The pointer to the driver's private data.
|
||||
|
||||
@retval EFI_SUCCESS Connection successful.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
|
||||
@retval Others Unexpected error happened.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
HttpBootConnectProxy (
|
||||
IN HTTP_BOOT_PRIVATE_DATA *Private
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HTTP_STATUS_CODE StatusCode;
|
||||
CHAR8 *HostName;
|
||||
EFI_HTTP_CONNECT_REQUEST_DATA *RequestData;
|
||||
HTTP_IO_RESPONSE_DATA *ResponseData;
|
||||
HTTP_IO *HttpIo;
|
||||
HTTP_IO_HEADER *HttpIoHeader;
|
||||
CHAR16 *Url;
|
||||
CHAR16 *ProxyUrl;
|
||||
UINTN UrlSize;
|
||||
|
||||
Url = NULL;
|
||||
ProxyUrl = NULL;
|
||||
RequestData = NULL;
|
||||
ResponseData = NULL;
|
||||
HttpIoHeader = NULL;
|
||||
|
||||
UrlSize = AsciiStrSize (Private->BootFileUri);
|
||||
Url = AllocatePool (UrlSize * sizeof (CHAR16));
|
||||
if (Url == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
AsciiStrToUnicodeStrS (Private->BootFileUri, Url, UrlSize);
|
||||
|
||||
UrlSize = AsciiStrSize (Private->ProxyUri);
|
||||
ProxyUrl = AllocatePool (UrlSize * (sizeof (CHAR16)));
|
||||
if (ProxyUrl == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
AsciiStrToUnicodeStrS (Private->ProxyUri, ProxyUrl, UrlSize);
|
||||
|
||||
//
|
||||
// Send HTTP request message.
|
||||
//
|
||||
|
||||
//
|
||||
// Build HTTP header for the request, 2 headers are needed to send a CONNECT method:
|
||||
// Host
|
||||
// User
|
||||
//
|
||||
HttpIoHeader = HttpIoCreateHeader (2);
|
||||
if (HttpIoHeader == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Add HTTP header field 1: Host (EndPoint URI)
|
||||
//
|
||||
HostName = NULL;
|
||||
Status = HttpUrlGetHostName (
|
||||
Private->BootFileUri,
|
||||
Private->BootFileUriParser,
|
||||
&HostName
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
Status = HttpIoSetHeader (
|
||||
HttpIoHeader,
|
||||
HTTP_HEADER_HOST,
|
||||
HostName
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Add HTTP header field 2: User-Agent
|
||||
//
|
||||
Status = HttpIoSetHeader (
|
||||
HttpIoHeader,
|
||||
HTTP_HEADER_USER_AGENT,
|
||||
HTTP_USER_AGENT_EFI_HTTP_BOOT
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Build the rest of HTTP request info.
|
||||
//
|
||||
RequestData = AllocatePool (sizeof (EFI_HTTP_CONNECT_REQUEST_DATA));
|
||||
if (RequestData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
RequestData->Base.Method = HttpMethodConnect;
|
||||
RequestData->Base.Url = Url;
|
||||
RequestData->ProxyUrl = ProxyUrl;
|
||||
|
||||
//
|
||||
// Send out the request to HTTP server.
|
||||
//
|
||||
HttpIo = &Private->HttpIo;
|
||||
Status = HttpIoSendRequest (
|
||||
HttpIo,
|
||||
&RequestData->Base,
|
||||
HttpIoHeader->HeaderCount,
|
||||
HttpIoHeader->Headers,
|
||||
0,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Receive HTTP response message.
|
||||
//
|
||||
|
||||
//
|
||||
// Use zero BodyLength to only receive the response headers.
|
||||
//
|
||||
ResponseData = AllocateZeroPool (sizeof (HTTP_IO_RESPONSE_DATA));
|
||||
if (ResponseData == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
Status = HttpIoRecvResponse (
|
||||
&Private->HttpIo,
|
||||
TRUE,
|
||||
ResponseData
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status) || EFI_ERROR (ResponseData->Status)) {
|
||||
if (EFI_ERROR (ResponseData->Status)) {
|
||||
StatusCode = HttpIo->RspToken.Message->Data.Response->StatusCode;
|
||||
HttpBootPrintErrorMessage (StatusCode);
|
||||
Status = ResponseData->Status;
|
||||
}
|
||||
}
|
||||
|
||||
EXIT:
|
||||
if (ResponseData != NULL) {
|
||||
FreePool (ResponseData);
|
||||
}
|
||||
|
||||
if (RequestData != NULL) {
|
||||
FreePool (RequestData);
|
||||
}
|
||||
|
||||
HttpIoFreeHeader (HttpIoHeader);
|
||||
|
||||
if (ProxyUrl != NULL) {
|
||||
FreePool (ProxyUrl);
|
||||
}
|
||||
|
||||
if (Url != NULL) {
|
||||
FreePool (Url);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function download the boot file by using UEFI HTTP protocol.
|
||||
|
||||
|
||||
@@ -86,6 +86,21 @@ HttpBootCreateHttpIo (
|
||||
IN HTTP_BOOT_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
This function establishes a connection through a proxy server
|
||||
|
||||
@param[in] Private The pointer to the driver's private data.
|
||||
|
||||
@retval EFI_SUCCESS Connection successful.
|
||||
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
|
||||
@retval Others Unexpected error happened.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
HttpBootConnectProxy (
|
||||
IN HTTP_BOOT_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
This function download the boot file by using UEFI HTTP protocol.
|
||||
|
||||
|
||||
@@ -319,7 +319,11 @@ HttpBootGetBootFileCaller (
|
||||
UINT32 Retries;
|
||||
|
||||
if (Private->BootFileSize == 0) {
|
||||
State = GetBootFileHead;
|
||||
if (Private->ProxyUri != NULL) {
|
||||
State = ConnectToProxy;
|
||||
} else {
|
||||
State = GetBootFileHead;
|
||||
}
|
||||
} else {
|
||||
State = LoadBootFile;
|
||||
}
|
||||
@@ -372,6 +376,16 @@ HttpBootGetBootFileCaller (
|
||||
|
||||
break;
|
||||
|
||||
case ConnectToProxy:
|
||||
Status = HttpBootConnectProxy (Private);
|
||||
if (Status == EFI_SUCCESS) {
|
||||
State = GetBootFileHead;
|
||||
} else {
|
||||
State = GetBootFileError;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case LoadBootFile:
|
||||
if (*BufferSize < Private->BootFileSize) {
|
||||
*BufferSize = Private->BootFileSize;
|
||||
|
||||
@@ -14,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
typedef enum {
|
||||
GetBootFileHead,
|
||||
GetBootFileGet,
|
||||
ConnectToProxy,
|
||||
LoadBootFile,
|
||||
GetBootFileError
|
||||
} HTTP_GET_BOOT_FILE_STATE;
|
||||
|
||||
Reference in New Issue
Block a user