From: Amaury Denoyelle Date: Wed, 29 Apr 2026 08:12:52 +0000 (+0200) Subject: MINOR: connection: define xprt_add_l6hs() X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9e6e0fd149be6cb2a7e96973decdb6ed875582d7;p=thirdparty%2Fhaproxy.git MINOR: connection: define xprt_add_l6hs() When QMux protocol is used, xprt_qmux layer is setup after SSL handshake completion but prior to the MUX initialization. Once transport parameters exchange is successful, the layer is removed and the MUX is started. The layer setup operation was performed directly on ssl_sock_io_cb(). Simplify the code by extracting it in a dedicated function xprt_add_l6hs(). The function is generic so the requested XPRT layer must be passed as argument. The code is mostly identical. One difference is that a check is performed to ensure no SSL handshake is pending. If this is the case, the function is a noop. This will become useful to support QMux transparently both in clear or on top of SSL. Another minor addition is that CO_FL_XPRT_READY flag is automatically resetted by xprt_add_l6hs(). This allows the code to use conn_xprt_start() standard function after XPRT init. --- diff --git a/include/haproxy/connection.h b/include/haproxy/connection.h index b9933642f..e4dac7bf3 100644 --- a/include/haproxy/connection.h +++ b/include/haproxy/connection.h @@ -114,6 +114,7 @@ int conn_reverse(struct connection *conn); const char *conn_err_code_name(struct connection *c); const char *conn_err_code_str(struct connection *c); int xprt_add_hs(struct connection *conn); +int xprt_add_l6hs(struct connection *conn, int xprt); void register_mux_proto(struct mux_proto_list *list); static inline void conn_report_term_evt(struct connection *conn, enum term_event_loc loc, unsigned char type); diff --git a/src/connection.c b/src/connection.c index c56049ed2..99ca36c1f 100644 --- a/src/connection.c +++ b/src/connection.c @@ -847,6 +847,43 @@ int xprt_add_hs(struct connection *conn) return 0; } +/* Activates an layer on top of connection. This handshake layer + * should be designed to work on top of the layer 6. If SSL is active and its + * handshake still in progress, this function does nothing. + * + * Returns 0 on success else a negative error code. + */ +int xprt_add_l6hs(struct connection *conn, int xprt) +{ + const struct xprt_ops *ops = xprt_get(xprt); + void *ops_ctx = NULL; + + /* Only QMux is supported as handshake on top of layer6 for now. */ + BUG_ON(xprt != XPRT_QMUX); + + if (conn->flags & CO_FL_ERROR) + return -1; + + /* Do nothing if SSL is in used but handshake still in progress. In + * this case, xprt layer will be added on handshake completion. + */ + if (conn->xprt == xprt_get(XPRT_SSL) && + (conn->flags & CO_FL_WAIT_L6_CONN)) { + return 0; + } + + if (ops->init(conn, &ops_ctx)) + return -1; + + ops->add_xprt(conn, ops_ctx, conn->xprt_ctx, conn->xprt, NULL, NULL); + conn->xprt = ops; + conn->xprt_ctx = ops_ctx; + /* Reset XPRT READY flag before the next conn_xprt_start(). */ + conn->flags &= ~CO_FL_XPRT_READY; + + return 0; +} + /* returns a short name for an error, typically the same as the enum name * without the "CO_ER_" prefix, or an empty string for no error (better eye * catching in logs). This is more compact for some debug cases. diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 3ab33c990..aa167b001 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -6973,11 +6973,8 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state) mux = !conn_is_back(conn) ? conn_select_mux_fe(conn) : conn_select_mux_be(conn); - if (mux->init_xprt == XPRT_QMUX) { - const struct xprt_ops *ops = xprt_get(XPRT_QMUX); - void *xprt_ctx_hs = NULL; - - ret = ops->init(conn, &xprt_ctx_hs); + if (mux->init_xprt) { + ret = xprt_add_l6hs(conn, mux->init_xprt); /* Frontend conn must be freed in case of XPRT init failure. */ if (ret) { if (!conn_is_back(conn)) { @@ -6989,15 +6986,7 @@ struct task *ssl_sock_io_cb(struct task *t, void *context, unsigned int state) goto leave; } - ret = ops->add_xprt(conn, xprt_ctx_hs, - conn->xprt_ctx, conn->xprt, NULL, NULL); - BUG_ON(ret); /* xprt_qmux add_xprt always succeeds */ - - conn->xprt = ops; - conn->xprt_ctx = xprt_ctx_hs; - - ret = conn->xprt->start(conn, xprt_ctx_hs); - BUG_ON(ret); + ret = conn_xprt_start(conn); } else { /* TODO MUX selection already performs by conn_select_mux_fe/be().