From: Amaury Denoyelle Date: Wed, 8 Apr 2026 08:33:10 +0000 (+0200) Subject: MEDIUM: mux-quic/xprt_qstrm: implement QMux record emission X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a993f0c5031ded33fb140ad4c712ae174a7d0c2e;p=thirdparty%2Fhaproxy.git MEDIUM: mux-quic/xprt_qstrm: implement QMux record emission This patch implements emission of the new Record layer for QMux frames. This handles mux-quic and xprt_qstrm layers as this is performed similarly in both cases. Currently, the simplest approach has been prefered : each frame is encoded in its own record. This is not the most efficient in size but it is extremely simple to implement for a first interop testing. --- diff --git a/src/mux_quic_qstrm.c b/src/mux_quic_qstrm.c index 3b4b44f46..1b9dc7629 100644 --- a/src/mux_quic_qstrm.c +++ b/src/mux_quic_qstrm.c @@ -242,6 +242,8 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) struct buffer *buf = &qcc->tx.qstrm_buf; unsigned char *pos, *old, *end; size_t ret; + /* Record size field length */ + const int lensz = quic_int_getsize(quic_int_cap_length(b_size(buf))); TRACE_ENTER(QMUX_EV_QCC_SEND, qcc->conn); @@ -258,12 +260,12 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) } } - b_reset(buf); list_for_each_entry_safe(frm, frm_old, frms, list) { loop: split_frm = next_frm = NULL; b_reset(buf); - old = pos = (unsigned char *)b_orig(buf); + /* Reserve 4 bytes for the record header. */ + old = pos = (unsigned char *)b_orig(buf) + lensz; end = (unsigned char *)b_wrap(buf); BUG_ON(!frm); @@ -292,6 +294,10 @@ int qcc_qstrm_send_frames(struct qcc *qcc, struct list *frms) qc_build_frm(frm, &pos, end, NULL); BUG_ON(pos - old > global.tune.bufsize); BUG_ON(pos == old); + + /* Encode record header and save built payload. */ + ret = b_quic_enc_int(buf, pos - old, lensz); + BUG_ON(!ret); b_add(buf, pos - old); ret = conn->xprt->snd_buf(conn, conn->xprt_ctx, buf, b_data(buf), NULL, 0, 0); diff --git a/src/xprt_qstrm.c b/src/xprt_qstrm.c index 5d6ac9adc..38f527d48 100644 --- a/src/xprt_qstrm.c +++ b/src/xprt_qstrm.c @@ -125,7 +125,7 @@ int conn_send_qstrm(struct connection *conn, struct xprt_qstrm_ctx *ctx, int fla struct buffer *buf = &ctx->txbuf; unsigned char *pos, *old, *end; size_t sent; - int ret; + int ret, lensz; if (!conn_ctrl_ready(conn)) goto fail; @@ -136,12 +136,17 @@ int conn_send_qstrm(struct connection *conn, struct xprt_qstrm_ctx *ctx, int fla /* Small buf is sufficient for our transport parameters. */ if (!b_size(buf) && !b_alloc_small(buf)) goto fail; + /* Record size field length */ + lensz = quic_int_getsize(quic_int_cap_length(b_size(buf))); if (!b_data(buf)) { - old = pos = (unsigned char *)b_orig(buf); + old = pos = (unsigned char *)b_orig(buf) + lensz; end = (unsigned char *)b_wrap(buf); ret = qc_build_frm(&frm, &pos, end, NULL); - BUG_ON(!ret); + BUG_ON(!ret); /* should never fail */ + + ret = b_quic_enc_int(buf, pos - old, lensz); + BUG_ON(!ret); /* should never fail */ b_add(buf, pos - old); }