From 42c495f3d7e953329e768a8fc52033a3784e9229 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 15 Oct 2025 11:56:16 +0200 Subject: [PATCH] MINOR: ncbmbuf: implement ncbmb_data() Implement ncbmb_data() function for the ncbmbuf type. Its purpose is similar to its ncbuf counterpart : it returns the size in bytes of data starting at a specific offset until the next gap. As the previous patch, this commit must be backported prior to the fix to come on QUIC CRYPTO frames parsing. --- include/haproxy/ncbmbuf.h | 2 ++ src/ncbmbuf.c | 42 +++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/haproxy/ncbmbuf.h b/include/haproxy/ncbmbuf.h index f114898d0..7006f0a7e 100644 --- a/include/haproxy/ncbmbuf.h +++ b/include/haproxy/ncbmbuf.h @@ -42,6 +42,8 @@ static inline ncb_sz_t ncbmb_size(const struct ncbmbuf *buf) int ncbmb_is_empty(const struct ncbmbuf *buf); +ncb_sz_t ncbmb_data(const struct ncbmbuf *buf, ncb_sz_t offset); + enum ncb_ret ncbmb_add(struct ncbmbuf *buf, ncb_sz_t off, const char *data, ncb_sz_t len, enum ncb_add_mode mode); diff --git a/src/ncbmbuf.c b/src/ncbmbuf.c index b2f052d3e..c0073d79c 100644 --- a/src/ncbmbuf.c +++ b/src/ncbmbuf.c @@ -69,7 +69,7 @@ struct itbmap { }; /* Returns true if all bits masked in are set. */ -static __attribute__((unused)) int itbmap_is_full(const struct itbmap *it) +static int itbmap_is_full(const struct itbmap *it) { if (!it->b) return 0; @@ -77,8 +77,8 @@ static __attribute__((unused)) int itbmap_is_full(const struct itbmap *it) return (*it->b & it->mask) == it->mask; } -static __attribute__((unused)) void itbmap_load(struct itbmap *it, ncb_sz_t off, - const struct ncbmbuf *buf) +static void itbmap_load(struct itbmap *it, ncb_sz_t off, + const struct ncbmbuf *buf) { const ncb_sz_t sz = ncbmb_size(buf); ncb_sz_t off_abs; @@ -117,7 +117,7 @@ static __attribute__((unused)) void itbmap_load(struct itbmap *it, ncb_sz_t off, /* Returns an iterator on the bitmap byte corresponding to offset * relative to head. */ -static __attribute__((unused)) struct itbmap itbmap_get(const struct ncbmbuf *buf, ncb_sz_t off) +static struct itbmap itbmap_get(const struct ncbmbuf *buf, ncb_sz_t off) { struct itbmap it; @@ -128,8 +128,8 @@ static __attribute__((unused)) struct itbmap itbmap_get(const struct ncbmbuf *bu } /* Returns the next bitmap byte relative to iterator. */ -static __attribute__((unused)) struct itbmap itbmap_next(const struct ncbmbuf *buf, - const struct itbmap *prev) +static struct itbmap itbmap_next(const struct ncbmbuf *buf, + const struct itbmap *prev) { const ncb_sz_t off_next = prev->off + prev->bits; struct itbmap next; @@ -215,10 +215,36 @@ int ncbmb_is_fragmented(const struct ncbmbuf *buf) return 0; } +/* Returns the number of bytes of data available in starting at offset + * until the next gap or the buffer end. The counted data may wrapped if + * the buffer storage is not aligned. + */ ncb_sz_t ncbmb_data(const struct ncbmbuf *buf, ncb_sz_t off) { - /* TODO */ - return 0; + struct itbmap it = itbmap_get(buf, off); + unsigned char value; + ncb_sz_t count = 0; + + while (itbmap_is_full(&it)) { + count += it.bits; + it = itbmap_next(buf, &it); + } + + if (it.b) { + value = *it.b & it.mask; + while (it.mask && !(it.mask & 0x80)) { + it.mask <<= 1; + value <<= 1; + } + + while (it.mask && (it.mask & 0x80) && (value & 0x80)) { + it.mask <<= 1; + value <<= 1; + ++count; + } + } + + return count; } /* Add a new block at of size in at offset . Note that -- 2.47.3