]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: htx: Improve htx_xfer API to not count HTX meta-data
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 20 May 2026 13:32:41 +0000 (15:32 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 20 May 2026 14:21:02 +0000 (16:21 +0200)
This patch add the ability to the htx_xfer() function to transfer data
without acounting the meta-data. By default, the <count> variable includes
the meta-data. But by setting the flag HTX_XFER_NO_METADATA, It is possible
to transfer HTX blocks without count meta-data. In that case, <count> will
not contain the blocks meta-data and the return value will not include them.

include/haproxy/htx.h
src/htx.c

index 3e61fb1fde19a0f0ae96249978a02e3fcb41d5ce..6497e8337a4150e6a92a2dc64967de4f8b7e9ec0 100644 (file)
@@ -66,6 +66,8 @@ struct buffer *htx_copy_to_large_buffer(struct buffer *dst, struct buffer *src);
 #define HTX_XFER_KEEP_SRC_BLKS     0x00000001 /* Don't remove xfer blocks from source messages during xfer */
 #define HTX_XFER_PARTIAL_HDRS_COPY 0x00000002 /* Allow partial copy of headers and trailers part */
 #define HTX_XFER_HDRS_ONLY         0x00000004 /* Only Transfer header blocks (start-line, header and EOH) */
+#define HTX_XFER_NO_METADATA       0x00000008 /* <count> don't include meta-data, only payload */
+
 size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int flags);
 
 /* Functions and macros to get parts of the start-line or length of these
index 16c09969a0f39936a4f72c164d2036c4df7546ea..f502da4f0641189cce46603f78ea1469eac277bf 100644 (file)
--- a/src/htx.c
+++ b/src/htx.c
@@ -730,17 +730,20 @@ struct htx_blk *htx_replace_blk_value(struct htx *htx, struct htx_blk *blk,
  *  - HTX_XFER_KEEP_SRC_BLKS: source blocks are not removed
  *  - HTX_XFER_PARTIAL_HDRS_COPY: partial headers and trailers part can be xferred
  *  - HTX_XFER_HDRS_ONLY: Only the headers part is xferred
+ *  - HTX_XFER_NO_METADATA: <count> don't include meta-data, only payload
  */
 size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int flags)
 {
        struct htx_blk *blk, *last_dstblk;
        size_t ret = 0;
+       size_t meta_sz = (flags & HTX_XFER_NO_METADATA) ? 0 : sizeof(*blk);
        uint32_t max, last_dstblk_sz;
        int dst_full = 0;
 
+
        last_dstblk = NULL;
        last_dstblk_sz = 0;
-       for (blk = htx_get_head_blk(src); blk && count; blk = htx_get_next_blk(src, blk)) {
+       for (blk = htx_get_head_blk(src); blk && count > meta_sz; blk = htx_get_next_blk(src, blk)) {
                struct ist v;
                enum htx_blk_type type;
                uint32_t sz;
@@ -755,7 +758,10 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                    type != HTX_BLK_HDR && type != HTX_BLK_EOH)
                        break;
 
-               max = htx_get_max_blksz(dst, count);
+               max = htx_free_data_space(dst);
+               if (max  > count - meta_sz)
+                       max = count - meta_sz;
+
                if (!max)
                        break;
 
@@ -771,8 +777,8 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                        }
                        last_dstblk = htx_get_tail_blk(dst);
                        last_dstblk_sz = v.len;
-                       count -= sizeof(*blk) + v.len;
-                       ret += sizeof(*blk) + v.len;
+                       count -= meta_sz + v.len;
+                       ret += meta_sz + v.len;
                        if (v.len != sz) {
                                dst_full = 1;
                                goto stop;
@@ -793,8 +799,8 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                        last_dstblk->info = blk->info;
                        htx_memcpy(htx_get_blk_ptr(dst, last_dstblk), htx_get_blk_ptr(src, blk), sz);
                        last_dstblk_sz = sz;
-                       count -= sizeof(*blk) + sz;
-                       ret += sizeof(*blk) + sz;
+                       count -= meta_sz + sz;
+                       ret += meta_sz + sz;
                        break;
                }
 
@@ -826,7 +832,7 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                        /* Remove partial headers/trailers from <dst> and rollback on <src> to not remove them later */
                        while (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL || type == HTX_BLK_HDR || type == HTX_BLK_TLR) {
                                BUG_ON(type != htx_get_blk_type(blk));
-                               ret -= sizeof(*blk) + htx_get_blksz(blk);
+                               ret -= meta_sz + htx_get_blksz(blk);
                                htx_remove_blk(dst, dstblk);
                                dstblk = htx_get_tail_blk(dst);
                                blk = htx_get_prev_blk(src, blk);