From: Christopher Faulet Date: Mon, 8 Apr 2019 08:42:41 +0000 (+0200) Subject: MEDIUM: connection: Add conn_upgrade_mux_fe() to handle mux upgrades X-Git-Tag: v2.0-dev3~289 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0016d8119e28b28332e077ba2d0260f3cb59709;p=thirdparty%2Fhaproxy.git MEDIUM: connection: Add conn_upgrade_mux_fe() to handle mux upgrades This function will handle mux upgrades, for frontend connections only. It will retrieve the best mux in the same way than conn_install_mux_fe except that the mode and optionnally the proto are forced. The new multiplexer is initialized using a new context and a specific input buffer. Then, the old one is destroyed. If an error occurred, everything is rolled back. --- diff --git a/include/proto/connection.h b/include/proto/connection.h index 3a98b349f2..98183cefd9 100644 --- a/include/proto/connection.h +++ b/include/proto/connection.h @@ -1158,6 +1158,47 @@ static inline int conn_install_mux_be(struct connection *conn, void *ctx, struct return conn_install_mux(conn, mux_ops, ctx, prx, sess); } +static inline int conn_upgrade_mux_fe(struct connection *conn, void *ctx, struct buffer *buf, + struct ist mux_proto, int mode) +{ + struct bind_conf *bind_conf = __objt_listener(conn->target)->bind_conf; + const struct mux_ops *old_mux, *new_mux; + void *old_mux_ctx; + const char *alpn_str = NULL; + int alpn_len = 0; + + if (!mux_proto.len) { + conn_get_alpn(conn, &alpn_str, &alpn_len); + mux_proto = ist2(alpn_str, alpn_len); + } + new_mux = conn_get_best_mux(conn, mux_proto, PROTO_SIDE_FE, mode); + old_mux = conn->mux; + + /* No mux found */ + if (!new_mux) + return -1; + + /* Same mux, nothing to do */ + if (old_mux == new_mux) + return 0; + + old_mux_ctx = conn->ctx; + conn->mux = new_mux; + conn->ctx = ctx; + conn_force_unsubscribe(conn); + if (new_mux->init(conn, bind_conf->frontend, conn->owner, buf) == -1) { + /* The mux upgrade failed, so restore the old mux */ + conn->ctx = old_mux_ctx; + conn->mux = old_mux; + return -1; + } + + /* The mux was upgraded, destroy the old one */ + *buf = BUF_NULL; + old_mux->destroy(old_mux_ctx); + return 0; +} + #endif /* _PROTO_CONNECTION_H */ /*