mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 07:37:02 +02:00
MEDIUM: filters: Use macros to call filters callbacks to speed-up processing
When no filter is attached to the stream, the CPU footprint due to the calls to filters_* functions is huge, especially for chunk-encoded messages. Using macros to check if we have some filters or not is a great improvement. Furthermore, instead of checking the filter list emptiness, we introduce a flag to know if filters are attached or not to a stream.
This commit is contained in:
parent
92d3638d2d
commit
3e34429515
@ -35,6 +35,50 @@
|
||||
#define FLT_NXT(flt, chn) ((flt)->next[CHN_IDX(chn)])
|
||||
#define FLT_FWD(flt, chn) ((flt)->fwd[CHN_IDX(chn)])
|
||||
|
||||
#define HAS_FILTERS(strm) ((strm)->strm_flt.has_filters)
|
||||
|
||||
#define FLT_STRM_CB_IMPL_0(strm, call) \
|
||||
do { \
|
||||
if (HAS_FILTERS(strm)) { call; } \
|
||||
} while (0)
|
||||
#define FLT_STRM_CB_IMPL_1(strm, call, default_ret, ...) \
|
||||
(HAS_FILTERS(strm) ? call : default_ret)
|
||||
#define FLT_STRM_CB_IMPL_2(strm, call, default_ret, on_error) \
|
||||
({ \
|
||||
int _ret; \
|
||||
if (HAS_FILTERS(strm)) { \
|
||||
_ret = call; \
|
||||
if (_ret < 0) { on_error; } \
|
||||
} \
|
||||
else \
|
||||
_ret = default_ret; \
|
||||
_ret; \
|
||||
})
|
||||
#define FLT_STRM_CB_IMPL_3(strm, call, default_ret, on_error, on_wait) \
|
||||
({ \
|
||||
int _ret; \
|
||||
if (HAS_FILTERS(strm)) { \
|
||||
_ret = call; \
|
||||
if (_ret < 0) { on_error; } \
|
||||
if (!_ret) { on_wait; } \
|
||||
} \
|
||||
else \
|
||||
_ret = default_ret; \
|
||||
_ret; \
|
||||
})
|
||||
|
||||
#define FLT_STRM_CB_IMPL_X(strm, call, A, B, C, CB_IMPL, ...) CB_IMPL
|
||||
|
||||
#define FLT_STRM_CB(strm, call, ...) \
|
||||
FLT_STRM_CB_IMPL_X(strm, call, ##__VA_ARGS__, \
|
||||
FLT_STRM_CB_IMPL_3(strm, call, ##__VA_ARGS__), \
|
||||
FLT_STRM_CB_IMPL_2(strm, call, ##__VA_ARGS__), \
|
||||
FLT_STRM_CB_IMPL_1(strm, call, ##__VA_ARGS__), \
|
||||
FLT_STRM_CB_IMPL_0(strm, call))
|
||||
|
||||
#define CALL_FILTER_ANALYZER(analyzer, strm, chn, bit) \
|
||||
if (!HAS_FILTERS(strm) || analyzer((strm), (chn), bit)) ; else break
|
||||
|
||||
extern struct pool_head *pool2_filter;
|
||||
|
||||
int flt_init(struct proxy *p);
|
||||
|
@ -128,6 +128,7 @@ struct stream {
|
||||
struct {
|
||||
struct list filters;
|
||||
struct filter *current[2]; /* 0: request, 1: response */
|
||||
char has_filters;
|
||||
} strm_flt;
|
||||
|
||||
struct task *task; /* the task associated with this stream */
|
||||
|
@ -295,6 +295,7 @@ flt_stream_add_filter(struct stream *s, struct filter *filter,
|
||||
f->conf = filter->conf;
|
||||
f->is_backend_filter = is_backend;
|
||||
LIST_ADDQ(&s->strm_flt.filters, &f->list);
|
||||
s->strm_flt.has_filters = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -309,6 +310,7 @@ flt_stream_init(struct stream *s)
|
||||
|
||||
LIST_INIT(&s->strm_flt.filters);
|
||||
memset(s->strm_flt.current, 0, sizeof(s->strm_flt.current));
|
||||
s->strm_flt.has_filters = 0;
|
||||
list_for_each_entry(filter, &strm_fe(s)->filters, list) {
|
||||
if (flt_stream_add_filter(s, filter, 0) < 0)
|
||||
return -1;
|
||||
@ -333,6 +335,8 @@ flt_stream_release(struct stream *s, int only_backend)
|
||||
pool_free2(pool2_filter, filter);
|
||||
}
|
||||
}
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
s->strm_flt.has_filters = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -393,9 +397,6 @@ flt_http_headers(struct stream *s, struct http_msg *msg)
|
||||
struct filter *filter;
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops && filter->ops->http_headers) {
|
||||
ret = filter->ops->http_headers(s, filter, msg);
|
||||
@ -419,9 +420,6 @@ flt_http_start_chunk(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops->http_start_chunk) {
|
||||
ret = filter->ops->http_start_chunk(s, filter, msg);
|
||||
@ -450,12 +448,6 @@ flt_http_data(struct stream *s, struct http_msg *msg)
|
||||
unsigned int buf_i;
|
||||
int ret = 0;
|
||||
|
||||
/* No filter, consume all available data */
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters)) {
|
||||
ret = MIN(msg->chunk_len, msg->chn->buf->i - msg->next);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Save buffer state */
|
||||
buf_i = msg->chn->buf->i;
|
||||
list_for_each_entry(filter, &s->strm_flt.filters, list) {
|
||||
@ -483,7 +475,6 @@ flt_http_data(struct stream *s, struct http_msg *msg)
|
||||
}
|
||||
/* Restore the original buffer state */
|
||||
msg->chn->buf->i = buf_i;
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -492,9 +483,6 @@ flt_http_end_chunk(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops->http_end_chunk) {
|
||||
ret = filter->ops->http_end_chunk(s, filter, msg);
|
||||
@ -513,9 +501,6 @@ flt_http_last_chunk(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops->http_last_chunk) {
|
||||
ret = filter->ops->http_last_chunk(s, filter, msg);
|
||||
@ -543,9 +528,6 @@ flt_http_chunk_trailers(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops->http_chunk_trailers) {
|
||||
ret = filter->ops->http_chunk_trailers(s, filter, msg);
|
||||
@ -570,9 +552,6 @@ flt_http_end(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
if (filter->ops->http_end) {
|
||||
ret = filter->ops->http_end(s, filter, msg);
|
||||
@ -594,9 +573,6 @@ flt_http_reset(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
struct filter *filter;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
return;
|
||||
|
||||
list_for_each_entry(filter, &s->strm_flt.filters, list) {
|
||||
if (filter->ops->http_reset)
|
||||
filter->ops->http_reset(s, filter, msg);
|
||||
@ -612,9 +588,6 @@ flt_http_reply(struct stream *s, short status, const struct chunk *msg)
|
||||
{
|
||||
struct filter *filter;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
return;
|
||||
|
||||
list_for_each_entry(filter, &s->strm_flt.filters, list) {
|
||||
if (filter->ops->http_reply)
|
||||
filter->ops->http_reply(s, filter, status, msg);
|
||||
@ -636,10 +609,6 @@ flt_http_forward_data(struct stream *s, struct http_msg *msg, unsigned int len)
|
||||
struct filter *filter = NULL;
|
||||
int ret = len;
|
||||
|
||||
/* No filter, forward all data */
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
list_for_each_entry(filter, &s->strm_flt.filters, list) {
|
||||
if (filter->ops->http_forward_data) {
|
||||
/* Remove bytes that the current filter considered as
|
||||
@ -719,9 +688,6 @@ flt_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
goto end;
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
if (filter->ops->channel_analyze) {
|
||||
ret = filter->ops->channel_analyze(s, filter, chn, an_bit);
|
||||
@ -732,7 +698,6 @@ flt_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
|
||||
check_result:
|
||||
ret = handle_analyzer_result(s, chn, 0, ret);
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
199
src/proto_http.c
199
src/proto_http.c
@ -935,7 +935,7 @@ int http_remove_header2(struct http_msg *msg, struct hdr_idx *idx, struct hdr_ct
|
||||
static void http_server_error(struct stream *s, struct stream_interface *si,
|
||||
int err, int finst, int status, const struct chunk *msg)
|
||||
{
|
||||
flt_http_reply(s, status, msg);
|
||||
FLT_STRM_CB(s, flt_http_reply(s, status, msg));
|
||||
channel_auto_read(si_oc(si));
|
||||
channel_abort(si_oc(si));
|
||||
channel_auto_close(si_oc(si));
|
||||
@ -970,7 +970,7 @@ void
|
||||
http_reply_and_close(struct stream *s, short status, struct chunk *msg)
|
||||
{
|
||||
s->txn->flags &= ~TX_WAIT_NEXT_RQ;
|
||||
flt_http_reply(s, status, msg);
|
||||
FLT_STRM_CB(s, flt_http_reply(s, status, msg));
|
||||
stream_int_retnclose(&s->si[0], msg);
|
||||
}
|
||||
|
||||
@ -4027,7 +4027,7 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s
|
||||
}
|
||||
memcpy(trash.str + trash.len, "\r\n\r\n", 4);
|
||||
trash.len += 4;
|
||||
flt_http_reply(s, txn->status, &trash);
|
||||
FLT_STRM_CB(s, flt_http_reply(s, txn->status, &trash));
|
||||
bo_inject(res->chn, trash.str, trash.len);
|
||||
/* "eat" the request */
|
||||
bi_fast_delete(req->chn->buf, req->sov);
|
||||
@ -5071,14 +5071,14 @@ void http_end_txn_clean_session(struct stream *s)
|
||||
si_idle_conn(&s->si[1], &srv->idle_conns);
|
||||
}
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters)) {
|
||||
s->req.analysers = strm_li(s) ? strm_li(s)->analysers : 0;
|
||||
s->res.analysers = 0;
|
||||
}
|
||||
else {
|
||||
if (HAS_FILTERS(s)) {
|
||||
s->req.analysers &= AN_FLT_END;
|
||||
s->res.analysers &= AN_FLT_END;
|
||||
}
|
||||
else {
|
||||
s->req.analysers = strm_li(s) ? strm_li(s)->analysers : 0;
|
||||
s->res.analysers = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5442,7 +5442,7 @@ 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;
|
||||
int ret, ret2;
|
||||
int ret;
|
||||
|
||||
if (unlikely(msg->msg_state < HTTP_MSG_BODY))
|
||||
return 0;
|
||||
@ -5462,25 +5462,16 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
* decide whether to return 100, 417 or anything else in return of
|
||||
* an "Expect: 100-continue" header.
|
||||
*/
|
||||
|
||||
if (msg->msg_state == HTTP_MSG_BODY) {
|
||||
/* we have msg->sov which points to the first byte of message
|
||||
* body, and req->buf.p still points to the beginning of the
|
||||
* message. We forward the headers now, as we don't need them
|
||||
* anymore, and we want to flush them.
|
||||
*/
|
||||
ret = flt_http_headers(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
ret = flt_http_forward_data(s, msg, msg->sov);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
b_adv(req->buf, ret);
|
||||
msg->next -= ret;
|
||||
msg->sov -= ret;
|
||||
FLT_STRM_CB(s, flt_http_headers(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ return 0);
|
||||
|
||||
/* The previous analysers guarantee that the state is somewhere
|
||||
* between MSG_BODY and the first MSG_DATA. So msg->sol and
|
||||
@ -5526,10 +5517,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
if (msg->msg_state == HTTP_MSG_DATA) {
|
||||
/* must still forward */
|
||||
/* we may have some pending data starting at req->buf->p */
|
||||
ret = flt_http_data(s, msg);
|
||||
if (ret < 0)
|
||||
goto aborted_xfer;
|
||||
msg->next += ret;
|
||||
ret = FLT_STRM_CB(s, flt_http_data(s, msg),
|
||||
/* default_ret */ MIN(msg->chunk_len, req->buf->i - msg->next),
|
||||
/* on_error */ goto aborted_xfer);
|
||||
msg->next += ret;
|
||||
msg->chunk_len -= ret;
|
||||
|
||||
if (msg->chunk_len) {
|
||||
@ -5561,13 +5552,16 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
goto return_bad_req;
|
||||
}
|
||||
}
|
||||
ret = (msg->chunk_len
|
||||
? flt_http_start_chunk(s, msg)
|
||||
: flt_http_last_chunk(s, msg));
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
if (!ret)
|
||||
goto missing_data;
|
||||
if (msg->chunk_len)
|
||||
FLT_STRM_CB(s, flt_http_start_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ goto missing_data);
|
||||
else
|
||||
FLT_STRM_CB(s, flt_http_last_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
msg->msg_state = msg->chunk_len ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS;
|
||||
@ -5586,11 +5580,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
goto return_bad_req;
|
||||
}
|
||||
}
|
||||
ret = flt_http_end_chunk(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
if (!ret)
|
||||
goto missing_data;
|
||||
FLT_STRM_CB(s, flt_http_end_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
msg->msg_state = HTTP_MSG_CHUNK_SIZE;
|
||||
@ -5607,11 +5600,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
goto return_bad_req;
|
||||
}
|
||||
}
|
||||
ret2 = flt_http_chunk_trailers(s, msg);
|
||||
if (ret2 < 0)
|
||||
goto return_bad_req;
|
||||
if (!ret2)
|
||||
goto missing_data;
|
||||
FLT_STRM_CB(s, flt_http_chunk_trailers(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
if (!ret)
|
||||
@ -5627,22 +5619,20 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
/* we may have some pending data starting at req->buf->p
|
||||
* such as last chunk of data or trailers.
|
||||
*/
|
||||
ret = flt_http_forward_data(s, msg, msg->next);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
ret = FLT_STRM_CB(s, flt_http_forward_data(s, msg, msg->next),
|
||||
/* default_ret */ msg->next,
|
||||
/* on_error */ goto return_bad_req);
|
||||
b_adv(req->buf, ret);
|
||||
msg->next -= ret;
|
||||
if (unlikely(!(s->req.flags & CF_WROTE_DATA) || msg->sov > 0))
|
||||
msg->sov -= ret;
|
||||
|
||||
if (msg->next)
|
||||
goto skip_resync_states;
|
||||
|
||||
ret = flt_http_end(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
if (!ret)
|
||||
goto skip_resync_states;
|
||||
FLT_STRM_CB(s, flt_http_end(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_req,
|
||||
/* on_wait */ goto skip_resync_states);
|
||||
msg->msg_state = HTTP_MSG_DONE;
|
||||
}
|
||||
else {
|
||||
@ -5703,14 +5693,14 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit)
|
||||
|
||||
missing_data:
|
||||
/* we may have some pending data starting at req->buf->p */
|
||||
ret = flt_http_forward_data(s, msg, msg->next);
|
||||
if (ret < 0)
|
||||
goto return_bad_req;
|
||||
ret = FLT_STRM_CB(s, flt_http_forward_data(s, msg, msg->next),
|
||||
/* default_ret */ msg->next,
|
||||
/* on_error */ goto return_bad_req);
|
||||
b_adv(req->buf, ret);
|
||||
msg->next -= ret;
|
||||
if (unlikely(!(s->req.flags & CF_WROTE_DATA) || msg->sov > 0))
|
||||
msg->sov -= ret;
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
if (!HAS_FILTERS(s))
|
||||
msg->chunk_len -= channel_forward(req, msg->chunk_len);
|
||||
|
||||
/* stop waiting for data if the input is closed before the end */
|
||||
@ -6162,7 +6152,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit)
|
||||
msg->msg_state = HTTP_MSG_RPBEFORE;
|
||||
txn->status = 0;
|
||||
s->logs.t_data = -1; /* was not a response yet */
|
||||
flt_http_reset(s, msg);
|
||||
FLT_STRM_CB(s, flt_http_reset(s, msg));
|
||||
goto next_one;
|
||||
|
||||
case 200:
|
||||
@ -6733,8 +6723,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) ||
|
||||
!LIST_ISEMPTY(&s->strm_flt.filters) ||
|
||||
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_HTTP_XFER_BODY;
|
||||
@ -6782,12 +6771,13 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
||||
* is performed at once on final states for all bytes parsed, or when leaving
|
||||
* on missing data.
|
||||
*/
|
||||
|
||||
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;
|
||||
int ret, ret2;
|
||||
int ret;
|
||||
|
||||
if (unlikely(msg->msg_state < HTTP_MSG_BODY))
|
||||
return 0;
|
||||
@ -6812,18 +6802,10 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
* message. We forward the headers now, as we don't need them
|
||||
* anymore, and we want to flush them.
|
||||
*/
|
||||
ret = flt_http_headers(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
ret = flt_http_forward_data(s, msg, msg->sov);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
b_adv(res->buf, ret);
|
||||
msg->next -= ret;
|
||||
msg->sov -= ret;
|
||||
FLT_STRM_CB(s, flt_http_headers(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ return 0);
|
||||
|
||||
/* The previous analysers guarantee that the state is somewhere
|
||||
* between MSG_BODY and the first MSG_DATA. So msg->sol and
|
||||
@ -6852,11 +6834,14 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
* found, so we must read the body until the server
|
||||
* connection is closed. In that case, we eat data as
|
||||
* they come. */
|
||||
if (!(msg->flags & HTTP_MSGF_XFER_LEN))
|
||||
msg->chunk_len = (res->buf->i - msg->next);
|
||||
ret = flt_http_data(s, msg);
|
||||
if (ret < 0)
|
||||
goto aborted_xfer;
|
||||
if (!(msg->flags & HTTP_MSGF_XFER_LEN)) {
|
||||
unsigned long long len = (res->buf->i - msg->next);
|
||||
msg->chunk_len += len;
|
||||
msg->body_len += len;
|
||||
}
|
||||
ret = FLT_STRM_CB(s, flt_http_data(s, msg),
|
||||
/* default_ret */ MIN(msg->chunk_len, res->buf->i - msg->next),
|
||||
/* on_error */ goto aborted_xfer);
|
||||
msg->next += ret;
|
||||
msg->chunk_len -= ret;
|
||||
if (msg->chunk_len) {
|
||||
@ -6891,11 +6876,10 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
goto return_bad_res;
|
||||
}
|
||||
}
|
||||
ret = flt_http_end_chunk(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
if (!ret)
|
||||
goto missing_data;
|
||||
FLT_STRM_CB(s, flt_http_end_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
msg->msg_state = HTTP_MSG_CHUNK_SIZE;
|
||||
@ -6916,13 +6900,16 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
goto return_bad_res;
|
||||
}
|
||||
}
|
||||
ret = (msg->chunk_len
|
||||
? flt_http_start_chunk(s, msg)
|
||||
: flt_http_last_chunk(s, msg));
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
if (!ret)
|
||||
goto missing_data;
|
||||
if (msg->chunk_len)
|
||||
FLT_STRM_CB(s, flt_http_start_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ goto missing_data);
|
||||
else
|
||||
FLT_STRM_CB(s, flt_http_last_chunk(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
msg->msg_state = msg->chunk_len ? HTTP_MSG_DATA : HTTP_MSG_TRAILERS;
|
||||
@ -6939,11 +6926,10 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
goto return_bad_res;
|
||||
}
|
||||
}
|
||||
ret2 = flt_http_chunk_trailers(s, msg);
|
||||
if (ret2 < 0)
|
||||
goto return_bad_res;
|
||||
if (!ret2)
|
||||
goto missing_data;
|
||||
FLT_STRM_CB(s, flt_http_chunk_trailers(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ goto missing_data);
|
||||
msg->next += msg->sol;
|
||||
msg->sol = 0;
|
||||
if (!ret)
|
||||
@ -6960,22 +6946,20 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
/* we may have some pending data starting at res->buf->p
|
||||
* such as a last chunk of data or trailers.
|
||||
*/
|
||||
ret = flt_http_forward_data(s, msg, msg->next);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
ret = FLT_STRM_CB(s, flt_http_forward_data(s, msg, msg->next),
|
||||
/* default_ret */ msg->next,
|
||||
/* on_error */ goto return_bad_res);
|
||||
b_adv(res->buf, ret);
|
||||
msg->next -= ret;
|
||||
if (msg->sov > 0)
|
||||
msg->sov -= ret;
|
||||
|
||||
if (msg->next)
|
||||
goto skip_resync_states;
|
||||
|
||||
ret = flt_http_end(s, msg);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
if (!ret)
|
||||
goto skip_resync_states;
|
||||
FLT_STRM_CB(s, flt_http_end(s, msg),
|
||||
/* default_ret */ 1,
|
||||
/* on_error */ goto return_bad_res,
|
||||
/* on_wait */ goto skip_resync_states);
|
||||
msg->msg_state = HTTP_MSG_DONE;
|
||||
/* fall through */
|
||||
|
||||
@ -7013,15 +6997,14 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit
|
||||
|
||||
missing_data:
|
||||
/* we may have some pending data starting at res->buf->p */
|
||||
ret = flt_http_forward_data(s, msg, msg->next);
|
||||
if (ret < 0)
|
||||
goto return_bad_res;
|
||||
ret = FLT_STRM_CB(s, flt_http_forward_data(s, msg, msg->next),
|
||||
/* default_ret */ msg->next,
|
||||
/* on_error */ goto return_bad_res);
|
||||
b_adv(res->buf, ret);
|
||||
msg->next -= ret;
|
||||
if (msg->sov > 0)
|
||||
msg->sov -= ret;
|
||||
|
||||
if (LIST_ISEMPTY(&s->strm_flt.filters))
|
||||
if (!HAS_FILTERS(s))
|
||||
msg->chunk_len -= channel_forward(res, msg->chunk_len);
|
||||
|
||||
if (res->flags & CF_SHUTW)
|
||||
|
144
src/stream.c
144
src/stream.c
@ -1765,107 +1765,95 @@ struct task *process_stream(struct task *t)
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_INSPECT_FE) {
|
||||
if (!flt_analyze(s, req, AN_REQ_INSPECT_FE))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_INSPECT_FE);
|
||||
if (!tcp_inspect_request(s, req, AN_REQ_INSPECT_FE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_INSPECT_FE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_WAIT_HTTP) {
|
||||
if (!flt_analyze(s, req, AN_REQ_WAIT_HTTP))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_WAIT_HTTP);
|
||||
if (!http_wait_for_request(s, req, AN_REQ_WAIT_HTTP))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_WAIT_HTTP);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_BODY) {
|
||||
if (!flt_analyze(s, req, AN_REQ_HTTP_BODY))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_HTTP_BODY);
|
||||
if (!http_wait_for_request_body(s, req, AN_REQ_HTTP_BODY))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_BODY);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_PROCESS_FE) {
|
||||
if (!flt_analyze(s, req, AN_REQ_HTTP_PROCESS_FE))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_HTTP_PROCESS_FE);
|
||||
if (!http_process_req_common(s, req, AN_REQ_HTTP_PROCESS_FE, sess->fe))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_FE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_SWITCHING_RULES) {
|
||||
if (!flt_analyze(s, req, AN_REQ_SWITCHING_RULES))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_SWITCHING_RULES);
|
||||
if (!process_switching_rules(s, req, AN_REQ_SWITCHING_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_SWITCHING_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_INSPECT_BE) {
|
||||
if (!flt_analyze(s, req, AN_REQ_INSPECT_BE))
|
||||
break;
|
||||
if (!tcp_inspect_request(s, req, AN_REQ_INSPECT_BE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
|
||||
if (!flt_analyze(s, req, AN_REQ_HTTP_PROCESS_BE))
|
||||
break;
|
||||
if (!http_process_req_common(s, req, AN_REQ_HTTP_PROCESS_BE, s->be))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_TARPIT) {
|
||||
if (!flt_analyze(s, req, AN_REQ_HTTP_TARPIT))
|
||||
break;
|
||||
if (!http_process_tarpit(s, req, AN_REQ_HTTP_TARPIT))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_SRV_RULES) {
|
||||
if (!flt_analyze(s, req, AN_REQ_SRV_RULES))
|
||||
break;
|
||||
if (!process_server_rules(s, req, AN_REQ_SRV_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_INNER) {
|
||||
if (!flt_analyze(s, req, AN_REQ_HTTP_INNER))
|
||||
break;
|
||||
if (!http_process_request(s, req, AN_REQ_HTTP_INNER))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
|
||||
if (!flt_analyze(s, req, AN_REQ_PRST_RDP_COOKIE))
|
||||
break;
|
||||
if (!tcp_persist_rdp_cookie(s, req, AN_REQ_PRST_RDP_COOKIE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_STICKING_RULES) {
|
||||
if (!flt_analyze(s, req, AN_REQ_STICKING_RULES))
|
||||
break;
|
||||
if (!process_sticking_rules(s, req, AN_REQ_STICKING_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_FLT_START_BE) {
|
||||
if (!flt_start_analyze(s, req, AN_FLT_START_BE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_FLT_START_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_INSPECT_BE) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_INSPECT_BE);
|
||||
if (!tcp_inspect_request(s, req, AN_REQ_INSPECT_BE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_INSPECT_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_PROCESS_BE) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_HTTP_PROCESS_BE);
|
||||
if (!http_process_req_common(s, req, AN_REQ_HTTP_PROCESS_BE, s->be))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_PROCESS_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_TARPIT) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_HTTP_TARPIT);
|
||||
if (!http_process_tarpit(s, req, AN_REQ_HTTP_TARPIT))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_TARPIT);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_SRV_RULES) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_SRV_RULES);
|
||||
if (!process_server_rules(s, req, AN_REQ_SRV_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_SRV_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_HTTP_INNER) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_HTTP_INNER);
|
||||
if (!http_process_request(s, req, AN_REQ_HTTP_INNER))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_HTTP_INNER);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_PRST_RDP_COOKIE) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_PRST_RDP_COOKIE);
|
||||
if (!tcp_persist_rdp_cookie(s, req, AN_REQ_PRST_RDP_COOKIE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_PRST_RDP_COOKIE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_REQ_STICKING_RULES) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, req, AN_REQ_STICKING_RULES);
|
||||
if (!process_sticking_rules(s, req, AN_REQ_STICKING_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(req->analysers, ana_list, ana_back, AN_REQ_STICKING_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_FLT_XFER_DATA) {
|
||||
if (!flt_xfer_data(s, req, AN_FLT_XFER_DATA))
|
||||
break;
|
||||
@ -1958,44 +1946,40 @@ struct task *process_stream(struct task *t)
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_FLT_START_FE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_RES_INSPECT) {
|
||||
if (!flt_analyze(s, res, AN_RES_INSPECT))
|
||||
if (ana_list & AN_FLT_START_BE) {
|
||||
if (!flt_start_analyze(s, res, AN_FLT_START_BE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_FLT_START_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_RES_INSPECT) {
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, res, AN_RES_INSPECT);
|
||||
if (!tcp_inspect_response(s, res, AN_RES_INSPECT))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_RES_INSPECT);
|
||||
}
|
||||
|
||||
if (ana_list & AN_RES_WAIT_HTTP) {
|
||||
if (!flt_analyze(s, res, AN_RES_WAIT_HTTP))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, res, AN_RES_WAIT_HTTP);
|
||||
if (!http_wait_for_response(s, res, AN_RES_WAIT_HTTP))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_RES_WAIT_HTTP);
|
||||
}
|
||||
|
||||
if (ana_list & AN_RES_STORE_RULES) {
|
||||
if (!flt_analyze(s, res, AN_RES_STORE_RULES))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, res, AN_RES_STORE_RULES);
|
||||
if (!process_store_rules(s, res, AN_RES_STORE_RULES))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_RES_STORE_RULES);
|
||||
}
|
||||
|
||||
if (ana_list & AN_RES_HTTP_PROCESS_BE) {
|
||||
if (!flt_analyze(s, res, AN_RES_HTTP_PROCESS_BE))
|
||||
break;
|
||||
CALL_FILTER_ANALYZER(flt_analyze, s, res, AN_RES_HTTP_PROCESS_BE);
|
||||
if (!http_process_res_common(s, res, AN_RES_HTTP_PROCESS_BE, s->be))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_RES_HTTP_PROCESS_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_FLT_START_BE) {
|
||||
if (!flt_start_analyze(s, res, AN_FLT_START_BE))
|
||||
break;
|
||||
UPDATE_ANALYSERS(res->analysers, ana_list, ana_back, AN_FLT_START_BE);
|
||||
}
|
||||
|
||||
if (ana_list & AN_FLT_XFER_DATA) {
|
||||
if (!flt_xfer_data(s, res, AN_FLT_XFER_DATA))
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user