From: Christopher Faulet Date: Mon, 8 Mar 2021 18:12:58 +0000 (+0100) Subject: MINOR: http-ana: Simplify creation/destruction of HTTP transactions X-Git-Tag: v2.4-dev15~47 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75f619ad922a53296fc958299550c6fed4a60055;p=thirdparty%2Fhaproxy.git MINOR: http-ana: Simplify creation/destruction of HTTP transactions Now allocation and initialization of HTTP transactions are performed in a unique function. Historically, there were two functions because the same TXN was reset for K/A connections in the legacy HTTP mode. Now, in HTX, K/A connections are handled at the mux level. A new stream, and thus a new TXN, is created for each request. In addition, the function responsible to end the TXN is now also reponsible to release it. So, now, http_create_txn() and http_destroy_txn() must be used to create and destroy an HTTP transaction. --- diff --git a/include/haproxy/http_ana.h b/include/haproxy/http_ana.h index ce28a7cdc3..d34fa56360 100644 --- a/include/haproxy/http_ana.h +++ b/include/haproxy/http_ana.h @@ -57,9 +57,8 @@ int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *repl int http_reply_message(struct stream *s, struct http_reply *reply); int http_forward_proxy_resp(struct stream *s, int final); -struct http_txn *http_alloc_txn(struct stream *s); -void http_init_txn(struct stream *s); -void http_end_txn(struct stream *s); +struct http_txn *http_create_txn(struct stream *s); +void http_destroy_txn(struct stream *s); /* for debugging, reports the HTTP/1 message state name (legacy version) */ static inline const char *h1_msg_state_str(enum h1_state msg_state) diff --git a/src/frontend.c b/src/frontend.c index 93c8a86377..a8ed2c4884 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -145,17 +145,8 @@ int frontend_accept(struct stream *s) goto out_free_reqcap; /* no memory */ } - if (fe->http_needed || IS_HTX_STRM(s)) { - /* we have to allocate header indexes only if we know - * that we may make use of them. This of course includes - * (mode == PR_MODE_HTTP). - */ - if (unlikely(!http_alloc_txn(s))) - goto out_free_rspcap; /* no memory */ - - /* and now initialize the HTTP transaction state */ - http_init_txn(s); - } + if ((fe->http_needed || IS_HTX_STRM(s)) && !http_create_txn(s)) + goto out_free_rspcap; /* everything's OK, let's go on */ return 1; diff --git a/src/http_ana.c b/src/http_ana.c index b0067c307a..51445e996b 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -5044,15 +5044,20 @@ void http_txn_reset_res(struct http_txn *txn) } /* - * 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. + * Create and initialize a new HTTP transaction for stream . This should be + * used before processing any new request. It returns the transaction or NLULL + * on error. */ -void http_init_txn(struct stream *s) +struct http_txn *http_create_txn(struct stream *s) { - struct http_txn *txn = s->txn; + struct http_txn *txn; struct conn_stream *cs = objt_cs(s->si[0].end); + txn = pool_alloc(pool_head_http_txn); + if (!txn) + return NULL; + s->txn = txn; + txn->flags = ((cs && cs->flags & CS_FL_NOT_FIRST) ? TX_NOT_FIRST : 0); txn->status = -1; txn->http_reply = NULL; @@ -5075,10 +5080,12 @@ void http_init_txn(struct stream *s) vars_init(&s->vars_txn, SCOPE_TXN); vars_init(&s->vars_reqres, SCOPE_REQ); + + return txn; } /* to be used at the end of a transaction */ -void http_end_txn(struct stream *s) +void http_destroy_txn(struct stream *s) { struct http_txn *txn = s->txn; @@ -5097,6 +5104,9 @@ void http_end_txn(struct stream *s) vars_prune(&s->vars_txn, s->sess, s); if (!LIST_ISEMPTY(&s->vars_reqres.head)) vars_prune(&s->vars_reqres, s->sess, s); + + pool_free(pool_head_http_txn, txn); + s->txn = NULL; } diff --git a/src/http_fetch.c b/src/http_fetch.c index 6c569a75bb..a4db061c16 100644 --- a/src/http_fetch.c +++ b/src/http_fetch.c @@ -208,12 +208,8 @@ struct htx *smp_prefetch_htx(struct sample *smp, struct channel *chn, struct che return NULL; } - if (!s->txn) { - if (unlikely(!http_alloc_txn(s))) - return NULL; /* not enough memory */ - http_init_txn(s); - txn = s->txn; - } + if (!s->txn && !http_create_txn(s)) + return NULL; txn = s->txn; msg = (!(chn->flags & CF_ISRESP) ? &txn->req : &txn->rsp); diff --git a/src/proxy.c b/src/proxy.c index d044150c07..cd7ba512e9 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -2145,13 +2145,8 @@ int stream_set_backend(struct stream *s, struct proxy *be) /* If the target backend requires HTTP processing, we have to allocate * the HTTP transaction if we did not have one. */ - 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 (unlikely(!s->txn && be->http_needed && !http_create_txn(s))) + return 0; if (s->txn) { /* If we chain a TCP frontend to an HTX backend, we must upgrade diff --git a/src/stream.c b/src/stream.c index eb64807743..8b8e26da14 100644 --- a/src/stream.c +++ b/src/stream.c @@ -658,7 +658,7 @@ static void stream_free(struct stream *s) hlua_ctx_destroy(s->hlua); s->hlua = NULL; if (s->txn) - http_end_txn(s); + http_destroy_txn(s); /* ensure the client-side transport layer is destroyed */ if (cli_cs) @@ -671,11 +671,6 @@ static void stream_free(struct stream *s) s->store[i].ts = NULL; } - if (s->txn) { - pool_free(pool_head_http_txn, s->txn); - s->txn = NULL; - } - if (s->resolv_ctx.requester) { __decl_thread(struct resolvers *resolvers = s->resolv_ctx.parent->arg.resolv.resolvers);