]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: extend function for QUIC varint encoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 17 Jan 2023 14:21:16 +0000 (15:21 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 19 Jan 2023 14:09:01 +0000 (15:09 +0100)
Slighty adjust b_quic_enc_int(). This function is used to encode an
integer as a QUIC varint in a struct buffer.

A new parameter is added to the function API to specify the width of the
encoded integer. By default, 0 should be use to ensure that the minimum
space is used. Other valid values are 1, 2, 4 or 8. An error is reported
if the width is not large enough.

This new parameter will be useful when buffer space is reserved prior to
encode an unknown integer value. The maximum size of 8 bytes will be
reserved and some data can be put after. When finally encoding the
integer, the width can be requested to be 8 bytes.

With this new parameter, a small refactoring of the function has been
conducted to remove some useless internal variables.

This should be backported up to 2.7. It will be mostly useful to
implement H3 trailers encoding.

include/haproxy/quic_enc.h
src/h3.c

index 45c2b4b4b86250f5773bad615c6b50b5d744f89b..4b856052472a72058bec92075b04c50fd5ac0660 100644 (file)
@@ -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 <val> into <b> buffer.
- * Returns 1 if succeeded (there was enough room in buf), 0 if not.
+/* Encode a QUIC variable-length integer <val> into <b> buffer. <width> 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;
 }
index e38464081a2490c52be5092ffc5f5c3fb495fc07..f30b3d9c7d4d1afddb95b171c794e59c4e85bb95 100644 (file)
--- 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)) {