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;
}
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);
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));
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;
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)) {