MINOR: quic: Variable-length integer encoding/decoding into/from buffer struct.

Add a function to encode a QUIC varint into a buffer struct. Samething for the
deconding part.
This commit is contained in:
Frédéric Lécaille 2021-03-04 19:12:20 +01:00 committed by Amaury Denoyelle
parent 422a39cf2c
commit 7a668f5acb

View File

@ -412,6 +412,46 @@ static inline int quic_dec_int(uint64_t *val,
return 1;
}
/* Decode a QUIC variable-length integer from <b> buffer into <val> supporting wrapping.
* Note that the result is a 64-bits integer but with the less significant
* 62 bits as relevant information. The most significant 2 bits encode
* the length of the integer.
* Note that this function update <b> buffer when a variable-length integer
* has successfully been parsed.
* Returns 1 and if succeeded (there was enough data in <buf>), 0 if not.
* If <retlen> is not null, increment <*retlen> by the number of bytes consumed to decode
* the varint.
*/
static inline size_t b_quic_dec_int(uint64_t *val, struct buffer *b, size_t *retlen)
{
const unsigned char *pos = (const unsigned char *)b_head(b);
const unsigned char *end = (const unsigned char *)b_wrap(b);
size_t size = b_size(b);
size_t data = b_data(b);
size_t save_len, len;
if (!data)
return 0;
save_len = len = 1 << (*pos >> QUIC_VARINT_BYTE_0_SHIFT);
if (data < len)
return 0;
*val = *pos & QUIC_VARINT_BYTE_0_BITMASK;
if (++pos == end)
pos -= size;
while (--len) {
*val = (*val << 8) | *pos;
if (++pos == end)
pos -= size;
}
if (retlen)
*retlen += save_len;
b_del(b, save_len);
return 1;
}
/* Encode a QUIC variable-length integer from <val> into <buf> buffer with <end> as first
* byte address after the end of this buffer.
* Returns 1 if succeeded (there was enough room in buf), 0 if not.
@ -439,6 +479,43 @@ 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.
*/
static inline int b_quic_enc_int(struct buffer *b, uint64_t val)
{
unsigned int shift;
unsigned char size_bits, *head, *pos, *wrap;
size_t save_len, len;
size_t data = b_data(b);
size_t size = b_size(b);
if (data == size)
return 0;
save_len = 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 = head = (unsigned char *)b_head(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;
}
*head |= size_bits;
b_add(b, save_len);
return 1;
}
/* Return the length in bytes of <pn> packet number depending on
* <largest_acked_pn> the largest ackownledged packet number.
*/