diff --git a/src/proto_http.c b/src/proto_http.c index f7b09db04..1b4e0aafc 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -74,168 +74,6 @@ #include #include -DECLARE_POOL(pool_head_http_txn, "http_txn", sizeof(struct http_txn)); -DECLARE_POOL(pool_head_uniqueid, "uniqueid", UNIQUEID_LEN); - -struct pool_head *pool_head_requri = NULL; -struct pool_head *pool_head_capture = NULL; - - -/* Allocate a new HTTP transaction for stream unless there is one already. - * 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_alloc(pool_head_http_txn); - if (!txn) - return txn; - - s->txn = txn; - return txn; -} - -void http_txn_reset_req(struct http_txn *txn) -{ - txn->req.flags = 0; - txn->req.msg_state = HTTP_MSG_RQBEFORE; /* at the very beginning of the request */ -} - -void http_txn_reset_res(struct http_txn *txn) -{ - txn->rsp.flags = 0; - txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */ -} - -/* - * Initialize a new HTTP transaction for stream . It is assumed that all - * the required fields are properly allocated and that we only need to (re)init - * them. This should be used before processing any new request. - */ -void http_init_txn(struct stream *s) -{ - struct http_txn *txn = s->txn; - struct conn_stream *cs = objt_cs(s->si[0].end); - - txn->flags = ((cs && cs->flags & CS_FL_NOT_FIRST) - ? (TX_NOT_FIRST|TX_WAIT_NEXT_RQ) - : 0); - txn->status = -1; - *(unsigned int *)txn->cache_hash = 0; - - txn->cookie_first_date = 0; - txn->cookie_last_date = 0; - - txn->srv_cookie = NULL; - txn->cli_cookie = NULL; - txn->uri = NULL; - - http_txn_reset_req(txn); - http_txn_reset_res(txn); - - txn->req.chn = &s->req; - txn->rsp.chn = &s->res; - - txn->auth.method = HTTP_AUTH_UNKNOWN; - - vars_init(&s->vars_txn, SCOPE_TXN); - vars_init(&s->vars_reqres, SCOPE_REQ); -} - -/* to be used at the end of a transaction */ -void http_end_txn(struct stream *s) -{ - struct http_txn *txn = s->txn; - struct proxy *fe = strm_fe(s); - - /* these ones will have been dynamically allocated */ - pool_free(pool_head_requri, txn->uri); - pool_free(pool_head_capture, txn->cli_cookie); - pool_free(pool_head_capture, txn->srv_cookie); - pool_free(pool_head_uniqueid, s->unique_id); - - s->unique_id = NULL; - txn->uri = NULL; - txn->srv_cookie = NULL; - txn->cli_cookie = NULL; - - if (s->req_cap) { - struct cap_hdr *h; - for (h = fe->req_cap; h; h = h->next) - pool_free(h->pool, s->req_cap[h->index]); - memset(s->req_cap, 0, fe->nb_req_cap * sizeof(void *)); - } - - if (s->res_cap) { - struct cap_hdr *h; - for (h = fe->rsp_cap; h; h = h->next) - pool_free(h->pool, s->res_cap[h->index]); - memset(s->res_cap, 0, fe->nb_rsp_cap * sizeof(void *)); - } - - if (!LIST_ISEMPTY(&s->vars_txn.head)) - vars_prune(&s->vars_txn, s->sess, s); - if (!LIST_ISEMPTY(&s->vars_reqres.head)) - vars_prune(&s->vars_reqres, s->sess, s); -} - -/* to be used at the end of a transaction to prepare a new one */ -void http_reset_txn(struct stream *s) -{ - http_end_txn(s); - http_init_txn(s); - - /* reinitialise the current rule list pointer to NULL. We are sure that - * any rulelist match the NULL pointer. - */ - s->current_rule_list = NULL; - - s->be = strm_fe(s); - s->logs.logwait = strm_fe(s)->to_log; - s->logs.level = 0; - stream_del_srv_conn(s); - s->target = NULL; - /* re-init store persistence */ - s->store_count = 0; - s->uniq_id = _HA_ATOMIC_XADD(&global.req_count, 1); - - s->req.flags |= CF_READ_DONTWAIT; /* one read is usually enough */ - - /* We must trim any excess data from the response buffer, because we - * may have blocked an invalid response from a server that we don't - * want to accidently forward once we disable the analysers, nor do - * we want those data to come along with next response. A typical - * example of such data would be from a buggy server responding to - * a HEAD with some data, or sending more than the advertised - * content-length. - */ - if (unlikely(ci_data(&s->res))) - b_set_data(&s->res.buf, co_data(&s->res)); - - /* Now we can realign the response buffer */ - c_realign_if_empty(&s->res); - - s->req.rto = strm_fe(s)->timeout.client; - s->req.wto = TICK_ETERNITY; - - s->res.rto = TICK_ETERNITY; - s->res.wto = strm_fe(s)->timeout.client; - - s->req.rex = TICK_ETERNITY; - s->req.wex = TICK_ETERNITY; - s->req.analyse_exp = TICK_ETERNITY; - s->res.rex = TICK_ETERNITY; - s->res.wex = TICK_ETERNITY; - s->res.analyse_exp = TICK_ETERNITY; - s->si[1].hcto = TICK_ETERNITY; -} - /* * Local variables: * c-indent-level: 8 diff --git a/src/proto_htx.c b/src/proto_htx.c index 88be56e52..a63efffa0 100644 --- a/src/proto_htx.c +++ b/src/proto_htx.c @@ -33,9 +33,14 @@ #include #include #include +#include extern const char *stat_status_codes[]; +struct pool_head *pool_head_requri = NULL; +struct pool_head *pool_head_capture = NULL; + + static void htx_end_request(struct stream *s); static void htx_end_response(struct stream *s); @@ -5790,6 +5795,164 @@ static void htx_debug_hdr(const char *dir, struct stream *s, const struct ist n, shut_your_big_mouth_gcc(write(1, trash.area, trash.data)); } +/* Allocate a new HTTP transaction for stream unless there is one already. + * 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_alloc(pool_head_http_txn); + if (!txn) + return txn; + + s->txn = txn; + return txn; +} + +void http_txn_reset_req(struct http_txn *txn) +{ + txn->req.flags = 0; + txn->req.msg_state = HTTP_MSG_RQBEFORE; /* at the very beginning of the request */ +} + +void http_txn_reset_res(struct http_txn *txn) +{ + txn->rsp.flags = 0; + txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */ +} + +/* + * Initialize a new HTTP transaction for stream . It is assumed that all + * the required fields are properly allocated and that we only need to (re)init + * them. This should be used before processing any new request. + */ +void http_init_txn(struct stream *s) +{ + struct http_txn *txn = s->txn; + struct conn_stream *cs = objt_cs(s->si[0].end); + + txn->flags = ((cs && cs->flags & CS_FL_NOT_FIRST) + ? (TX_NOT_FIRST|TX_WAIT_NEXT_RQ) + : 0); + txn->status = -1; + *(unsigned int *)txn->cache_hash = 0; + + txn->cookie_first_date = 0; + txn->cookie_last_date = 0; + + txn->srv_cookie = NULL; + txn->cli_cookie = NULL; + txn->uri = NULL; + + http_txn_reset_req(txn); + http_txn_reset_res(txn); + + txn->req.chn = &s->req; + txn->rsp.chn = &s->res; + + txn->auth.method = HTTP_AUTH_UNKNOWN; + + vars_init(&s->vars_txn, SCOPE_TXN); + vars_init(&s->vars_reqres, SCOPE_REQ); +} + +/* to be used at the end of a transaction */ +void http_end_txn(struct stream *s) +{ + struct http_txn *txn = s->txn; + struct proxy *fe = strm_fe(s); + + /* these ones will have been dynamically allocated */ + pool_free(pool_head_requri, txn->uri); + pool_free(pool_head_capture, txn->cli_cookie); + pool_free(pool_head_capture, txn->srv_cookie); + pool_free(pool_head_uniqueid, s->unique_id); + + s->unique_id = NULL; + txn->uri = NULL; + txn->srv_cookie = NULL; + txn->cli_cookie = NULL; + + if (s->req_cap) { + struct cap_hdr *h; + for (h = fe->req_cap; h; h = h->next) + pool_free(h->pool, s->req_cap[h->index]); + memset(s->req_cap, 0, fe->nb_req_cap * sizeof(void *)); + } + + if (s->res_cap) { + struct cap_hdr *h; + for (h = fe->rsp_cap; h; h = h->next) + pool_free(h->pool, s->res_cap[h->index]); + memset(s->res_cap, 0, fe->nb_rsp_cap * sizeof(void *)); + } + + if (!LIST_ISEMPTY(&s->vars_txn.head)) + vars_prune(&s->vars_txn, s->sess, s); + if (!LIST_ISEMPTY(&s->vars_reqres.head)) + vars_prune(&s->vars_reqres, s->sess, s); +} + +/* to be used at the end of a transaction to prepare a new one */ +void http_reset_txn(struct stream *s) +{ + http_end_txn(s); + http_init_txn(s); + + /* reinitialise the current rule list pointer to NULL. We are sure that + * any rulelist match the NULL pointer. + */ + s->current_rule_list = NULL; + + s->be = strm_fe(s); + s->logs.logwait = strm_fe(s)->to_log; + s->logs.level = 0; + stream_del_srv_conn(s); + s->target = NULL; + /* re-init store persistence */ + s->store_count = 0; + s->uniq_id = _HA_ATOMIC_XADD(&global.req_count, 1); + + s->req.flags |= CF_READ_DONTWAIT; /* one read is usually enough */ + + /* We must trim any excess data from the response buffer, because we + * may have blocked an invalid response from a server that we don't + * want to accidently forward once we disable the analysers, nor do + * we want those data to come along with next response. A typical + * example of such data would be from a buggy server responding to + * a HEAD with some data, or sending more than the advertised + * content-length. + */ + if (unlikely(ci_data(&s->res))) + b_set_data(&s->res.buf, co_data(&s->res)); + + /* Now we can realign the response buffer */ + c_realign_if_empty(&s->res); + + s->req.rto = strm_fe(s)->timeout.client; + s->req.wto = TICK_ETERNITY; + + s->res.rto = TICK_ETERNITY; + s->res.wto = strm_fe(s)->timeout.client; + + s->req.rex = TICK_ETERNITY; + s->req.wex = TICK_ETERNITY; + s->req.analyse_exp = TICK_ETERNITY; + s->res.rex = TICK_ETERNITY; + s->res.wex = TICK_ETERNITY; + s->res.analyse_exp = TICK_ETERNITY; + s->si[1].hcto = TICK_ETERNITY; +} + + +DECLARE_POOL(pool_head_http_txn, "http_txn", sizeof(struct http_txn)); +DECLARE_POOL(pool_head_uniqueid, "uniqueid", UNIQUEID_LEN); __attribute__((constructor)) static void __htx_protocol_init(void)