From 9b8e11e691619b9cc0336f57bcdfacb015864a97 Mon Sep 17 00:00:00 2001 From: Olivier Houchard Date: Fri, 25 Oct 2019 16:19:26 +0200 Subject: [PATCH] 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. --- include/types/connection.h | 7 +++++++ src/mux_fcgi.c | 15 +++++++++++++++ src/mux_h1.c | 14 ++++++++++++++ src/mux_h2.c | 19 +++++++++++++++++++ src/mux_pt.c | 14 ++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/include/types/connection.h b/include/types/connection.h index f6a7d1b7e..165a683ae 100644 --- a/include/types/connection.h +++ b/include/types/connection.h @@ -331,6 +331,12 @@ struct xprt_ops { 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 function will automatically be @@ -359,6 +365,7 @@ struct mux_ops { 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_fcgi.c b/src/mux_fcgi.c index ed8b3def5..d2d2dd430 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -3000,6 +3000,20 @@ static int fcgi_wake(struct connection *conn) return (fcgi_process(fconn)); } + +static int fcgi_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; + } +} + /* Connection timeout management. The principle is that if there's no receipt * nor sending for a certain amount of time, the connection is closed. If the * MUX buffer still has lying data or is not allocatable, the connection is @@ -4050,6 +4064,7 @@ static const struct mux_ops mux_fcgi_ops = { .unsubscribe = fcgi_unsubscribe, .shutr = fcgi_shutr, .shutw = fcgi_shutw, + .ctl = fcgi_ctl, .show_fd = fcgi_show_fd, .flags = MX_FL_HTX, .name = "FCGI", diff --git a/src/mux_h1.c b/src/mux_h1.c index e28e86b74..66ffdb70b 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -2727,6 +2727,19 @@ static int h1_snd_pipe(struct conn_stream *cs, struct pipe *pipe) } #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) { @@ -2974,6 +2987,7 @@ static const struct mux_ops mux_h1_ops = { .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 bb0a94de4..e83f346e3 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -3792,6 +3792,24 @@ static const struct conn_stream *h2_get_first_cs(const struct connection *conn) 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 */ @@ -6095,6 +6113,7 @@ static const struct mux_ops h2_ops = { .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 6092a92b6..6cbc689ce 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -333,6 +333,19 @@ static int mux_pt_snd_pipe(struct conn_stream *cs, struct pipe *pipe) } #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 @@ const struct mux_ops mux_pt_ops = { .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,