*/
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;
}
return htx_append_msg(htx, htx_msg);
}
-/* Remove all blocks except headers. Trailers will also be removed too. */
+/* Remove all blocks except headers. Trailers will also be removed too. The EOM
+ * flag, if set on the payload part, it is then reinserted. It means a EOT black
+ * could be added if the message only contains payload.
+ */
static inline void htx_skip_msg_payload(struct htx *htx)
{
struct htx_blk *blk = htx_get_first_blk(htx);
+ int eom = 0;
while (blk) {
enum htx_blk_type type = htx_get_blk_type(blk);
- blk = ((type > HTX_BLK_EOH)
- ? htx_remove_blk(htx, blk)
- : htx_get_next_blk(htx, blk));
+ if (type > HTX_BLK_EOH) {
+ eom |= !!(blk->flags & HTX_BLK_FL_EOM);
+ blk = htx_remove_blk(htx, blk);
+ }
+ else
+ blk = htx_get_next_blk(htx, blk);
}
+ if (eom)
+ htx_set_eom(htx);
}
/* Returns the number of used blocks in the HTX message <htx>. Note that it is
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;
goto stop;
}
last_dstblk->flags = blk->flags;
+ if (last_dstblk->flags & HTX_BLK_FL_EOM)
+ dst->flags |= HTX_FL_HAS_EOM;
break;
default:
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;
}
}
- /* 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;
}
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;
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;
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;
/* 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;
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;
* 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. On
* success, the EOM flag is set on <dst> if also set on <src>.
+ *
+ * It is the caller responsibility to take care the result remains valid.
*/
int htx_append_msg(struct htx *dst, const struct htx *src)
{