From: "Saloni Kasbekar" <saloni.kasbekar@intel.com>
To: devel@edk2.groups.io
Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>,
Maciej Rabeda <maciej.rabeda@linux.intel.com>,
Wu Jiaxin <jiaxin.wu@intel.com>, Siyuan Fu <siyuan.fu@intel.com>
Subject: [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL
Date: Fri, 2 Dec 2022 11:12:23 -0800 [thread overview]
Message-ID: <5725304efc9d9463081770ed01fb3d07c405ab2e.1670008048.git.saloni.kasbekar@intel.com> (raw)
In-Reply-To: <cover.1670008048.git.saloni.kasbekar@intel.com>
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951
Update HTTP Protocol with variables to support Proxy
Use state machine to call HttpBootGetBootFile()
Add switch/case for EfiHttpRequest request method
Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
NetworkPkg/HttpBootDxe/HttpBootImpl.c | 178 +++++++++++++++++---------
NetworkPkg/HttpBootDxe/HttpBootImpl.h | 7 +
NetworkPkg/HttpDxe/HttpImpl.c | 59 +++++++--
NetworkPkg/HttpDxe/HttpProto.c | 18 ++-
NetworkPkg/HttpDxe/HttpProto.h | 9 ++
5 files changed, 199 insertions(+), 72 deletions(-)
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
index 5735b96d9e..4748de0603 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -278,6 +278,122 @@ HttpBootDhcp (
return Status;
}
+/**
+ Issue calls to HttpBootGetBootFile() based on current Boot File State
+
+ @param[in] Private The pointer to the driver's private data.
+ @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
+ code of EFI_SUCCESS, the amount of data transferred to
+ Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of Buffer required to retrieve the requested file.
+ @param[in] Buffer The memory buffer to transfer the file to. If Buffer is NULL,
+ then the size of the requested file is returned in
+ BufferSize.
+ @param[out] ImageType The image type of the downloaded file.
+
+ @retval EFI_SUCCESS The file was loaded.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is not NULL but Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.
+ BufferSize has been updated with the size needed to complete
+ the request.
+ @retval EFI_ACCESS_DENIED Server authentication failed.
+ @retval Others Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpBootGetBootFileCaller (
+ IN HTTP_BOOT_PRIVATE_DATA *Private,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer OPTIONAL,
+ OUT HTTP_BOOT_IMAGE_TYPE *ImageType
+ )
+{
+ HTTP_GET_BOOT_FILE_STATE State;
+ EFI_STATUS Status;
+
+ if (Private->BootFileSize == 0) {
+ State = GetBootFileHead;
+ } else {
+ State = LoadBootFile;
+ }
+
+ for ( ; ;) {
+ switch (State) {
+ case GetBootFileHead:
+ //
+ // Try to use HTTP HEAD method.
+ //
+ Status = HttpBootGetBootFile (
+ Private,
+ TRUE,
+ &Private->BootFileSize,
+ NULL,
+ &Private->ImageType
+ );
+ if ((EFI_ERROR (Status)) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ if ((Private->AuthData != NULL) && (Status == EFI_ACCESS_DENIED)) {
+ //
+ // Try to use HTTP HEAD method again since the Authentication information is provided.
+ //
+ State = GetBootFileHead;
+ } else {
+ State = GetBootFileGet;
+ }
+ } else {
+ State = LoadBootFile;
+ }
+
+ break;
+
+ case GetBootFileGet:
+ //
+ // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
+ //
+ ASSERT (Private->BootFileSize == 0);
+ Status = HttpBootGetBootFile (
+ Private,
+ FALSE,
+ &Private->BootFileSize,
+ NULL,
+ &Private->ImageType
+ );
+ if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
+ State = GetBootFileError;
+ } else {
+ State = LoadBootFile;
+ }
+
+ break;
+
+ case LoadBootFile:
+ if (*BufferSize < Private->BootFileSize) {
+ *BufferSize = Private->BootFileSize;
+ *ImageType = Private->ImageType;
+ Status = EFI_BUFFER_TOO_SMALL;
+ return Status;
+ }
+
+ //
+ // Load the boot file into Buffer
+ //
+ Status = HttpBootGetBootFile (
+ Private,
+ FALSE,
+ BufferSize,
+ Buffer,
+ ImageType
+ );
+ return Status;
+
+ case GetBootFileError:
+ default:
+ AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP server.\n");
+ return Status;
+ }
+ }
+}
+
/**
Attempt to download the boot file through HTTP message exchange.
@@ -349,68 +465,10 @@ HttpBootLoadFile (
}
}
- if (Private->BootFileSize == 0) {
- //
- // Discover the information about the bootfile if we haven't.
- //
-
- //
- // Try to use HTTP HEAD method.
- //
- Status = HttpBootGetBootFile (
- Private,
- TRUE,
- &Private->BootFileSize,
- NULL,
- &Private->ImageType
- );
- if ((Private->AuthData != NULL) && (Status == EFI_ACCESS_DENIED)) {
- //
- // Try to use HTTP HEAD method again since the Authentication information is provided.
- //
- Status = HttpBootGetBootFile (
- Private,
- TRUE,
- &Private->BootFileSize,
- NULL,
- &Private->ImageType
- );
- } else if ((EFI_ERROR (Status)) && (Status != EFI_BUFFER_TOO_SMALL)) {
- //
- // Failed to get file size by HEAD method, may be trunked encoding, try HTTP GET method.
- //
- ASSERT (Private->BootFileSize == 0);
- Status = HttpBootGetBootFile (
- Private,
- FALSE,
- &Private->BootFileSize,
- NULL,
- &Private->ImageType
- );
- if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
- AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP server.\n");
- goto ON_EXIT;
- }
- }
- }
-
- if (*BufferSize < Private->BootFileSize) {
- *BufferSize = Private->BootFileSize;
- *ImageType = Private->ImageType;
- Status = EFI_BUFFER_TOO_SMALL;
- goto ON_EXIT;
- }
-
//
- // Load the boot file into Buffer
+ // Load the Boot File
//
- Status = HttpBootGetBootFile (
- Private,
- FALSE,
- BufferSize,
- Buffer,
- ImageType
- );
+ Status = HttpBootGetBootFileCaller (Private, BufferSize, Buffer, ImageType);
ON_EXIT:
HttpBootUninstallCallback (Private);
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
index 55adc9cb50..33da4fec51 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h
@@ -11,6 +11,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define HTTP_BOOT_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20)
+typedef enum {
+ GetBootFileHead,
+ GetBootFileGet,
+ LoadBootFile,
+ GetBootFileError
+} HTTP_GET_BOOT_FILE_STATE;
+
/**
Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index 7c5c925cf7..a761ce3d5d 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -162,6 +162,7 @@ EfiHttpConfigure (
HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;
HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;
HttpInstance->ConnectionClose = FALSE;
+ HttpInstance->ProxyConnected = FALSE;
if (HttpConfigData->LocalAddressIsIPv6) {
CopyMem (
@@ -244,6 +245,8 @@ EfiHttpRequest (
CHAR8 *RequestMsg;
CHAR8 *Url;
UINTN UrlLen;
+ CHAR8 *ProxyUrl;
+ UINTN ProxyUrlLen;
CHAR16 *HostNameStr;
HTTP_TOKEN_WRAP *Wrap;
CHAR8 *FileUrl;
@@ -254,6 +257,7 @@ EfiHttpRequest (
// Initializations
//
Url = NULL;
+ ProxyUrl = NULL;
UrlParser = NULL;
RemotePort = 0;
HostName = NULL;
@@ -277,12 +281,18 @@ EfiHttpRequest (
//
// Only support GET, HEAD, DELETE, PATCH, PUT and POST method in current implementation.
//
- if ((Request != NULL) && (Request->Method != HttpMethodGet) &&
- (Request->Method != HttpMethodHead) && (Request->Method != HttpMethodDelete) &&
- (Request->Method != HttpMethodPut) && (Request->Method != HttpMethodPost) &&
- (Request->Method != HttpMethodPatch))
- {
- return EFI_UNSUPPORTED;
+ if (Request != NULL) {
+ switch (Request->Method) {
+ case HttpMethodGet:
+ case HttpMethodHead:
+ case HttpMethodDelete:
+ case HttpMethodPut:
+ case HttpMethodPost:
+ case HttpMethodPatch:
+ break;
+ default:
+ return EFI_UNSUPPORTED;
+ }
}
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);
@@ -337,22 +347,49 @@ EfiHttpRequest (
}
//
- // Parse the URI of the remote host.
+ // Parse the Request URI.
//
Url = HttpInstance->Url;
UrlLen = StrLen (Request->Url) + 1;
- if (UrlLen > HTTP_URL_BUFFER_LEN) {
+ if (UrlLen > HttpInstance->UrlLen) {
Url = AllocateZeroPool (UrlLen);
if (Url == NULL) {
return EFI_OUT_OF_RESOURCES;
}
- FreePool (HttpInstance->Url);
- HttpInstance->Url = Url;
+ if (HttpInstance->Url != NULL) {
+ FreePool (HttpInstance->Url);
+ }
+
+ HttpInstance->Url = Url;
+ HttpInstance->UrlLen = UrlLen;
}
UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen);
+ //
+ // In case of HTTP Connect, parse proxy URI from Request.
+ //
+ if (Request->Method == HttpMethodConnect) {
+ ProxyUrl = HttpInstance->ProxyUrl;
+ ProxyUrlLen = StrLen (Request->ProxyUrl) + 1;
+ if (ProxyUrlLen > HttpInstance->ProxyUrlLen) {
+ ProxyUrl = AllocateZeroPool (ProxyUrlLen);
+ if (ProxyUrl == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (HttpInstance->ProxyUrl != NULL) {
+ FreePool (HttpInstance->ProxyUrl);
+ }
+
+ HttpInstance->ProxyUrl = ProxyUrl;
+ HttpInstance->ProxyUrlLen = ProxyUrlLen;
+ }
+
+ UnicodeStrToAsciiStrS (Request->ProxyUrl, ProxyUrl, ProxyUrlLen);
+ }
+
//
// From the information in Url, the HTTP instance will
// be able to determine whether to use http or https.
@@ -395,7 +432,7 @@ EfiHttpRequest (
}
UrlParser = NULL;
- Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
+ Status = HttpParseUrl (Url, (UINT32)AsciiStrLen (Url), FALSE, &UrlParser);
if (EFI_ERROR (Status)) {
goto Error1;
}
diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c
index 33ae622c3f..6767d90c7d 100644
--- a/NetworkPkg/HttpDxe/HttpProto.c
+++ b/NetworkPkg/HttpDxe/HttpProto.c
@@ -737,6 +737,8 @@ HttpInitProtocol (
goto ON_ERROR;
}
+ HttpInstance->UrlLen = HTTP_URL_BUFFER_LEN;
+
return EFI_SUCCESS;
ON_ERROR:
@@ -846,9 +848,23 @@ HttpCleanProtocol (
if (HttpInstance->Url != NULL) {
FreePool (HttpInstance->Url);
- HttpInstance->Url = NULL;
+ HttpInstance->Url = NULL;
+ HttpInstance->UrlLen = 0;
+ }
+
+ if (HttpInstance->ProxyUrl != NULL) {
+ FreePool (HttpInstance->ProxyUrl);
+ HttpInstance->ProxyUrl = NULL;
+ HttpInstance->ProxyUrlLen = 0;
}
+ if (HttpInstance->EndPointHostName != NULL) {
+ FreePool (HttpInstance->EndPointHostName);
+ HttpInstance->EndPointHostName = NULL;
+ }
+
+ HttpInstance->ProxyConnected = FALSE;
+
NetMapClean (&HttpInstance->TxTokens);
NetMapClean (&HttpInstance->RxTokens);
diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h
index 620eb39158..3e4e86dad9 100644
--- a/NetworkPkg/HttpDxe/HttpProto.h
+++ b/NetworkPkg/HttpDxe/HttpProto.h
@@ -164,6 +164,15 @@ typedef struct _HTTP_PROTOCOL {
NET_MAP RxTokens;
CHAR8 *Url;
+ UINTN UrlLen;
+
+ //
+ // Proxy support
+ //
+ CHAR8 *ProxyUrl;
+ UINTN ProxyUrlLen;
+ BOOLEAN ProxyConnected;
+ CHAR8 *EndPointHostName;
//
// Https Support
--
2.36.1.windows.1
next prev parent reply other threads:[~2022-12-02 19:12 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL Saloni Kasbekar
2022-12-02 19:12 ` Saloni Kasbekar [this message]
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu Saloni Kasbekar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5725304efc9d9463081770ed01fb3d07c405ab2e.1670008048.git.saloni.kasbekar@intel.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox