mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-03-14 19:41:33 +01:00
MINOR: filters: rework RESUME_FILTER_* macros as inline functions
There is no need to have those helpers defined as macro, and since it is not mandatory, code maintenance is much easier using functions, thus let's switch to function definitions. Also, we change the way we iterate over the list so that the calling function now has a pseudo API to get and iterate over filter pointers while keeping control on how they implement the iterating logic. One benefit of this is that we will also be able to switch between lists depending on the channel type, which is a prerequisite for upcoming rework that split the filter list over request and response channels (commit will follow) No change of behavior is expected.
This commit is contained in:
parent
f47b800ac3
commit
e88b219331
160
src/filters.c
160
src/filters.c
@ -34,61 +34,75 @@ DECLARE_STATIC_TYPED_POOL(pool_head_filter, "filter", struct filter);
|
||||
|
||||
static int handle_analyzer_result(struct stream *s, struct channel *chn, unsigned int an_bit, int ret);
|
||||
|
||||
/* - RESUME_FILTER_LOOP and RESUME_FILTER_END must always be used together.
|
||||
* The first one begins a loop and the seconds one ends it.
|
||||
/* - resume_filter_list_start() and resume_filter_list_next() must always be used together.
|
||||
* The first one sets the first filter value and the second one allows to get the
|
||||
* next one until NULL is returned
|
||||
*
|
||||
* - BREAK_EXECUTION must be used to break the loop and set the filter from
|
||||
* which to resume the next time.
|
||||
* - resume_filter_list_break() must be used to break the iteration and set the filter
|
||||
* from which to resume the next time (that is, resume_filter_list_start() will allow
|
||||
* to resume from value at the time of the break)
|
||||
*
|
||||
* Here is an example:
|
||||
*
|
||||
* RESUME_FILTER_LOOP(stream, channel) {
|
||||
* ...
|
||||
* if (cond)
|
||||
* BREAK_EXECUTION(stream, channel, label);
|
||||
* ...
|
||||
* } RESUME_FILTER_END;
|
||||
* struct filter *filter;
|
||||
*
|
||||
* for (filter = resume_filter_list_start(stream, channel); filter
|
||||
* filter = resume_filter_list_next(stream, channel, filter)) {
|
||||
* ...
|
||||
* if (cond) {
|
||||
* resume_filter_list_break(stream, channel, filter, ret);
|
||||
goto label;
|
||||
* }
|
||||
* }
|
||||
* ...
|
||||
* label:
|
||||
* ...
|
||||
*
|
||||
*/
|
||||
#define RESUME_FILTER_LOOP(strm, chn) \
|
||||
do { \
|
||||
struct filter *filter; \
|
||||
\
|
||||
if (strm_flt(strm)->current[CHN_IDX(chn)]) { \
|
||||
filter = strm_flt(strm)->current[CHN_IDX(chn)]; \
|
||||
strm_flt(strm)->current[CHN_IDX(chn)] = NULL; \
|
||||
if (!(chn_prod(chn)->flags & SC_FL_ERROR) && \
|
||||
!(chn->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) { \
|
||||
(strm)->waiting_entity.type = STRM_ENTITY_NONE; \
|
||||
(strm)->waiting_entity.ptr = NULL; \
|
||||
} \
|
||||
goto resume_execution; \
|
||||
} \
|
||||
\
|
||||
list_for_each_entry(filter, &strm_flt(s)->filters, list) { \
|
||||
resume_execution:
|
||||
static inline struct filter *resume_filter_list_start(struct stream *strm, struct channel *chn)
|
||||
{
|
||||
struct filter *filter;
|
||||
|
||||
#define RESUME_FILTER_END \
|
||||
} \
|
||||
} while(0)
|
||||
if (strm_flt(strm)->current[CHN_IDX(chn)]) {
|
||||
filter = strm_flt(strm)->current[CHN_IDX(chn)];
|
||||
strm_flt(strm)->current[CHN_IDX(chn)] = NULL;
|
||||
if (!(chn_prod(chn)->flags & SC_FL_ERROR) &&
|
||||
!(chn->flags & (CF_READ_TIMEOUT|CF_WRITE_TIMEOUT))) {
|
||||
(strm)->waiting_entity.type = STRM_ENTITY_NONE;
|
||||
(strm)->waiting_entity.ptr = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
filter = LIST_NEXT(&strm_flt(strm)->filters, struct filter *, list);
|
||||
if (&filter->list == &strm_flt(strm)->filters)
|
||||
filter = NULL; /* empty list */
|
||||
}
|
||||
|
||||
#define BREAK_EXECUTION(strm, chn, label) \
|
||||
do { \
|
||||
if (ret == 0) { \
|
||||
s->waiting_entity.type = STRM_ENTITY_FILTER; \
|
||||
s->waiting_entity.ptr = filter; \
|
||||
} \
|
||||
else if (ret < 0) { \
|
||||
(strm)->last_entity.type = STRM_ENTITY_FILTER; \
|
||||
(strm)->last_entity.ptr = filter; \
|
||||
} \
|
||||
strm_flt(strm)->current[CHN_IDX(chn)] = filter; \
|
||||
goto label; \
|
||||
} while (0)
|
||||
return filter;
|
||||
}
|
||||
|
||||
static inline struct filter *resume_filter_list_next(struct stream *strm, struct channel *chn,
|
||||
struct filter *filter)
|
||||
{
|
||||
filter = LIST_NEXT(&filter->list, struct filter *, list);
|
||||
if (&filter->list == &strm_flt(strm)->filters)
|
||||
filter = NULL; /* end of list */
|
||||
return filter;
|
||||
}
|
||||
|
||||
static inline void resume_filter_list_break(struct stream *strm, struct channel *chn,
|
||||
struct filter *filter, int ret)
|
||||
{
|
||||
if (ret == 0) {
|
||||
strm->waiting_entity.type = STRM_ENTITY_FILTER;
|
||||
strm->waiting_entity.ptr = filter;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
strm->last_entity.type = STRM_ENTITY_FILTER;
|
||||
strm->last_entity.ptr = filter;
|
||||
}
|
||||
strm_flt(strm)->current[CHN_IDX(chn)] = filter;
|
||||
}
|
||||
|
||||
/* List head of all known filter keywords */
|
||||
static struct flt_kw_list flt_keywords = {
|
||||
@ -599,12 +613,14 @@ flt_set_stream_backend(struct stream *s, struct proxy *be)
|
||||
int
|
||||
flt_http_end(struct stream *s, struct http_msg *msg)
|
||||
{
|
||||
struct filter *filter;
|
||||
unsigned long long *strm_off = &FLT_STRM_OFF(s, msg->chn);
|
||||
unsigned int offset = 0;
|
||||
int ret = 1;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
|
||||
RESUME_FILTER_LOOP(s, msg->chn) {
|
||||
for (filter = resume_filter_list_start(s, msg->chn); filter;
|
||||
filter = resume_filter_list_next(s, msg->chn, filter)) {
|
||||
unsigned long long flt_off = FLT_OFF(filter, msg->chn);
|
||||
offset = flt_off - *strm_off;
|
||||
|
||||
@ -618,10 +634,12 @@ flt_http_end(struct stream *s, struct http_msg *msg)
|
||||
DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
|
||||
filter->calls++;
|
||||
ret = FLT_OPS(filter)->http_end(s, filter, msg);
|
||||
if (ret <= 0)
|
||||
BREAK_EXECUTION(s, msg->chn, end);
|
||||
if (ret <= 0) {
|
||||
resume_filter_list_break(s, msg->chn, filter, ret);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} RESUME_FILTER_END;
|
||||
}
|
||||
|
||||
c_adv(msg->chn, offset);
|
||||
*strm_off += offset;
|
||||
@ -750,6 +768,7 @@ flt_http_payload(struct stream *s, struct http_msg *msg, unsigned int len)
|
||||
int
|
||||
flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
{
|
||||
struct filter *filter;
|
||||
int ret = 1;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
|
||||
@ -761,7 +780,8 @@ flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
chn->flags |= CF_FLT_ANALYZE;
|
||||
chn->analysers |= ((chn->flags & CF_ISRESP) ? AN_RES_FLT_END : AN_REQ_FLT_END);
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
for (filter = resume_filter_list_start(s, chn); filter;
|
||||
filter = resume_filter_list_next(s, chn, filter)) {
|
||||
if (!(chn->flags & CF_ISRESP)) {
|
||||
if (an_bit == AN_REQ_FLT_START_BE &&
|
||||
!(filter->flags & FLT_FL_IS_BACKEND_FILTER))
|
||||
@ -778,10 +798,12 @@ flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
|
||||
filter->calls++;
|
||||
ret = FLT_OPS(filter)->channel_start_analyze(s, filter, chn);
|
||||
if (ret <= 0)
|
||||
BREAK_EXECUTION(s, chn, end);
|
||||
if (ret <= 0) {
|
||||
resume_filter_list_break(s, chn, filter, ret);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} RESUME_FILTER_END;
|
||||
}
|
||||
|
||||
end:
|
||||
ret = handle_analyzer_result(s, chn, an_bit, ret);
|
||||
@ -802,20 +824,24 @@ flt_start_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)
|
||||
{
|
||||
struct filter *filter;
|
||||
int ret = 1;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
for (filter = resume_filter_list_start(s, chn); filter;
|
||||
filter = resume_filter_list_next(s, chn, filter)) {
|
||||
if (FLT_OPS(filter)->channel_pre_analyze && (filter->pre_analyzers & an_bit)) {
|
||||
DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
|
||||
filter->calls++;
|
||||
ret = FLT_OPS(filter)->channel_pre_analyze(s, filter, chn, an_bit);
|
||||
if (ret <= 0)
|
||||
BREAK_EXECUTION(s, chn, check_result);
|
||||
if (ret <= 0) {
|
||||
resume_filter_list_break(s, chn, filter, ret);
|
||||
goto check_result;
|
||||
}
|
||||
filter->pre_analyzers &= ~an_bit;
|
||||
}
|
||||
} RESUME_FILTER_END;
|
||||
}
|
||||
|
||||
check_result:
|
||||
ret = handle_analyzer_result(s, chn, 0, ret);
|
||||
@ -867,20 +893,24 @@ int
|
||||
flt_analyze_http_headers(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
{
|
||||
struct http_msg *msg;
|
||||
struct filter *filter;
|
||||
int ret = 1;
|
||||
|
||||
msg = ((chn->flags & CF_ISRESP) ? &s->txn->rsp : &s->txn->req);
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s, s->txn, msg);
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
for (filter = resume_filter_list_start(s, chn); filter;
|
||||
filter = resume_filter_list_next(s, chn, filter)) {
|
||||
if (FLT_OPS(filter)->http_headers) {
|
||||
DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s);
|
||||
filter->calls++;
|
||||
ret = FLT_OPS(filter)->http_headers(s, filter, msg);
|
||||
if (ret <= 0)
|
||||
BREAK_EXECUTION(s, chn, check_result);
|
||||
if (ret <= 0) {
|
||||
resume_filter_list_break(s, chn, filter, ret);
|
||||
goto check_result;
|
||||
}
|
||||
}
|
||||
} RESUME_FILTER_END;
|
||||
}
|
||||
|
||||
if (HAS_DATA_FILTERS(s, chn)) {
|
||||
size_t data = http_get_hdrs_size(htxbuf(&chn->buf));
|
||||
@ -907,6 +937,7 @@ int
|
||||
flt_end_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
{
|
||||
int ret = 1;
|
||||
struct filter *filter;
|
||||
|
||||
DBG_TRACE_ENTER(STRM_EV_STRM_ANA|STRM_EV_FLT_ANA, s);
|
||||
|
||||
@ -915,7 +946,8 @@ flt_end_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
if (!(chn->flags & CF_FLT_ANALYZE))
|
||||
goto sync;
|
||||
|
||||
RESUME_FILTER_LOOP(s, chn) {
|
||||
for (filter = resume_filter_list_start(s, chn); filter;
|
||||
filter = resume_filter_list_next(s, chn, filter)) {
|
||||
FLT_OFF(filter, chn) = 0;
|
||||
unregister_data_filter(s, chn, filter);
|
||||
|
||||
@ -923,10 +955,12 @@ flt_end_analyze(struct stream *s, struct channel *chn, unsigned int an_bit)
|
||||
DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s);
|
||||
filter->calls++;
|
||||
ret = FLT_OPS(filter)->channel_end_analyze(s, filter, chn);
|
||||
if (ret <= 0)
|
||||
BREAK_EXECUTION(s, chn, end);
|
||||
if (ret <= 0) {
|
||||
resume_filter_list_break(s, chn, filter, ret);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
} RESUME_FILTER_END;
|
||||
}
|
||||
|
||||
end:
|
||||
/* We don't remove yet this analyzer because we need to synchronize the
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user