Blame SOURCES/0044-curl-7.61.1-retry-http11.patch

f9145b
From 78b62ef1206621e8f4f1628ad4eb0a7be877c96f Mon Sep 17 00:00:00 2001
f9145b
From: Johannes Schindelin <johannes.schindelin@gmx.de>
f9145b
Date: Fri, 7 Dec 2018 17:04:39 +0100
f9145b
Subject: [PATCH] Upon HTTP_1_1_REQUIRED, retry the request with HTTP/1.1
f9145b
f9145b
This is a companion patch to cbea2fd2c (NTLM: force the connection to
f9145b
HTTP/1.1, 2018-12-06): with NTLM, we can switch to HTTP/1.1
f9145b
preemptively. However, with other (Negotiate) authentication it is not
f9145b
clear to this developer whether there is a way to make it work with
f9145b
HTTP/2, so let's try HTTP/2 first and fall back in case we encounter the
f9145b
error HTTP_1_1_REQUIRED.
f9145b
f9145b
Note: we will still keep the NTLM workaround, as it avoids an extra
f9145b
round trip.
f9145b
f9145b
Daniel Stenberg helped a lot with this patch, in particular by
f9145b
suggesting to introduce the Curl_h2_http_1_1_error() function.
f9145b
f9145b
Closes #3349
f9145b
f9145b
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
f9145b
f9145b
Upstream-commit: d997aa0e963c5be5de100dccdc5208d39bd3d62b
f9145b
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
f9145b
---
f9145b
 lib/http2.c |  8 ++++++++
f9145b
 lib/http2.h |  4 ++++
f9145b
 lib/multi.c | 20 ++++++++++++++++++++
f9145b
 3 files changed, 32 insertions(+)
f9145b
f9145b
diff --git a/lib/http2.c b/lib/http2.c
f9145b
index d769193..3071097 100644
f9145b
--- a/lib/http2.c
f9145b
+++ b/lib/http2.c
f9145b
@@ -2300,6 +2300,14 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data)
f9145b
     Curl_http2_remove_child(data->set.stream_depends_on, data);
f9145b
 }
f9145b
 
f9145b
+/* Only call this function for a transfer that already got a HTTP/2
f9145b
+   CURLE_HTTP2_STREAM error! */
f9145b
+bool Curl_h2_http_1_1_error(struct connectdata *conn)
f9145b
+{
f9145b
+  struct http_conn *httpc = &conn->proto.httpc;
f9145b
+  return (httpc->error_code == NGHTTP2_HTTP_1_1_REQUIRED);
f9145b
+}
f9145b
+
f9145b
 #else /* !USE_NGHTTP2 */
f9145b
 
f9145b
 /* Satisfy external references even if http2 is not compiled in. */
f9145b
diff --git a/lib/http2.h b/lib/http2.h
f9145b
index 21cd9b8..91e504c 100644
f9145b
--- a/lib/http2.h
f9145b
+++ b/lib/http2.h
f9145b
@@ -59,6 +59,9 @@ CURLcode Curl_http2_add_child(struct Curl_easy *parent,
f9145b
 void Curl_http2_remove_child(struct Curl_easy *parent,
f9145b
                              struct Curl_easy *child);
f9145b
 void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
f9145b
+
f9145b
+/* returns true if the HTTP/2 stream error was HTTP_1_1_REQUIRED */
f9145b
+bool Curl_h2_http_1_1_error(struct connectdata *conn);
f9145b
 #else /* USE_NGHTTP2 */
f9145b
 #define Curl_http2_init(x) CURLE_UNSUPPORTED_PROTOCOL
f9145b
 #define Curl_http2_send_request(x) CURLE_UNSUPPORTED_PROTOCOL
f9145b
@@ -74,6 +77,7 @@ void Curl_http2_cleanup_dependencies(struct Curl_easy *data);
f9145b
 #define Curl_http2_add_child(x, y, z)
f9145b
 #define Curl_http2_remove_child(x, y)
f9145b
 #define Curl_http2_cleanup_dependencies(x)
f9145b
+#define Curl_h2_http_1_1_error(x) 0
f9145b
 #endif
f9145b
 
f9145b
 #endif /* HEADER_CURL_HTTP2_H */
f9145b
diff --git a/lib/multi.c b/lib/multi.c
f9145b
index 0f57fd5..d64ba94 100644
f9145b
--- a/lib/multi.c
f9145b
+++ b/lib/multi.c
f9145b
@@ -46,6 +46,7 @@
f9145b
 #include "vtls/vtls.h"
f9145b
 #include "connect.h"
f9145b
 #include "http_proxy.h"
f9145b
+#include "http2.h"
f9145b
 /* The last 3 #include files should be in this order */
f9145b
 #include "curl_printf.h"
f9145b
 #include "curl_memory.h"
f9145b
@@ -1943,6 +1944,25 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
f9145b
           done = TRUE;
f9145b
         }
f9145b
       }
f9145b
+      else if((CURLE_HTTP2_STREAM == result) &&
f9145b
+                Curl_h2_http_1_1_error(data->easy_conn)) {
f9145b
+        CURLcode ret = Curl_retry_request(data->easy_conn, &newurl);
f9145b
+
f9145b
+        infof(data, "Forcing HTTP/1.1 for NTLM");
f9145b
+        data->set.httpversion = CURL_HTTP_VERSION_1_1;
f9145b
+
f9145b
+        if(!ret)
f9145b
+          retry = (newurl)?TRUE:FALSE;
f9145b
+        else
f9145b
+          result = ret;
f9145b
+
f9145b
+        if(retry) {
f9145b
+          /* if we are to retry, set the result to OK and consider the
f9145b
+             request as done */
f9145b
+          result = CURLE_OK;
f9145b
+          done = TRUE;
f9145b
+        }
f9145b
+      }
f9145b
 
f9145b
       if(result) {
f9145b
         /*
f9145b
-- 
f9145b
2.37.3
f9145b