]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: htx: Store the first block position instead of the start-line one
authorChristopher Faulet <cfaulet@haproxy.com>
Thu, 23 May 2019 09:03:26 +0000 (11:03 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 28 May 2019 05:42:33 +0000 (07:42 +0200)
We don't store the start-line position anymore in the HTX message. Instead we
store the first block position to analyze. For now, it is almost the same. But
once all changes will be made on this part, this position will have to be used
by HTX analyzers, and only in the analysis context, to know where the analyse
should start.

When new blocks are added in an HTX message, if the first block position is not
defined, it is set. When the block pointed by it is removed, it is set to the
block following it. -1 remains the value to unset the position. the first block
position is unset when the HTX message is empty. It may also be unset on a
non-empty message, meaning every blocks were already analyzed.

From HTX analyzers point of view, this position is always set during headers
analysis. When they are waiting for a request or a response, if it is unset, it
means the analysis should wait. But once the analysis is started, and as long as
headers are not forwarded, it points to the message start-line.

As mentionned, outside the HTX analysis, no code must rely on the first block
position. So multiplexers and applets must always use the head position to start
a loop on an HTX message.

include/common/htx.h
include/proto/channel.h
src/cache.c
src/hlua.c
src/http_fetch.c
src/http_htx.c
src/htx.c
src/proto_htx.c

index ec9909851d84837309f3d17c558ef73107188968..25c28c8c45c05c6e58abf510205e194ece7263da 100644 (file)
@@ -161,7 +161,7 @@ struct htx {
        uint64_t extra;  /* known bytes amount remaining to receive */
        uint32_t flags;  /* HTX_FL_* */
 
-       int32_t sl_pos; /* position of the start-line of the HTTP message. -1 if unset */
+       int32_t  first;  /* position of the first block to (re)start the analyse. -1 if unset. */
 
        struct htx_blk blocks[0]; /* Blocks representing the HTTP message itself */
 };
@@ -413,8 +413,8 @@ static inline enum htx_blk_type htx_get_tail_type(const struct htx *htx)
        return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED);
 }
 
-/* Returns the position of the first block in the HTX message <htx>. It is the
- * sl_pos if set, otherwise it is the head.
+/* Returns the position of the first block in the HTX message <htx>. If unset,
+ * or if <htx> is empty, -1 is returned.
  *
  * 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
@@ -422,13 +422,13 @@ static inline enum htx_blk_type htx_get_tail_type(const struct htx *htx)
  */
 static inline int32_t htx_get_first(const struct htx *htx)
 {
-       if (htx->sl_pos != -1)
-               return htx->sl_pos;
-       return htx->head;
+       if (!htx->used)
+               return -1;
+       return htx->first;
 }
 
-/* Returns the first HTX block in the HTX message <htx>. If <blk> is the head,
- * NULL returned.
+/* Returns the first HTX block in the HTX message <htx>. If unset or if <htx> is
+ * empty, NULL returned.
  */
 static inline struct htx_blk *htx_get_first_blk(const struct htx *htx)
 {
@@ -717,7 +717,7 @@ static inline void htx_reset(struct htx *htx)
        htx->data = htx->used = htx->tail = htx->head  = htx->front = 0;
        htx->extra = 0;
        htx->flags = HTX_FL_NONE;
-       htx->sl_pos = -1;
+       htx->first = -1;
 }
 
 /* returns the available room for raw data in buffer <buf> once HTX overhead is
@@ -832,8 +832,8 @@ static inline void htx_dump(struct htx *htx)
        fprintf(stderr, "htx:%p [ size=%u - data=%u - used=%u - wrap=%s - extra=%llu]\n",
                htx, htx->size, htx->data, htx->used, (htx->tail >= htx->head) ? "NO" : "YES",
                (unsigned long long)htx->extra);
-       fprintf(stderr, "\tsl_pos=%d - head=%u, tail=%u - front=%u\n",
-               htx->sl_pos, htx->head, htx->tail, htx->front);
+       fprintf(stderr, "\tfirst=%d - head=%u, tail=%u - front=%u\n",
+               htx->first, htx->head, htx->tail, htx->front);
 
        for (pos = htx_get_head(htx); pos != -1; pos = htx_get_next(htx, pos)) {
                struct htx_sl     *sl;
index 077b3ae1f191191ade48c8aa353ac28234717aa8..3ebaf7fce3926bb6441a58db08d4ae7a7c2f4978 100644 (file)
@@ -923,7 +923,7 @@ static inline void channel_htx_fwd_headers(struct channel *chn, struct htx *htx)
                struct htx_blk *blk = htx_get_blk(htx, pos);
                data += htx_get_blksz(blk);
                if (htx_get_blk_type(blk) == HTX_BLK_EOH) {
-                       htx->sl_pos = htx_get_next(htx, pos);
+                       htx->first = htx_get_next(htx, pos);
                        break;
                }
        }
index 1fec57e240df5bc36f1a8e51731b6d1ee8fed9d8..4371910fc87ccb606913ca499be4a1b1c62fd7e7 100644 (file)
@@ -913,10 +913,6 @@ static size_t htx_cache_dump_headers(struct appctx *appctx, struct htx *htx)
                if (!blk)
                        return 0;
 
-               /* Set the start-line offset */
-               if (type == HTX_BLK_RES_SL)
-                       htx->sl_pos = htx_get_blk_pos(htx, blk);
-
                /* Copy info and data */
                blk->info = info;
                memcpy(htx_get_blk_ptr(htx, blk), b_peek(tmp, offset+4), sz);
index bb8c93da6b7f7bc69aac08463ffe7a64be191679..3c9c70a78eabc91562cf850351e993a9e415eccf 100644 (file)
@@ -3944,11 +3944,16 @@ static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
        if (IS_HTX_STRM(s)) {
                /* HTX version */
                struct htx *htx = htxbuf(&s->req.buf);
-               struct htx_sl *sl = http_get_stline(htx);
+               struct htx_blk *blk;
+               struct htx_sl *sl;
                struct ist path;
                unsigned long long len = 0;
                int32_t pos;
 
+               blk = htx_get_first_blk(htx);
+               BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
+               sl = htx_get_blk_ptr(htx, blk);
+
                /* Stores the request method. */
                lua_pushstring(L, "method");
                lua_pushlstring(L, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl));
@@ -4366,7 +4371,7 @@ __LJMP static int hlua_applet_htx_recv_yield(lua_State *L, int status, lua_KCont
        htx = htx_from_buf(&req->buf);
        len = MAY_LJMP(luaL_checkinteger(L, 2));
        count = co_data(req);
-       blk = htx_get_first_blk(htx);
+       blk = htx_get_head_blk(htx);
        while (count && len && blk) {
                enum htx_blk_type type = htx_get_blk_type(blk);
                uint32_t sz = htx_get_blksz(blk);
index 05074d6eb4fc98266bb8bc5f0b9f57c675d6b141..a184f2f3ba0464781b9cef9fdb81e4349c093a60 100644 (file)
@@ -203,7 +203,7 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, int vol)
 
                if (msg->msg_state < HTTP_MSG_BODY) {
                        /* Analyse not yet started */
-                       if (htx_is_empty(htx) || htx->sl_pos == -1) {
+                       if (htx_is_empty(htx) || htx->first == -1) {
                                /* Parsing is done by the mux, just wait */
                                smp->flags |= SMP_F_MAY_CHANGE;
                                return NULL;
index 15865d5022a1803e6f8b13fc38f3472f58fa35f1..b9501bed73f8e452dfa0cefb9fad79b109a6693c 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <common/config.h>
+#include <common/debug.h>
 #include <common/cfgparse.h>
 #include <common/h1.h>
 #include <common/http.h>
 struct buffer htx_err_chunks[HTTP_ERR_SIZE];
 
 /* Returns the next unporocessed start line in the HTX message. It returns NULL
- * is the start-line is undefined (sl_pos == 1). Otherwise, it returns the
+ * if the start-line is undefined (first == -1). Otherwise, it returns the
  * pointer on the htx_sl structure.
  */
 struct htx_sl *http_get_stline(struct htx *htx)
 {
        struct htx_blk *blk;
 
-       if (htx->sl_pos == -1)
-               return NULL;
-
-       blk = htx_get_blk(htx, htx->sl_pos);
+       BUG_ON(htx->first == -1);
+       blk = htx_get_first_blk(htx);
        if (!blk)
                return NULL;
+       BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL && htx_get_blk_type(blk) != HTX_BLK_RES_SL);
        return htx_get_blk_ptr(htx, blk);
 }
 
@@ -143,7 +143,7 @@ int http_add_header(struct htx *htx, const struct ist n, const struct ist v)
 
        /* <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->sl_pos; prev = htx_get_prev(htx, prev)) {
+       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 type = htx_get_blk_type(pblk);
 
@@ -169,18 +169,14 @@ int http_add_header(struct htx *htx, const struct ist n, const struct ist v)
 }
 
 /* Replaces parts of the start-line of the HTX message <htx>. It returns 1 on
- * success, otherwise it returns 0. The right block is search in the HTX
- * message.
+ * success, otherwise it returns 0.
  */
 int http_replace_stline(struct htx *htx, const struct ist p1, const struct ist p2, const struct ist p3)
 {
        struct htx_blk *blk;
 
-       if (htx->sl_pos == -1)
-               return 0;
-
-       blk = htx_get_blk(htx, htx->sl_pos);
-       if (!htx_replace_stline(htx, blk, p1, p2, p3))
+       blk = htx_get_first_blk(htx);
+       if (!blk || !htx_replace_stline(htx, blk, p1, p2, p3))
                return 0;
        return 1;
 }
index a7623b6d93ce732f802d9da606ddfdff6d3cbf0d..dbf8dea3797498d7edbadd93b8539a06994f93e1 100644 (file)
--- a/src/htx.c
+++ b/src/htx.c
@@ -28,7 +28,7 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk)
        struct htx_blk *newblk, *oldblk;
        uint32_t new, old, blkpos;
        uint32_t addr, blksz;
-       int32_t sl_pos = -1;
+       int32_t first = -1;
 
        if (!htx->used)
                return NULL;
@@ -51,8 +51,8 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk)
                blksz = htx_get_blksz(oldblk);
 
                /* update the start-line position */
-               if (htx->sl_pos == old)
-                       sl_pos = new;
+               if (htx->first == old)
+                       first = new;
 
                /* if <blk> is defined, set its new position */
                if (blk != NULL && blk == oldblk)
@@ -65,7 +65,7 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk)
        }
 
        htx->used = new;
-       htx->sl_pos = sl_pos;
+       htx->first = first;
        htx->head = 0;
        htx->front = htx->tail = new - 1;
        memcpy((void *)htx->blocks, (void *)tmp->blocks, htx->size);
@@ -94,7 +94,7 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz)
 
        if (!htx->used) {
                /* Empty message */
-               htx->front = htx->head = htx->tail = 0;
+               htx->front = htx->head = htx->tail = htx->first = 0;
                htx->used = 1;
                blk = htx_get_blk(htx, htx->tail);
                blk->addr = 0;
@@ -188,6 +188,9 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz)
        htx->tail  = tail;
        htx->used  = used;
        htx->data += blksz;
+       /* Set first position if not already set */
+       if (htx->first == -1)
+               htx->first = tail;
        return blk;
 }
 
@@ -220,15 +223,11 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk)
                /* Mark the block as unused, decrement allocated size */
                htx->data -= htx_get_blksz(blk);
                blk->info = ((uint32_t)HTX_BLK_UNUSED << 28);
-               if (htx->sl_pos == pos)
-                       htx->sl_pos = -1;
        }
 
        /* This is the last block in use */
-       if (htx->used == 1/* || !htx->data */) {
-               htx->front = htx->head = htx->tail = 0;
-               htx->used = 0;
-               htx->data = 0;
+       if (htx->used == 1) {
+               htx_reset(htx);
                return NULL;
        }
 
@@ -271,13 +270,9 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk)
        }
 
        blk = htx_get_blk(htx, next);
-       if (htx->sl_pos == -1) {
-               /* Try to update the start-line payload addr, if possible */
-               type = htx_get_blk_type(blk);
-               if (type == HTX_BLK_REQ_SL || type == HTX_BLK_RES_SL)
-                       htx->sl_pos = htx_get_blk_pos(htx, blk);
-       }
   end:
+       if (pos == htx->first)
+               htx->first = (blk ? htx_get_blk_pos(htx, blk) : -1);
        if (pos == htx->front)
                htx->front = htx_find_front(htx);
        return blk;
@@ -542,9 +537,6 @@ struct htx_ret htx_xfer_blks(struct htx *dst, struct htx *src, uint32_t count,
                        htx_cut_data_blk(src, blk, sz);
                        break;
                }
-
-               if (dst->sl_pos == -1 && src->sl_pos == htx_get_blk_pos(src, blk))
-                       dst->sl_pos = htx_get_blk_pos(dst, dstblk);
          next:
                blk = htx_remove_blk(src, blk);
                if (type == mark)
@@ -682,8 +674,6 @@ struct htx_sl *htx_add_stline(struct htx *htx, enum htx_blk_type type, unsigned
        blk->info += size;
 
        sl = htx_get_blk_ptr(htx, blk);
-       if (htx->sl_pos == -1)
-               htx->sl_pos = htx_get_blk_pos(htx, blk);
        sl->hdrs_bytes = -1;
        sl->flags = flags;
 
index dc0762d73f96a06e280d56c6878514137e617a59..7cc26ba3105d71a62b5313e47bfe22764ba842a3 100644 (file)
@@ -132,7 +132,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
         * a timeout or connection reset is not counted as an error. However
         * a bad request is.
         */
-       if (unlikely(htx_is_empty(htx) || htx->sl_pos == -1)) {
+       if (unlikely(htx_is_empty(htx) || htx->first == -1)) {
                if (htx->flags & HTX_FL_UPGRADE)
                        goto failed_keep_alive;
 
@@ -279,6 +279,7 @@ int htx_wait_for_request(struct stream *s, struct channel *req, int an_bit)
        txn->flags &= ~TX_WAIT_NEXT_RQ;
        req->analyse_exp = TICK_ETERNITY;
 
+       BUG_ON(htx_get_first_type(htx) != HTX_BLK_REQ_SL);
        sl = http_get_stline(htx);
 
        /* 0: we might have to print this header in debug mode */
@@ -1470,7 +1471,7 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
         * errors somewhere else.
         */
   next_one:
-       if (unlikely(htx_is_empty(htx) || htx->sl_pos == -1)) {
+       if (unlikely(htx_is_empty(htx) || htx->first == -1)) {
                /* 1: have we encountered a read error ? */
                if (rep->flags & CF_READ_ERROR) {
                        struct connection *conn = NULL;
@@ -1625,6 +1626,7 @@ int htx_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
         */
 
        msg->msg_state = HTTP_MSG_BODY;
+       BUG_ON(htx_get_first_type(htx) != HTX_BLK_RES_SL);
        sl = http_get_stline(htx);
 
        /* 0: we might have to print this header in debug mode */