MINOR: mux: Add a new method to get informations about a mux.

Add a new method, ctl(), to muxes. It uses a "enum mux_ctl_type" to
let it know which information we're asking for, and can output it either
directly by returning the expected value, or by using an optional argument.
"output" argument.
Right now, the only known mux_ctl_type is MUX_STATUS, that will return 0 if
the mux is not ready, or MUX_STATUS_READY if the mux is ready.

We probably want to backport this to 1.9 and 2.0.

(cherry picked from commit 9b8e11e691619b9cc0336f57bcdfacb015864a97)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
diff --git a/include/types/connection.h b/include/types/connection.h
index cc2fb17..ecd3377 100644
--- a/include/types/connection.h
+++ b/include/types/connection.h
@@ -331,6 +331,12 @@
 	int (*add_xprt)(struct connection *conn, void *xprt_ctx, void *toadd_ctx, const struct xprt_ops *toadd_ops, void **oldxprt_ctx, const struct xprt_ops **oldxprt_ops); /* Add a new XPRT as the new xprt, and return the old one */
 };
 
+enum mux_ctl_type {
+	MUX_STATUS, /* Expects an int as output, sets it to a combinaison of MUX_STATUS flags */
+};
+
+#define MUX_STATUS_READY (1 << 0)
+
 /* mux_ops describes the mux operations, which are to be performed at the
  * connection level after data are exchanged with the transport layer in order
  * to propagate them to streams. The <init> function will automatically be
@@ -359,6 +365,7 @@
 	void (*destroy)(void *ctx); /* Let the mux know one of its users left, so it may have to disappear */
 	void (*reset)(struct connection *conn); /* Reset the mux, because we're re-trying to connect */
 	const struct cs_info *(*get_cs_info)(struct conn_stream *cs); /* Return info on the specified conn_stream or NULL if not defined */
+	int (*ctl)(struct connection *conn, enum mux_ctl_type mux_ctl, void *arg); /* Provides informations about the mux */
 	unsigned int flags;                           /* some flags characterizing the mux's capabilities (MX_FL_*) */
 	char name[8];                                 /* mux layer name, zero-terminated */
 };
diff --git a/src/mux_h1.c b/src/mux_h1.c
index 4f3ba67..2c58d74 100644
--- a/src/mux_h1.c
+++ b/src/mux_h1.c
@@ -2498,6 +2498,19 @@
 }
 #endif
 
+static int h1_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *output)
+{
+	int ret = 0;
+	switch (mux_ctl) {
+	case MUX_STATUS:
+		if (conn->flags & CO_FL_CONNECTED)
+			ret |= MUX_STATUS_READY;
+		return ret;
+	default:
+		return -1;
+	}
+}
+
 /* for debugging with CLI's "show fd" command */
 static void h1_show_fd(struct buffer *msg, struct connection *conn)
 {
@@ -2556,6 +2569,7 @@
 	.shutw       = h1_shutw,
 	.show_fd     = h1_show_fd,
 	.reset       = h1_reset,
+	.ctl         = h1_ctl,
 	.flags       = MX_FL_HTX,
 	.name        = "H1",
 };
diff --git a/src/mux_h2.c b/src/mux_h2.c
index ac34a72..8116df4 100644
--- a/src/mux_h2.c
+++ b/src/mux_h2.c
@@ -3217,6 +3217,24 @@
 	return NULL;
 }
 
+static int h2_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *output)
+{
+	int ret = 0;
+	struct h2c *h2c = conn->ctx;
+
+	switch (mux_ctl) {
+	case MUX_STATUS:
+		/* Only consider the mux to be ready if we're done with
+		 * the preface and settings, and we had no error.
+		 */
+		if (h2c->st0 >= H2_CS_FRAME_H && h2c->st0 < H2_CS_ERROR)
+			ret |= MUX_STATUS_READY;
+		return ret;
+	default:
+		return -1;
+	}
+}
+
 /*
  * Destroy the mux and the associated connection, if it is no longer used
  */
@@ -5932,6 +5950,7 @@
 	.used_streams = h2_used_streams,
 	.shutr = h2_shutr,
 	.shutw = h2_shutw,
+	.ctl = h2_ctl,
 	.show_fd = h2_show_fd,
 	.flags = MX_FL_CLEAN_ABRT,
 	.name = "H2",
@@ -5960,6 +5979,7 @@
 	.used_streams = h2_used_streams,
 	.shutr = h2_shutr,
 	.shutw = h2_shutw,
+	.ctl = h2_ctl,
 	.show_fd = h2_show_fd,
 	.flags = MX_FL_CLEAN_ABRT|MX_FL_HTX,
 	.name = "H2",
diff --git a/src/mux_pt.c b/src/mux_pt.c
index 813c5fa..c66b746 100644
--- a/src/mux_pt.c
+++ b/src/mux_pt.c
@@ -333,6 +333,19 @@
 }
 #endif
 
+static int mux_pt_ctl(struct connection *conn, enum mux_ctl_type mux_ctl, void *output)
+{
+	int ret = 0;
+	switch (mux_ctl) {
+	case MUX_STATUS:
+		if (conn->flags & CO_FL_CONNECTED)
+			ret |= MUX_STATUS_READY;
+		return ret;
+	default:
+		return -1;
+	}
+}
+
 /* The mux operations */
 const struct mux_ops mux_pt_ops = {
 	.init = mux_pt_init,
@@ -351,6 +364,7 @@
 	.avail_streams = mux_pt_avail_streams,
 	.used_streams = mux_pt_used_streams,
 	.destroy = mux_pt_destroy_meth,
+	.ctl = mux_pt_ctl,
 	.shutr = mux_pt_shutr,
 	.shutw = mux_pt_shutw,
 	.flags = MX_FL_NONE,