diff --git a/include/haproxy/quic_enc.h b/include/haproxy/quic_enc.h index 45c2b4b4b..4b8560524 100644 --- a/include/haproxy/quic_enc.h +++ b/include/haproxy/quic_enc.h @@ -198,39 +198,44 @@ static inline int quic_enc_int(unsigned char **buf, const unsigned char *end, ui return 1; } -/* Encode a QUIC variable-length integer into buffer. - * Returns 1 if succeeded (there was enough room in buf), 0 if not. +/* Encode a QUIC variable-length integer into buffer. can be + * set to specify the desired output width. By default use 0 for the minimal + * integer size. Other valid values are 1, 2, 4 or 8. + * + * Returns 1 on success else 0. */ -static inline int b_quic_enc_int(struct buffer *b, uint64_t val) +static inline int b_quic_enc_int(struct buffer *b, uint64_t val, int width) { - unsigned int shift; - unsigned char size_bits, *tail, *pos, *wrap; - size_t save_len, len; - size_t data = b_data(b); - size_t size = b_size(b); + char *pos; + int save_width, len; - if (data == size) - return 0; + /* width can only by 0, 1, 2, 4 or 8 */ + BUG_ON(width && (width > 8 || atleast2(width))); - save_len = len = quic_int_getsize(val); + len = quic_int_getsize(val); if (!len) return 0; - shift = (len - 1) * 8; - /* set the bits of byte#0 which gives the length of the encoded integer */ - size_bits = quic_log2(len) << QUIC_VARINT_BYTE_0_SHIFT; - pos = tail = (unsigned char *)b_tail(b); - wrap = (unsigned char *)b_wrap(b); - while (len--) { - *pos++ = val >> shift; - shift -= 8; - if (pos == wrap) - pos -= size; - if (++data == size && len) - return 0; + /* Check that buffer room is sufficient and width big enough if set. */ + if (b_room(b) < len || (width && width < len)) + return 0; + + if (!width) + width = len; + save_width = width; + + pos = b_tail(b); + while (width--) { + /* Encode the shifted integer or 0 if width bigger than integer length. */ + *pos++ = width >= len ? 0 : val >> (width * 8); + + if (pos == b_wrap(b)) + pos = b_orig(b); } - *tail |= size_bits; - b_add(b, save_len); + + /* set the bits of byte#0 which gives the length of the encoded integer */ + *b_tail(b) |= quic_log2(save_width) << QUIC_VARINT_BYTE_0_SHIFT; + b_add(b, save_width); return 1; } diff --git a/src/h3.c b/src/h3.c index e38464081..f30b3d9c7 100644 --- a/src/h3.c +++ b/src/h3.c @@ -1042,17 +1042,17 @@ static int h3_control_send(struct qcs *qcs, void *ctx) quic_int_getsize(h3_settings_max_field_section_size); } - b_quic_enc_int(&pos, H3_UNI_S_T_CTRL); + b_quic_enc_int(&pos, H3_UNI_S_T_CTRL, 0); /* Build a SETTINGS frame */ - b_quic_enc_int(&pos, H3_FT_SETTINGS); - b_quic_enc_int(&pos, frm_len); - b_quic_enc_int(&pos, H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY); - b_quic_enc_int(&pos, h3_settings_qpack_max_table_capacity); - b_quic_enc_int(&pos, H3_SETTINGS_QPACK_BLOCKED_STREAMS); - b_quic_enc_int(&pos, h3_settings_qpack_blocked_streams); + b_quic_enc_int(&pos, H3_FT_SETTINGS, 0); + b_quic_enc_int(&pos, frm_len, 0); + b_quic_enc_int(&pos, H3_SETTINGS_QPACK_MAX_TABLE_CAPACITY, 0); + b_quic_enc_int(&pos, h3_settings_qpack_max_table_capacity, 0); + b_quic_enc_int(&pos, H3_SETTINGS_QPACK_BLOCKED_STREAMS, 0); + b_quic_enc_int(&pos, h3_settings_qpack_blocked_streams, 0); if (h3_settings_max_field_section_size) { - b_quic_enc_int(&pos, H3_SETTINGS_MAX_FIELD_SECTION_SIZE); - b_quic_enc_int(&pos, h3_settings_max_field_section_size); + b_quic_enc_int(&pos, H3_SETTINGS_MAX_FIELD_SECTION_SIZE, 0); + b_quic_enc_int(&pos, h3_settings_max_field_section_size, 0); } res = mux_get_buf(qcs); @@ -1177,7 +1177,7 @@ static int h3_resp_headers_send(struct qcs *qcs, struct htx *htx) frame_length_size = quic_int_getsize(b_data(&headers_buf)); res->head += 4 - frame_length_size; b_putchr(res, 0x01); /* h3 HEADERS frame type */ - if (!b_quic_enc_int(res, b_data(&headers_buf))) + if (!b_quic_enc_int(res, b_data(&headers_buf), 0)) ABORT_NOW(); b_add(res, b_data(&headers_buf)); @@ -1252,7 +1252,7 @@ static int h3_resp_data_send(struct qcs *qcs, struct htx *htx, size_t count) BUG_ON(fsize <= 0); b_putchr(&outbuf, 0x00); /* h3 frame type = DATA */ - b_quic_enc_int(&outbuf, fsize); /* h3 frame length */ + b_quic_enc_int(&outbuf, fsize, 0); /* h3 frame length */ b_putblk(&outbuf, htx_get_blk_ptr(htx, blk), fsize); total += fsize; @@ -1407,9 +1407,9 @@ static int h3_send_goaway(struct h3c *h3c) pos = b_make((char *)data, sizeof(data), 0, 0); - b_quic_enc_int(&pos, H3_FT_GOAWAY); - b_quic_enc_int(&pos, frm_len); - b_quic_enc_int(&pos, h3c->id_goaway); + b_quic_enc_int(&pos, H3_FT_GOAWAY, 0); + b_quic_enc_int(&pos, frm_len, 0); + b_quic_enc_int(&pos, h3c->id_goaway, 0); res = mux_get_buf(qcs); if (!res || b_room(res) < b_data(&pos)) {