}
/* Transfer HTX blocks from <src> to <dst>, stopping on the first block of the
- * type <mark> (typically EOH, EOD or EOM) or when <count> bytes of data were
- * moved. It returns the number of bytes of data moved and the last HTX block
- * inserted in <dst>.
+ * type <mark> (typically EOH, EOD or EOM) or when <count> bytes were moved
+ * (including payload and meta-data). It returns the number of bytes moved and
+ * the last HTX block inserted in <dst>.
*/
struct htx_ret htx_xfer_blks(struct htx *dst, struct htx *src, uint32_t count,
enum htx_blk_type mark)
enum htx_blk_type type;
uint32_t info, max, sz, ret;
- ret = 0;
+ ret = htx_used_space(dst);
blk = htx_get_blk(src, htx_get_head(src));
dstblk = NULL;
- while (blk && ret <= count) {
+
+ while (blk && count) {
type = htx_get_blk_type(blk);
/* Ingore unused block */
if (type == HTX_BLK_UNUSED)
goto next;
- sz = htx_get_blksz(blk);
- if (!sz) {
- dstblk = htx_reserve_nxblk(dst, 0);
- if (!dstblk)
- break;
- dstblk->info = blk->info;
- goto next;
- }
+ sz = htx_get_blksz(blk);
info = blk->info;
- max = htx_free_data_space(dst);
- if (max > count - ret)
- max = count - ret;
+ max = htx_get_max_blksz(dst, count);
+ if (!max)
+ break;
if (sz > max) {
- sz = max;
- info = (type << 28) + sz;
/* Headers and pseudo headers must be fully copied */
- if (type != HTX_BLK_DATA || !sz)
+ if (type != HTX_BLK_DATA)
break;
+ sz = max;
+ info = (type << 28) + sz;
}
dstblk = htx_reserve_nxblk(dst, sz);
dstblk->info = info;
memcpy(htx_get_blk_ptr(dst, dstblk), htx_get_blk_ptr(src, blk), sz);
- ret += sz;
+ count -= sizeof(dstblk) + sz;
if (blk->info != info) {
/* Partial move: don't remove <blk> from <src> but
* resize its content */
- blk->addr += sz;
- htx_set_blk_value_len(blk, htx_get_blksz(blk) - sz);
- src->data -= sz;
+ htx_cut_data_blk(src, blk, sz);
break;
}
}
+ end:
+ ret = htx_used_space(dst) - ret;
return (struct htx_ret){.ret = ret, .blk = dstblk};
}
struct h2c *h2c = h2s->h2c;
struct htx *h2s_htx = NULL;
struct htx *buf_htx = NULL;
- struct htx_ret htx_ret;
size_t ret = 0;
/* transfer possibly pending data to the upper layer */
goto end;
}
+ ret = h2s_htx->data;
buf_htx = htx_from_buf(buf);
count = htx_free_data_space(buf_htx);
if (flags & CO_RFL_KEEP_RSV) {
count -= global.tune.maxrewrite;
}
- htx_ret = htx_xfer_blks(buf_htx, h2s_htx, count, HTX_BLK_EOM);
+ htx_xfer_blks(buf_htx, h2s_htx, count, HTX_BLK_EOM);
if (h2s_htx->flags & HTX_FL_PARSING_ERROR)
buf_htx->flags |= HTX_FL_PARSING_ERROR;
buf_htx->extra = (h2s_htx->extra ? (h2s_htx->data + h2s_htx->extra) : 0);
htx_to_buf(buf_htx, buf);
htx_to_buf(h2s_htx, &h2s->rxbuf);
- ret = htx_ret.ret;
+ ret -= h2s_htx->data;
}
else {
ret = b_xfer(buf, &h2s->rxbuf, count);