mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-17 02:56:51 +00:00
BUG/MAJOR: channel: Fix the definition order of channel analyzers
It is important to defined analyzers (AN_REQ_* and AN_RES_*) in the same order they are evaluated in process_stream. This order is really important because during analyzers evaluation, we run them in the order of the lower bit to the higher one. This way, when an analyzer adds/removes another one during its evaluation, we know if it is located before or after it. So, when it adds an analyzer which is located before it, we can switch to it immediately, even if it has already been called once but removed since. With the time, and introduction of new analyzers, this order was broken up. the main problems come from the filter analyzers. We used values not related with their evaluation order. Furthermore, we used same values for request and response analyzers. So, to fix the bug, filter analyzers have been splitted in 2 distinct lists to have different analyzers for the request channel than those for the response channel. And of course, we have moved them to the right place. Some other analyzers have been reordered to respect the evaluation order: * AN_REQ_HTTP_TARPIT has been moved just before AN_REQ_SRV_RULES * AN_REQ_PRST_RDP_COOKIE has been moved just before AN_REQ_STICKING_RULES * AN_RES_STORE_RULES has been moved just after AN_RES_WAIT_HTTP Note today we have 29 analyzers, all stored into a 32 bits bitfield. So we can still add 4 more analyzers before having a problem. A good way to fend off the problem for a while could be to have a different bitfield for request and response analyzers. [wt: all of this must be backported to 1.7, and part of it must be backported to 1.6 and 1.5]
This commit is contained in:
parent
401c64bfe4
commit
0184ea71a6
@ -760,13 +760,13 @@ are listed in 'include/types/channels.h'. Here is an example:
|
||||
To surround activity of a filter during the channel analyzing, two new analyzers
|
||||
has been added:
|
||||
|
||||
* 'flt_start_analyze' (AN_FLT_START_FE/AN_FLT_START_BE): For a specific
|
||||
filter, this analyzer is called before any call to the 'channel_analyze'
|
||||
callback. From the filter point of view, it calls the
|
||||
* 'flt_start_analyze' (AN_REQ/RES_FLT_START_FE/AN_REQ_RES_FLT_START_BE): For
|
||||
a specific filter, this analyzer is called before any call to the
|
||||
'channel_analyze' callback. From the filter point of view, it calls the
|
||||
'flt_ops.channel_start_analyze' callback.
|
||||
|
||||
* 'flt_end_analyze' (AN_FLT_END): For a specific filter, this analyzer is
|
||||
called when all other analyzers have finished their processing. From the
|
||||
* 'flt_end_analyze' (AN_REQ/RES_FLT_END): For a specific filter, this analyzer
|
||||
is called when all other analyzers have finished their processing. From the
|
||||
filter point of view, it calls the 'flt_ops.channel_end_analyze' callback.
|
||||
|
||||
For TCP streams, these analyzers are called only once. For HTTP streams, if the
|
||||
|
@ -133,39 +133,51 @@
|
||||
* The field is blanked by channel_init() and only by analysers themselves
|
||||
* afterwards.
|
||||
*/
|
||||
/* unused: 0x00000001 */
|
||||
/* AN_REQ_FLT_START_FE: 0x00000001 */
|
||||
#define AN_REQ_INSPECT_FE 0x00000002 /* inspect request contents in the frontend */
|
||||
#define AN_REQ_WAIT_HTTP 0x00000004 /* wait for an HTTP request */
|
||||
#define AN_REQ_HTTP_BODY 0x00000008 /* wait for HTTP request body */
|
||||
#define AN_REQ_HTTP_PROCESS_FE 0x00000010 /* process the frontend's HTTP part */
|
||||
#define AN_REQ_SWITCHING_RULES 0x00000020 /* apply the switching rules */
|
||||
#define AN_REQ_INSPECT_BE 0x00000040 /* inspect request contents in the backend */
|
||||
#define AN_REQ_HTTP_PROCESS_BE 0x00000080 /* process the backend's HTTP part */
|
||||
#define AN_REQ_SRV_RULES 0x00000100 /* use-server rules */
|
||||
#define AN_REQ_HTTP_INNER 0x00000200 /* inner processing of HTTP request */
|
||||
#define AN_REQ_HTTP_TARPIT 0x00000400 /* wait for end of HTTP tarpit */
|
||||
#define AN_REQ_STICKING_RULES 0x00000800 /* table persistence matching */
|
||||
/* AN_REQ_FLT_START_BE: 0x00000040 */
|
||||
#define AN_REQ_INSPECT_BE 0x00000080 /* inspect request contents in the backend */
|
||||
#define AN_REQ_HTTP_PROCESS_BE 0x00000100 /* process the backend's HTTP part */
|
||||
#define AN_REQ_HTTP_TARPIT 0x00000200 /* wait for end of HTTP tarpit */
|
||||
#define AN_REQ_SRV_RULES 0x00000400 /* use-server rules */
|
||||
#define AN_REQ_HTTP_INNER 0x00000800 /* inner processing of HTTP request */
|
||||
#define AN_REQ_PRST_RDP_COOKIE 0x00001000 /* persistence on rdp cookie */
|
||||
#define AN_REQ_HTTP_XFER_BODY 0x00002000 /* forward request body */
|
||||
#define AN_REQ_ALL 0x00003ffe /* all of the request analysers */
|
||||
#define AN_REQ_STICKING_RULES 0x00002000 /* table persistence matching */
|
||||
/* AN_REQ_FLT_HTTP_HDRS: 0x00004000 */
|
||||
#define AN_REQ_HTTP_XFER_BODY 0x00008000 /* forward request body */
|
||||
/* AN_REQ_FLT_XFER_DATA: 0x00010000 */
|
||||
/* AN_REQ_FLT_END: 0x00020000 */
|
||||
#define AN_REQ_ALL 0x0000bfbe /* all of the request analysers */
|
||||
|
||||
/* response analysers */
|
||||
#define AN_RES_INSPECT 0x00010000 /* content inspection */
|
||||
#define AN_RES_WAIT_HTTP 0x00020000 /* wait for HTTP response */
|
||||
#define AN_RES_HTTP_PROCESS_BE 0x00040000 /* process backend's HTTP part */
|
||||
#define AN_RES_HTTP_PROCESS_FE 0x00040000 /* process frontend's HTTP part (same for now) */
|
||||
#define AN_RES_STORE_RULES 0x00080000 /* table persistence matching */
|
||||
#define AN_RES_HTTP_XFER_BODY 0x00100000 /* forward response body */
|
||||
#define AN_RES_ALL 0x001f0000 /* all of the response analysers */
|
||||
/* AN_RES_FLT_START_FE: 0x00040000 */
|
||||
/* AN_RES_FLT_START_BE: 0x00080000 */
|
||||
#define AN_RES_INSPECT 0x00100000 /* content inspection */
|
||||
#define AN_RES_WAIT_HTTP 0x00200000 /* wait for HTTP response */
|
||||
#define AN_RES_STORE_RULES 0x00400000 /* table persistence matching */
|
||||
#define AN_RES_HTTP_PROCESS_BE 0x00800000 /* process backend's HTTP part */
|
||||
#define AN_RES_HTTP_PROCESS_FE 0x00800000 /* process frontend's HTTP part (same for now) */
|
||||
/* AN_RES_FLT_HTTP_HDRS: 0x01000000 */
|
||||
#define AN_RES_HTTP_XFER_BODY 0x02000000 /* forward response body */
|
||||
/* AN_RES_FLT_XFER_DATA: 0x04000000 */
|
||||
/* AN_RES_FLT_END: 0x08000000 */
|
||||
#define AN_RES_ALL 0x02f00000 /* all of the response analysers */
|
||||
|
||||
#define AN_FLT_START_FE 0x01000000
|
||||
#define AN_FLT_START_BE 0x02000000
|
||||
#define AN_FLT_END 0x04000000
|
||||
#define AN_FLT_XFER_DATA 0x08000000
|
||||
#define AN_FLT_HTTP_HDRS 0x10000000
|
||||
#define AN_REQ_FLT_START_FE 0x00000001
|
||||
#define AN_REQ_FLT_START_BE 0x00000040
|
||||
#define AN_REQ_FLT_HTTP_HDRS 0x00004000
|
||||
#define AN_REQ_FLT_XFER_DATA 0x00010000
|
||||
#define AN_REQ_FLT_END 0x00020000
|
||||
|
||||
#define AN_FLT_ALL_FE 0x0d000000
|
||||
#define AN_FLT_ALL_BE 0x0e000000
|
||||
#define AN_RES_FLT_START_FE 0x00040000
|
||||
#define AN_RES_FLT_START_BE 0x00080000
|
||||
#define AN_RES_FLT_HTTP_HDRS 0x01000000
|
||||
#define AN_RES_FLT_XFER_DATA 0x04000000
|
||||
#define AN_RES_FLT_END 0x08000000
|
||||
|
||||
/* Magic value to forward infinite size (TCP, ...), used with ->to_forward */
|
||||
#define CHN_INFINITE_FORWARD MAX_RANGE(unsigned int)
|
||||
|
@ -8592,11 +8592,11 @@ out_uri_auth_compat:
|
||||
|
||||
/* Add filters analyzers if needed */
|
||||
if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
|
||||
curproxy->fe_req_ana |= AN_FLT_ALL_FE;
|
||||
curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
|
||||
curproxy->fe_req_ana |= AN_REQ_FLT_START_FE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
|
||||
curproxy->fe_rsp_ana |= AN_RES_FLT_START_FE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
|
||||
if (curproxy->mode == PR_MODE_HTTP) {
|
||||
curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
|
||||
curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
|
||||
curproxy->fe_req_ana |= AN_REQ_FLT_HTTP_HDRS;
|
||||
curproxy->fe_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8622,11 +8622,11 @@ out_uri_auth_compat:
|
||||
|
||||
/* Add filters analyzers if needed */
|
||||
if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
|
||||
curproxy->be_req_ana |= AN_FLT_ALL_BE;
|
||||
curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
|
||||
curproxy->be_req_ana |= AN_REQ_FLT_START_BE | AN_REQ_FLT_XFER_DATA | AN_REQ_FLT_END;
|
||||
curproxy->be_rsp_ana |= AN_RES_FLT_START_BE | AN_RES_FLT_XFER_DATA | AN_RES_FLT_END;
|
||||
if (curproxy->mode == PR_MODE_HTTP) {
|
||||
curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
|
||||
curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
|
||||
curproxy->be_req_ana |= AN_REQ_FLT_HTTP_HDRS;
|
||||
curproxy->be_rsp_ana |= AN_RES_FLT_HTTP_HDRS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -694,8 +694,16 @@ flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
* so we do not need to check the filter list's emptiness. */
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
if (an_bit == AN_FLT_START_BE && !(filter->flags & FLT_FL_IS_BACKEND_FILTER))
|
||||
continue;
|
||||
if (!(chn->flags & CF_ISRESP)) {
|
||||
if (an_bit == AN_REQ_FLT_START_BE &&
|
||||
!(filter->flags & FLT_FL_IS_BACKEND_FILTER))
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
if (an_bit == AN_RES_FLT_START_BE &&
|
||||
!(filter->flags & FLT_FL_IS_BACKEND_FILTER))
|
||||
continue;
|
||||
}
|
||||
|
||||
FLT_NXT(filter, chn) = 0;
|
||||
FLT_FWD(filter, chn) = 0;
|
||||
@ -764,9 +772,9 @@ flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is the AN_FLT_HTTP_HDRS analyzer, used to filter HTTP headers
|
||||
* or a request or a response. Returns 0 if an error occurs or if it needs to
|
||||
* wait, any other value otherwise.
|
||||
* This function is the AN_REQ/RES_FLT_HTTP_HDRS analyzer, used to filter HTTP
|
||||
* headers or a request or a response. Returns 0 if an error occurs or if it
|
||||
* needs to wait, any other value otherwise.
|
||||
*/
|
||||
int
|
||||
flt_analyze_http_headers(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
@ -828,7 +836,7 @@ end:
|
||||
|
||||
/* Check if 'channel_end_analyze' callback has been called for the
|
||||
* request and the response. */
|
||||
if (!(s->req.analysers & AN_FLT_END) && !(s->res.analysers & AN_FLT_END)) {
|
||||
if (!(s->req.analysers & AN_REQ_FLT_END) && !(s->res.analysers & AN_RES_FLT_END)) {
|
||||
/* When we are waiting for a new request, so we must reset
|
||||
* stream analyzers. The input must not be closed the request
|
||||
* channel, else it is useless to wait. */
|
||||
@ -967,11 +975,11 @@ flt_forward_data(struct stream *s, struct channel *chn, unsigned int len)
|
||||
|
||||
/*
|
||||
* Called when TCP data must be filtered on a channel. This function is the
|
||||
* AN_FLT_XFER_DATA analyzer. When called, it is responsible to forward data
|
||||
* when the proxy is not in http mode. Behind the scene, it calls consecutively
|
||||
* 'tcp_data' and 'tcp_forward_data' callbacks for all "data" filters attached
|
||||
* to a stream. Returns 0 if an error occurs or if it needs to wait, any other
|
||||
* value otherwise.
|
||||
* AN_REQ/RES_FLT_XFER_DATA analyzer. When called, it is responsible to forward
|
||||
* data when the proxy is not in http mode. Behind the scene, it calls
|
||||
* consecutively 'tcp_data' and 'tcp_forward_data' callbacks for all "data"
|
||||
* filters attached to a stream. Returns 0 if an error occurs or if it needs to
|
||||
* wait, any other value otherwise.
|
||||
*/
|
||||
int
|
||||
flt_xfer_data(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
@ -1045,12 +1053,12 @@ handle_analyzer_result(struct stream *s, struct channel *chn,
|
||||
channel_abort(&s->res);
|
||||
|
||||
if (!(chn->flags & CF_ISRESP)) {
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
finst = SF_FINST_R;
|
||||
/* FIXME: incr counters */
|
||||
}
|
||||
else {
|
||||
s->res.analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END;
|
||||
finst = SF_FINST_H;
|
||||
/* FIXME: incr counters */
|
||||
}
|
||||
|
@ -2718,7 +2718,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
txn->status = 400;
|
||||
msg->msg_state = HTTP_MSG_ERROR;
|
||||
http_reply_and_close(s, txn->status, NULL);
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
stream_inc_http_req_ctr(s);
|
||||
proxy_inc_fe_req_ctr(sess->fe);
|
||||
sess->fe->fe_counters.failed_req++;
|
||||
@ -2749,7 +2749,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
txn->status = 408;
|
||||
msg->msg_state = HTTP_MSG_ERROR;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_408));
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
|
||||
stream_inc_http_req_ctr(s);
|
||||
proxy_inc_fe_req_ctr(sess->fe);
|
||||
@ -2778,7 +2778,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
txn->status = 400;
|
||||
msg->msg_state = HTTP_MSG_ERROR;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
stream_inc_http_err_ctr(s);
|
||||
stream_inc_http_req_ctr(s);
|
||||
proxy_inc_fe_req_ctr(sess->fe);
|
||||
@ -2834,7 +2834,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
*/
|
||||
txn->status = 0;
|
||||
msg->msg_state = HTTP_MSG_RQBEFORE;
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
s->logs.logwait = 0;
|
||||
s->logs.level = 0;
|
||||
s->res.flags &= ~CF_EXPECT_MORE; /* speed up sending a previous response */
|
||||
@ -3161,7 +3161,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit)
|
||||
if (!(s->flags & SF_FINST_MASK))
|
||||
s->flags |= SF_FINST_R;
|
||||
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
return 0;
|
||||
}
|
||||
@ -4219,8 +4219,8 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s
|
||||
bi_fast_delete(req->chn->buf, req->sov);
|
||||
req->next -= req->sov;
|
||||
req->sov = 0;
|
||||
s->req.analysers = AN_REQ_HTTP_XFER_BODY | (s->req.analysers & AN_FLT_END);
|
||||
s->res.analysers = AN_RES_HTTP_XFER_BODY | (s->req.analysers & AN_FLT_END);
|
||||
s->req.analysers = AN_REQ_HTTP_XFER_BODY | (s->req.analysers & AN_REQ_FLT_END);
|
||||
s->res.analysers = AN_RES_HTTP_XFER_BODY | (s->req.analysers & AN_RES_FLT_END);
|
||||
req->msg_state = HTTP_MSG_CLOSED;
|
||||
res->msg_state = HTTP_MSG_DONE;
|
||||
/* Trim any possible response */
|
||||
@ -4236,7 +4236,7 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s
|
||||
trash.len += 23;
|
||||
}
|
||||
http_reply_and_close(s, txn->status, &trash);
|
||||
req->chn->analysers &= AN_FLT_END;
|
||||
req->chn->analysers &= AN_REQ_FLT_END;
|
||||
}
|
||||
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
@ -4379,8 +4379,8 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
s->flags |= SF_FINST_R;
|
||||
|
||||
/* enable the minimally required analyzers to handle keep-alive and compression on the HTTP response */
|
||||
req->analysers &= (AN_REQ_HTTP_BODY | AN_FLT_HTTP_HDRS | AN_FLT_END);
|
||||
req->analysers &= ~AN_FLT_XFER_DATA;
|
||||
req->analysers &= (AN_REQ_HTTP_BODY | AN_REQ_FLT_HTTP_HDRS | AN_REQ_FLT_END);
|
||||
req->analysers &= ~AN_REQ_FLT_XFER_DATA;
|
||||
req->analysers |= AN_REQ_HTTP_XFER_BODY;
|
||||
goto done;
|
||||
}
|
||||
@ -4437,7 +4437,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
if (s->be->cookie_name || sess->fe->capture_name)
|
||||
manage_client_side_cookies(s, req);
|
||||
|
||||
req->analysers &= AN_FLT_END; /* remove switching rules etc... */
|
||||
req->analysers &= AN_REQ_FLT_END; /* remove switching rules etc... */
|
||||
req->analysers |= AN_REQ_HTTP_TARPIT;
|
||||
req->analyse_exp = tick_add_ifset(now_ms, s->be->timeout.tarpit);
|
||||
if (!req->analyse_exp)
|
||||
@ -4492,7 +4492,7 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s
|
||||
if (!(s->flags & SF_FINST_MASK))
|
||||
s->flags |= SF_FINST_R;
|
||||
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
return 0;
|
||||
|
||||
@ -4548,7 +4548,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
if (unlikely((conn = si_alloc_conn(&s->si[1])) == NULL)) {
|
||||
txn->req.msg_state = HTTP_MSG_ERROR;
|
||||
txn->status = 500;
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_500));
|
||||
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
@ -4780,7 +4780,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
}
|
||||
|
||||
if (msg->flags & HTTP_MSGF_XFER_LEN) {
|
||||
req->analysers &= ~AN_FLT_XFER_DATA;
|
||||
req->analysers &= ~AN_REQ_FLT_XFER_DATA;
|
||||
req->analysers |= AN_REQ_HTTP_XFER_BODY;
|
||||
#ifdef TCP_QUICKACK
|
||||
/* We expect some data from the client. Unless we know for sure
|
||||
@ -4823,7 +4823,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit)
|
||||
|
||||
txn->req.msg_state = HTTP_MSG_ERROR;
|
||||
txn->status = 400;
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
|
||||
|
||||
sess->fe->fe_counters.failed_req++;
|
||||
@ -4867,7 +4867,7 @@ int http_process_tarpit(struct stream *s, struct channel *req, int an_bit)
|
||||
if (!(req->flags & CF_READ_ERROR))
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_500));
|
||||
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
req->analyse_exp = TICK_ETERNITY;
|
||||
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
@ -5022,7 +5022,7 @@ int http_wait_for_request_body(struct stream *s, struct channel *req, int an_bit
|
||||
s->flags |= SF_FINST_R;
|
||||
|
||||
return_err_msg:
|
||||
req->analysers &= AN_FLT_END;
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
sess->fe->fe_counters.failed_req++;
|
||||
if (sess->listener->counters)
|
||||
sess->listener->counters->failed_req++;
|
||||
@ -5272,8 +5272,8 @@ void http_end_txn_clean_session(struct stream *s)
|
||||
}
|
||||
|
||||
if (HAS_FILTERS(s)) {
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END;
|
||||
}
|
||||
else {
|
||||
s->req.analysers = strm_li(s) ? strm_li(s)->analysers : 0;
|
||||
@ -5591,25 +5591,25 @@ int http_resync_states(struct stream *s)
|
||||
txn->rsp.msg_state == HTTP_MSG_TUNNEL ||
|
||||
(txn->req.msg_state == HTTP_MSG_CLOSED &&
|
||||
txn->rsp.msg_state == HTTP_MSG_CLOSED)) {
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
channel_auto_close(&s->req);
|
||||
channel_auto_read(&s->req);
|
||||
s->res.analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END;
|
||||
channel_auto_close(&s->res);
|
||||
channel_auto_read(&s->res);
|
||||
if (txn->req.msg_state == HTTP_MSG_TUNNEL && HAS_REQ_DATA_FILTERS(s))
|
||||
s->req.analysers |= AN_FLT_XFER_DATA;
|
||||
s->req.analysers |= AN_REQ_FLT_XFER_DATA;
|
||||
if (txn->rsp.msg_state == HTTP_MSG_TUNNEL && HAS_RSP_DATA_FILTERS(s))
|
||||
s->res.analysers |= AN_FLT_XFER_DATA;
|
||||
s->res.analysers |= AN_RES_FLT_XFER_DATA;
|
||||
}
|
||||
else if ((txn->req.msg_state >= HTTP_MSG_DONE &&
|
||||
(txn->rsp.msg_state == HTTP_MSG_CLOSED || (s->res.flags & CF_SHUTW))) ||
|
||||
txn->rsp.msg_state == HTTP_MSG_ERROR ||
|
||||
txn->req.msg_state == HTTP_MSG_ERROR) {
|
||||
s->res.analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END;
|
||||
channel_auto_close(&s->res);
|
||||
channel_auto_read(&s->res);
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
channel_abort(&s->req);
|
||||
channel_auto_close(&s->req);
|
||||
channel_auto_read(&s->req);
|
||||
@ -5818,8 +5818,8 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
txn->status = 400;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_400));
|
||||
}
|
||||
req->analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
s->flags |= SF_ERR_PRXCOND;
|
||||
@ -5840,8 +5840,8 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
txn->status = 502;
|
||||
http_reply_and_close(s, txn->status, http_error_message(s, HTTP_ERR_502));
|
||||
}
|
||||
req->analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
req->analysers &= AN_REQ_FLT_END;
|
||||
s->res.analysers &= AN_RES_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
|
||||
sess->fe->fe_counters.srv_aborts++;
|
||||
s->be->be_counters.srv_aborts++;
|
||||
@ -5977,7 +5977,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
}
|
||||
abort_response:
|
||||
channel_auto_close(rep);
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
txn->status = 502;
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
channel_truncate(rep);
|
||||
@ -6012,7 +6012,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
}
|
||||
|
||||
channel_auto_close(rep);
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
txn->status = 502;
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
channel_truncate(rep);
|
||||
@ -6037,7 +6037,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
}
|
||||
|
||||
channel_auto_close(rep);
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
txn->status = 504;
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
channel_truncate(rep);
|
||||
@ -6057,7 +6057,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
if (objt_server(s->target))
|
||||
objt_server(s->target)->counters.cli_aborts++;
|
||||
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
channel_auto_close(rep);
|
||||
|
||||
txn->status = 400;
|
||||
@ -6087,7 +6087,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
}
|
||||
|
||||
channel_auto_close(rep);
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
txn->status = 502;
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
channel_truncate(rep);
|
||||
@ -6108,7 +6108,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
goto abort_keep_alive;
|
||||
|
||||
s->be->be_counters.failed_resp++;
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
channel_auto_close(rep);
|
||||
|
||||
if (!(s->flags & SF_ERR_MASK))
|
||||
@ -6467,8 +6467,8 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
* any other information so that the client retries.
|
||||
*/
|
||||
txn->status = 0;
|
||||
rep->analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
channel_auto_close(rep);
|
||||
s->logs.logwait = 0;
|
||||
s->logs.level = 0;
|
||||
@ -6568,7 +6568,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
||||
}
|
||||
s->be->be_counters.failed_resp++;
|
||||
return_srv_prx_502:
|
||||
rep->analysers &= AN_FLT_END;
|
||||
rep->analysers &= AN_RES_FLT_END;
|
||||
txn->status = 502;
|
||||
s->logs.t_data = -1; /* was not a valid response */
|
||||
s->si[1].flags |= SI_FL_NOLINGER;
|
||||
@ -6788,7 +6788,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
||||
skip_header_mangling:
|
||||
if ((msg->flags & HTTP_MSGF_XFER_LEN) || HAS_FILTERS(s) ||
|
||||
(txn->flags & TX_CON_WANT_MSK) == TX_CON_WANT_TUN) {
|
||||
rep->analysers &= ~AN_FLT_XFER_DATA;
|
||||
rep->analysers &= ~AN_RES_FLT_XFER_DATA;
|
||||
rep->analysers |= AN_RES_HTTP_XFER_BODY;
|
||||
}
|
||||
|
||||
@ -6966,8 +6966,8 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
txn->rsp.msg_state = HTTP_MSG_ERROR;
|
||||
/* don't send any error message as we're in the body */
|
||||
http_reply_and_close(s, txn->status, NULL);
|
||||
res->analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
res->analysers &= AN_RES_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
if (objt_server(s->target))
|
||||
health_adjust(objt_server(s->target), HANA_STATUS_HTTP_HDRRSP);
|
||||
|
||||
@ -6981,8 +6981,8 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
txn->rsp.msg_state = HTTP_MSG_ERROR;
|
||||
/* don't send any error message as we're in the body */
|
||||
http_reply_and_close(s, txn->status, NULL);
|
||||
res->analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
res->analysers &= AN_RES_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END; /* we're in data phase, we want to abort both directions */
|
||||
|
||||
sess->fe->fe_counters.cli_aborts++;
|
||||
s->be->be_counters.cli_aborts++;
|
||||
|
@ -1172,7 +1172,7 @@ int stream_set_backend(struct stream *s, struct proxy *be)
|
||||
/* Be sure to filter request headers if the backend is an HTTP proxy and
|
||||
* if there are filters attached to the stream. */
|
||||
if (s->be->mode == PR_MODE_HTTP && HAS_FILTERS(s))
|
||||
s->req.analysers |= AN_FLT_HTTP_HDRS;
|
||||
s->req.analysers |= AN_REQ_FLT_HTTP_HDRS;
|
||||
|
||||
if (s->txn) {
|
||||
if (be->options2 & PR_O2_RSPBUG_OK)
|
||||
|
28
src/stream.c
28
src/stream.c
@ -725,7 +725,7 @@ static void sess_establish(struct stream *s)
|
||||
/* Be sure to filter response headers if the backend is an HTTP proxy
|
||||
* and if there are filters attached to the stream. */
|
||||
if (s->be->mode == PR_MODE_HTTP && HAS_FILTERS(s))
|
||||
rep->analysers |= AN_FLT_HTTP_HDRS;
|
||||
rep->analysers |= AN_RES_FLT_HTTP_HDRS;
|
||||
|
||||
rep->flags |= CF_READ_ATTACHED; /* producer is now attached */
|
||||
if (req->flags & CF_WAKE_CONNECT) {
|
||||
@ -1155,7 +1155,7 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
|
||||
if (fe == s->be) {
|
||||
s->req.analysers &= ~AN_REQ_INSPECT_BE;
|
||||
s->req.analysers &= ~AN_REQ_HTTP_PROCESS_BE;
|
||||
s->req.analysers &= ~AN_FLT_START_BE;
|
||||
s->req.analysers &= ~AN_REQ_FLT_START_BE;
|
||||
}
|
||||
|
||||
/* as soon as we know the backend, we must check if we have a matching forced or ignored
|
||||
@ -1196,7 +1196,7 @@ static int process_switching_rules(struct stream *s, struct channel *req, int an
|
||||
|
||||
if (s->txn)
|
||||
s->txn->status = 500;
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->req.analysers &= AN_REQ_FLT_END;
|
||||
s->req.analyse_exp = TICK_ETERNITY;
|
||||
return 0;
|
||||
}
|
||||
@ -1465,7 +1465,7 @@ static int process_store_rules(struct stream *s, struct channel *rep, int an_bit
|
||||
/* These 2 following macros call an analayzer for the specified channel if the
|
||||
* right flag is set. The first one is used for "filterable" analyzers. If a
|
||||
* stream has some registered filters, pre and post analyaze callbacks are
|
||||
* called. The second are used for other analyzers (AN_FLT_* and
|
||||
* called. The second are used for other analyzers (AN_REQ/RES_FLT_* and
|
||||
* AN_REQ/RES_HTTP_XFER_BODY) */
|
||||
#define FLT_ANALYZE(strm, chn, fun, list, back, flag, ...) \
|
||||
{ \
|
||||
@ -1785,13 +1785,13 @@ struct task *process_stream(struct task *t)
|
||||
ana_list = ana_back = req->analysers;
|
||||
while (ana_list && max_loops--) {
|
||||
/* Warning! ensure that analysers are always placed in ascending order! */
|
||||
ANALYZE (s, req, flt_start_analyze, ana_list, ana_back, AN_FLT_START_FE);
|
||||
ANALYZE (s, req, flt_start_analyze, ana_list, ana_back, AN_REQ_FLT_START_FE);
|
||||
FLT_ANALYZE(s, req, tcp_inspect_request, ana_list, ana_back, AN_REQ_INSPECT_FE);
|
||||
FLT_ANALYZE(s, req, http_wait_for_request, ana_list, ana_back, AN_REQ_WAIT_HTTP);
|
||||
FLT_ANALYZE(s, req, http_wait_for_request_body, ana_list, ana_back, AN_REQ_HTTP_BODY);
|
||||
FLT_ANALYZE(s, req, http_process_req_common, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE, sess->fe);
|
||||
FLT_ANALYZE(s, req, process_switching_rules, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
|
||||
ANALYZE (s, req, flt_start_analyze, ana_list, ana_back, AN_FLT_START_BE);
|
||||
ANALYZE (s, req, flt_start_analyze, ana_list, ana_back, AN_REQ_FLT_START_BE);
|
||||
FLT_ANALYZE(s, req, tcp_inspect_request, ana_list, ana_back, AN_REQ_INSPECT_BE);
|
||||
FLT_ANALYZE(s, req, http_process_req_common, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE, s->be);
|
||||
FLT_ANALYZE(s, req, http_process_tarpit, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
|
||||
@ -1799,10 +1799,10 @@ struct task *process_stream(struct task *t)
|
||||
FLT_ANALYZE(s, req, http_process_request, ana_list, ana_back, AN_REQ_HTTP_INNER);
|
||||
FLT_ANALYZE(s, req, tcp_persist_rdp_cookie, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
|
||||
FLT_ANALYZE(s, req, process_sticking_rules, ana_list, ana_back, AN_REQ_STICKING_RULES);
|
||||
ANALYZE (s, req, flt_analyze_http_headers, ana_list, ana_back, AN_FLT_HTTP_HDRS);
|
||||
ANALYZE (s, req, flt_analyze_http_headers, ana_list, ana_back, AN_REQ_FLT_HTTP_HDRS);
|
||||
ANALYZE (s, req, http_request_forward_body, ana_list, ana_back, AN_REQ_HTTP_XFER_BODY);
|
||||
ANALYZE (s, req, flt_xfer_data, ana_list, ana_back, AN_FLT_XFER_DATA);
|
||||
ANALYZE (s, req, flt_end_analyze, ana_list, ana_back, AN_FLT_END);
|
||||
ANALYZE (s, req, flt_xfer_data, ana_list, ana_back, AN_REQ_FLT_XFER_DATA);
|
||||
ANALYZE (s, req, flt_end_analyze, ana_list, ana_back, AN_REQ_FLT_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1872,16 +1872,16 @@ struct task *process_stream(struct task *t)
|
||||
ana_list = ana_back = res->analysers;
|
||||
while (ana_list && max_loops--) {
|
||||
/* Warning! ensure that analysers are always placed in ascending order! */
|
||||
ANALYZE (s, res, flt_start_analyze, ana_list, ana_back, AN_FLT_START_FE);
|
||||
ANALYZE (s, res, flt_start_analyze, ana_list, ana_back, AN_FLT_START_BE);
|
||||
ANALYZE (s, res, flt_start_analyze, ana_list, ana_back, AN_RES_FLT_START_FE);
|
||||
ANALYZE (s, res, flt_start_analyze, ana_list, ana_back, AN_RES_FLT_START_BE);
|
||||
FLT_ANALYZE(s, res, tcp_inspect_response, ana_list, ana_back, AN_RES_INSPECT);
|
||||
FLT_ANALYZE(s, res, http_wait_for_response, ana_list, ana_back, AN_RES_WAIT_HTTP);
|
||||
FLT_ANALYZE(s, res, process_store_rules, ana_list, ana_back, AN_RES_STORE_RULES);
|
||||
FLT_ANALYZE(s, res, http_process_res_common, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE, s->be);
|
||||
ANALYZE (s, res, flt_analyze_http_headers, ana_list, ana_back, AN_FLT_HTTP_HDRS);
|
||||
ANALYZE (s, res, flt_analyze_http_headers, ana_list, ana_back, AN_RES_FLT_HTTP_HDRS);
|
||||
ANALYZE (s, res, http_response_forward_body, ana_list, ana_back, AN_RES_HTTP_XFER_BODY);
|
||||
ANALYZE (s, res, flt_xfer_data, ana_list, ana_back, AN_FLT_XFER_DATA);
|
||||
ANALYZE (s, res, flt_end_analyze, ana_list, ana_back, AN_FLT_END);
|
||||
ANALYZE (s, res, flt_xfer_data, ana_list, ana_back, AN_RES_FLT_XFER_DATA);
|
||||
ANALYZE (s, res, flt_end_analyze, ana_list, ana_back, AN_RES_FLT_END);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user