]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Variable-length integer encoding/decoding into/from buffer struct.
authorFrédéric Lécaille <flecaille@haproxy.com>
Thu, 4 Mar 2021 18:12:20 +0000 (19:12 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Sep 2021 13:27:25 +0000 (15:27 +0200)
Add a function to encode a QUIC varint into a buffer struct. Samething for the
deconding part.

include/haproxy/xprt_quic.h

index c2471cc8818d6330e3e6b3c06735d2d843429b81..e3bef42b3fb986382e830a79d775ed1a806dc79c 100644 (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.
  */