From: Frédéric Lécaille Date: Thu, 4 Mar 2021 18:12:20 +0000 (+0100) Subject: MINOR: quic: Variable-length integer encoding/decoding into/from buffer struct. X-Git-Tag: v2.5-dev8~145 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7a668f5acb1bbb6c07c1130efc943b98fd7ff5fc;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/xprt_quic.h b/include/haproxy/xprt_quic.h index c2471cc881..e3bef42b3f 100644 --- a/include/haproxy/xprt_quic.h +++ b/include/haproxy/xprt_quic.h @@ -412,6 +412,46 @@ static inline int quic_dec_int(uint64_t *val, return 1; } +/* Decode a QUIC variable-length integer from buffer into 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 buffer when a variable-length integer + * has successfully been parsed. + * Returns 1 and if succeeded (there was enough data in ), 0 if not. + * If 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 into buffer with 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 into 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 packet number depending on * the largest ackownledged packet number. */