]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: htx: Add HTX_BLK_FL_EOM flag and set it on last block of the message
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 8 Jul 2026 14:46:12 +0000 (16:46 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 24 Jul 2026 10:20:43 +0000 (12:20 +0200)
HTX_BLK_FL_EOM flag was introduced to be set on the last block of an HTX
message. It must be set on the tail block when the HTX_FL_HAS_EOM is set.
Now, only the HTX API must set these flags by hand. From outside of the HTX
API, htx_set_eom() function must be used.

A BUG_ON() was added to unsure the flag is added on valid blocks. It is possible
to add it on EOH, EOT and DATA blocks only.

include/haproxy/htx-t.h
include/haproxy/htx.h
src/hlua.c
src/htx.c

index c5a9d213e00d857772c6ca3b17587f96fbbd50ee..a25efcc79a98a071da636db8ec9983003e297232 100644 (file)
@@ -215,6 +215,7 @@ enum htx_blk_type {
 };
 
 #define HTX_BLK_FL_NONE 0x00 /* For init purpose */
+#define HTX_BLK_FL_EOM  0x01 /* flag marking the end of the message */
 
 /* One HTX block descriptor */
 struct htx_blk {
index f2e6ac7823cfe4d14ed6f81a82f0f5e7f025419a..91b6c9f352ee574786144db3ca350ab9201960a4 100644 (file)
@@ -847,11 +847,18 @@ static inline int htx_expect_more(const struct htx *htx)
  */
 static inline int htx_set_eom(struct htx *htx)
 {
+       struct htx_blk *blk;
+
        if (htx_is_empty(htx)) {
                if (!htx_add_endof(htx, HTX_BLK_EOT))
                        return 0;
        }
 
+       blk = ASSUME_NONNULL(htx_get_tail_blk(htx));
+       BUG_ON(htx_get_blk_type(blk) != HTX_BLK_EOH &&
+              htx_get_blk_type(blk) != HTX_BLK_EOT &&
+              htx_get_blk_type(blk) != HTX_BLK_DATA);
+       blk->flags |= HTX_BLK_FL_EOM;
        htx->flags |= HTX_FL_HAS_EOM;
        return 1;
 }
index 3249e140fcddc68c1b593ce74112bcf1936256b9..30fc07b28281a619cbb7a926804de0848421049a 100644 (file)
@@ -7901,11 +7901,19 @@ __LJMP static int hlua_http_msg_unset_eom(lua_State *L)
 {
        struct http_msg *msg;
        struct htx *htx;
+       struct htx_blk *blk;
 
        MAY_LJMP(check_args(L, 1, "set_eom"));
        msg = MAY_LJMP(hlua_checkhttpmsg(L, 1));
        htx = htxbuf(&msg->chn->buf);
        htx->flags &= ~HTX_FL_HAS_EOM;
+
+       for (blk = htx_get_tail_blk(htx); blk; blk = htx_get_prev_blk(htx, blk)) {
+               if (blk->flags & HTX_BLK_FL_EOM) {
+                       blk->flags &= ~HTX_BLK_FL_EOM;
+                       break;
+               }
+       }
        return 0;
 }
 
index b5cee55b1ea3d765537904a86069393811fd8378..d18a16cdbc4fc5ff1f814d61cde140b33ae23c0b 100644 (file)
--- a/src/htx.c
+++ b/src/htx.c
@@ -394,6 +394,10 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk)
        prevblk = htx_get_prev_blk(htx, blk);
        nextblk = htx_get_next_blk(htx, blk);
 
+       /* Move EOM flag on the previous block if any */
+       if (prevblk)
+               prevblk->flags |= (blk->flags & HTX_BLK_FL_EOM);
+
        /* There is at least 2 used blocks, so (head != tail and tail > 0) */
 
        type = htx_get_blk_type(blk);
@@ -582,7 +586,9 @@ struct htx_blk *htx_add_data_atonce(struct htx *htx, struct ist data)
        sz = htx_get_blksz(tailblk);
 
        /* Don't try to append data if the last inserted block is not of the
-        * same type */
+        * same type or if it is the end of the message */
+       if (tailblk->flags & HTX_BLK_FL_EOM)
+               goto add_new_block;
        if (htx_get_blk_type(tailblk) != HTX_BLK_DATA) {
                if (htx_get_blk_type(tailblk) > HTX_BLK_DATA)
                        flags |= HTX_FL_UNORDERED;
@@ -811,6 +817,8 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                                goto stop;
                        }
                        last_dstblk->flags = blk->flags;
+                       if (last_dstblk->flags & HTX_BLK_FL_EOM)
+                               dst->flags |= HTX_FL_HAS_EOM;
                        break;
 
                default:
@@ -827,6 +835,8 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                        last_dstblk->flags = blk->flags;
                        last_dstblk->info = blk->info;
                        htx_memcpy(htx_get_blk_ptr(dst, last_dstblk), htx_get_blk_ptr(src, blk), sz);
+                       if (last_dstblk->flags & HTX_BLK_FL_EOM)
+                               dst->flags |= HTX_FL_HAS_EOM;
                        last_dstblk_sz = sz;
                        count -= meta_sz + sz;
                        ret += meta_sz + sz;
@@ -897,9 +907,9 @@ size_t htx_xfer(struct htx *dst, struct htx *src, size_t count, unsigned int fla
                }
        }
 
-       /* Everything was copied, transfer terminal HTX flags too */
+       /* Everything was copied, transfer HTX error flags too */
        if (!blk) {
-               dst->flags |= (src->flags & (HTX_FL_HAS_EOM|HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR));
+               dst->flags |= (src->flags & (HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR));
                if (!(flags & HTX_XFER_KEEP_SRC_BLKS))
                        src->flags = 0;
        }
@@ -1043,7 +1053,9 @@ struct htx_ret htx_reserve_max_data(struct htx *htx)
                goto rsv_new_block;
 
        /* Don't try to append data if the last inserted block is not of the
-        * same type */
+        * same type or if it is the end of the message */
+       if (tailblk->flags & HTX_BLK_FL_EOM)
+               goto rsv_new_block;
        if (htx_get_blk_type(tailblk) != HTX_BLK_DATA) {
                if (htx_get_blk_type(tailblk) > HTX_BLK_DATA)
                        flags |= HTX_FL_UNORDERED;
@@ -1121,7 +1133,9 @@ size_t htx_add_data(struct htx *htx, const struct ist data)
                goto add_new_block;
 
        /* Don't try to append data if the last inserted block is not of the
-        * same type */
+        * same type or if it is the end of the message */
+       if (tailblk->flags & HTX_BLK_FL_EOM)
+               goto add_new_block;
        if (htx_get_blk_type(tailblk) != HTX_BLK_DATA) {
                if (htx_get_blk_type(tailblk) > HTX_BLK_DATA)
                        flags |= HTX_FL_UNORDERED;
@@ -1193,8 +1207,11 @@ struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data)
                return NULL;
 
        for (pblk = htx_get_prev_blk(htx, blk); pblk; pblk = htx_get_prev_blk(htx, pblk)) {
-               if (htx_get_blk_type(pblk) <= HTX_BLK_DATA)
+               if (htx_get_blk_type(pblk) <= HTX_BLK_DATA) {
+                       blk->flags |= (pblk->flags & HTX_BLK_FL_EOM);
+                       pblk->flags &= ~HTX_BLK_FL_EOM;
                        break;
+               }
 
                /* Swap .addr and .info fields */
                blk->flags ^= pblk->flags; pblk->flags ^= blk->flags; blk->flags ^= pblk->flags;
@@ -1211,7 +1228,10 @@ struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data)
 
 /* Moves the block <blk> just before the block <ref>. Both blocks must be in the
  * HTX message <htx> and <blk> must be placed after <ref>. pointer to these
- * blocks are updated to remain valid after the move. */
+ * blocks are updated to remain valid after the move.
+ *
+ * It is the caller responsibility to take care the result remains valid.
+ */
 void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk **ref)
 {
        struct htx_blk *cblk, *pblk;
@@ -1220,6 +1240,12 @@ void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk *
        for (pblk = htx_get_prev_blk(htx, cblk); pblk; pblk = htx_get_prev_blk(htx, pblk)) {
                htx->flags |= HTX_FL_UNORDERED;
 
+               /* transfer EOM to <pblk> before swapping blocs */
+               if (cblk->flags & HTX_BLK_FL_EOM) {
+                       pblk->flags |= HTX_BLK_FL_EOM;
+                       cblk->flags &= ~HTX_BLK_FL_EOM;
+               }
+
                /* Swap .flags, .addr and .info fields */
                cblk->flags ^= pblk->flags; pblk->flags ^= cblk->flags; cblk->flags ^= pblk->flags;
                cblk->addr ^= pblk->addr; pblk->addr ^= cblk->addr; cblk->addr ^= pblk->addr;
@@ -1238,6 +1264,8 @@ void htx_move_blk_before(struct htx *htx, struct htx_blk **blk, struct htx_blk *
 /* Append the HTX message <src> to the HTX message <dst>. It returns 1 on
  * success and 0 on error.  All the message or nothing is copied. If an error
  * occurred, all blocks from <src> already appended to <dst> are truncated.
+ *
+ * It is the caller responsibility to take care the result remains valid.
  */
 int htx_append_msg(struct htx *dst, const struct htx *src)
 {