<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
Anyone?</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
FWIW I've been doing at least 20 boots a day with this, 200-300 MiB at a time. Super stable.</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
This is also tracked now <a href="https://bugzilla.tianocore.org/show_bug.cgi?id=2720">https://bugzilla.tianocore.org/show_bug.cgi?id=2720</a></div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div style="font-family: Consolas, Courier, monospace; font-size: 12pt; color: rgb(0, 0, 0);">
A</div>
<div id="appendonsend"></div>
<hr style="display:inline-block;width:98%" tabindex="-1">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" style="font-size:11pt" color="#000000"><b>From:</b> devel@edk2.groups.io <devel@edk2.groups.io> on behalf of Andrei Warkentin via groups.io <andrey.warkentin=gmail.com@groups.io><br>
<b>Sent:</b> Thursday, May 14, 2020 2:02 AM<br>
<b>To:</b> devel@edk2.groups.io <devel@edk2.groups.io><br>
<b>Cc:</b> maciej.rabeda@linux.intel.com <maciej.rabeda@linux.intel.com>; jiaxin.wu@intel.com <jiaxin.wu@intel.com>; siyuan.fu@intel.com <siyuan.fu@intel.com><br>
<b>Subject:</b> [edk2-devel] [edk2][PATCH 1/1] HttpBoot: handle servers which may FIN after file sizing in HttpBootLoadFile</font>
<div> </div>
</div>
<div class="BodyFragment"><font size="2"><span style="font-size:11pt;">
<div class="PlainText">Python http.server seems to FIN after the first HEAD request to size<br>
the loaded file is completed and ACKed. What happens next is interesting.<br>
On low latency connections, the GET request to download may get sent<br>
after the server sends the FIN but before the client has a chance to<br>
process it. The net result is:<br>
- Server ignores GET<br>
- HttpBootLoadFile returns EFI_CONNECTION_FIN. Boot fails.<br>
<br>
In the other case, client handles the FIN before attempting the GET,<br>
so there's a proper three-way handshake as part of GET.<br>
<br>
The solution is to retry HttpBootLoadFile 2 times if it returns<br>
EFI_CONNECTION_FIN. This is because HttpBootLoadFile may issue up to<br>
3 requests: HEAD/GET to get size and final GET to load. Some servers<br>
may send a FIN after each request. The first request (HEAD) is not<br>
supposed to fail this way, so only the two subsequent GET request<br>
may result in a FIN.<br>
<br>
Fixes <a href="https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2720&data=02%7C01%7Cawarkentin%40vmware.com%7C73254836459946b2441e08d7f7d4c742%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C0%7C0%7C637250365557622212&sdata=HOKwm430VLz1xB9yyrF3T7XKgYipWy5%2FH%2BKbWuIhm24%3D&reserved=0">
https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fbugzilla.tianocore.org%2Fshow_bug.cgi%3Fid%3D2720&data=02%7C01%7Cawarkentin%40vmware.com%7C73254836459946b2441e08d7f7d4c742%7Cb39138ca3cee4b4aa4d6cd83d9dd62f0%7C0%7C0%7C637250365557622212&sdata=HOKwm430VLz1xB9yyrF3T7XKgYipWy5%2FH%2BKbWuIhm24%3D&reserved=0</a><br>
<br>
Signed-off-by: Andrei Warkentin <andrey.warkentin@gmail.com><br>
---<br>
NetworkPkg/HttpBootDxe/HttpBootImpl.c | 27 +++++++++++++++++++-<br>
NetworkPkg/HttpDxe/HttpImpl.c | 5 ++++<br>
2 files changed, 31 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c<br>
index 4a51f35cdd..2d74d5f293 100644<br>
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c<br>
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c<br>
@@ -288,6 +288,7 @@ HttpBootDhcp (<br>
@retval EFI_NOT_STARTED The driver is in stopped state.<br>
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the boot file. BufferSize has<br>
been updated with the size needed to complete the request.<br>
+ @retval EFI_CONNECTION_FIN Server had closed the connection while we were waiting downloading.<br>
@retval EFI_DEVICE_ERROR An unexpected network error occurred.<br>
@retval Others Other errors as indicated.<br>
<br>
@@ -535,6 +536,7 @@ HttpBootStop (<br>
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory entry.<br>
BufferSize has been updated with the size needed to complete<br>
the request.<br>
+ @retval EFI_CONNECTION_FIN Server had closed the connection while we were waiting for a response.<br>
<br>
**/<br>
EFI_STATUS<br>
@@ -553,6 +555,7 @@ HttpBootDxeLoadFile (<br>
BOOLEAN UsingIpv6;<br>
EFI_STATUS Status;<br>
HTTP_BOOT_IMAGE_TYPE ImageType;<br>
+ UINTN MaxTries;<br>
<br>
if (This == NULL || BufferSize == NULL || FilePath == NULL) {<br>
return EFI_INVALID_PARAMETER;<br>
@@ -598,7 +601,29 @@ HttpBootDxeLoadFile (<br>
// Load the boot file.<br>
//<br>
ImageType = ImageTypeMax;<br>
- Status = HttpBootLoadFile (Private, BufferSize, Buffer, &ImageType);<br>
+ //<br>
+ // HttpBootLoadFile may issue up to 2 requests: HEAD/GET to get<br>
+ // size and final GET to load. Some servers may send a FIN after<br>
+ // each request. The first request (HEAD) is not supposed to<br>
+ // fail this way, so only the two possible GETs need the special<br>
+ // handling.<br>
+ //<br>
+ MaxTries = 2;<br>
+ do {<br>
+ Status = HttpBootLoadFile (Private, BufferSize, Buffer, &ImageType);<br>
+ if (Status == EFI_CONNECTION_FIN) {<br>
+ if (Private->HttpCreated) {<br>
+ //<br>
+ // Tear down HTTP/TCP state entirely. Http->Configure (NULL) is not<br>
+ // sufficient (EFI_ACCESS_DENIED from TCP stack on subsequent<br>
+ // HttpBootLoadFile.<br>
+ //<br>
+ HttpIoDestroyIo (&Private->HttpIo);<br>
+ Private->HttpCreated = FALSE;<br>
+ }<br>
+ }<br>
+ } while (MaxTries-- && Status == EFI_CONNECTION_FIN);<br>
+<br>
if (EFI_ERROR (Status)) {<br>
if (Status == EFI_BUFFER_TOO_SMALL && (ImageType == ImageTypeVirtualCd || ImageType == ImageTypeVirtualDisk)) {<br>
Status = EFI_WARN_FILE_SYSTEM;<br>
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c<br>
index 5a6ecbc9d9..34a33b09f7 100644<br>
--- a/NetworkPkg/HttpDxe/HttpImpl.c<br>
+++ b/NetworkPkg/HttpDxe/HttpImpl.c<br>
@@ -959,6 +959,8 @@ HttpBodyParserCallback (<br>
@retval EFI_OUT_OF_RESOURCES Failed to complete the operation due to lack of resources.<br>
@retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6Token or<br>
the EFI_HTTP_UTILITIES_PROTOCOL is not available.<br>
+ @retval EFI_CONNECTION_FIN Server had closed the connection while we were waiting for<br>
+ a response.<br>
<br>
**/<br>
EFI_STATUS<br>
@@ -1528,6 +1530,9 @@ Error:<br>
@retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.<br>
@retval EFI_ACCESS_DENIED An open TCP connection is not present with the host<br>
specified by response URL.<br>
+<br>
+ @retval EFI_CONNECTION_FIN Server had closed the connection while we were waiting for<br>
+ a response.<br>
**/<br>
EFI_STATUS<br>
EFIAPI<br>
-- <br>
2.17.1<br>
<br>
<br>
<br>
<br>
</div>
</span></font></div>
</body>
</html>
<div width="1" style="color:white;clear:both">_._,_._,_</div>
<hr>
Groups.io Links:<p>
You receive all messages sent to this group.
<p>
<a target="_blank" href="https://edk2.groups.io/g/devel/message/59772">View/Reply Online (#59772)</a> |
|
<a target="_blank" href="https://groups.io/mt/74200034/1813853">Mute This Topic</a>
| <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br>
<br>
<a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> |
<a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> |
<a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a>
[edk2-devel-archive@redhat.com]<br>
<div width="1" style="color:white;clear:both">_._,_._,_</div>