MINOR: proxy: add a new option "http-use-htx"

This option makes a proxy use only HTX-compatible muxes instead of the
HTTP-compatible ones for HTTP modes. It must be set on both ends, this
is checked at parsing time.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 9cc2a67..b4c67c6 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2114,6 +2114,7 @@
 option http-server-close             (*)  X          X         X         X
 option http-tunnel                   (*)  X          X         X         -
 option http-use-proxy-header         (*)  X          X         X         -
+option http-use-htx                  (*)  X          X         X         X
 option httpchk                            X          -         X         X
 option httpclose                     (*)  X          X         X         X
 option httplog                            X          X         X         X
@@ -6018,6 +6019,39 @@
   See also : "option httpclose", and "option http-server-close".
 
 
+option http-use-htx
+no option http-use-htx
+  Switch to the new HTX internal representation for HTTP protocol elements
+  May be used in sections :   defaults | frontend | listen | backend
+                                 yes   |    yes   |   yes  |   yes
+  Arguments : none
+
+  By default, the HTTP protocol is processed as-is. Inserting, deleting, or
+  modifying a header field requires to rewrite the affected part in the buffer
+  and to move the buffer's tail accordingly. Since this principle has deep
+  roots in haproxy, the HTTP/2 protocol is converted to HTTP/1.1 before being
+  processed this way. It also results in the inability to establish HTTP/2
+  connections to servers because of the loss of HTTP/2 semantics in the HTTP/1
+  representation.
+
+  HTX is the name of a totally new native internal representation for the HTTP
+  protocol, that is agnostic to the version and aims at preserving semantics
+  all along the chain. It relies on a fast parsing, tokenizing and indexing of
+  the protocol elements so that no more memory moves are necessary and that
+  most elements are directly accessed. This mechanism is still limited to the
+  most basic operations (no compression, filters, Lua, applets, cache, etc).
+  But it supports using either HTTP/1 or HTTP/2 on any side regardless of the
+  other side's version.
+
+  This option indicates that HTX needs to be used. It will cause errors to be
+  emitted if incompatible features are used, but will allow H2 to be selected
+  as a server protocol. It is recommended to use this option on new reasonably
+  simple configurations, but since the feature still has incomplete functional
+  coverage, it is not enabled by default.
+
+  See also : "mode http"
+
+
 option httpchk
 option httpchk <uri>
 option httpchk <method> <uri>
diff --git a/include/proto/connection.h b/include/proto/connection.h
index 47825a0..1aa0ed9 100644
--- a/include/proto/connection.h
+++ b/include/proto/connection.h
@@ -971,7 +971,14 @@
 		struct ist mux_proto;
 		const char *alpn_str = NULL;
 		int alpn_len = 0;
-		int mode = (1 << (bind_conf->frontend->mode == PR_MODE_HTTP));
+		int mode;
+
+		if (bind_conf->frontend->mode == PR_MODE_TCP)
+			mode = PROTO_MODE_TCP;
+		else if (bind_conf->frontend->options2 & PR_O2_USE_HTX)
+			mode = PROTO_MODE_HTX;
+		else
+			mode = PROTO_MODE_HTTP;
 
 		conn_get_alpn(conn, &alpn_str, &alpn_len);
 		mux_proto = ist2(alpn_str, alpn_len);
@@ -1003,7 +1010,13 @@
 	else {
 		int mode;
 
-		mode = (1 << (prx->mode == PR_MODE_HTTP));
+		if (prx->mode == PR_MODE_TCP)
+			mode = PROTO_MODE_TCP;
+		else if (prx->options2 & PR_O2_USE_HTX)
+			mode = PROTO_MODE_HTX;
+		else
+			mode = PROTO_MODE_HTTP;
+
 		mux_ops = conn_get_best_mux(conn, ist(NULL), PROTO_SIDE_BE, mode);
 		if (!mux_ops)
 			return -1;
diff --git a/include/types/connection.h b/include/types/connection.h
index 827df36..889decb 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -425,7 +425,8 @@
 	PROTO_MODE_NONE = 0,
 	PROTO_MODE_TCP  = 1 << 0, // must not be changed!
 	PROTO_MODE_HTTP = 1 << 1, // must not be changed!
-	PROTO_MODE_ANY  = PROTO_MODE_TCP | PROTO_MODE_HTTP,
+	PROTO_MODE_HTX  = 1 << 2, // must not be changed!
+	PROTO_MODE_ANY  = PROTO_MODE_TCP | PROTO_MODE_HTTP, // note: HTX is experimental and must not appear here
 };
 
 enum proto_proxy_side {
diff --git a/include/types/proxy.h b/include/types/proxy.h
index b5f5b9b..da09848 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -151,7 +151,7 @@
 #define PR_O2_SRC_ADDR	0x00100000	/* get the source ip and port for logs */
 
 #define PR_O2_FAKE_KA   0x00200000      /* pretend we do keep-alive with server eventhough we close */
-/* unused: 0x00400000 */
+#define PR_O2_USE_HTX   0x00400000      /* use the HTX representation for the HTTP protocol */
 #define PR_O2_EXP_NONE  0x00000000      /* http-check : no expect rule */
 #define PR_O2_EXP_STS   0x00800000      /* http-check expect status */
 #define PR_O2_EXP_RSTS  0x01000000      /* http-check expect rstatus */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index a262404..8d8b6ea 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -208,6 +208,7 @@
 	{ "http-use-proxy-header",        PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
 	{ "http-pretend-keepalive",       PR_O2_FAKE_KA,   PR_CAP_BE, 0, PR_MODE_HTTP },
 	{ "http-no-delay",                PR_O2_NODELAY,   PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
+	{ "http-use-htx",                 PR_O2_USE_HTX,   PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
 	{ NULL, 0, 0, 0 }
 };
 
@@ -7792,6 +7793,13 @@
 					 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
 					 target->conf.file, target->conf.line);
 				cfgerr++;
+			} else if ((curproxy->options2 ^ target->options2) & PR_O2_USE_HTX) {
+				ha_alert("%s %s '%s' (%s:%d) tries to use %s %s '%s' (%s:%d) as its default backend, both of which disagree on 'option http-use-htx'.\n",
+					 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
+					 curproxy->conf.file, curproxy->conf.line,
+					 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
+					 target->conf.file, target->conf.line);
+				cfgerr++;
 			} else {
 				free(curproxy->defbe.name);
 				curproxy->defbe.be = target;
@@ -7872,6 +7880,13 @@
 					 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
 					 target->conf.file, target->conf.line);
 				cfgerr++;
+			} else if ((curproxy->options2 ^ target->options2) & PR_O2_USE_HTX) {
+				ha_alert("%s %s '%s' (%s:%d) tries to use %s %s '%s' (%s:%d) in a 'use_backend' rule, both of which disagree on 'option http-use-htx'.\n",
+					 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
+					 curproxy->conf.file, curproxy->conf.line,
+					 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
+					 target->conf.file, target->conf.line);
+				cfgerr++;
 			} else {
 				free((void *)rule->be.name);
 				rule->be.backend = target;