From 0937bc43cffb616b890aa86dee47bf9517e6cdd8 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 22 Dec 2009 15:03:09 +0100 Subject: [PATCH] [MINOR] http: move the http transaction init/cleanup code to proto_http This code really belongs to the http part since it's transaction-specific. This will also make it easier to later reinitialize a transaction in order to support keepalive. --- include/proto/proto_http.h | 4 ++ src/client.c | 35 ++++------------ src/proto_http.c | 81 ++++++++++++++++++++++++++++++++++++++ src/session.c | 5 +-- 4 files changed, 94 insertions(+), 31 deletions(-) diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index d5a7306bc..50d595792 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -91,6 +91,10 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s, struct buffer *buf, struct http_msg *msg, struct proxy *other_end); +void http_init_txn(struct session *s); +void http_end_txn(struct session *s); +void http_reset_txn(struct session *s); + /* to be used when contents change in an HTTP message */ #define http_msg_move_end(msg, bytes) do { \ unsigned int _bytes = (bytes); \ diff --git a/src/client.c b/src/client.c index 492cae706..866fc871e 100644 --- a/src/client.c +++ b/src/client.c @@ -259,7 +259,6 @@ int event_accept(int fd) { proxy_inc_fe_ctr(l, p); /* note: cum_beconn will be increased once assigned */ txn = &s->txn; - txn->flags = 0; /* Those variables will be checked and freed if non-NULL in * session.c:session_free(). It is important that they are * properly initialized. @@ -272,36 +271,15 @@ int event_accept(int fd) { txn->hdr_idx.v = NULL; txn->hdr_idx.size = txn->hdr_idx.used = 0; - /* we always initialize the HTTP structure because we may use it later */ - txn->status = -1; - txn->req.hdr_content_len = 0LL; - txn->rsp.hdr_content_len = 0LL; - txn->req.msg_state = HTTP_MSG_RQBEFORE; /* at the very beginning of the request */ - txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */ - txn->req.sol = txn->req.eol = NULL; - txn->req.som = txn->req.eoh = 0; /* relative to the buffer */ - txn->rsp.sol = txn->rsp.eol = NULL; - txn->rsp.som = txn->rsp.eoh = 0; /* relative to the buffer */ - txn->req.err_pos = txn->rsp.err_pos = -2; /* block buggy requests/responses */ - chunk_reset(&txn->auth_hdr); - if (p->options2 & PR_O2_REQBUG_OK) - txn->req.err_pos = -1; /* let buggy requests pass */ - if (p->mode == PR_MODE_HTTP) { /* the captures are only used in HTTP frontends */ - if (p->nb_req_cap > 0) { - if ((txn->req.cap = pool_alloc2(p->req_cap_pool)) == NULL) + if (p->nb_req_cap > 0 && + (txn->req.cap = pool_alloc2(p->req_cap_pool)) == NULL) goto out_fail_reqcap; /* no memory */ - memset(txn->req.cap, 0, p->nb_req_cap*sizeof(char *)); - } - - if (p->nb_rsp_cap > 0) { - if ((txn->rsp.cap = pool_alloc2(p->rsp_cap_pool)) == NULL) + if (p->nb_rsp_cap > 0 && + (txn->rsp.cap = pool_alloc2(p->rsp_cap_pool)) == NULL) goto out_fail_rspcap; /* no memory */ - - memset(txn->rsp.cap, 0, p->nb_rsp_cap*sizeof(char *)); - } } if (p->acl_requires & ACL_USE_L7_ANY) { @@ -313,10 +291,11 @@ int event_accept(int fd) { if ((txn->hdr_idx.v = pool_alloc2(p->hdr_idx_pool)) == NULL) goto out_fail_idx; /* no memory */ - - hdr_idx_init(&txn->hdr_idx); } + if (p->mode == PR_MODE_HTTP) + http_init_txn(s); + if ((p->mode == PR_MODE_TCP || p->mode == PR_MODE_HTTP) && (p->logfac1 >= 0 || p->logfac2 >= 0)) { if (p->to_log) { diff --git a/src/proto_http.c b/src/proto_http.c index f61bfe6b2..c5bfc45ce 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -5018,6 +5018,87 @@ void debug_hdr(const char *dir, struct session *t, const char *start, const char write(1, trash, len); } +/* + * Initialize a new HTTP transaction for session . 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 session *s) +{ + struct http_txn *txn = &s->txn; + struct proxy *fe = s->fe; + + txn->flags = 0; + txn->status = -1; + + txn->req.sol = txn->req.eol = NULL; + txn->req.som = txn->req.eoh = 0; /* relative to the buffer */ + txn->rsp.sol = txn->rsp.eol = NULL; + txn->rsp.som = txn->rsp.eoh = 0; /* relative to the buffer */ + txn->req.hdr_content_len = 0LL; + txn->rsp.hdr_content_len = 0LL; + txn->req.msg_state = HTTP_MSG_RQBEFORE; /* at the very beginning of the request */ + txn->rsp.msg_state = HTTP_MSG_RPBEFORE; /* at the very beginning of the response */ + chunk_reset(&txn->auth_hdr); + + txn->req.err_pos = txn->rsp.err_pos = -2; /* block buggy requests/responses */ + if (fe->options2 & PR_O2_REQBUG_OK) + txn->req.err_pos = -1; /* let buggy requests pass */ + + if (txn->req.cap) + memset(txn->req.cap, 0, fe->nb_req_cap * sizeof(void *)); + + if (txn->rsp.cap) + memset(txn->rsp.cap, 0, fe->nb_rsp_cap * sizeof(void *)); + + if (txn->hdr_idx.v) + hdr_idx_init(&txn->hdr_idx); +} + +/* to be used at the end of a transaction */ +void http_end_txn(struct session *s) +{ + struct http_txn *txn = &s->txn; + + /* these ones will have been dynamically allocated */ + pool_free2(pool2_requri, txn->uri); + pool_free2(pool2_capture, txn->cli_cookie); + pool_free2(pool2_capture, txn->srv_cookie); + txn->uri = NULL; + txn->srv_cookie = NULL; + txn->cli_cookie = NULL; +} + +/* to be used at the end of a transaction to prepare a new one */ +void http_reset_txn(struct session *s) +{ + http_end_txn(s); + http_init_txn(s); + + s->be = s->fe; + s->req->analysers = s->listener->analysers; + s->logs.logwait = s->fe->to_log; + s->srv = s->prev_srv = s->srv_conn = NULL; + s->pend_pos = NULL; + s->conn_retries = s->be->conn_retries; + + s->req->flags |= BF_READ_DONTWAIT; /* one read is usually enough */ + + s->req->rto = s->fe->timeout.client; + s->req->wto = s->be->timeout.server; + s->req->cto = s->be->timeout.connect; + + s->rep->rto = s->be->timeout.server; + s->rep->wto = s->fe->timeout.client; + s->rep->cto = TICK_ETERNITY; + + s->req->rex = TICK_ETERNITY; + s->req->wex = TICK_ETERNITY; + s->req->analyse_exp = TICK_ETERNITY; + s->rep->rex = TICK_ETERNITY; + s->rep->wex = TICK_ETERNITY; + s->rep->analyse_exp = TICK_ETERNITY; +} /************************************************************************/ /* The code below is dedicated to ACL parsing and matching */ diff --git a/src/session.c b/src/session.c index b86526ac8..d310a4875 100644 --- a/src/session.c +++ b/src/session.c @@ -97,9 +97,8 @@ void session_free(struct session *s) pool_free2(fe->req_cap_pool, txn->req.cap); } } - pool_free2(pool2_requri, txn->uri); - pool_free2(pool2_capture, txn->cli_cookie); - pool_free2(pool2_capture, txn->srv_cookie); + + http_end_txn(s); list_for_each_entry_safe(bref, back, &s->back_refs, users) { /* we have to unlink all watchers. We must not relink them if