From 324a97ecf82e5e415c3c9fb4df093053c1efedf1 Mon Sep 17 00:00:00 2001
From: Diego Bes <dbesprosvan@ahoffeld-pc.tango.corp>
Date: Fri, 18 Mar 2016 15:25:56 -0700
Subject: [PATCH] http2: support "prior knowledge", no upgrade from HTTP/1.1
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Supports HTTP/2 over clear TCP

- Optimize switching to HTTP/2 by removing calls to init and setup
before switching. Switching will eventually call setup and setup calls
init.

- Supports new version to “force” the use of HTTP/2 over clean TCP

- Add common line parameter “--http2-prior-knowledge” to the Curl
  command line tool.
---
 docs/HTTP2.md                    |  3 +++
 docs/curl.1                      |  5 +++++
 docs/libcurl/symbols-in-versions |  1 +
 include/curl/curl.h              |  2 ++
 lib/http.c                       | 20 ++++++++++++--------
 src/tool_getparam.c              |  5 +++++
 src/tool_help.c                  |  1 +
 7 files changed, 29 insertions(+), 8 deletions(-)

diff --git a/docs/HTTP2.md b/docs/HTTP2.md
index 81b3d5e216..5294ab5fa5 100644
--- a/docs/HTTP2.md
+++ b/docs/HTTP2.md
@@ -96,6 +96,9 @@ curl tool
 
 curl offers the `--http2` command line option to enable use of HTTP/2.
 
+curl offers the `--http2-prior-knowledge` command line option to enable use of 
+HTTP/2 without HTTP/1.1 Upgrade.
+
 Since 7.47.0, the curl tool enables HTTP/2 by default for HTTPS connections.
 
 HTTP Alternative Services
diff --git a/docs/curl.1 b/docs/curl.1
index 0b0f4d29d2..4a61b6554d 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -150,6 +150,11 @@ version. (Added in 7.33.0)
 .IP "--http2"
 (HTTP) Tells curl to issue its requests using HTTP 2. This requires that the
 underlying libcurl was built to support it. (Added in 7.33.0)
+.IP "--http2-prior-knowledge"
+(HTTP) Tells curl to issue its requests using HTTP 2 without HTTP/1.1 Upgrade. 
+This requires prior knowledge that the server supports HTTP 2.
+This requires that the underlying libcurl was built to support it. 
+(Added in 7.49.0)
 .IP "--no-npn"
 Disable the NPN TLS extension. NPN is enabled by default if libcurl was built
 with an SSL library that supports NPN. NPN is used by a libcurl that supports
diff --git a/docs/libcurl/symbols-in-versions b/docs/libcurl/symbols-in-versions
index daf1809abc..2e4f15f39d 100644
--- a/docs/libcurl/symbols-in-versions
+++ b/docs/libcurl/symbols-in-versions
@@ -695,6 +695,7 @@ CURL_HTTP_VERSION_1_1           7.9.1
 CURL_HTTP_VERSION_2             7.43.0
 CURL_HTTP_VERSION_2_0           7.33.0
 CURL_HTTP_VERSION_2TLS          7.47.0
+CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE 7.49.0
 CURL_HTTP_VERSION_NONE          7.9.1
 CURL_IPRESOLVE_V4               7.10.8
 CURL_IPRESOLVE_V6               7.10.8
diff --git a/include/curl/curl.h b/include/curl/curl.h
index e0d5c0f4eb..96ea1f2a03 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -1727,6 +1727,8 @@ enum {
   CURL_HTTP_VERSION_1_1,  /* please use HTTP 1.1 in the request */
   CURL_HTTP_VERSION_2_0,  /* please use HTTP 2 in the request */
   CURL_HTTP_VERSION_2TLS, /* use version 2 for HTTPS, version 1.1 for HTTP */
+  CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE,  /* please use HTTP 2 without HTTP/1.1
+                                           Upgrade */
 
   CURL_HTTP_VERSION_LAST /* *ILLEGAL* http version */
 };
diff --git a/lib/http.c b/lib/http.c
index 94a1e936e7..f261b3deb5 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1792,13 +1792,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
     switch(conn->negnpn) {
     case CURL_HTTP_VERSION_2:
       conn->httpversion = 20; /* we know we're on HTTP/2 now */
-      result = Curl_http2_init(conn);
-      if(result)
-        return result;
-
-      result = Curl_http2_setup(conn);
-      if(result)
-        return result;
 
       result = Curl_http2_switched(conn, NULL, 0);
       if(result)
@@ -1808,7 +1801,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
       /* continue with HTTP/1.1 when explicitly requested */
       break;
     default:
-      /* and as fallback */
+      /* Check if user wants to use HTTP/2 with clear TCP*/
+#ifdef USE_NGHTTP2
+      if(conn->data->set.httpversion ==
+         CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+        DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
+        conn->httpversion = 20;
+
+        result = Curl_http2_switched(conn, NULL, 0);
+        if(result)
+          return result;
+      }
+#endif
       break;
     }
   }
diff --git a/src/tool_getparam.c b/src/tool_getparam.c
index 61f50464bb..9bb1b0c5f3 100644
--- a/src/tool_getparam.c
+++ b/src/tool_getparam.c
@@ -184,6 +184,7 @@ static const struct LongShort aliases[]= {
   {"0",   "http1.0",                 FALSE},
   {"01",  "http1.1",                 FALSE},
   {"02",  "http2",                   FALSE},
+  {"03",  "http2-prior-knowledge",   FALSE},
   {"1",  "tlsv1",                    FALSE},
   {"10",  "tlsv1.0",                 FALSE},
   {"11",  "tlsv1.1",                 FALSE},
@@ -1036,6 +1037,10 @@ ParameterError getparameter(char *flag,    /* f or -long-flag */
         /* HTTP version 2.0 */
         config->httpversion = CURL_HTTP_VERSION_2_0;
         break;
+      case '3':
+        /* HTTP version 2.0 over clean TCP*/
+        config->httpversion = CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE;
+        break;
       }
       break;
     case '1': /* --tlsv1* options */
diff --git a/src/tool_help.c b/src/tool_help.c
index a1a6fb4934..42159f4d91 100644
--- a/src/tool_help.c
+++ b/src/tool_help.c
@@ -111,6 +111,7 @@ static const char *const helptext[] = {
   " -0, --http1.0       Use HTTP 1.0 (H)",
   "     --http1.1       Use HTTP 1.1 (H)",
   "     --http2         Use HTTP 2 (H)",
+  "     --http2-prior-knowledge  Use HTTP 2 without HTTP/1.1 Upgrade (H)",
   "     --ignore-content-length  Ignore the HTTP Content-Length header",
   " -i, --include       Include protocol headers in the output (H/F)",
   " -k, --insecure      Allow connections to SSL sites without certs (H)",
-- 
GitLab