]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: connection: define xprt_add_l6hs()
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 29 Apr 2026 08:12:52 +0000 (10:12 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 21 May 2026 13:09:10 +0000 (15:09 +0200)
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.

include/haproxy/connection.h
src/connection.c
src/ssl_sock.c

index b9933642feda17f4075d11788b810e94b9334ab0..e4dac7bf31b538d43521cea540e1bb5e9a5c4c02 100644 (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);
index c56049ed29cf29351fa511ef32be92f4055abe66..99ca36c1f1a95f75700f34a4e6eec7833ab38a02 100644 (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.
index 3ab33c9900d753edc3e71ebdfbe6029fda61659b..aa167b001304a7c4a4e63df14d94992262a3b1b1 100644 (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().