diff --git a/include/common/htx.h b/include/common/htx.h index cb998b99e..65f0ec300 100644 --- a/include/common/htx.h +++ b/include/common/htx.h @@ -189,7 +189,7 @@ struct htx_blk *htx_add_all_trailers(struct htx *htx, const struct http_hdr *hdr struct htx_blk *htx_add_endof(struct htx *htx, enum htx_blk_type type); struct htx_blk *htx_add_data_atonce(struct htx *htx, const struct ist data); size_t htx_add_data(struct htx *htx, const struct ist data); -struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, const struct ist data); +struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data); int htx_reqline_to_h1(const struct htx_sl *sl, struct buffer *chk); int htx_stline_to_h1(const struct htx_sl *sl, struct buffer *chk); diff --git a/src/flt_http_comp.c b/src/flt_http_comp.c index 13f87bead..b04dcd145 100644 --- a/src/flt_http_comp.c +++ b/src/flt_http_comp.c @@ -256,7 +256,10 @@ comp_http_payload(struct stream *s, struct filter *filter, struct http_msg *msg, if (htx_compression_buffer_end(st, &trash, 1) < 0) goto error; if (b_data(&trash)) { - blk = htx_add_data_before(htx, blk, ist2(b_head(&trash), b_data(&trash))); + struct htx_blk *last = htx_add_last_data(htx, ist2(b_head(&trash), b_data(&trash))); + if (!last) + goto error; + blk = htx_get_next_blk(htx, last); if (!blk) goto error; to_forward += b_data(&trash); diff --git a/src/htx.c b/src/htx.c index 8be38d6f7..8dce7c892 100644 --- a/src/htx.c +++ b/src/htx.c @@ -868,22 +868,29 @@ size_t htx_add_data(struct htx *htx, const struct ist data) return len; } -struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, - const struct ist data) -{ - struct htx_blk *blk; - int32_t prev; - /* FIXME: check data.len (< 256MB) */ - blk = htx_add_blk(htx, HTX_BLK_DATA, data.len); +/* Adds an HTX block of type DATA in just after all other DATA + * blocks. Because it relies on htx_add_data_atonce(), It may be happened to a + * DATA block if possible. But, if the function succeeds, it will be the last + * DATA block in all cases. If an error occurred, NULL is returned. Otherwise, + * on success, the updated block (or the new one) is returned. + */ +struct htx_blk *htx_add_last_data(struct htx *htx, struct ist data) +{ + struct htx_blk *blk, *pblk; + + blk = htx_add_data_atonce(htx, data); if (!blk) return NULL; - blk->info += data.len; - memcpy(htx_get_blk_ptr(htx, blk), data.ptr, data.len); + for (pblk = htx_get_prev_blk(htx, blk); pblk; pblk = htx_get_prev_blk(htx, pblk)) { + int32_t cur, prev; - for (prev = htx_get_prev(htx, htx->tail); prev != -1; prev = htx_get_prev(htx, prev)) { - struct htx_blk *pblk = htx_get_blk(htx, prev); + if (htx_get_blk_type(pblk) <= HTX_BLK_DATA) + break; + + cur = htx_get_blk_pos(htx, blk); + prev = htx_get_blk_pos(htx, pblk); /* Swap .addr and .info fields */ blk->addr ^= pblk->addr; pblk->addr ^= blk->addr; blk->addr ^= pblk->addr; @@ -891,11 +898,11 @@ struct htx_blk *htx_add_data_before(struct htx *htx, const struct htx_blk *ref, if (blk->addr == pblk->addr) blk->addr += htx_get_blksz(pblk); - htx->front = prev; - - if (pblk == ref) - break; blk = pblk; + if (htx->front == cur) + htx->front = prev; + else if (htx->front == prev) + htx->front = cur; } if (htx_get_blk_pos(htx, blk) != htx->front)