MINOR: h3: extend function for QUIC varint encoding

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.
This commit is contained in:
Amaury Denoyelle 2023-01-17 15:21:16 +01:00
parent 8ad2669175
commit 7d78eff889
2 changed files with 44 additions and 39 deletions

View 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;
}

View File

@ -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)) {