diff --git a/include/common/htx.h b/include/common/htx.h index 78e62a500..003680a2b 100644 --- a/include/common/htx.h +++ b/include/common/htx.h @@ -152,8 +152,8 @@ struct htx { uint32_t used; /* number of blocks in use */ uint32_t tail; /* last inserted block */ + uint32_t head; /* older inserted block */ uint32_t front; /* block's position of the first content before the blocks table */ - uint32_t wrap; /* the position were the blocks table wraps, if any */ uint64_t extra; /* known bytes amount remaining to receive */ uint32_t flags; /* HTX_FL_* */ @@ -345,6 +345,21 @@ static inline uint32_t htx_get_blksz(const struct htx_blk *blk) } } +/* Returns the wrap position, ie the position where the blocks table wraps. + * + * An signed 32-bits integer is returned to handle -1 case. Blocks position are + * store on unsigned 32-bits integer, but it is impossible to have so much + * blocks to overflow a 32-bits signed integer ! + */ +static inline int32_t htx_get_wrap(const struct htx *htx) +{ + if (!htx->used) + return -1; + return ((htx->tail >= htx->head) + ? (htx->used + htx->head) + : (htx->used - 1) + (htx->head - htx->tail)); +} + /* Returns the position of the oldest entry (head). * * An signed 32-bits integer is returned to handle -1 case. Blocks position are @@ -353,10 +368,7 @@ static inline uint32_t htx_get_blksz(const struct htx_blk *blk) */ static inline int32_t htx_get_head(const struct htx *htx) { - if (!htx->used) - return -1; - - return (((htx->tail + 1U < htx->used) ? htx->wrap : 0) + htx->tail + 1U - htx->used); + return (htx->used ? htx->head : -1); } /* Returns the oldest HTX block (head) if the HTX message is not @@ -424,8 +436,10 @@ static inline int32_t htx_get_prev(const struct htx *htx, uint32_t pos) head = htx_get_head(htx); if (head == -1 || pos == head) return -1; - if (!pos) - return (htx->wrap - 1); + if (!pos) { + /* htx_get_wrap() is always greater than 1 here */ + return (htx_get_wrap(htx) - 1); + } return (pos - 1); } @@ -450,14 +464,11 @@ static inline struct htx_blk *htx_get_prev_blk(const struct htx *htx, */ static inline int32_t htx_get_next(const struct htx *htx, uint32_t pos) { - if (!htx->used) - return -1; - - if (pos == htx->tail) + if (!htx->used || pos == htx->tail) return -1; pos++; - if (pos >= htx->wrap) - pos = 0; + if (pos == htx_get_wrap(htx)) + return 0; return pos; } @@ -663,7 +674,7 @@ static inline int htx_almost_full(const struct htx *htx) static inline void htx_reset(struct htx *htx) { - htx->data = htx->used = htx->tail = htx->wrap = htx->front = 0; + htx->data = htx->used = htx->tail = htx->head = htx->front = 0; htx->extra = 0; htx->flags = HTX_FL_NONE; htx->sl_off = -1; @@ -779,11 +790,10 @@ static inline void htx_dump(struct htx *htx) int32_t pos; fprintf(stderr, "htx:%p [ size=%u - data=%u - used=%u - wrap=%s - extra=%llu]\n", - htx, htx->size, htx->data, htx->used, - (!htx->used || htx->tail+1 == htx->wrap) ? "NO" : "YES", + htx, htx->size, htx->data, htx->used, (htx->tail >= htx->head) ? "NO" : "YES", (unsigned long long)htx->extra); - fprintf(stderr, "\thead=%d - tail=%u - front=%u - wrap=%u\n", - htx_get_head(htx), htx->tail, htx->front, htx->wrap); + fprintf(stderr, "\thead=%u, tail=%u - front=%u\n", + htx->head, htx->tail, htx->front); for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) { struct htx_sl *sl; diff --git a/src/http_htx.c b/src/http_htx.c index 8a407cdff..471f1ab81 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -68,12 +68,10 @@ int http_find_header(const struct htx *htx, const struct ist name, struct htx_blk *blk = ctx->blk; struct ist n, v; enum htx_blk_type type; - uint32_t pos; if (blk) { char *p; - pos = htx_get_blk_pos(htx, blk); if (!ctx->value.ptr) goto rescan_hdr; if (full) @@ -96,15 +94,13 @@ int http_find_header(const struct htx *htx, const struct ist name, if (!htx->used) return 0; - pos = htx_get_head(htx); - while (1) { + for (blk = htx_get_head_blk(htx); blk; blk = htx_get_next_blk(htx, blk)) { rescan_hdr: - blk = htx_get_blk(htx, pos); type = htx_get_blk_type(blk); if (type == HTX_BLK_EOH || type == HTX_BLK_EOM) break; if (type != HTX_BLK_HDR) - goto next_blk; + continue; if (name.len) { /* If no name was passed, we want any header. So skip the comparison */ n = htx_get_blk_name(htx, blk); @@ -128,17 +124,13 @@ int http_find_header(const struct htx *htx, const struct ist name, ctx->lws_after++; } if (!v.len) - goto next_blk; + continue; ctx->blk = blk; ctx->value = v; return 1; next_blk: - if (pos == htx->tail) - break; - pos++; - if (pos >= htx->wrap) - pos = 0; + ; } ctx->blk = NULL; diff --git a/src/htx.c b/src/htx.c index 9deddb15c..9f75f7afa 100644 --- a/src/htx.c +++ b/src/htx.c @@ -42,10 +42,8 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk) /* start from the head */ for (old = htx_get_head(htx); old != -1; old = htx_get_next(htx, old)) { oldblk = htx_get_blk(htx, old); - if (htx_get_blk_type(oldblk) == HTX_BLK_UNUSED) { - htx->used--; + if (htx_get_blk_type(oldblk) == HTX_BLK_UNUSED) continue; - } newblk = htx_get_blk(tmp, new); newblk->addr = addr; @@ -66,8 +64,9 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk) } + htx->used = new; htx->sl_off = sl_off; - htx->wrap = htx->used; + htx->head = 0; htx->front = htx->tail = new - 1; memcpy((void *)htx->blocks, (void *)tmp->blocks, htx->size); @@ -95,8 +94,8 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) if (!htx->used) { /* Empty message */ - htx->front = htx->tail = 0; - htx->wrap = htx->used = 1; + htx->front = htx->head = htx->tail = 0; + htx->used = 1; blk = htx_get_blk(htx, htx->tail); blk->addr = 0; htx->data = blksz; @@ -104,10 +103,10 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) } used = htx->used + 1; - tail = htx->tail + 1; prev = htx->tail; - wrap = htx->wrap; - head = htx_get_head(htx); + head = htx->head; + tail = htx->tail + 1; + wrap = htx_get_wrap(htx); if (tail == wrap) { frtblk = htx_get_blk(htx, htx->front); @@ -178,7 +177,6 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) /* need to defragment the table before inserting upfront */ htx_defrag(htx, NULL); frtblk = htx_get_blk(htx, htx->front); - wrap = htx->wrap + 1; tail = htx->tail + 1; used = htx->used + 1; blk = htx_get_blk(htx, tail); @@ -187,7 +185,6 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) } } - htx->wrap = wrap; htx->tail = tail; htx->used = used; htx->data += blksz; @@ -216,7 +213,7 @@ struct htx_blk *htx_add_blk(struct htx *htx, enum htx_blk_type type, uint32_t bl struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) { enum htx_blk_type type = htx_get_blk_type(blk); - uint32_t next, head, pos; + uint32_t next, pos, wrap; if (type != HTX_BLK_UNUSED) { /* Mark the block as unused, decrement allocated size */ @@ -228,28 +225,27 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) /* This is the last block in use */ if (htx->used == 1/* || !htx->data */) { - htx->front = htx->tail = 0; - htx->wrap = htx->used = 0; + htx->front = htx->head = htx->tail = 0; + htx->used = 0; htx->data = 0; return NULL; } /* There is at least 2 blocks, so tail is always >= 0 */ pos = htx_get_blk_pos(htx, blk); - head = htx_get_head(htx); blk = NULL; next = pos + 1; /* By default retrun the next block */ - if (htx->tail + 1 == htx->wrap) { + wrap = htx_get_wrap(htx); + if (htx->tail + 1 == wrap) { /* The HTTP message doesn't wrap */ - if (pos == head) { - /* remove the head, so just return the new head */ + if (pos == htx->head) { + /* move the head forward */ htx->used--; - next = htx_get_head(htx); + htx->head++; } else if (pos == htx->tail) { /* remove the tail. this was the last inserted block so * return NULL. */ - htx->wrap--; htx->tail--; htx->used--; goto end; @@ -260,17 +256,17 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) if (pos == htx->tail) { /* remove the tail. try to unwrap the message (pos == 0) * and return NULL. */ - htx->tail = ((pos == 0) ? htx->wrap-1 : htx->tail-1); + htx->tail = ((pos == 0) ? wrap-1 : htx->tail-1); htx->used--; goto end; } - else if (pos == head) { - /* remove the head, try to unwrap the message (pos+1 == - * wrap) and return the new head */ + else if (pos == htx->head) { + /* move the head forward and try to unwrap the message + * (head+1 == wrap) */ htx->used--; - if (pos + 1 == htx->wrap) - htx->wrap = htx->tail + 1; - next = htx_get_head(htx); + htx->head++; + if (htx->head == wrap) + htx->head = next = 0; } } diff --git a/src/stream.c b/src/stream.c index 1d2e6ce02..e6530343e 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3295,7 +3295,7 @@ static int stats_dump_full_strm_to_buffer(struct stream_interface *si, struct st chunk_appendf(&trash, " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", htx, htx->flags, htx->size, htx->data, htx->used, - (!htx->used || htx->tail+1 == htx->wrap) ? "NO" : "YES", + (htx->tail >= htx->head) ? "NO" : "YES", (unsigned long long)htx->extra); } @@ -3334,7 +3334,7 @@ static int stats_dump_full_strm_to_buffer(struct stream_interface *si, struct st chunk_appendf(&trash, " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", htx, htx->flags, htx->size, htx->data, htx->used, - (!htx->used || htx->tail+1 == htx->wrap) ? "NO" : "YES", + (htx->tail >= htx->head) ? "NO" : "YES", (unsigned long long)htx->extra); }