From 62fcc48bcf3c467d0db5440abd34509a97fa5acc Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Mon, 30 Mar 2026 16:39:57 +0200 Subject: [PATCH] MINOR: quic: implement QMux transport params frame parser/builder 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 | 6 +++++ src/quic_frame.c | 55 ++++++++++++++++++++++++++++++++++++--- src/quic_tp.c | 10 +++---- 3 files changed, 63 insertions(+), 8 deletions(-) diff --git a/include/haproxy/quic_tp.h b/include/haproxy/quic_tp.h index ce7ec59ef..18d6cf573 100644 --- a/include/haproxy/quic_tp.h +++ b/include/haproxy/quic_tp.h @@ -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) diff --git a/src/quic_frame.c b/src/quic_frame.c index 09bb0ac29..edf81f14a 100644 --- a/src/quic_frame.c +++ b/src/quic_frame.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -1011,10 +1011,44 @@ static int quic_build_handshake_done_frame(unsigned char **pos, const unsigned c return 1; } +/* Encodes a QX_TRANSPORT_PARAMETER frame at 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 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(¶ms_frm->params, 1, *pos, end)) + return 0; + return 1; } diff --git a/src/quic_tp.c b/src/quic_tp.c index 64f990e76..a56d6cb75 100644 --- a/src/quic_tp.c +++ b/src/quic_tp.c @@ -416,9 +416,9 @@ static int quic_transport_param_enc_mem(unsigned char **buf, const unsigned char /* Encode 64-bits value as variable length integer into . * 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;