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.
This commit is contained in:
Amaury Denoyelle 2026-04-29 10:12:52 +02:00
parent e98595e4e5
commit 9e6e0fd149
3 changed files with 41 additions and 14 deletions

View file

@ -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);

View file

@ -847,6 +847,43 @@ int xprt_add_hs(struct connection *conn)
return 0;
}
/* Activates an <xprt> layer on top of <conn> 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.

View file

@ -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().