]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: implement QMux transport params frame parser/builder
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 30 Mar 2026 14:39:57 +0000 (16:39 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 2 Apr 2026 12:02:04 +0000 (14:02 +0200)
Implement parse/build methods for QX_TRANSPORT_PARAMETER frame. Both
functions may fail due to buffer space too small (encoding) or truncated
frame (parsing).

include/haproxy/quic_tp.h
src/quic_frame.c
src/quic_tp.c

index ce7ec59ef776a568d625c9eaf6757382785b1846..18d6cf5733f42754612502f3d00390719b195269 100644 (file)
@@ -129,6 +129,12 @@ static inline void quic_transport_params_dump(struct buffer *b,
        quic_tp_version_info_dump(b, &p->version_information, local);
 }
 
+int quic_transport_param_enc_int(unsigned char **buf,
+                                 const unsigned char *end,
+                                 uint64_t type, uint64_t val);
+int quic_transport_params_decode(struct quic_transport_params *p, int server,
+                                 const unsigned char *buf, const unsigned char *end);
+
 static inline void quic_early_transport_params_dump(struct buffer *b,
                                                     const struct quic_conn *qc,
                                                     const struct quic_early_transport_params *p)
index 09bb0ac29a08f713011620f5e5368380298e5be7..edf81f14ab2fccb19f0b75f69abeed3a09a265aa 100644 (file)
@@ -17,7 +17,7 @@
 #include <haproxy/quic_enc.h>
 #include <haproxy/quic_frame.h>
 #include <haproxy/quic_rx-t.h>
-#include <haproxy/quic_tp-t.h>
+#include <haproxy/quic_tp.h>
 #include <haproxy/quic_trace.h>
 #include <haproxy/quic_tx.h>
 #include <haproxy/trace.h>
@@ -1011,10 +1011,44 @@ static int quic_build_handshake_done_frame(unsigned char **pos, const unsigned c
        return 1;
 }
 
+/* Encodes a QX_TRANSPORT_PARAMETER <frm> frame at <pos> buffer position.
+ * Returns 1 on success else 0.
+ */
 static int quic_build_qmux_transport_parameters(unsigned char **pos, const unsigned char *end,
                                                 struct quic_frame *frm, struct quic_conn *conn)
 {
-       /* TODO */
+       unsigned char *old = *pos;
+       struct buffer buf;
+
+       /* Reserve space for Length field encoded as a max varint size. */
+       if (end - *pos < 8)
+               return 0;
+
+       /* Encode a 0 length field for now. */
+       buf = b_make((char *)*pos, end - *pos, 0, 0);
+       if (!b_quic_enc_int(&buf, 0, 8))
+               return 0;
+       *pos += 8;
+
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_MAX_IDLE_TIMEOUT, 30000))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_DATA, 16384))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_LOCAL, 16384))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_BIDI_REMOTE, 16384))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAM_DATA_UNI, 16384))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAMS_BIDI, 100))
+               return 0;
+       if (!quic_transport_param_enc_int(pos, end, QUIC_TP_INITIAL_MAX_STREAMS_UNI, 100))
+               return 0;
+
+       /* Re-encode the real length field now. */
+       buf = b_make((char *)old, 8, 0, 0);
+       b_quic_enc_int(&buf, *pos - old - 8, 8);
+
        return 1;
 }
 
@@ -1028,10 +1062,25 @@ static int quic_parse_handshake_done_frame(struct quic_frame *frm, struct quic_c
        return 1;
 }
 
+/* Parse a QX_TRANSPORT_PARAMETER frame at <pos> buffer position.
+ * Returns 1 on success else 0.
+ */
 static int quic_parse_qmux_transport_parameters(struct quic_frame *frm, struct quic_conn *qc,
                                                 const unsigned char **pos, const unsigned char *end)
 {
-       /* TODO */
+       struct qf_qx_transport_parameters *params_frm = &frm->qmux_transport_params;
+       uint64_t len;
+
+       if (!quic_dec_int(&len, pos, end))
+               return 0;
+
+       if (len > end - *pos)
+               return 0;
+       end = *pos + len;
+
+       if (!quic_transport_params_decode(&params_frm->params, 1, *pos, end))
+               return 0;
+
        return 1;
 }
 
index 64f990e764c2f06e4fbf9c8b78502fff7271d7a4..a56d6cb755ed7bdcc4ea0a88815fec134eb16277 100644 (file)
@@ -416,9 +416,9 @@ static int quic_transport_param_enc_mem(unsigned char **buf, const unsigned char
 /* Encode <val> 64-bits value as variable length integer into <buf>.
  * Returns 1 if succeeded, 0 if not.
  */
-static int quic_transport_param_enc_int(unsigned char **buf,
-                                        const unsigned char *end,
-                                        uint64_t type, uint64_t val)
+int quic_transport_param_enc_int(unsigned char **buf,
+                                 const unsigned char *end,
+                                 uint64_t type, uint64_t val)
 {
        size_t len;
 
@@ -633,8 +633,8 @@ int quic_transport_params_encode(unsigned char *buf,
  *
  * Returns 1 on success else 0 if decoding is truncated.
  */
-static int quic_transport_params_decode(struct quic_transport_params *p, int server,
-                                        const unsigned char *buf, const unsigned char *end)
+int quic_transport_params_decode(struct quic_transport_params *p, int server,
+                                 const unsigned char *buf, const unsigned char *end)
 {
        const unsigned char *pos;
        uint64_t type, len = 0;