static inline struct htx_blk *htx_add_header(struct htx *htx, const struct ist name,
const struct ist value)
{
- struct htx_blk *blk, *tailblk;
+ struct htx_blk *blk, *tailblk, *prevblk;
if (name.len > 255 || value.len > 1048575)
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;
+ if (!tailblk)
+ goto end;
+
+ for (prevblk = htx_get_prev_blk(htx, blk);
+ prevblk && htx_get_blk_type(prevblk) > HTX_BLK_HDR;
+ prevblk = htx_get_prev_blk(htx, blk)) {
+
+ /* Swap .addr and .info fields */
+ blk->addr ^= prevblk->addr; prevblk->addr ^= blk->addr; blk->addr ^= prevblk->addr;
+ blk->info ^= prevblk->info; prevblk->info ^= blk->info; blk->info ^= prevblk->info;
+ blk = prevblk;
+ }
+
+ end:
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, *tailblk;
+ struct htx_blk *blk, *tailblk, *prevblk;
if (name.len > 255 || value.len > 1048575)
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;
+ if (!tailblk)
+ goto end;
+
+ for (prevblk = htx_get_prev_blk(htx, blk);
+ prevblk && htx_get_blk_type(prevblk) > HTX_BLK_TLR;
+ prevblk = htx_get_prev_blk(htx, blk)) {
+
+ /* Swap .addr and .info fields */
+ blk->addr ^= prevblk->addr; prevblk->addr ^= blk->addr; blk->addr ^= prevblk->addr;
+ blk->info ^= prevblk->info; prevblk->info ^= blk->info; blk->info ^= prevblk->info;
+ blk = prevblk;
+ }
+
+ end:
return blk;
}
*/
int http_add_header(struct htx *htx, const struct ist n, const struct ist v, int update_authority)
{
- struct htx_blk *blk;
- struct htx_sl *sl;
- enum htx_blk_type type = htx_get_tail_type(htx);
- int32_t prev;
-
- blk = htx_add_header(htx, n, v);
- if (!blk)
+ if (!htx_add_header(htx, n, v))
goto fail;
- if (unlikely(type < HTX_BLK_EOH))
- goto end;
-
- /* <blk> is the head, swap it iteratively with its predecessor to place
- * it just before the end-of-header block. So blocks remains ordered. */
- for (prev = htx_get_prev(htx, htx->tail); prev != htx->first; prev = htx_get_prev(htx, prev)) {
- struct htx_blk *pblk = htx_get_blk(htx, prev);
- enum htx_blk_type ptype = htx_get_blk_type(pblk);
-
- /* Swap .addr and .info fields */
- blk->addr ^= pblk->addr; pblk->addr ^= blk->addr; blk->addr ^= pblk->addr;
- blk->info ^= pblk->info; pblk->info ^= blk->info; blk->info ^= pblk->info;
-
- if (blk->addr == pblk->addr)
- blk->addr += htx_get_blksz(pblk);
-
- /* Stop when end-of-header is reached */
- if (ptype == HTX_BLK_EOH)
- break;
-
- blk = pblk;
- }
-
- end:
if (update_authority) {
- sl = http_get_stline(htx);
+ struct htx_sl *sl = http_get_stline(htx);
+
if (sl && (sl->flags & HTX_SL_F_HAS_AUTHORITY) && isteqi(n, ist("host"))) {
if (!http_update_authority(htx, sl, v))
goto fail;