From: Amaury Denoyelle Date: Wed, 11 Jun 2025 13:38:59 +0000 (+0200) Subject: MINOR: mux-quic: instantiate first stream on backend side X-Git-Tag: v3.3-dev2~68 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1efaca8a57a9c077ff88f3334492693c68569cbe;p=thirdparty%2Fhaproxy.git MINOR: mux-quic: instantiate first stream on backend side Adjust qmux_init() to handle frontend and backend sides differently. Most notably, on backend side, the first bidirectional stream is created preemptively. This step is necessary as MUX layer will be woken up just after handshake completion. --- diff --git a/src/mux_quic.c b/src/mux_quic.c index 046627e24..b3fcd6517 100644 --- a/src/mux_quic.c +++ b/src/mux_quic.c @@ -134,6 +134,7 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type) qcs->stream = NULL; qcs->qcc = qcc; + qcs->sd = NULL; qcs->flags = QC_SF_NONE; qcs->st = QC_SS_IDLE; qcs->ctx = NULL; @@ -3405,6 +3406,7 @@ static int qmux_init(struct connection *conn, struct proxy *prx, { struct qcc *qcc; struct quic_transport_params *lparams, *rparams; + void *conn_ctx = conn->ctx; TRACE_ENTER(QMUX_EV_QCC_NEW); @@ -3530,27 +3532,48 @@ static int qmux_init(struct connection *conn, struct proxy *prx, if (qcc->app_ops == &h3_ops && !conn_is_back(conn)) proxy_inc_fe_cum_sess_ver_ctr(sess->listener, prx, 3); - /* Register conn for idle front closing. This is done once everything is allocated. */ - if (!conn_is_back(conn)) + if (!conn_is_back(conn)) { + /* Register conn for idle front closing. */ LIST_APPEND(&mux_stopping_data[tid].list, &conn->stopping_list); - /* init read cycle */ - tasklet_wakeup(qcc->wait_event.tasklet); + /* init read cycle */ + tasklet_wakeup(qcc->wait_event.tasklet); - /* MUX is initialized before QUIC handshake completion if early data - * received. Flag connection to delay stream processing if - * wait-for-handshake is active. - */ - if (conn->handle.qc->state < QUIC_HS_ST_COMPLETE) { - if (!(conn->flags & CO_FL_EARLY_SSL_HS)) { - TRACE_STATE("flag connection with early data", QMUX_EV_QCC_WAKE, conn); - conn->flags |= CO_FL_EARLY_SSL_HS; - /* subscribe for handshake completion */ - conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV, - &qcc->wait_event); - qcc->flags |= QC_CF_WAIT_HS; + /* MUX is initialized before QUIC handshake completion if early data + * received. Flag connection to delay stream processing if + * wait-for-handshake is active. + */ + if (conn->handle.qc->state < QUIC_HS_ST_COMPLETE) { + if (!(conn->flags & CO_FL_EARLY_SSL_HS)) { + TRACE_STATE("flag connection with early data", QMUX_EV_QCC_WAKE, conn); + conn->flags |= CO_FL_EARLY_SSL_HS; + /* subscribe for handshake completion */ + conn->xprt->subscribe(conn, conn->xprt_ctx, SUB_RETRY_RECV, + &qcc->wait_event); + qcc->flags |= QC_CF_WAIT_HS; + } } } + else { + /* Initiate backend side transfer by creating the first + * bidirectional stream. MUX will then be woken up on QUIC + * handshake completion so that stream layer can start the + * transfer itself. + */ + struct qcs *qcs; + struct stconn *sc = conn_ctx; + + qcs = qcc_init_stream_local(qcc, 1); + if (!qcs) { + TRACE_PROTO("Cannot allocate a new locally initiated streeam", + QMUX_EV_QCC_NEW|QMUX_EV_QCC_ERR, conn); + goto err; + } + + sc_attach_mux(sc, qcs, conn); + qcs->sd = sc->sedesc; + qcc->nb_sc++; + } TRACE_LEAVE(QMUX_EV_QCC_NEW, conn); return 0;