static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
const struct ist value)
{
- struct htx_blk *blk;
+ struct htx_blk *blk, *tailblk;
if (name.len > 255 || value.len > 1048575)
return NULL;
+ tailblk = htx_get_tail_blk(htx);
blk = htx_add_blk(htx, HTX_BLK_HDR, name.len + value.len);
if (!blk)
return NULL;
blk->info += (value.len << 8) + name.len;
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
+ if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOH)
+ htx->flags |= HTX_FL_UNORDERED;
return blk;
}
static inline struct htx_blk *htx_add_trailer(struct htx *htx, const struct ist name,
const struct ist value)
{
- struct htx_blk *blk;
+ struct htx_blk *blk, *tailblk;
if (name.len > 255 || value.len > 1048575)
return NULL;
+ tailblk = htx_get_tail_blk(htx);
blk = htx_add_blk(htx, HTX_BLK_TLR, name.len + value.len);
if (!blk)
return NULL;
blk->info += (value.len << 8) + name.len;
ist2bin_lc(htx_get_blk_ptr(htx, blk), name);
memcpy(htx_get_blk_ptr(htx, blk) + name.len, value.ptr, value.len);
+ if (tailblk && htx_get_blk_type(tailblk) >= HTX_BLK_EOT)
+ htx->flags |= HTX_FL_UNORDERED;
return blk;
}
htx->head_addr = tmp->head_addr;
htx->end_addr = tmp->end_addr;
htx->tail_addr = tmp->tail_addr;
- htx->flags &= ~HTX_FL_FRAGMENTED;
+ htx->flags &= ~(HTX_FL_FRAGMENTED|HTX_FL_UNORDERED);
htx_memcpy((void *)htx->blocks, (void *)tmp->blocks, htx->size);
free_trash_chunk(chunk);
struct htx_ret htxret = { .blk = NULL, .ret = 0 };
if (count == htx->data) {
- uint32_t flags = (htx->flags & ~HTX_FL_FRAGMENTED); /* Preserve flags except FRAGMENTED */
+ /* Preserve flags except FRAGMENTED and UNORDERED */
+ uint32_t flags = (htx->flags & ~(HTX_FL_FRAGMENTED|HTX_FL_UNORDERED));
htx_reset(htx);
htx->flags = flags; /* restore flags */
{
struct htx_blk *blk, *tailblk;
void *ptr;
- uint32_t len, sz, tailroom, headroom;
+ uint32_t sz, tailroom, headroom;
+ uint32_t flags = 0;
if (htx->head == -1)
goto add_new_block;
/* Don't try to append data if the last inserted block is not of the
* same type */
- if (htx_get_blk_type(tailblk) != HTX_BLK_DATA)
+ 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;
+ }
/*
* Same type and enough space: append data
BUG_ON((int32_t)headroom < 0);
BUG_ON((int32_t)tailroom < 0);
- len = data.len;
if (tailblk->addr+sz == htx->tail_addr) {
if (data.len <= tailroom)
goto append_data;
else if (!htx->head_addr) {
- len = tailroom;
- goto append_data;
+ /* Not enough space in tailroom: Defrag instead of wrapping */
}
}
else if (tailblk->addr+sz == htx->head_addr && data.len <= headroom)
goto append_data;
- goto add_new_block;
+ /* Unable to append data in the DATA block, defrag the message first and append data */
+ htx_defrag(htx, NULL, 0);
+ tailblk = htx_get_tail_blk(htx);
+ if (tailblk == NULL)
+ goto add_new_block;
+ sz = htx_get_blksz(tailblk);
+ if (sz + data.len >= (256 << 20))
+ goto add_new_block;
append_data:
/* Append data and update the block itself */
ptr = htx_get_blk_ptr(htx, tailblk);
- htx_memcpy(ptr+sz, data.ptr, len);
- htx_change_blk_value_len(htx, tailblk, sz+len);
-
- if (data.len == len) {
- blk = tailblk;
- goto end;
- }
- data = istadv(data, len);
+ htx_memcpy(ptr+sz, data.ptr, data.len);
+ htx_change_blk_value_len(htx, tailblk, sz+data.len);
+ blk = tailblk;
+ goto end;
add_new_block:
blk = htx_add_blk(htx, HTX_BLK_DATA, data.len);
if (!blk)
return NULL;
-
blk->info += data.len;
htx_memcpy(htx_get_blk_ptr(htx, blk), data.ptr, data.len);
+ htx->flags |= flags;
end:
BUG_ON((int32_t)htx->tail_addr < 0);
/* set the new block size and update HTX message */
htx_set_blk_value_len(blk, v.len + delta);
htx->data += delta;
+ htx->flags |= HTX_FL_FRAGMENTED;
}
else { /* Do a degrag first (it is always an expansion) */
struct htx_blk tmpblk;
for (blk = htx_get_head_blk(src); blk && blk != srcref; blk = htx_remove_blk(src, blk));
}
- end:
+ if (htx_is_empty(src))
+ dst->flags |= (src->flags & (HTX_FL_EOM|HTX_FL_PARSING_ERROR|HTX_FL_PROCESSING_ERROR));
+
ret = htx_used_space(dst) - ret;
return (struct htx_ret){.ret = ret, .blk = dstblk};
}
if (ret == 3)
blk = htx_defrag(htx, blk, (type << 28) + (value.len << 8) + name.len);
else {
+ if (ret == 2)
+ htx->flags |= HTX_FL_FRAGMENTED;
/* Set the new block size and update HTX message */
blk->info = (type << 28) + (value.len << 8) + name.len;
htx->data += delta;
blk = htx_defrag(htx, blk, (type << 28) + sz + delta);
}
else {
+ if (ret == 2)
+ htx->flags |= HTX_FL_FRAGMENTED;
/* Set the new block size and update HTX message */
blk->info = (type << 28) + sz + delta;
htx->data += delta;
struct htx_blk *blk, *tailblk;
uint32_t sz, room;
int32_t len = htx_free_data_space(htx);
+ uint32_t flags = 0;
if (htx->head == -1)
goto rsv_new_block;
tailblk = htx_get_tail_blk(htx);
if (tailblk == NULL)
goto rsv_new_block;
- sz = htx_get_blksz(tailblk);
/* Don't try to append data if the last inserted block is not of the
* same type */
- if (htx_get_blk_type(tailblk) != HTX_BLK_DATA)
+ if (htx_get_blk_type(tailblk) != HTX_BLK_DATA) {
+ if (htx_get_blk_type(tailblk) > HTX_BLK_DATA)
+ flags |= HTX_FL_UNORDERED;
goto rsv_new_block;
+ }
+
+ if (htx->flags & HTX_FL_FRAGMENTED) {
+ htx_defrag(htx, NULL, 0);
+ tailblk = htx_get_tail_blk(htx);
+ if (tailblk == NULL)
+ goto rsv_new_block;
+ }
+ sz = htx_get_blksz(tailblk);
/*
* Same type and enough space: append data
blk = htx_add_blk(htx, HTX_BLK_DATA, len);
if (!blk)
return (struct htx_ret){.ret = 0, .blk = NULL};
+ htx->flags |= flags;
blk->info += len;
return (struct htx_ret){.ret = 0, .blk = blk};
}
void *ptr;
uint32_t sz, room;
int32_t len = data.len;
+ uint32_t flags = 0;
/* Not enough space to store data */
if (len > htx_free_data_space(htx))
tailblk = htx_get_tail_blk(htx);
if (tailblk == NULL)
goto add_new_block;
- sz = htx_get_blksz(tailblk);
/* Don't try to append data if the last inserted block is not of the
* same type */
- if (htx_get_blk_type(tailblk) != HTX_BLK_DATA)
+ 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;
+ }
+ if (htx->flags & HTX_FL_FRAGMENTED) {
+ htx_defrag(htx, NULL, 0);
+ tailblk = htx_get_tail_blk(htx);
+ if (tailblk == NULL)
+ goto add_new_block;
+ }
+ sz = htx_get_blksz(tailblk);
+ if (sz + data.len >= (256 << 20))
+ goto add_new_block;
/*
* Same type and enough space: append data
*/
if (!blk)
return 0;
+ htx->flags |= flags;
blk->info += len;
htx_memcpy(htx_get_blk_ptr(htx, blk), data.ptr, len);
return len;
cblk = *blk;
for (pblk = htx_get_prev_blk(htx, cblk); pblk; pblk = htx_get_prev_blk(htx, pblk)) {
+ htx->flags |= HTX_FL_UNORDERED;
+
/* Swap .addr and .info fields */
cblk->addr ^= pblk->addr; pblk->addr ^= cblk->addr; cblk->addr ^= pblk->addr;
cblk->info ^= pblk->info; pblk->info ^= cblk->info; cblk->info ^= pblk->info;