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);
#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
* - 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
* 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);
/*
* 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 */
};
}
/*
- * 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);
}
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
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;
}
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;
}
/* 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 */
/* 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__)) \