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_* */
}
}
-/* Returns the position of the oldest entry (head).
+/* 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_head(const struct htx *htx)
+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));
+}
- return (((htx->tail + 1U < htx->used) ? htx->wrap : 0) + htx->tail + 1U - htx->used);
+/* Returns the position of the oldest entry (head).
+ *
+ * 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_head(const struct htx *htx)
+{
+ return (htx->used ? htx->head : -1);
}
/* Returns the oldest HTX block (head) if the HTX message is not
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);
}
*/
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;
}
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;
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;
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)
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);
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;
/* 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;
}
+ 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);
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;
}
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);
/* 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);
}
}
- htx->wrap = wrap;
htx->tail = tail;
htx->used = used;
htx->data += blksz;
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 */
/* 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;
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;
}
}
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);
}
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);
}