]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: mux-quic/xprt_qstrm: implement QMux record emission
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 8 Apr 2026 08:33:10 +0000 (10:33 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 10 Apr 2026 08:20:52 +0000 (10:20 +0200)
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.

src/mux_quic_qstrm.c
src/xprt_qstrm.c

index 3b4b44f46897f72a2f7e61e1f8564431174ba67c..1b9dc762970f19e64568d944ba6d0b340d197506 100644 (file)
@@ -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);
index 5d6ac9adcdbd2cb032f7c0f4b2f7e906903d525e..38f527d4874c7af40f0503ff3c84cea695adac04 100644 (file)
@@ -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);
        }