diff --git a/include/proto/filters.h b/include/proto/filters.h index 702028562..c351f6e20 100644 --- a/include/proto/filters.h +++ b/include/proto/filters.h @@ -114,7 +114,8 @@ void flt_http_reset(struct stream *s, struct http_msg *msg); void flt_http_reply(struct stream *s, short status, const struct chunk *msg); int flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit); -int flt_analyze(struct stream *s, struct channel *chn, unsigned int an_bit); +int flt_pre_analyze(struct stream *s, struct channel *chn, unsigned int an_bit); +int flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit); int flt_analyze_http_headers(struct stream *s, struct channel *chn, unsigned int an_bit); int flt_end_analyze(struct stream *s, struct channel *chn, unsigned int an_bit); diff --git a/include/types/channel.h b/include/types/channel.h index b31f493a0..dd5099311 100644 --- a/include/types/channel.h +++ b/include/types/channel.h @@ -156,6 +156,7 @@ #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 */ #define AN_FLT_START_FE 0x01000000 #define AN_FLT_START_BE 0x02000000 diff --git a/include/types/filters.h b/include/types/filters.h index e01e22599..62fcfb129 100644 --- a/include/types/filters.h +++ b/include/types/filters.h @@ -77,10 +77,14 @@ struct flt_kw_list { * - channel_start_analyze: Called when a filter starts to analyze a channel. * Returns a negative value if an error occurs, 0 if * it needs to wait, any other value otherwise. - * - channel_analyze : Called before each analyzer attached to a channel, + * - channel_pre_analyze : Called before each analyzer attached to a channel, * expects analyzers responsible for data sending. * Returns a negative value if an error occurs, 0 if * it needs to wait, any other value otherwise. + * - channel_post_analyze: Called after each analyzer attached to a channel, + * expects analyzers responsible for data sending. + * Returns a negative value if an error occurs, + * any other value otherwise. * - channel_end_analyze : Called when all other analyzers have finished their * processing. * Returns a negative value if an error occurs, 0 if @@ -140,7 +144,8 @@ struct flt_ops { * Channel callbacks */ int (*channel_start_analyze)(struct stream *s, struct filter *f, struct channel *chn); - int (*channel_analyze) (struct stream *s, struct filter *f, struct channel *chn, unsigned int an_bit); + int (*channel_pre_analyze) (struct stream *s, struct filter *f, struct channel *chn, unsigned int an_bit); + int (*channel_post_analyze) (struct stream *s, struct filter *f, struct channel *chn, unsigned int an_bit); int (*channel_end_analyze) (struct stream *s, struct filter *f, struct channel *chn); /* @@ -202,6 +207,8 @@ struct filter { * 0: request channel, 1: response channel */ unsigned int fwd[2]; /* Offset, relative to buf->p, to the next byte to forward for a specific channel * 0: request channel, 1: response channel */ + unsigned int pre_analyzers; /* bit field indicating analyzers to pre-process */ + unsigned int post_analyzers; /* bit field indicating analyzers to post-process */ struct list list; /* Next filter for the same proxy/stream */ }; diff --git a/src/filters.c b/src/filters.c index 051aa4873..139440d15 100644 --- a/src/filters.c +++ b/src/filters.c @@ -656,20 +656,23 @@ flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) } /* - * Calls 'channel_analyze' callback for all filters attached to a stream. This - * function is called before each analyzer attached to a channel, expects - * analyzers responsible for data sending. 'channel_analyze' callback is - * resumable, so this function returns 0 if an error occurs or if it needs to - * wait, any other value otherwise. + * Calls 'channel_pre_analyze' callback for all filters attached to a + * stream. This function is called BEFORE each analyzer attached to a channel, + * expects analyzers responsible for data sending. 'channel_pre_analyze' + * callback is resumable, so this function returns 0 if an error occurs or if it + * needs to wait, any other value otherwise. + * + * Note this function can be called many times for the same analyzer. In fact, + * it is called until the analyzer finishes its processing. */ int -flt_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) +flt_pre_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) { int ret = 1; RESUME_FILTER_LOOP(s, chn) { - if (FLT_OPS(filter)->channel_analyze) { - ret = FLT_OPS(filter)->channel_analyze(s, filter, chn, an_bit); + if (FLT_OPS(filter)->channel_pre_analyze && (filter->pre_analyzers & an_bit)) { + ret = FLT_OPS(filter)->channel_pre_analyze(s, filter, chn, an_bit); if (ret <= 0) BREAK_EXECUTION(s, chn, check_result); } @@ -679,6 +682,31 @@ flt_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) return handle_analyzer_result(s, chn, 0, ret); } +/* + * Calls 'channel_post_analyze' callback for all filters attached to a + * stream. This function is called AFTER each analyzer attached to a channel, + * expects analyzers responsible for data sending. 'channel_post_analyze' + * callback is NOT resumable, so this function returns a 0 if an error occurs, + * any other value otherwise. + * + * Here, AFTER means when the analyzer finishes its processing. + */ +int +flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) +{ + struct filter *filter; + int ret = 1; + + list_for_each_entry(filter, &strm_flt(s)->filters, list) { + if (FLT_OPS(filter)->channel_post_analyze && (filter->post_analyzers & an_bit)) { + ret = FLT_OPS(filter)->channel_post_analyze(s, filter, chn, an_bit); + if (ret < 0) + break; + } + } + return handle_analyzer_result(s, chn, 0, ret); +} + /* * 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 diff --git a/src/flt_trace.c b/src/flt_trace.c index 8a9d14dfa..a052ab59b 100644 --- a/src/flt_trace.c +++ b/src/flt_trace.c @@ -145,7 +145,8 @@ trace_chn_start_analyze(struct stream *s, struct filter *filter, STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s)", __FUNCTION__, channel_label(chn), proxy_mode(s), stream_pos(s)); - register_data_filter(s, chn, filter); + filter->pre_analyzers |= (AN_REQ_ALL | AN_RES_ALL); + filter->post_analyzers |= (AN_REQ_ALL | AN_RES_ALL); return 1; } @@ -216,10 +217,11 @@ trace_chn_analyze(struct stream *s, struct filter *filter, ana = "unknown"; } - STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - analyzer=%s", + STRM_TRACE(conf, s, "%-25s: channel=%-10s - mode=%-5s (%s) - " + "analyzer=%s - step=%s", __FUNCTION__, channel_label(chn), proxy_mode(s), stream_pos(s), - ana); + ana, ((chn->analysers & an_bit) ? "PRE" : "POST")); return 1; } @@ -413,7 +415,8 @@ struct flt_ops trace_ops = { /* Handle channels activity */ .channel_start_analyze = trace_chn_start_analyze, - .channel_analyze = trace_chn_analyze, + .channel_pre_analyze = trace_chn_analyze, + .channel_post_analyze = trace_chn_analyze, .channel_end_analyze = trace_chn_end_analyze, /* Filter HTTP requests and responses */ diff --git a/src/stream.c b/src/stream.c index 24eba1b71..2ca3b3600 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1498,17 +1498,19 @@ 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, 'channel_analyaze' callback is called. - * The second are used for other analyzers (AN_FLT_* and + * stream has some registered filters, pre and post analyaze callbacks are + * called. The second are used for other analyzers (AN_FLT_* and * AN_REQ/RES_HTTP_XFER_BODY) */ #define FLT_ANALYZE(strm, chn, fun, list, back, flag, ...) \ { \ if ((list) & (flag)) { \ if (HAS_FILTERS(strm)) { \ - if (!flt_analyze((strm), (chn), (flag))) \ + if (!flt_pre_analyze((strm), (chn), (flag))) \ break; \ if (!fun((strm), (chn), (flag), ##__VA_ARGS__)) \ break; \ + if (!flt_post_analyze((strm), (chn), (flag))) \ + break; \ } \ else { \ if (!fun((strm), (chn), (flag), ##__VA_ARGS__)) \