From 8b8ab2824e7cc74fa2d93b5d71ca1aaec7925e15 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 16 Oct 2025 15:05:50 +0200 Subject: [PATCH] MINOR: ncbmbuf: implement advance operation Implement ncbmb_advance() function for the ncbmbuf type. This allows to remove bytes in front of the buffer, regardless of the existing gaps. This is implemented by resetting the corresponding bits of the bitmap. As the previous patch, this commit must be backported prior to the fix to come on QUIC CRYPTO frames parsing. --- include/haproxy/ncbmbuf.h | 1 + src/ncbmbuf.c | 52 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/include/haproxy/ncbmbuf.h b/include/haproxy/ncbmbuf.h index 7006f0a7e..4974f53cf 100644 --- a/include/haproxy/ncbmbuf.h +++ b/include/haproxy/ncbmbuf.h @@ -46,5 +46,6 @@ 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); +enum ncb_ret ncbmb_advance(struct ncbmbuf *buf, ncb_sz_t adv); #endif /* _HAPROXY_NCBMBUF_H */ diff --git a/src/ncbmbuf.c b/src/ncbmbuf.c index c0073d79c..252219b1b 100644 --- a/src/ncbmbuf.c +++ b/src/ncbmbuf.c @@ -147,6 +147,13 @@ static struct itbmap itbmap_next(const struct ncbmbuf *buf, return next; } +/* ******** bit set/unset utilities ******** */ + +static void bit_unset(unsigned char *value, char i) +{ + *value &= ~(1 << (8 - i)); +} + /* ******** public API ******** */ /* Initialize or reset by clearing all data. Its size is untouched. @@ -278,8 +285,51 @@ enum ncb_ret ncbmb_add(struct ncbmbuf *buf, ncb_sz_t off, return NCB_RET_OK; } +/* Advance the head of to the offset . Data at the start of buffer + * will be lost while some space will be formed at the end to be able to insert + * new data. + * + * Always returns NCB_RET_OK as this operation cannot fail. + */ enum ncb_ret ncbmb_advance(struct ncbmbuf *buf, ncb_sz_t adv) { - /* TODO */ + struct itbmap it; + + BUG_ON_HOT(adv > ncbmb_size(buf)); + + while (adv) { + it = itbmap_get(buf, 0); + if (it.bits <= adv) { + adv -= it.bits; + /* Reset all bits in current bitmap byte. */ + *it.b &= ~it.mask; + buf->head += it.bits; + } + else { + int i = 1; + + while (!(it.mask & 0x80)) { + it.mask <<= 1; + ++i; + } + + /* Last bitmap byte to adjust, unset each bit + * individually until new offset is reached. + */ + while (adv) { + bit_unset(it.b, i); + --adv; + ++i; + ++buf->head; + } + } + + /* Adjust head if pointer has wrapped. */ + if (buf->head >= ncbmb_size(buf)) { + BUG_ON_HOT(buf->head >= ncbmb_size(buf) * 2); + buf->head -= ncbmb_size(buf); + } + } + return NCB_RET_OK; } -- 2.47.3