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.
diff --git a/src/filters.c b/src/filters.c
index 974c742..01dc5fa 100644
--- a/src/filters.c
+++ b/src/filters.c
@@ -295,6 +295,7 @@
 	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 @@
 
 	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 @@
 			pool_free2(pool2_filter, filter);
 		}
 	}
+	if (LIST_ISEMPTY(&s->strm_flt.filters))
+		s->strm_flt.has_filters = 0;
 }
 
 /*
@@ -393,9 +397,6 @@
 	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 @@
 {
 	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 @@
 	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 @@
 	}
 	/* Restore the original buffer state */
 	msg->chn->buf->i = buf_i;
- end:
 	return ret;
 }
 
@@ -492,9 +483,6 @@
 {
 	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 @@
 {
 	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 @@
 {
 	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 @@
 {
 	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 @@
 {
 	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 @@
 {
 	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 @@
 	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 @@
 {
 	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 @@
 
  check_result:
 	ret = handle_analyzer_result(s, chn, 0, ret);
- end:
 	return ret;
 }
 
diff --git a/src/proto_http.c b/src/proto_http.c
index 48d12f0..3b39e9c 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -935,7 +935,7 @@
 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 @@
 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 @@
 		}
 		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 @@
 			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 @@
 	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 @@
 	 * 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 @@
 		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 @@
 					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 @@
 					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 @@
 					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 @@
 			/* 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 @@
 
  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 @@
 		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 @@
 	}
 
  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 @@
  * 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 @@
 		 * 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 @@
 			  * 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 @@
 					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 @@
 					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 @@
 					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 @@
 			/* 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 @@
 
  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)
diff --git a/src/stream.c b/src/stream.c
index c5d6d43..a274ea4 100644
--- a/src/stream.c
+++ b/src/stream.c
@@ -1765,107 +1765,95 @@
 				}
 
 				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))
+				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) {
-					if (!flt_analyze(s, req, AN_REQ_HTTP_PROCESS_BE))
-						break;
+					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) {
-					if (!flt_analyze(s, req, AN_REQ_HTTP_TARPIT))
-						break;
+					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) {
-					if (!flt_analyze(s, req, AN_REQ_SRV_RULES))
-						break;
+					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) {
-					if (!flt_analyze(s, req, AN_REQ_HTTP_INNER))
-						break;
+					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) {
-					if (!flt_analyze(s, req, AN_REQ_PRST_RDP_COOKIE))
-						break;
+					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) {
-					if (!flt_analyze(s, req, AN_REQ_STICKING_RULES))
-						break;
+					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_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_FLT_XFER_DATA) {
 					if (!flt_xfer_data(s, req, AN_FLT_XFER_DATA))
 						break;
@@ -1958,44 +1946,40 @@
 					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;