From: Christopher Faulet Date: Wed, 8 Jul 2026 14:46:12 +0000 (+0200) Subject: MEDIUM: htx: Add HTX_BLK_FL_EOM flag and set it on last block of the message X-Git-Url: https://git.kaiwu.me/?a=commitdiff_plain;h=77e18838f2a4370efd499d4550bb44b5dc062945;p=haproxy.git MEDIUM: htx: Add HTX_BLK_FL_EOM flag and set it on last block of the message 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. --- diff --git a/include/haproxy/htx-t.h b/include/haproxy/htx-t.h index c5a9d213e..a25efcc79 100644 --- a/include/haproxy/htx-t.h +++ b/include/haproxy/htx-t.h @@ -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 { diff --git a/include/haproxy/htx.h b/include/haproxy/htx.h index f2e6ac782..91b6c9f35 100644 --- a/include/haproxy/htx.h +++ b/include/haproxy/htx.h @@ -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; } diff --git a/src/hlua.c b/src/hlua.c index 3249e140f..30fc07b28 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -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; } diff --git a/src/htx.c b/src/htx.c index b5cee55b1..d18a16cdb 100644 --- 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 just before the block . Both blocks must be in the * HTX message and must be placed after . 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 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 to the HTX message . It returns 1 on * success and 0 on error. All the message or nothing is copied. If an error * occurred, all blocks from already appended to 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) {