]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MAJOR: http: move http_txn out of struct stream
authorWilly Tarreau <w@1wt.eu>
Fri, 3 Apr 2015 21:46:31 +0000 (23:46 +0200)
committerWilly Tarreau <w@1wt.eu>
Mon, 6 Apr 2015 09:35:52 +0000 (11:35 +0200)
Now this one is dynamically allocated. It means that 280 bytes of memory
are saved per TCP stream, but more importantly that it will become
possible to remove the l7 pointer from fetches and converters since
it will be deduced from the stream and will support being null.

A lot of care was taken because it's easy to forget a test somewhere,
and the previous code used to always trust s->txn for being valid, but
all places seem to have been visited.

All HTTP fetch functions check the txn first so we shouldn't have any
issue there even when called from TCP. When branching from a TCP frontend
to an HTTP backend, the txn is properly allocated at the same time as the
hdr_idx.

14 files changed:
include/proto/proto_http.h
include/types/proto_http.h
include/types/stream.h
src/backend.c
src/compression.c
src/dumpstats.c
src/frontend.c
src/hlua.c
src/log.c
src/peers.c
src/proto_http.c
src/proto_tcp.c
src/proxy.c
src/stream.c

index 477b9b05613d71935710b288f06c8f639479bafa..a8056af88ea4b5842b612b2af35d3aba757fb6bc 100644 (file)
@@ -114,6 +114,7 @@ unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hle
                          struct hdr_idx *idx, int occ,
                          struct hdr_ctx *ctx, char **vptr, int *vlen);
 
+struct http_txn *http_alloc_txn(struct stream *s);
 void http_init_txn(struct stream *s);
 void http_end_txn(struct stream *s);
 void http_reset_txn(struct stream *s);
index b7dc4b53f966ef29863451e50ba29591d6ea1b8c..d1fdf7585473b9672130e84125b774eaba07ee50 100644 (file)
@@ -545,6 +545,8 @@ extern struct http_res_action_kw_list http_res_keywords;
 
 extern const struct http_method_name http_known_methods[HTTP_METH_OTHER];
 
+extern struct pool_head *pool2_http_txn;
+
 #endif /* _TYPES_PROTO_HTTP_H */
 
 /*
index 80d84ac1050158cf1592c0af610b9ffb21e8ae88..3a0a60f5ffb2d1b72c82dc623abc578b2ef47081 100644 (file)
@@ -124,7 +124,7 @@ struct stream {
        struct server *srv_conn;        /* stream already has a slot on a server and is not in queue */
        struct pendconn *pend_pos;      /* if not NULL, points to the position in the pending queue */
 
-       struct http_txn txn;            /* current HTTP transaction being processed. Should become a list. */
+       struct http_txn *txn;           /* current HTTP transaction being processed. Should become a list. */
 
        struct task *task;              /* the task associated with this stream */
        struct list list;               /* position in global streams list */
index 2c2a61e7a7287c9208693fae73cec0ee0c64e573..a8cf644c0d2704ea6299c2650679912348c8ad08 100644 (file)
@@ -300,7 +300,7 @@ struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)
 struct server *get_server_ph_post(struct stream *s)
 {
        unsigned int hash = 0;
-       struct http_txn *txn  = &s->txn;
+       struct http_txn *txn  = s->txn;
        struct channel  *req  = &s->req;
        struct http_msg *msg  = &txn->req;
        struct proxy    *px   = s->be;
@@ -378,7 +378,7 @@ struct server *get_server_ph_post(struct stream *s)
 struct server *get_server_hh(struct stream *s)
 {
        unsigned int hash = 0;
-       struct http_txn *txn  = &s->txn;
+       struct http_txn *txn  = s->txn;
        struct proxy    *px   = s->be;
        unsigned int     plen = px->hh_len;
        unsigned long    len;
@@ -553,7 +553,7 @@ int assign_server(struct stream *s)
        if (conn &&
            (conn->flags & CO_FL_CONNECTED) &&
            objt_server(conn->target) && __objt_server(conn->target)->proxy == s->be &&
-           ((s->txn.flags & TX_PREFER_LAST) ||
+           ((s->txn && s->txn->flags & TX_PREFER_LAST) ||
             ((s->be->options & PR_O_PREF_LAST) &&
              (!s->be->max_ka_queue ||
               server_has_room(__objt_server(conn->target)) ||
@@ -627,29 +627,29 @@ int assign_server(struct stream *s)
 
                        case BE_LB_HASH_URI:
                                /* URI hashing */
-                               if (s->txn.req.msg_state < HTTP_MSG_BODY)
+                               if (!s->txn || s->txn->req.msg_state < HTTP_MSG_BODY)
                                        break;
                                srv = get_server_uh(s->be,
-                                                   b_ptr(s->req.buf, -http_uri_rewind(&s->txn.req)),
-                                                   s->txn.req.sl.rq.u_l);
+                                                   b_ptr(s->req.buf, -http_uri_rewind(&s->txn->req)),
+                                                   s->txn->req.sl.rq.u_l);
                                break;
 
                        case BE_LB_HASH_PRM:
                                /* URL Parameter hashing */
-                               if (s->txn.req.msg_state < HTTP_MSG_BODY)
+                               if (!s->txn || s->txn->req.msg_state < HTTP_MSG_BODY)
                                        break;
 
                                srv = get_server_ph(s->be,
-                                                   b_ptr(s->req.buf, -http_uri_rewind(&s->txn.req)),
-                                                   s->txn.req.sl.rq.u_l);
+                                                   b_ptr(s->req.buf, -http_uri_rewind(&s->txn->req)),
+                                                   s->txn->req.sl.rq.u_l);
 
-                               if (!srv && s->txn.meth == HTTP_METH_POST)
+                               if (!srv && s->txn->meth == HTTP_METH_POST)
                                        srv = get_server_ph_post(s);
                                break;
 
                        case BE_LB_HASH_HDR:
                                /* Header Parameter hashing */
-                               if (s->txn.req.msg_state < HTTP_MSG_BODY)
+                               if (!s->txn || s->txn->req.msg_state < HTTP_MSG_BODY)
                                        break;
                                srv = get_server_hh(s);
                                break;
@@ -861,9 +861,9 @@ int assign_server_and_queue(struct stream *s)
                         */
 
                        if (prev_srv != objt_server(s->target)) {
-                               if ((s->txn.flags & TX_CK_MASK) == TX_CK_VALID) {
-                                       s->txn.flags &= ~TX_CK_MASK;
-                                       s->txn.flags |= TX_CK_DOWN;
+                               if (s->txn && (s->txn->flags & TX_CK_MASK) == TX_CK_VALID) {
+                                       s->txn->flags &= ~TX_CK_MASK;
+                                       s->txn->flags |= TX_CK_DOWN;
                                }
                                s->flags |= SF_REDISP;
                                prev_srv->counters.redispatches++;
@@ -973,7 +973,7 @@ static void assign_tproxy_address(struct stream *s)
                        memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from));
                break;
        case CO_SRC_TPROXY_DYN:
-               if (src->bind_hdr_occ) {
+               if (src->bind_hdr_occ && s->txn) {
                        char *vptr;
                        int vlen;
                        int rewind;
@@ -983,9 +983,9 @@ static void assign_tproxy_address(struct stream *s)
                        ((struct sockaddr_in *)&srv_conn->addr.from)->sin_port = 0;
                        ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr = 0;
 
-                       b_rew(s->req.buf, rewind = http_hdr_rewind(&s->txn.req));
-                       if (http_get_hdr(&s->txn.req, src->bind_hdr_name, src->bind_hdr_len,
-                                        &s->txn.hdr_idx, src->bind_hdr_occ, NULL, &vptr, &vlen)) {
+                       b_rew(s->req.buf, rewind = http_hdr_rewind(&s->txn->req));
+                       if (http_get_hdr(&s->txn->req, src->bind_hdr_name, src->bind_hdr_len,
+                                        &s->txn->hdr_idx, src->bind_hdr_occ, NULL, &vptr, &vlen)) {
                                ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr =
                                        htonl(inetaddr_host_lim(vptr, vptr + vlen));
                        }
index 0ae634f2e120c9a85ea62e9c30894677ba3a6b1e..50d41c119d44f1111cd0328d22d506975da98d05 100644 (file)
@@ -184,7 +184,7 @@ int http_compression_buffer_init(struct stream *s, struct buffer *in, struct buf
  */
 int http_compression_buffer_add_data(struct stream *s, struct buffer *in, struct buffer *out)
 {
-       struct http_msg *msg = &s->txn.rsp;
+       struct http_msg *msg = &s->txn->rsp;
        int consumed_data = 0;
        int data_process_len;
        int block1, block2;
@@ -234,7 +234,7 @@ int http_compression_buffer_end(struct stream *s, struct buffer **in, struct buf
 {
        int to_forward;
        int left;
-       struct http_msg *msg = &s->txn.rsp;
+       struct http_msg *msg = &s->txn->rsp;
        struct buffer *ib = *in, *ob = *out;
        char *tail;
 
index 2aed81a71173c4cdb91ada48440178ebe6b5de24..c24f81551301c7899eeb4ffd9b3c63fdae578e0e 100644 (file)
@@ -4422,13 +4422,13 @@ static int stats_process_http_post(struct stream_interface *si)
        int reql;
 
        temp = get_trash_chunk();
-       if (temp->size < s->txn.req.body_len) {
+       if (temp->size < s->txn->req.body_len) {
                /* too large request */
                appctx->ctx.stats.st_code = STAT_STATUS_EXCD;
                goto out;
        }
 
-       reql = bo_getblk(si_oc(si), temp->str, s->txn.req.body_len, s->txn.req.eoh + 2);
+       reql = bo_getblk(si_oc(si), temp->str, s->txn->req.body_len, s->txn->req.eoh + 2);
        if (reql <= 0) {
                /* we need more data */
                appctx->ctx.stats.st_code = STAT_STATUS_NONE;
@@ -4742,7 +4742,7 @@ static int stats_send_http_headers(struct stream_interface *si)
        else
                chunk_appendf(&trash, "\r\n");
 
-       s->txn.status = 200;
+       s->txn->status = 200;
        s->logs.tv_request = now;
 
        if (bi_putchk(si_ic(si), &trash) == -1) {
@@ -4789,7 +4789,7 @@ static int stats_send_http_redirect(struct stream_interface *si)
                     (appctx->ctx.stats.flags & STAT_NO_REFRESH) ? ";norefresh" : "",
                     scope_txt);
 
-       s->txn.status = 303;
+       s->txn->status = 303;
        s->logs.tv_request = now;
 
        if (bi_putchk(si_ic(si), &trash) == -1) {
@@ -4822,7 +4822,7 @@ static void http_stats_io_handler(struct stream_interface *si)
        /* all states are processed in sequence */
        if (appctx->st0 == STAT_HTTP_HEAD) {
                if (stats_send_http_headers(si)) {
-                       if (s->txn.meth == HTTP_METH_HEAD)
+                       if (s->txn->meth == HTTP_METH_HEAD)
                                appctx->st0 = STAT_HTTP_DONE;
                        else
                                appctx->st0 = STAT_HTTP_DUMP;
@@ -5134,10 +5134,11 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct st
                             " age=%s)\n",
                             human_time(now.tv_sec - sess->logs.accept_date.tv_sec, 1));
 
-               chunk_appendf(&trash,
+               if (sess->txn)
+                       chunk_appendf(&trash,
                             "  txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s waiting=%d\n",
-                            &sess->txn, sess->txn.flags, sess->txn.meth, sess->txn.status,
-                             http_msg_state_str(sess->txn.req.msg_state), http_msg_state_str(sess->txn.rsp.msg_state), !LIST_ISEMPTY(&sess->buffer_wait));
+                             sess->txn, sess->txn->flags, sess->txn->meth, sess->txn->status,
+                             http_msg_state_str(sess->txn->req.msg_state), http_msg_state_str(sess->txn->rsp.msg_state), !LIST_ISEMPTY(&sess->buffer_wait));
 
                chunk_appendf(&trash,
                             "  si[0]=%p (state=%s flags=0x%02x endp0=%s:%p exp=%s, et=0x%03x)\n",
@@ -5247,7 +5248,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct st
                             sess->req.buf,
                             sess->req.buf->data, sess->req.buf->o,
                             (int)(sess->req.buf->p - sess->req.buf->data),
-                            sess->txn.req.next, sess->req.buf->i,
+                            sess->txn ? sess->txn->req.next : 0, sess->req.buf->i,
                             sess->req.buf->size);
 
                chunk_appendf(&trash,
@@ -5276,7 +5277,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct st
                             sess->res.buf,
                             sess->res.buf->data, sess->res.buf->o,
                             (int)(sess->res.buf->p - sess->res.buf->data),
-                            sess->txn.rsp.next, sess->res.buf->i,
+                            sess->txn ? sess->txn->rsp.next : 0, sess->res.buf->i,
                             sess->res.buf->size);
 
                if (bi_putchk(si_ic(si), &trash) == -1) {
index 3a71bc4eebcd61542c2854d2261a5fe393f7ac8e..3a28d6fd45dcc83d529a2af0939d3b0955641e61 100644 (file)
@@ -127,9 +127,7 @@ int frontend_accept(struct stream *s)
                 * that we may make use of them. This of course includes
                 * (mode == PR_MODE_HTTP).
                 */
-               s->txn.hdr_idx.size = global.tune.max_http_hdr;
-
-               if (unlikely((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL))
+               if (unlikely(!http_alloc_txn(s)))
                        goto out_free_rspcap; /* no memory */
 
                /* and now initialize the HTTP transaction state */
index e54c02914e91a0bffee11c20be775d37e899dc7e..43d9c1b369a48ce36f4cc5b5b973046ec7d78ce7 100644 (file)
@@ -2169,13 +2169,7 @@ __LJMP static int hlua_socket_new(lua_State *L)
        socket->s->res_cap = NULL;
 
        /* XXX: See later. */
-       socket->s->txn.sessid = NULL;
-       socket->s->txn.srv_cookie = NULL;
-       socket->s->txn.cli_cookie = NULL;
-       socket->s->txn.uri = NULL;
-       socket->s->txn.hdr_idx.v = NULL;
-       socket->s->txn.hdr_idx.size = 0;
-       socket->s->txn.hdr_idx.used = 0;
+       socket->s->txn = NULL;
 
        /* Configure "left" stream interface as applet. This "si" produce
         * and use the data received from the server. The applet is initialized
@@ -2971,17 +2965,20 @@ __LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, str
        /* Create the table. */
        lua_newtable(L);
 
+       if (!htxn->s->txn)
+               return 1;
+
        /* Build array of headers. */
        old_idx = 0;
-       cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn.hdr_idx);
+       cur_next = msg->chn->buf->p + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
 
        while (1) {
-               cur_idx = htxn->s->txn.hdr_idx.v[old_idx].next;
+               cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
                if (!cur_idx)
                        break;
                old_idx = cur_idx;
 
-               cur_hdr  = &htxn->s->txn.hdr_idx.v[cur_idx];
+               cur_hdr  = &htxn->s->txn->hdr_idx.v[cur_idx];
                cur_ptr  = cur_next;
                cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
 
@@ -3021,7 +3018,7 @@ __LJMP static int hlua_http_req_get_headers(lua_State *L)
        MAY_LJMP(check_args(L, 1, "req_get_headers"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_get_headers(L, htxn, &htxn->s->txn.req);
+       return hlua_http_get_headers(L, htxn, &htxn->s->txn->req);
 }
 
 __LJMP static int hlua_http_res_get_headers(lua_State *L)
@@ -3031,7 +3028,7 @@ __LJMP static int hlua_http_res_get_headers(lua_State *L)
        MAY_LJMP(check_args(L, 1, "res_get_headers"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_get_headers(L, htxn, &htxn->s->txn.rsp);
+       return hlua_http_get_headers(L, htxn, &htxn->s->txn->rsp);
 }
 
 /* This function replace full header, or just a value in
@@ -3062,7 +3059,7 @@ __LJMP static int hlua_http_req_rep_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.req, HTTP_REQ_ACT_REPLACE_HDR));
+       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, HTTP_REQ_ACT_REPLACE_HDR));
 }
 
 __LJMP static int hlua_http_res_rep_hdr(lua_State *L)
@@ -3072,7 +3069,7 @@ __LJMP static int hlua_http_res_rep_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 4, "res_rep_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.rsp, HTTP_RES_ACT_REPLACE_HDR));
+       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, HTTP_RES_ACT_REPLACE_HDR));
 }
 
 __LJMP static int hlua_http_req_rep_val(lua_State *L)
@@ -3082,7 +3079,7 @@ __LJMP static int hlua_http_req_rep_val(lua_State *L)
        MAY_LJMP(check_args(L, 4, "req_rep_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.req, HTTP_REQ_ACT_REPLACE_VAL));
+       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, HTTP_REQ_ACT_REPLACE_VAL));
 }
 
 __LJMP static int hlua_http_res_rep_val(lua_State *L)
@@ -3092,7 +3089,7 @@ __LJMP static int hlua_http_res_rep_val(lua_State *L)
        MAY_LJMP(check_args(L, 4, "res_rep_val"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn.rsp, HTTP_RES_ACT_REPLACE_VAL));
+       return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, HTTP_RES_ACT_REPLACE_VAL));
 }
 
 /* This function deletes all the occurences of an header.
@@ -3103,7 +3100,7 @@ __LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn,
        size_t len;
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
        struct hdr_ctx ctx;
-       struct http_txn *txn = &htxn->s->txn;
+       struct http_txn *txn = htxn->s->txn;
 
        ctx.idx = 0;
        while (http_find_header2(name, len, msg->chn->buf->p, &txn->hdr_idx, &ctx))
@@ -3118,7 +3115,7 @@ __LJMP static int hlua_http_req_del_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 2, "req_del_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_del_hdr(L, htxn, &htxn->s->txn.req);
+       return hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
 }
 
 __LJMP static int hlua_http_res_del_hdr(lua_State *L)
@@ -3128,7 +3125,7 @@ __LJMP static int hlua_http_res_del_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 2, "req_del_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_del_hdr(L, htxn, &htxn->s->txn.rsp);
+       return hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
 }
 
 /* This function adds an header. It is a wrapper used by
@@ -3157,7 +3154,7 @@ __LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn,
        p++;
        memcpy(p, value, value_len);
 
-       lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn.hdr_idx,
+       lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
                                                 trash.str, trash.len) != 0);
 
        return 0;
@@ -3170,7 +3167,7 @@ __LJMP static int hlua_http_req_add_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 3, "req_add_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_add_hdr(L, htxn, &htxn->s->txn.req);
+       return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
 }
 
 __LJMP static int hlua_http_res_add_hdr(lua_State *L)
@@ -3180,7 +3177,7 @@ __LJMP static int hlua_http_res_add_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 3, "res_add_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       return hlua_http_add_hdr(L, htxn, &htxn->s->txn.rsp);
+       return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
 }
 
 static int hlua_http_req_set_hdr(lua_State *L)
@@ -3190,8 +3187,8 @@ static int hlua_http_req_set_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 3, "req_set_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       hlua_http_del_hdr(L, htxn, &htxn->s->txn.req);
-       return hlua_http_add_hdr(L, htxn, &htxn->s->txn.req);
+       hlua_http_del_hdr(L, htxn, &htxn->s->txn->req);
+       return hlua_http_add_hdr(L, htxn, &htxn->s->txn->req);
 }
 
 static int hlua_http_res_set_hdr(lua_State *L)
@@ -3201,8 +3198,8 @@ static int hlua_http_res_set_hdr(lua_State *L)
        MAY_LJMP(check_args(L, 3, "res_set_hdr"));
        htxn = MAY_LJMP(hlua_checkhttp(L, 1));
 
-       hlua_http_del_hdr(L, htxn, &htxn->s->txn.rsp);
-       return hlua_http_add_hdr(L, htxn, &htxn->s->txn.rsp);
+       hlua_http_del_hdr(L, htxn, &htxn->s->txn->rsp);
+       return hlua_http_add_hdr(L, htxn, &htxn->s->txn->rsp);
 }
 
 /* This function set the method. */
@@ -3211,7 +3208,7 @@ static int hlua_http_req_set_meth(lua_State *L)
        struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
        size_t name_len;
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
-       struct http_txn *txn = &htxn->s->txn;
+       struct http_txn *txn = htxn->s->txn;
 
        lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s, txn) != -1);
        return 1;
@@ -3223,7 +3220,7 @@ static int hlua_http_req_set_path(lua_State *L)
        struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
        size_t name_len;
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
-       struct http_txn *txn = &htxn->s->txn;
+       struct http_txn *txn = htxn->s->txn;
 
        lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s, txn) != -1);
        return 1;
@@ -3235,7 +3232,7 @@ static int hlua_http_req_set_query(lua_State *L)
        struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
        size_t name_len;
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
-       struct http_txn *txn = &htxn->s->txn;
+       struct http_txn *txn = htxn->s->txn;
 
        /* Check length. */
        if (name_len > trash.size - 1) {
@@ -3259,7 +3256,7 @@ static int hlua_http_req_set_uri(lua_State *L)
        struct hlua_txn *htxn = MAY_LJMP(hlua_checkhttp(L, 1));
        size_t name_len;
        const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
-       struct http_txn *txn = &htxn->s->txn;
+       struct http_txn *txn = htxn->s->txn;
 
        lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s, txn) != -1);
        return 1;
index 949dc29fcd5a13b16b45f4233d0e8d990af47cc5..97a20807f744185d366b69e12e4287accccf7baa 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -922,7 +922,7 @@ int build_logline(struct stream *s, char *dst, size_t maxsize, struct list *list
        struct session *sess = strm_sess(s);
        struct proxy *fe = sess->fe;
        struct proxy *be = s->be;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        char *uri;
        struct tm tm;
        int t_request;
@@ -1615,7 +1615,7 @@ void strm_log(struct stream *s)
               ((s->flags & SF_ERR_MASK) > SF_ERR_LOCAL) ||
              (((s->flags & SF_ERR_MASK) == SF_ERR_NONE) &&
               (s->si[1].conn_retries != s->be->conn_retries)) ||
-             ((sess->fe->mode == PR_MODE_HTTP) && s->txn.status >= 500);
+             ((sess->fe->mode == PR_MODE_HTTP) && s->txn && s->txn->status >= 500);
 
        if (!err && (sess->fe->options2 & PR_O2_NOLOGNORM))
                return;
index 08ccfa9bbc14d25f72b861ebf77f7bbbe9a38ed0..b5d1d8e0bcc9bbb063a244ae7578a9e60e55fe27 100644 (file)
@@ -1113,7 +1113,6 @@ static struct stream *peer_session_create(struct peer *peer, struct peer_session
        struct proxy *p = (struct proxy *)l->frontend; /* attached frontend */
        struct appctx *appctx;
        struct stream *s;
-       struct http_txn *txn;
        struct task *t;
        struct connection *conn;
 
@@ -1218,17 +1217,7 @@ static struct stream *peer_session_create(struct peer *peer, struct peer_session
        s->uniq_id = 0;
        s->unique_id = NULL;
 
-       txn = &s->txn;
-       /* Those variables will be checked and freed if non-NULL in
-        * stream.c:stream_free(). It is important that they are
-        * properly initialized.
-        */
-       txn->sessid = NULL;
-       txn->srv_cookie = NULL;
-       txn->cli_cookie = NULL;
-       txn->uri = NULL;
-       txn->hdr_idx.v = NULL;
-       txn->hdr_idx.size = txn->hdr_idx.used = 0;
+       s->txn = NULL;
 
        channel_init(&s->req);
        s->req.flags |= CF_READ_ATTACHED; /* the producer is already connected */
index 8bd6b5ef544c1411255b5df879cd1a7bc5e979fe..9b682702fc0c4362f933939e8a1b02f8a29de10d 100644 (file)
@@ -834,7 +834,7 @@ static void http_server_error(struct stream *s, struct stream_interface *si,
        channel_auto_close(si_ic(si));
        channel_auto_read(si_ic(si));
        if (status > 0 && msg) {
-               s->txn.status = status;
+               s->txn->status = status;
                bo_inject(si_ic(si), msg->str, msg->len);
        }
        if (!(s->flags & SF_ERR_MASK))
@@ -1001,7 +1001,7 @@ void http_perform_server_redirect(struct stream *s, struct stream_interface *si)
        /* 3: add the request URI. Since it was already forwarded, we need
         * to temporarily rewind the buffer.
         */
-       txn = &s->txn;
+       txn = s->txn;
        b_rew(s->req.buf, rewind = http_hdr_rewind(&txn->req));
 
        path = http_get_path(txn);
@@ -1060,7 +1060,7 @@ void http_return_srv_error(struct stream *s, struct stream_interface *si)
                                  503, http_error_message(s, HTTP_ERR_503));
        else if (err_type & SI_ET_CONN_ABRT)
                http_server_error(s, si, SF_ERR_CLICL, SF_FINST_C,
-                                 503, (s->txn.flags & TX_NOT_FIRST) ? NULL :
+                                 503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
                                  http_error_message(s, HTTP_ERR_503));
        else if (err_type & SI_ET_QUEUE_TO)
                http_server_error(s, si, SF_ERR_SRVTO, SF_FINST_Q,
@@ -1070,7 +1070,7 @@ void http_return_srv_error(struct stream *s, struct stream_interface *si)
                                  503, http_error_message(s, HTTP_ERR_503));
        else if (err_type & SI_ET_CONN_TO)
                http_server_error(s, si, SF_ERR_SRVTO, SF_FINST_C,
-                                 503, (s->txn.flags & TX_NOT_FIRST) ? NULL :
+                                 503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
                                  http_error_message(s, HTTP_ERR_503));
        else if (err_type & SI_ET_CONN_ERR)
                http_server_error(s, si, SF_ERR_SRVCL, SF_FINST_C,
@@ -1078,7 +1078,7 @@ void http_return_srv_error(struct stream *s, struct stream_interface *si)
                                  http_error_message(s, HTTP_ERR_503));
        else if (err_type & SI_ET_CONN_RES)
                http_server_error(s, si, SF_ERR_RESOURCE, SF_FINST_C,
-                                 503, (s->txn.flags & TX_NOT_FIRST) ? NULL :
+                                 503, (s->txn->flags & TX_NOT_FIRST) ? NULL :
                                  http_error_message(s, HTTP_ERR_503));
        else /* SI_ET_CONN_OTHER and others */
                http_server_error(s, si, SF_ERR_INTERNAL, SF_FINST_C,
@@ -1437,7 +1437,7 @@ int
 get_http_auth(struct stream *s)
 {
 
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct chunk auth_method;
        struct hdr_ctx ctx;
        char *h, *p;
@@ -2240,7 +2240,7 @@ int parse_qvalue(const char *qvalue, const char **end)
  */
 int select_compression_request_header(struct stream *s, struct buffer *req)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->req;
        struct hdr_ctx ctx;
        struct comp_algo *comp_algo = NULL;
@@ -2351,7 +2351,7 @@ int select_compression_request_header(struct stream *s, struct buffer *req)
  */
 int select_compression_response_header(struct stream *s, struct buffer *res)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->rsp;
        struct hdr_ctx ctx;
        struct comp_type *comp_type;
@@ -2550,7 +2550,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
        int cur_idx;
        int use_close_only;
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->req;
        struct hdr_ctx ctx;
 
@@ -3103,7 +3103,7 @@ int http_handle_stats(struct stream *s, struct channel *req)
 {
        struct stats_admin_rule *stats_admin_rule;
        struct stream_interface *si = &s->si[1];
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->req;
        struct uri_auth *uri_auth = s->be->uri_auth;
        const char *uri, *h, *lookup;
@@ -3114,7 +3114,7 @@ int http_handle_stats(struct stream *s, struct channel *req)
        appctx->st1 = appctx->st2 = 0;
        appctx->ctx.stats.st_code = STAT_STATUS_INIT;
        appctx->ctx.stats.flags |= STAT_FMT_HTML; /* assume HTML mode by default */
-       if ((msg->flags & HTTP_MSGF_VER_11) && (s->txn.meth != HTTP_METH_HEAD))
+       if ((msg->flags & HTTP_MSGF_VER_11) && (s->txn->meth != HTTP_METH_HEAD))
                appctx->ctx.stats.flags |= STAT_CHUNKED;
 
        uri = msg->chn->buf->p + msg->sl.rq.u;
@@ -3197,7 +3197,7 @@ int http_handle_stats(struct stream *s, struct channel *req)
                int ret = 1;
 
                if (stats_admin_rule->cond) {
-                       ret = acl_exec_cond(stats_admin_rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                       ret = acl_exec_cond(stats_admin_rule->cond, s->be, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
                        ret = acl_pass(ret);
                        if (stats_admin_rule->cond->pol == ACL_COND_UNLESS)
                                ret = !ret;
@@ -3258,7 +3258,7 @@ int http_transform_header_str(struct stream* s, struct http_msg *msg,
 {
        struct hdr_ctx ctx;
        char *buf = msg->chn->buf->p;
-       struct hdr_idx *idx = &s->txn.hdr_idx;
+       struct hdr_idx *idx = &s->txn->hdr_idx;
        int (*http_find_hdr_func)(const char *name, int len, char *sol,
                                  struct hdr_idx *idx, struct hdr_ctx *ctx);
        struct chunk *output = get_trash_chunk();
@@ -3565,7 +3565,7 @@ resume_execution:
                                void *ptr;
 
                                t = rule->act_prm.trk_ctr.table.t;
-                               key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ | SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL);
+                               key = stktable_fetch_key(t, s->be, s, s->txn, SMP_OPT_DIR_REQ | SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL);
 
                                if (key && (ts = stktable_get_entry(t, key))) {
                                        stream_track_stkctr(&s->stkctr[http_req_trk_idx(rule->action)], t, ts);
@@ -4073,7 +4073,7 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s
 int http_process_req_common(struct stream *s, struct channel *req, int an_bit, struct proxy *px)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->req;
        struct redirect_rule *rule;
        struct cond_wordlist *wl;
@@ -4314,7 +4314,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
 int http_process_request(struct stream *s, struct channel *req, int an_bit)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->req;
        struct connection *cli_conn = objt_conn(s->si[1].end);
 
@@ -4592,7 +4592,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
         * that parameter. This will be done in another analyser.
         */
        if (!(s->flags & (SF_ASSIGNED|SF_DIRECT)) &&
-           s->txn.meth == HTTP_METH_POST && s->be->url_param_name != NULL &&
+           s->txn->meth == HTTP_METH_POST && s->be->url_param_name != NULL &&
            (msg->flags & (HTTP_MSGF_CNT_LEN|HTTP_MSGF_TE_CHNK))) {
                channel_dont_connect(req);
                req->analysers |= AN_REQ_HTTP_BODY;
@@ -4661,7 +4661,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
  */
 int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
 
        /* This connection is being tarpitted. The CLIENT side has
         * already set the connect expiration date to the right
@@ -4707,8 +4707,8 @@ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
 int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
-       struct http_msg *msg = &s->txn.req;
+       struct http_txn *txn = s->txn;
+       struct http_msg *msg = &s->txn->req;
 
        /* We have to parse the HTTP request body to find any required data.
         * "balance url_param check_post" should have been the only way to get
@@ -4903,7 +4903,7 @@ int http_send_name_header(struct http_txn *txn, struct proxy* be, const char* sr
  */
 void http_end_txn_clean_session(struct stream *s)
 {
-       int prev_status = s->txn.status;
+       int prev_status = s->txn->status;
        struct proxy *fe = strm_sess(s)->fe;
 
        /* FIXME: We need a more portable way of releasing a backend's and a
@@ -4915,7 +4915,7 @@ void http_end_txn_clean_session(struct stream *s)
        /* unless we're doing keep-alive, we want to quickly close the connection
         * to the server.
         */
-       if (((s->txn.flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
+       if (((s->txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
            !si_conn_ready(&s->si[1])) {
                s->si[1].flags |= SI_FL_NOLINGER | SI_FL_NOHALF;
                si_shutr(&s->si[1]);
@@ -4931,10 +4931,10 @@ void http_end_txn_clean_session(struct stream *s)
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
        stream_process_counters(s);
 
-       if (s->txn.status) {
+       if (s->txn->status) {
                int n;
 
-               n = s->txn.status / 100;
+               n = s->txn->status / 100;
                if (n < 1 || n > 5)
                        n = 0;
 
@@ -4997,7 +4997,7 @@ void http_end_txn_clean_session(struct stream *s)
        /* only release our endpoint if we don't intend to reuse the
         * connection.
         */
-       if (((s->txn.flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
+       if (((s->txn->flags & TX_CON_WANT_MSK) != TX_CON_WANT_KAL) ||
            !si_conn_ready(&s->si[1])) {
                si_release_endpoint(&s->si[1]);
        }
@@ -5013,9 +5013,9 @@ void http_end_txn_clean_session(struct stream *s)
        s->flags &= ~(SF_CURR_SESS|SF_REDIRECTABLE|SF_SRV_REUSED);
        s->flags &= ~(SF_ERR_MASK|SF_FINST_MASK|SF_REDISP);
 
-       s->txn.meth = 0;
+       s->txn->meth = 0;
        http_reset_txn(s);
-       s->txn.flags |= TX_NOT_FIRST | TX_WAIT_NEXT_RQ;
+       s->txn->flags |= TX_NOT_FIRST | TX_WAIT_NEXT_RQ;
 
        if (prev_status == 401 || prev_status == 407) {
                /* In HTTP keep-alive mode, if we receive a 401, we still have
@@ -5025,7 +5025,7 @@ void http_end_txn_clean_session(struct stream *s)
                 * an opportunity for sending the challenge to the proper place,
                 * it's better to do it (at least it helps with debugging).
                 */
-               s->txn.flags |= TX_PREFER_LAST;
+               s->txn->flags |= TX_PREFER_LAST;
        }
 
        if (fe->options2 & PR_O2_INDEPSTR)
@@ -5074,7 +5074,7 @@ void http_end_txn_clean_session(struct stream *s)
 int http_sync_req_state(struct stream *s)
 {
        struct channel *chn = &s->req;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        unsigned int old_flags = chn->flags;
        unsigned int old_state = txn->req.msg_state;
 
@@ -5212,7 +5212,7 @@ int http_sync_req_state(struct stream *s)
 int http_sync_res_state(struct stream *s)
 {
        struct channel *chn = &s->res;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        unsigned int old_flags = chn->flags;
        unsigned int old_state = txn->rsp.msg_state;
 
@@ -5340,7 +5340,7 @@ int http_sync_res_state(struct stream *s)
  */
 int http_resync_states(struct stream *s)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        int old_req_state = txn->req.msg_state;
        int old_res_state = txn->rsp.msg_state;
 
@@ -5417,8 +5417,8 @@ int http_resync_states(struct stream *s)
 int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
-       struct http_msg *msg = &s->txn.req;
+       struct http_txn *txn = s->txn;
+       struct http_msg *msg = &s->txn->req;
 
        if (unlikely(msg->msg_state < HTTP_MSG_BODY))
                return 0;
@@ -5589,7 +5589,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
                                channel_auto_read(req);
                                channel_auto_close(req);
                        }
-                       else if (s->txn.meth == HTTP_METH_POST) {
+                       else if (s->txn->meth == HTTP_METH_POST) {
                                /* POST requests may require to read extra CRLF
                                 * sent by broken browsers and which could cause
                                 * an RST to be sent upon close on some systems
@@ -5722,7 +5722,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
 int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->rsp;
        struct hdr_ctx ctx;
        int use_close_only;
@@ -6290,7 +6290,7 @@ skip_content_length:
 int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, struct proxy *px)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct http_msg *msg = &txn->rsp;
        struct proxy *cur_proxy;
        struct cond_wordlist *wl;
@@ -6630,8 +6630,8 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
 int http_response_forward_body(struct stream *s, struct channel *res, int an_bit)
 {
        struct session *sess = s->sess;
-       struct http_txn *txn = &s->txn;
-       struct http_msg *msg = &s->txn.rsp;
+       struct http_txn *txn = s->txn;
+       struct http_msg *msg = &s->txn->rsp;
        static struct buffer *tmpbuf = &buf_empty;
        int compressing = 0;
        int ret;
@@ -6947,7 +6947,7 @@ int apply_filter_to_req_headers(struct stream *s, struct channel *req, struct hd
 {
        char *cur_ptr, *cur_end, *cur_next;
        int cur_idx, old_idx, last_hdr;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct hdr_idx_elem *cur_hdr;
        int delta;
 
@@ -7059,7 +7059,7 @@ int apply_filter_to_req_line(struct stream *s, struct channel *req, struct hdr_e
 {
        char *cur_ptr, *cur_end;
        int done;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        int delta;
 
        if (unlikely(txn->flags & (TX_CLDENY | TX_CLTARPIT)))
@@ -7151,7 +7151,7 @@ int apply_filter_to_req_line(struct stream *s, struct channel *req, struct hdr_e
  */
 int apply_filters_to_request(struct stream *s, struct channel *req, struct proxy *px)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct hdr_exp *exp;
 
        for (exp = px->req_exp; exp; exp = exp->next) {
@@ -7207,7 +7207,7 @@ int apply_filters_to_request(struct stream *s, struct channel *req, struct proxy
  * If the server is found, it's assigned to the stream.
  */
 void manage_client_side_appsession(struct stream *s, const char *buf, int len) {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        appsess *asession = NULL;
        char *sessid_temp = NULL;
 
@@ -7359,7 +7359,7 @@ int del_hdr_value(struct buffer *buf, char **from, char *next)
  */
 void manage_client_side_cookies(struct stream *s, struct channel *req)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct session *sess = s->sess;
        int preserve_hdr;
        int cur_idx, old_idx;
@@ -7811,7 +7811,7 @@ int apply_filter_to_resp_headers(struct stream *s, struct channel *rtr, struct h
 {
        char *cur_ptr, *cur_end, *cur_next;
        int cur_idx, old_idx, last_hdr;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct hdr_idx_elem *cur_hdr;
        int delta;
 
@@ -7902,7 +7902,7 @@ int apply_filter_to_sts_line(struct stream *s, struct channel *rtr, struct hdr_e
 {
        char *cur_ptr, *cur_end;
        int done;
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        int delta;
 
 
@@ -7975,7 +7975,7 @@ int apply_filter_to_sts_line(struct stream *s, struct channel *rtr, struct hdr_e
  */
 int apply_filters_to_response(struct stream *s, struct channel *rtr, struct proxy *px)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct hdr_exp *exp;
 
        for (exp = px->rsp_exp; exp; exp = exp->next) {
@@ -8033,7 +8033,7 @@ int apply_filters_to_response(struct stream *s, struct channel *rtr, struct prox
  */
 void manage_server_side_cookies(struct stream *s, struct channel *res)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct session *sess = s->sess;
        struct server *srv;
        int is_cookie2;
@@ -8397,7 +8397,7 @@ void manage_server_side_cookies(struct stream *s, struct channel *res)
  */
 void check_response_for_cacheability(struct stream *s, struct channel *rtr)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        char *p1, *p2;
 
        char *cur_ptr, *cur_end, *cur_next;
@@ -8493,7 +8493,7 @@ void get_srv_from_appsession(struct stream *s, const char *begin, int len)
        int mode = s->be->options2 & PR_O2_AS_M_ANY;
 
        if (s->be->appsession_name == NULL ||
-           (s->txn.meth != HTTP_METH_GET && s->txn.meth != HTTP_METH_POST && s->txn.meth != HTTP_METH_HEAD)) {
+           (s->txn->meth != HTTP_METH_GET && s->txn->meth != HTTP_METH_POST && s->txn->meth != HTTP_METH_HEAD)) {
                return;
        }
 
@@ -8625,7 +8625,7 @@ void http_capture_bad_message(struct error_snapshot *es, struct stream *s,
        es->ev_id = error_snapshot_id++;
        es->b_flags = chn->flags;
        es->s_flags = s->flags;
-       es->t_flags = s->txn.flags;
+       es->t_flags = s->txn->flags;
        es->m_flags = msg->flags;
        es->b_out = chn->buf->o;
        es->b_wrap = chn->buf->data + chn->buf->size - chn->buf->p;
@@ -8789,6 +8789,34 @@ void debug_hdr(const char *dir, struct stream *s, const char *start, const char
        shut_your_big_mouth_gcc(write(1, trash.str, trash.len));
 }
 
+
+/* Allocate a new HTTP transaction for stream <s> unless there is one already.
+ * The hdr_idx is allocated as well. In case of allocation failure, everything
+ * allocated is freed and NULL is returned. Otherwise the new transaction is
+ * assigned to the stream and returned.
+ */
+struct http_txn *http_alloc_txn(struct stream *s)
+{
+       struct http_txn *txn = s->txn;
+
+       if (txn)
+               return txn;
+
+       txn = pool_alloc2(pool2_http_txn);
+       if (!txn)
+               return txn;
+
+       txn->hdr_idx.size = global.tune.max_http_hdr;
+       txn->hdr_idx.v    = pool_alloc2(pool2_hdr_idx);
+       if (!txn->hdr_idx.v) {
+               pool_free2(pool2_http_txn, txn);
+               return NULL;
+       }
+
+       s->txn = txn;
+       return txn;
+}
+
 /*
  * Initialize a new HTTP transaction for stream <s>. It is assumed that all
  * the required fields are properly allocated and that we only need to (re)init
@@ -8796,7 +8824,7 @@ void debug_hdr(const char *dir, struct stream *s, const char *start, const char
  */
 void http_init_txn(struct stream *s)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct proxy *fe = strm_sess(s)->fe;
 
        txn->flags = 0;
@@ -8805,6 +8833,11 @@ void http_init_txn(struct stream *s)
        txn->cookie_first_date = 0;
        txn->cookie_last_date = 0;
 
+       txn->sessid = NULL;
+       txn->srv_cookie = NULL;
+       txn->cli_cookie = NULL;
+       txn->uri = NULL;
+
        txn->req.flags = 0;
        txn->req.sol = txn->req.eol = txn->req.eoh = 0; /* relative to the buffer */
        txn->req.next = 0;
@@ -8833,7 +8866,7 @@ void http_init_txn(struct stream *s)
 /* to be used at the end of a transaction */
 void http_end_txn(struct stream *s)
 {
-       struct http_txn *txn = &s->txn;
+       struct http_txn *txn = s->txn;
        struct proxy *fe = strm_sess(s)->fe;
 
        /* release any possible compression context */
@@ -9876,8 +9909,10 @@ smp_prefetch_http(struct proxy *px, struct stream *s, void *l7, unsigned int opt
        struct http_txn *txn = l7;
        struct http_msg *msg = &txn->req;
 
-       /* Note: hdr_idx.v cannot be NULL in this ACL because the ACL is tagged
-        * as a layer7 ACL, which involves automatic allocation of hdr_idx.
+       /* Note: this function may only be used from places where
+        * http_init_txn() has already been done, and implies that <s>,
+        * <txn>, and <hdr_idx.v> are properly set. An extra check protects
+        * against an eventual mistake in the fetch capability matrix.
         */
 
        if (unlikely(!s || !txn))
@@ -10668,7 +10703,7 @@ smp_fetch_http_first_req(struct proxy *px, struct stream *s, void *l7, unsigned
                          const struct arg *args, struct sample *smp, const char *kw, void *private)
 {
        smp->type = SMP_T_BOOL;
-       smp->data.uint = !(s->txn.flags & TX_NOT_FIRST);
+       smp->data.uint = !(s->txn->flags & TX_NOT_FIRST);
        return 1;
 }
 
@@ -10687,7 +10722,7 @@ smp_fetch_http_auth(struct proxy *px, struct stream *l4, void *l7, unsigned int
                return 0;
 
        smp->type = SMP_T_BOOL;
-       smp->data.uint = check_user(args->data.usr, l4->txn.auth.user, l4->txn.auth.pass);
+       smp->data.uint = check_user(args->data.usr, l4->txn->auth.user, l4->txn->auth.pass);
        return 1;
 }
 
@@ -10709,7 +10744,7 @@ smp_fetch_http_auth_grp(struct proxy *px, struct stream *l4, void *l7, unsigned
         * report that it unconditionally does not match. Otherwise we return
         * a string containing the username.
         */
-       if (!check_user(args->data.usr, l4->txn.auth.user, l4->txn.auth.pass))
+       if (!check_user(args->data.usr, l4->txn->auth.user, l4->txn->auth.pass))
                return 0;
 
        /* pat_match_auth() will need the user list */
@@ -10717,8 +10752,8 @@ smp_fetch_http_auth_grp(struct proxy *px, struct stream *l4, void *l7, unsigned
 
        smp->type = SMP_T_STR;
        smp->flags = SMP_F_CONST;
-       smp->data.str.str = l4->txn.auth.user;
-       smp->data.str.len = strlen(l4->txn.auth.user);
+       smp->data.str.str = l4->txn->auth.user;
+       smp->data.str.len = strlen(l4->txn->auth.user);
 
        return 1;
 }
index e77edc43b1bce2237d679a462a1c93ddd068652d..af61c54dc2fb922a37329827d20a3fa987371b1e 100644 (file)
@@ -1134,7 +1134,7 @@ int tcp_inspect_request(struct stream *s, struct channel *req, int an_bit)
                enum acl_test_res ret = ACL_TEST_PASS;
 
                if (rule->cond) {
-                       ret = acl_exec_cond(rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ | partial);
+                       ret = acl_exec_cond(rule->cond, s->be, s, s->txn, SMP_OPT_DIR_REQ | partial);
                        if (ret == ACL_TEST_MISS)
                                goto missing_data;
 
@@ -1175,7 +1175,7 @@ resume_execution:
                                        continue;
 
                                t = rule->act_prm.trk_ctr.table.t;
-                               key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.trk_ctr.expr, &smp);
+                               key = stktable_fetch_key(t, s->be, s, s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.trk_ctr.expr, &smp);
 
                                if ((smp.flags & SMP_F_MAY_CHANGE) && !(partial & SMP_OPT_FINAL))
                                        goto missing_data; /* key might appear later */
@@ -1193,7 +1193,7 @@ resume_execution:
                                char **cap = s->req_cap;
                                int len;
 
-                               key = sample_fetch_string(s->be, s, &s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.cap.expr);
+                               key = sample_fetch_string(s->be, s, s->txn, SMP_OPT_DIR_REQ | partial, rule->act_prm.cap.expr);
                                if (!key)
                                        continue;
 
@@ -1292,7 +1292,7 @@ int tcp_inspect_response(struct stream *s, struct channel *rep, int an_bit)
                enum acl_test_res ret = ACL_TEST_PASS;
 
                if (rule->cond) {
-                       ret = acl_exec_cond(rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_RES | partial);
+                       ret = acl_exec_cond(rule->cond, s->be, s, s->txn, SMP_OPT_DIR_RES | partial);
                        if (ret == ACL_TEST_MISS) {
                                /* just set the analyser timeout once at the beginning of the response */
                                if (!tick_isset(rep->analyse_exp) && s->be->tcp_rep.inspect_delay)
@@ -1407,7 +1407,7 @@ int tcp_exec_req_rules(struct stream *s)
                                        continue;
 
                                t = rule->act_prm.trk_ctr.table.t;
-                               key = stktable_fetch_key(t, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL);
+                               key = stktable_fetch_key(t, s->be, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->act_prm.trk_ctr.expr, NULL);
 
                                if (key && (ts = stktable_get_entry(t, key)))
                                        stream_track_stkctr(&s->stkctr[tcp_trk_idx(rule->action)], t, ts);
index 9b23db025fd4022eeb87dbd2b6e13402fc40f031..f55aaa48a4807475d994e5379f8b6fd2cc05049a 100644 (file)
@@ -940,39 +940,40 @@ int stream_set_backend(struct stream *s, struct proxy *be)
        if (be->options2 & PR_O2_INDEPSTR)
                s->si[1].flags |= SI_FL_INDEP_STR;
 
-       if (be->options2 & PR_O2_RSPBUG_OK)
-               s->txn.rsp.err_pos = -1; /* let buggy responses pass */
-       s->flags |= SF_BE_ASSIGNED;
-
        /* If the target backend requires HTTP processing, we have to allocate
-        * a struct hdr_idx for it if we did not have one.
+        * the HTTP transaction and hdr_idx if we did not have one.
         */
-       if (unlikely(!s->txn.hdr_idx.v && be->http_needed)) {
-               s->txn.hdr_idx.size = global.tune.max_http_hdr;
-               if ((s->txn.hdr_idx.v = pool_alloc2(pool2_hdr_idx)) == NULL)
+       if (unlikely(!s->txn && be->http_needed)) {
+               if (unlikely(!http_alloc_txn(s)))
                        return 0; /* not enough memory */
 
                /* and now initialize the HTTP transaction state */
                http_init_txn(s);
        }
 
-       /* If we chain to an HTTP backend running a different HTTP mode, we
-        * have to re-adjust the desired keep-alive/close mode to accommodate
-        * both the frontend's and the backend's modes.
-        */
-       if (strm_sess(s)->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP &&
-           ((strm_sess(s)->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE)))
-               http_adjust_conn_mode(s, &s->txn, &s->txn.req);
-
-       /* If an LB algorithm needs to access some pre-parsed body contents,
-        * we must not start to forward anything until the connection is
-        * confirmed otherwise we'll lose the pointer to these data and
-        * prevent the hash from being doable again after a redispatch.
-        */
-       if (be->mode == PR_MODE_HTTP &&
-           (be->lbprm.algo & (BE_LB_KIND | BE_LB_PARM)) == (BE_LB_KIND_HI | BE_LB_HASH_PRM))
-               s->txn.req.flags |= HTTP_MSGF_WAIT_CONN;
+       if (s->txn) {
+               if (be->options2 & PR_O2_RSPBUG_OK)
+                       s->txn->rsp.err_pos = -1; /* let buggy responses pass */
 
+               /* If we chain to an HTTP backend running a different HTTP mode, we
+                * have to re-adjust the desired keep-alive/close mode to accommodate
+                * both the frontend's and the backend's modes.
+                */
+               if (strm_sess(s)->fe->mode == PR_MODE_HTTP && be->mode == PR_MODE_HTTP &&
+                   ((strm_sess(s)->fe->options & PR_O_HTTP_MODE) != (be->options & PR_O_HTTP_MODE)))
+                       http_adjust_conn_mode(s, s->txn, &s->txn->req);
+
+               /* If an LB algorithm needs to access some pre-parsed body contents,
+                * we must not start to forward anything until the connection is
+                * confirmed otherwise we'll lose the pointer to these data and
+                * prevent the hash from being doable again after a redispatch.
+                */
+               if (be->mode == PR_MODE_HTTP &&
+                   (be->lbprm.algo & (BE_LB_KIND | BE_LB_PARM)) == (BE_LB_KIND_HI | BE_LB_HASH_PRM))
+                       s->txn->req.flags |= HTTP_MSGF_WAIT_CONN;
+       }
+
+       s->flags |= SF_BE_ASSIGNED;
        if (be->options2 & PR_O2_NODELAY) {
                s->req.flags |= CF_NEVER_WAIT;
                s->res.flags |= CF_NEVER_WAIT;
index cd0f8bd9e7b324daa9b4c57b2cda2d8ff65ab1fc..f12b2c36a29810eb064f9865463249a05db51317 100644 (file)
@@ -425,7 +425,6 @@ int stream_complete(struct stream *s)
        struct session *sess = s->sess;
        struct listener *l = sess->listener;
        struct proxy *p = sess->fe;
-       struct http_txn *txn;
        struct task *t = s->task;
        struct connection *conn = __objt_conn(s->target);
        int ret;
@@ -531,23 +530,7 @@ int stream_complete(struct stream *s)
        s->res.wex = TICK_ETERNITY;
        s->res.analyse_exp = TICK_ETERNITY;
 
-       txn = &s->txn;
-       /* Those variables will be checked and freed if non-NULL in
-        * stream.c:stream_free(). It is important that they are
-        * properly initialized.
-        */
-       txn->sessid = NULL;
-       txn->srv_cookie = NULL;
-       txn->cli_cookie = NULL;
-       txn->uri = NULL;
-       txn->hdr_idx.v = NULL;
-       txn->hdr_idx.size = txn->hdr_idx.used = 0;
-       txn->flags = 0;
-       txn->req.flags = 0;
-       txn->rsp.flags = 0;
-       /* the HTTP messages need to know what buffer they're associated with */
-       txn->req.chn = &s->req;
-       txn->rsp.chn = &s->res;
+       s->txn = NULL;
 
        HLUA_INIT(&s->hlua);
 
@@ -591,7 +574,6 @@ int stream_complete(struct stream *s)
  */
 static void stream_free(struct stream *s)
 {
-       struct http_txn *txn = &s->txn;
        struct session *sess = strm_sess(s);
        struct proxy *fe = sess->fe;
        struct bref *bref, *back;
@@ -636,7 +618,8 @@ static void stream_free(struct stream *s)
                stream_offer_buffers();
 
        hlua_ctx_destroy(&s->hlua);
-       http_end_txn(s);
+       if (s->txn)
+               http_end_txn(s);
 
        /* ensure the client-side transport layer is destroyed */
        if (cli_conn)
@@ -649,7 +632,12 @@ static void stream_free(struct stream *s)
                s->store[i].ts = NULL;
        }
 
-       pool_free2(pool2_hdr_idx, txn->hdr_idx.v);
+       if (s->txn) {
+               pool_free2(pool2_hdr_idx, s->txn->hdr_idx.v);
+               pool_free2(pool2_http_txn, s->txn);
+               s->txn = NULL;
+       }
+
        if (fe) {
                pool_free2(fe->rsp_cap_pool, s->res_cap);
                pool_free2(fe->req_cap_pool, s->req_cap);
@@ -1080,7 +1068,6 @@ static void sess_establish(struct stream *s)
                }
        }
        else {
-               s->txn.rsp.msg_state = HTTP_MSG_RPBEFORE;
                rep->flags |= CF_READ_DONTWAIT; /* a single read is enough to get response headers */
        }
 
@@ -1404,7 +1391,7 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
                        int ret = 1;
 
                        if (rule->cond) {
-                               ret = acl_exec_cond(rule->cond, fe, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                               ret = acl_exec_cond(rule->cond, fe, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
                                ret = acl_pass(ret);
                                if (rule->cond->pol == ACL_COND_UNLESS)
                                        ret = !ret;
@@ -1457,7 +1444,7 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
                int ret = 1;
 
                if (prst_rule->cond) {
-                       ret = acl_exec_cond(prst_rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                       ret = acl_exec_cond(prst_rule->cond, s->be, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
                        ret = acl_pass(ret);
                        if (prst_rule->cond->pol == ACL_COND_UNLESS)
                                ret = !ret;
@@ -1486,7 +1473,8 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
        if (!(s->flags & SF_FINST_MASK))
                s->flags |= SF_FINST_R;
 
-       s->txn.status = 500;
+       if (s->txn)
+               s->txn->status = 500;
        s->req.analysers = 0;
        s->req.analyse_exp = TICK_ETERNITY;
        return 0;
@@ -1514,7 +1502,7 @@ static int process_server_rules(struct stream *s, struct channel *req, int an_bi
                list_for_each_entry(rule, &px->server_rules, list) {
                        int ret;
 
-                       ret = acl_exec_cond(rule->cond, s->be, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                       ret = acl_exec_cond(rule->cond, s->be, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
                        ret = acl_pass(ret);
                        if (rule->cond->pol == ACL_COND_UNLESS)
                                ret = !ret;
@@ -1579,7 +1567,7 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_
                        continue;
 
                if (rule->cond) {
-                       ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
+                       ret = acl_exec_cond(rule->cond, px, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL);
                        ret = acl_pass(ret);
                        if (rule->cond->pol == ACL_COND_UNLESS)
                                ret = !ret;
@@ -1588,7 +1576,7 @@ static int process_sticking_rules(struct stream *s, struct channel *req, int an_
                if (ret) {
                        struct stktable_key *key;
 
-                       key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL);
+                       key = stktable_fetch_key(rule->table.t, px, s, s->txn, SMP_OPT_DIR_REQ|SMP_OPT_FINAL, rule->expr, NULL);
                        if (!key)
                                continue;
 
@@ -1682,7 +1670,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
                        continue;
 
                if (rule->cond) {
-                       ret = acl_exec_cond(rule->cond, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
+                       ret = acl_exec_cond(rule->cond, px, s, s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL);
                        ret = acl_pass(ret);
                        if (rule->cond->pol == ACL_COND_UNLESS)
                                ret = !ret;
@@ -1691,7 +1679,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
                if (ret) {
                        struct stktable_key *key;
 
-                       key = stktable_fetch_key(rule->table.t, px, s, &s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL);
+                       key = stktable_fetch_key(rule->table.t, px, s, s->txn, SMP_OPT_DIR_RES|SMP_OPT_FINAL, rule->expr, NULL);
                        if (!key)
                                continue;
 
@@ -1780,7 +1768,8 @@ struct task *process_stream(struct task *t)
        //        si_f->state, si_b->state, si_b->err_type, req->flags, res->flags);
 
        /* this data may be no longer valid, clear it */
-       memset(&s->txn.auth, 0, sizeof(s->txn.auth));
+       if (s->txn)
+               memset(&s->txn->auth, 0, sizeof(s->txn->auth));
 
        /* This flag must explicitly be set every time */
        req->flags &= ~(CF_READ_NOEXP|CF_WAKE_WRITE);
@@ -2445,7 +2434,7 @@ struct task *process_stream(struct task *t)
                            (s->be->server_id_hdr_name != NULL) &&
                            (s->be->mode == PR_MODE_HTTP) &&
                            objt_server(s->target)) {
-                               http_send_name_header(&s->txn, s->be, objt_server(s->target)->id);
+                               http_send_name_header(s->txn, s->be, objt_server(s->target)->id);
                        }
 
                        srv = objt_server(s->target);
@@ -2722,10 +2711,10 @@ struct task *process_stream(struct task *t)
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
        stream_process_counters(s);
 
-       if (s->txn.status) {
+       if (s->txn && s->txn->status) {
                int n;
 
-               n = s->txn.status / 100;
+               n = s->txn->status / 100;
                if (n < 1 || n > 5)
                        n = 0;