diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:35:11 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:35:11 +0000 |
commit | da76459dc21b5af2449af2d36eb95226cb186ce2 (patch) | |
tree | 542ebb3c1e796fac2742495b8437331727bbbfa0 /addons/ot/src/filter.c | |
parent | Initial commit. (diff) | |
download | haproxy-upstream/2.6.12.tar.xz haproxy-upstream/2.6.12.zip |
Adding upstream version 2.6.12.upstream/2.6.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'addons/ot/src/filter.c')
-rw-r--r-- | addons/ot/src/filter.c | 1176 |
1 files changed, 1176 insertions, 0 deletions
diff --git a/addons/ot/src/filter.c b/addons/ot/src/filter.c new file mode 100644 index 0000000..cf67fd2 --- /dev/null +++ b/addons/ot/src/filter.c @@ -0,0 +1,1176 @@ +/*** + * Copyright 2020 HAProxy Technologies + * + * This file is part of the HAProxy OpenTracing filter. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "include.h" + + +/* + * OpenTracing filter id, used to identify OpenTracing filters. + * The name of this variable is consistent with the other filter names + * declared in include/haproxy/filters.h . + */ +const char *ot_flt_id = "the OpenTracing filter"; + + +/*** + * NAME + * flt_ot_is_disabled - + * + * ARGUMENTS + * f - + * event - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * - + */ +bool flt_ot_is_disabled(const struct filter *f FLT_OT_DBG_ARGS(, int event)) +{ +#ifdef DEBUG_OT + const struct flt_ot_conf *conf = FLT_OT_CONF(f); + const char *msg; +#endif + bool retval; + + retval = FLT_OT_RT_CTX(f->ctx)->flag_disabled ? 1 : 0; + +#ifdef DEBUG_OT + msg = retval ? " (disabled)" : ""; + + if (FLT_OT_IN_RANGE(event, 0, FLT_OT_EVENT_MAX - 1)) + FLT_OT_DBG(2, "filter '%s', type: %s, event: '%s' %d%s", conf->id, flt_ot_type(f), flt_ot_event_data[event].name, event, msg); + else + FLT_OT_DBG(2, "filter '%s', type: %s%s", conf->id, flt_ot_type(f), msg); +#endif + + return retval; +} + + +/*** + * NAME + * flt_ot_return_int - + * + * ARGUMENTS + * f - + * err - + * retval - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * - + */ +static int flt_ot_return_int(const struct filter *f, char **err, int retval) +{ + struct flt_ot_runtime_context *rt_ctx = f->ctx; + + if ((retval == FLT_OT_RET_ERROR) || ((err != NULL) && (*err != NULL))) { + if (rt_ctx->flag_harderr) { + FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)"); + + rt_ctx->flag_disabled = 1; + + _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1); + } else { + FLT_OT_DBG(1, "WARNING: filter soft-error"); + } + + retval = FLT_OT_RET_OK; + } + + FLT_OT_ERR_FREE(*err); + + return retval; +} + + +/*** + * NAME + * flt_ot_return_void - + * + * ARGUMENTS + * f - + * err - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_return_void(const struct filter *f, char **err) +{ + struct flt_ot_runtime_context *rt_ctx = f->ctx; + + if ((err != NULL) && (*err != NULL)) { + if (rt_ctx->flag_harderr) { + FLT_OT_DBG(1, "WARNING: filter hard-error (disabled)"); + + rt_ctx->flag_disabled = 1; + + _HA_ATOMIC_ADD(FLT_OT_CONF(f)->cnt.disabled + 1, 1); + } else { + FLT_OT_DBG(1, "WARNING: filter soft-error"); + } + } + + FLT_OT_ERR_FREE(*err); +} + + +/*** + * NAME + * flt_ot_init - Initialize the filter. + * + * ARGUMENTS + * p - + * fconf - + * + * DESCRIPTION + * It initializes the filter for a proxy. You may define this callback + * if you need to complete your filter configuration. + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_init(struct proxy *p, struct flt_conf *fconf) +{ + struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL); + char *err = NULL; + int retval = FLT_OT_RET_ERROR; + + FLT_OT_FUNC("%p, %p", p, fconf); + + if (conf == NULL) + FLT_OT_RETURN_INT(retval); + + flt_ot_cli_init(); + + /* + * Initialize the OpenTracing library. + */ + retval = ot_init(&(conf->tracer->tracer), conf->tracer->plugin, &err); + if (retval != FLT_OT_RET_ERROR) + /* Do nothing. */; + else if (err != NULL) { + FLT_OT_ALERT("%s", err); + + FLT_OT_ERR_FREE(err); + } + + FLT_OT_RETURN_INT(retval); +} + + +/*** + * NAME + * flt_ot_deinit - Free resources allocated by the filter. + * + * ARGUMENTS + * p - + * fconf - + * + * DESCRIPTION + * It cleans up what the parsing function and the init callback have done. + * This callback is useful to release memory allocated for the filter + * configuration. + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_deinit(struct proxy *p, struct flt_conf *fconf) +{ + struct flt_ot_conf **conf = (fconf == NULL) ? NULL : (typeof(conf))&(fconf->conf); +#ifdef DEBUG_OT + int i; +#endif + + FLT_OT_FUNC("%p, %p", p, fconf); + + if (conf == NULL) + FLT_OT_RETURN(); + + ot_debug(); + ot_close(&((*conf)->tracer->tracer)); + +#ifdef DEBUG_OT + FLT_OT_DBG(0, "--- used events ----------"); + for (i = 0; i < FLT_OT_TABLESIZE((*conf)->cnt.event); i++) + if ((*conf)->cnt.event[i].flag_used) + FLT_OT_DBG(0, " %02d: %" PRIu64 " / %" PRIu64, i, (*conf)->cnt.event[i].htx[0], (*conf)->cnt.event[i].htx[1]); +#endif + + flt_ot_conf_free(conf); + + FLT_OT_MEMINFO(); + + FLT_OT_RETURN(); +} + + +/*** + * NAME + * flt_ot_check - Check configuration of the filter for the specified proxy. + * + * ARGUMENTS + * p - + * fconf - + * + * DESCRIPTION + * Optionally, by implementing the flt_ot_check() callback, you add a + * step to check the internal configuration of your filter after the + * parsing phase, when the HAProxy configuration is fully defined. + * + * RETURN VALUE + * Returns the number of encountered errors. + */ +static int flt_ot_check(struct proxy *p, struct flt_conf *fconf) +{ + struct proxy *px; + struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL); + struct flt_ot_conf_group *conf_group; + struct flt_ot_conf_scope *conf_scope; + struct flt_ot_conf_ph *ph_group, *ph_scope; + int retval = 0, scope_unused_cnt = 0, span_root_cnt = 0; + + FLT_OT_FUNC("%p, %p", p, fconf); + + if (conf == NULL) + FLT_OT_RETURN_INT(++retval); + + /* + * If only the proxy specified with the <p> parameter is checked, then + * no duplicate filters can be found that are not defined in the same + * configuration sections. + */ + for (px = proxies_list; px != NULL; px = px->next) { + struct flt_conf *fconf_tmp; + + FLT_OT_DBG(2, "proxy '%s'", px->id); + + /* + * The names of all OT filters (filter ID) should be checked, + * they must be unique. + */ + list_for_each_entry(fconf_tmp, &(px->filter_configs), list) + if ((fconf_tmp != fconf) && (fconf_tmp->id == ot_flt_id)) { + struct flt_ot_conf *conf_tmp = fconf_tmp->conf; + + FLT_OT_DBG(2, " OT filter '%s'", conf_tmp->id); + + if (strcmp(conf_tmp->id, conf->id) == 0) { + FLT_OT_ALERT("''%s' : duplicated filter ID'", conf_tmp->id); + + retval++; + } + } + } + + if (FLT_OT_DEREF(conf->tracer, id, NULL) == NULL) { + FLT_OT_ALERT("''%s' : no tracer found'", conf->id); + + retval++; + } + + /* + * Checking that all defined 'ot-group' sections have correctly declared + * 'ot-scope' sections (ie whether the declared 'ot-scope' sections have + * corresponding definitions). + */ + list_for_each_entry(conf_group, &(conf->groups), list) + list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) { + bool flag_found = 0; + + list_for_each_entry(conf_scope, &(conf->scopes), list) + if (strcmp(ph_scope->id, conf_scope->id) == 0) { + ph_scope->ptr = conf_scope; + conf_scope->flag_used = 1; + flag_found = 1; + + break; + } + + if (!flag_found) { + FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_GROUP_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf_group->id, ph_scope->id); + + retval++; + } + } + + if (conf->tracer != NULL) { + /* + * Checking that all declared 'groups' keywords have correctly + * defined 'ot-group' sections. + */ + list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list) { + bool flag_found = 0; + + list_for_each_entry(conf_group, &(conf->groups), list) + if (strcmp(ph_group->id, conf_group->id) == 0) { + ph_group->ptr = conf_group; + conf_group->flag_used = 1; + flag_found = 1; + + break; + } + + if (!flag_found) { + FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_GROUP_ID " '%s''", conf->tracer->id, ph_group->id); + + retval++; + } + } + + /* + * Checking that all declared 'scopes' keywords have correctly + * defined 'ot-scope' sections. + */ + list_for_each_entry(ph_scope, &(conf->tracer->ph_scopes), list) { + bool flag_found = 0; + + list_for_each_entry(conf_scope, &(conf->scopes), list) + if (strcmp(ph_scope->id, conf_scope->id) == 0) { + ph_scope->ptr = conf_scope; + conf_scope->flag_used = 1; + flag_found = 1; + + break; + } + + if (!flag_found) { + FLT_OT_ALERT("'" FLT_OT_PARSE_SECTION_TRACER_ID " '%s' : try to use undefined " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->tracer->id, ph_scope->id); + + retval++; + } + } + } + + FLT_OT_DBG(3, "--- filter '%s' configuration ----------", conf->id); + FLT_OT_DBG(3, "- defined spans ----------"); + + list_for_each_entry(conf_scope, &(conf->scopes), list) { + if (conf_scope->flag_used) { + struct flt_ot_conf_span *conf_span; + + /* + * In principle, only one span should be labeled + * as a root span. + */ + list_for_each_entry(conf_span, &(conf_scope->spans), list) { + FLT_OT_DBG_CONF_SPAN(" ", conf_span); + + span_root_cnt += conf_span->flag_root ? 1 : 0; + } + +#ifdef DEBUG_OT + conf->cnt.event[conf_scope->event].flag_used = 1; +#endif + + /* Set the flags of the analyzers used. */ + conf->tracer->analyzers |= flt_ot_event_data[conf_scope->event].an_bit; + } else { + FLT_OT_ALERT("''%s' : unused " FLT_OT_PARSE_SECTION_SCOPE_ID " '%s''", conf->id, conf_scope->id); + + scope_unused_cnt++; + } + } + + /* + * Unused scopes or a number of root spans other than one do not + * necessarily have to be errors, but it is good to print it when + * starting HAProxy. + */ + if (scope_unused_cnt > 0) + FLT_OT_ALERT("''%s' : %d scope(s) not in use'", conf->id, scope_unused_cnt); + + if (LIST_ISEMPTY(&(conf->scopes))) + /* Do nothing. */; + else if (span_root_cnt == 0) + FLT_OT_ALERT("''%s' : no span is marked as the root span'", conf->id); + else if (span_root_cnt > 1) + FLT_OT_ALERT("''%s' : multiple spans are marked as the root span'", conf->id); + + FLT_OT_DBG_LIST(conf, group, "", "defined", _group, + FLT_OT_DBG_CONF_GROUP(" ", _group); + FLT_OT_DBG_LIST(_group, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope))); + FLT_OT_DBG_LIST(conf, scope, "", "defined", _scope, FLT_OT_DBG_CONF_SCOPE(" ", _scope)); + + if (conf->tracer != NULL) { + FLT_OT_DBG(3, " --- tracer '%s' configuration ----------", conf->tracer->id); + FLT_OT_DBG_LIST(conf->tracer, ph_group, " ", "used", _group, FLT_OT_DBG_CONF_PH(" ", _group)); + FLT_OT_DBG_LIST(conf->tracer, ph_scope, " ", "used", _scope, FLT_OT_DBG_CONF_PH(" ", _scope)); + } + + FLT_OT_RETURN_INT(retval); +} + + +/*** + * NAME + * flt_ot_init_per_thread - + * + * ARGUMENTS + * p - + * fconf - + * + * DESCRIPTION + * It initializes the filter for each thread. It works the same way than + * flt_ot_init() but in the context of a thread. This callback is called + * after the thread creation. + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_init_per_thread(struct proxy *p, struct flt_conf *fconf) +{ + struct flt_ot_conf *conf = FLT_OT_DEREF(fconf, conf, NULL); + char *err = NULL; + int retval = FLT_OT_RET_ERROR; + + FLT_OT_FUNC("%p, %p", p, fconf); + + if (conf == NULL) + FLT_OT_RETURN_INT(retval); + + /* + * Start the OpenTracing library tracer thread. + * Enable HTX streams filtering. + */ + if (!(fconf->flags & FLT_CFG_FL_HTX)) { + retval = ot_start(conf->tracer->tracer, conf->tracer->cfgbuf, &err); + if (retval != FLT_OT_RET_ERROR) + fconf->flags |= FLT_CFG_FL_HTX; + else if (err != NULL) { + FLT_OT_ALERT("%s", err); + + FLT_OT_ERR_FREE(err); + } + } else { + retval = FLT_OT_RET_OK; + } + + FLT_OT_RETURN_INT(retval); +} + + +#ifdef DEBUG_OT + +/*** + * NAME + * flt_ot_deinit_per_thread - + * + * ARGUMENTS + * p - + * fconf - + * + * DESCRIPTION + * It cleans up what the init_per_thread callback have done. It is called + * in the context of a thread, before exiting it. + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_deinit_per_thread(struct proxy *p, struct flt_conf *fconf) +{ + FLT_OT_FUNC("%p, %p", p, fconf); + + FLT_OT_RETURN(); +} + +#endif /* DEBUG_OT */ + + +/*** + * NAME + * flt_ot_attach - Called when a filter instance is created and attach to a stream. + * + * ARGUMENTS + * s - + * f - + * + * DESCRIPTION + * It is called after a filter instance creation, when it is attached to a + * stream. This happens when the stream is started for filters defined on + * the stream's frontend and when the backend is set for filters declared + * on the stream's backend. It is possible to ignore the filter, if needed, + * by returning 0. This could be useful to have conditional filtering. + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 to ignore the filter, + * any other value otherwise. + */ +static int flt_ot_attach(struct stream *s, struct filter *f) +{ + const struct flt_ot_conf *conf = FLT_OT_CONF(f); + char *err = NULL; + + FLT_OT_FUNC("%p, %p", s, f); + + if (conf->tracer->flag_disabled) { + FLT_OT_DBG(2, "filter '%s', type: %s (disabled)", conf->id, flt_ot_type(f)); + + FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE); + } + else if (conf->tracer->rate_limit < FLT_OT_FLOAT_U32(FLT_OT_RATE_LIMIT_MAX, FLT_OT_RATE_LIMIT_MAX)) { + uint32_t rnd = ha_random32(); + + if (conf->tracer->rate_limit <= rnd) { + FLT_OT_DBG(2, "filter '%s', type: %s (ignored: %u <= %u)", conf->id, flt_ot_type(f), conf->tracer->rate_limit, rnd); + + FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE); + } + } + + FLT_OT_DBG(2, "filter '%s', type: %s (run)", conf->id, flt_ot_type(f)); + + f->ctx = flt_ot_runtime_context_init(s, f, &err); + FLT_OT_ERR_FREE(err); + if (f->ctx == NULL) { + FLT_OT_LOG(LOG_EMERG, "failed to create context"); + + FLT_OT_RETURN_INT(FLT_OT_RET_IGNORE); + } + + /* + * AN_REQ_WAIT_HTTP and AN_RES_WAIT_HTTP analyzers can only be used + * in the .channel_post_analyze callback function. + */ + f->pre_analyzers |= conf->tracer->analyzers & ((AN_REQ_ALL & ~AN_REQ_WAIT_HTTP & ~AN_REQ_HTTP_TARPIT) | (AN_RES_ALL & ~AN_RES_WAIT_HTTP)); + f->post_analyzers |= conf->tracer->analyzers & (AN_REQ_WAIT_HTTP | AN_RES_WAIT_HTTP); + + FLT_OT_LOG(LOG_INFO, "%08x %08x", f->pre_analyzers, f->post_analyzers); + +#ifdef USE_OT_VARS + flt_ot_vars_dump(s); +#endif + flt_ot_http_headers_dump(&(s->req)); + + FLT_OT_RETURN_INT(FLT_OT_RET_OK); +} + + +#ifdef DEBUG_OT + +/*** + * NAME + * flt_ot_stream_start - Called when a stream is created. + * + * ARGUMENTS + * s - + * f - + * + * DESCRIPTION + * It is called when a stream is started. This callback can fail by + * returning a negative value. It will be considered as a critical error + * by HAProxy which disabled the listener for a short time. + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_stream_start(struct stream *s, struct filter *f) +{ + char *err = NULL; + int retval = FLT_OT_RET_OK; + + FLT_OT_FUNC("%p, %p", s, f); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(retval); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_stream_set_backend - Called when a backend is set for a stream. + * + * ARGUMENTS + * s - + * f - + * be - + * + * DESCRIPTION + * It is called when a backend is set for a stream. This callbacks will be + * called for all filters attached to a stream (frontend and backend). Note + * this callback is not called if the frontend and the backend are the same. + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_stream_set_backend(struct stream *s, struct filter *f, struct proxy *be) +{ + char *err = NULL; + int retval = FLT_OT_RET_OK; + + FLT_OT_FUNC("%p, %p, %p", s, f, be); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(retval); + + FLT_OT_DBG(3, "backend: %s", be->id); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_stream_stop - Called when a stream is destroyed. + * + * ARGUMENTS + * s - + * f - + * + * DESCRIPTION + * It is called when a stream is stopped. This callback always succeed. + * Anyway, it is too late to return an error. + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_stream_stop(struct stream *s, struct filter *f) +{ + char *err = NULL; + + FLT_OT_FUNC("%p, %p", s, f); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN(); + + flt_ot_return_void(f, &err); + + FLT_OT_RETURN(); +} + +#endif /* DEBUG_OT */ + + +/*** + * NAME + * flt_ot_detach - Called when a filter instance is detach from a stream, just before its destruction. + * + * ARGUMENTS + * s - + * f - + * + * DESCRIPTION + * It is called when a filter instance is detached from a stream, before its + * destruction. This happens when the stream is stopped for filters defined + * on the stream's frontend and when the analyze ends for filters defined on + * the stream's backend. + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_detach(struct stream *s, struct filter *f) +{ + FLT_OT_FUNC("%p, %p", s, f); + + FLT_OT_DBG(2, "filter '%s', type: %s", FLT_OT_CONF(f)->id, flt_ot_type(f)); + + flt_ot_runtime_context_free(f); + + FLT_OT_RETURN(); +} + + +/*** + * NAME + * flt_ot_check_timeouts - Called when a stream is woken up because of an expired timer. + * + * ARGUMENTS + * s - + * f - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_check_timeouts(struct stream *s, struct filter *f) +{ + char *err = NULL; + + FLT_OT_FUNC("%p, %p", s, f); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN(); + + s->pending_events |= TASK_WOKEN_MSG; + + flt_ot_return_void(f, &err); + + FLT_OT_RETURN(); +} + + +/*** + * NAME + * flt_ot_channel_start_analyze - Called when analyze starts for a given channel. + * + * ARGUMENTS + * s - + * f - + * chn - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_channel_start_analyze(struct stream *s, struct filter *f, struct channel *chn) +{ + char *err = NULL; + int retval; + + FLT_OT_FUNC("%p, %p, %p", s, f, chn); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_START : FLT_OT_EVENT_REQ_CLIENT_SESS_START))) + FLT_OT_RETURN_INT(FLT_OT_RET_OK); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s)); + + if (chn->flags & CF_ISRESP) { + /* The response channel. */ + chn->analysers |= f->pre_analyzers & AN_RES_ALL; + + /* The event 'on-server-session-start'. */ + retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_START, &err); + if (retval == FLT_OT_RET_WAIT) { + channel_dont_read(chn); + channel_dont_close(chn); + } + } else { + /* The request channel. */ + chn->analysers |= f->pre_analyzers & AN_REQ_ALL; + + /* The event 'on-client-session-start'. */ + retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_START, &err); + } + +// register_data_filter(s, chn, f); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_channel_pre_analyze - Called before a processing happens on a given channel. + * + * ARGUMENTS + * s - + * f - + * chn - the channel on which the analyzing is done + * an_bit - the analyzer id + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_channel_pre_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit) +{ + char *err = NULL; + int i, event = -1, retval; + + FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit); + + for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++) + if (flt_ot_event_data[i].an_bit == an_bit) { + event = i; + + break; + } + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event))) + FLT_OT_RETURN_INT(FLT_OT_RET_OK); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit)); + + retval = flt_ot_event_run(s, f, chn, event, &err); + + if ((retval == FLT_OT_RET_WAIT) && (chn->flags & CF_ISRESP)) { + channel_dont_read(chn); + channel_dont_close(chn); + } + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_channel_post_analyze - Called after a processing happens on a given channel. + * + * ARGUMENTS + * s - + * f - + * chn - + * an_bit - + * + * DESCRIPTION + * This function, for its part, is not resumable. It is called when a + * filterable analyzer finishes its processing. So it called once for + * the same analyzer. + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_channel_post_analyze(struct stream *s, struct filter *f, struct channel *chn, uint an_bit) +{ + char *err = NULL; + int i, event = -1, retval; + + FLT_OT_FUNC("%p, %p, %p, 0x%08x", s, f, chn, an_bit); + + for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_event_data); i++) + if (flt_ot_event_data[i].an_bit == an_bit) { + event = i; + + break; + } + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, event))) + FLT_OT_RETURN_INT(FLT_OT_RET_OK); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s), analyzer: %s", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), flt_ot_analyzer(an_bit)); + + retval = flt_ot_event_run(s, f, chn, event, &err); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_channel_end_analyze - Called when analyze ends for a given channel. + * + * ARGUMENTS + * s - + * f - + * chn - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_channel_end_analyze(struct stream *s, struct filter *f, struct channel *chn) +{ + char *err = NULL; + int rc, retval; + + FLT_OT_FUNC("%p, %p, %p", s, f, chn); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, (chn->flags & CF_ISRESP) ? FLT_OT_EVENT_RES_SERVER_SESS_END : FLT_OT_EVENT_REQ_CLIENT_SESS_END))) + FLT_OT_RETURN_INT(FLT_OT_RET_OK); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s)); + + if (chn->flags & CF_ISRESP) { + /* The response channel, event 'on-server-session-end'. */ + retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_RES_SERVER_SESS_END, &err); + } else { + /* The request channel, event 'on-client-session-end'. */ + retval = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_CLIENT_SESS_END, &err); + + /* + * In case an event using server response is defined and not + * executed, event 'on-server-unavailable' is called here. + */ + if ((FLT_OT_CONF(f)->tracer->analyzers & AN_RES_ALL) && !(FLT_OT_RT_CTX(f->ctx)->analyzers & AN_RES_ALL)) { + rc = flt_ot_event_run(s, f, chn, FLT_OT_EVENT_REQ_SERVER_UNAVAILABLE, &err); + if ((retval == FLT_OT_RET_OK) && (rc != FLT_OT_RET_OK)) + retval = rc; + } + } + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +#ifdef DEBUG_OT + +/*** + * NAME + * flt_ot_http_headers - + * + * ARGUMENTS + * s - + * f - + * msg - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_http_headers(struct stream *s, struct filter *f, struct http_msg *msg) +{ + char *err = NULL; + struct htx *htx = htxbuf(&(msg->chn->buf)); + struct htx_sl *sl = http_get_stline(htx); + int retval = FLT_OT_RET_OK; + + FLT_OT_FUNC("%p, %p, %p", s, f, msg); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(retval); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s), %.*s %.*s %.*s", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), HTX_SL_P1_LEN(sl), HTX_SL_P1_PTR(sl), HTX_SL_P2_LEN(sl), HTX_SL_P2_PTR(sl), HTX_SL_P3_LEN(sl), HTX_SL_P3_PTR(sl)); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_http_payload - + * + * ARGUMENTS + * s - + * f - + * msg - + * offset - + * len - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_http_payload(struct stream *s, struct filter *f, struct http_msg *msg, uint offset, uint len) +{ + char *err = NULL; + int retval = len; + + FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, msg, offset, len); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(len); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval); + + if (retval != len) + task_wakeup(s->task, TASK_WOKEN_MSG); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_http_end - + * + * ARGUMENTS + * s - + * f - + * msg - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, 0 if it needs to wait, + * any other value otherwise. + */ +static int flt_ot_http_end(struct stream *s, struct filter *f, struct http_msg *msg) +{ + char *err = NULL; + int retval = FLT_OT_RET_OK; + + FLT_OT_FUNC("%p, %p, %p", s, f, msg); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(retval); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s)); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + + +/*** + * NAME + * flt_ot_http_reset - + * + * ARGUMENTS + * s - + * f - + * msg - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_http_reset(struct stream *s, struct filter *f, struct http_msg *msg) +{ + char *err = NULL; + + FLT_OT_FUNC("%p, %p, %p", s, f, msg); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN(); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s)", flt_ot_chn_label(msg->chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s)); + + flt_ot_return_void(f, &err); + + FLT_OT_RETURN(); +} + + +/*** + * NAME + * flt_ot_http_reply - + * + * ARGUMENTS + * s - + * f - + * status - + * msg - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * This function does not return a value. + */ +static void flt_ot_http_reply(struct stream *s, struct filter *f, short status, const struct buffer *msg) +{ + char *err = NULL; + + FLT_OT_FUNC("%p, %p, %hd, %p", s, f, status, msg); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN(); + + FLT_OT_DBG(3, "channel: -, mode: %s (%s)", flt_ot_pr_mode(s), flt_ot_stream_pos(s)); + + flt_ot_return_void(f, &err); + + FLT_OT_RETURN(); +} + + +/*** + * NAME + * flt_ot_tcp_payload - + * + * ARGUMENTS + * s - + * f - + * chn - + * offset - + * len - + * + * DESCRIPTION + * - + * + * RETURN VALUE + * Returns a negative value if an error occurs, any other value otherwise. + */ +static int flt_ot_tcp_payload(struct stream *s, struct filter *f, struct channel *chn, uint offset, uint len) +{ + char *err = NULL; + int retval = len; + + FLT_OT_FUNC("%p, %p, %p, %u, %u", s, f, chn, offset, len); + + if (flt_ot_is_disabled(f FLT_OT_DBG_ARGS(, -1))) + FLT_OT_RETURN_INT(len); + + FLT_OT_DBG(3, "channel: %s, mode: %s (%s), offset: %u, len: %u, forward: %d", flt_ot_chn_label(chn), flt_ot_pr_mode(s), flt_ot_stream_pos(s), offset, len, retval); + + if (s->flags & SF_HTX) { + } else { + } + + if (retval != len) + task_wakeup(s->task, TASK_WOKEN_MSG); + + FLT_OT_RETURN_INT(flt_ot_return_int(f, &err, retval)); +} + +#endif /* DEBUG_OT */ + + +struct flt_ops flt_ot_ops = { + /* Callbacks to manage the filter lifecycle. */ + .init = flt_ot_init, + .deinit = flt_ot_deinit, + .check = flt_ot_check, + .init_per_thread = flt_ot_init_per_thread, + .deinit_per_thread = FLT_OT_DBG_IFDEF(flt_ot_deinit_per_thread, NULL), + + /* Stream callbacks. */ + .attach = flt_ot_attach, + .stream_start = FLT_OT_DBG_IFDEF(flt_ot_stream_start, NULL), + .stream_set_backend = FLT_OT_DBG_IFDEF(flt_ot_stream_set_backend, NULL), + .stream_stop = FLT_OT_DBG_IFDEF(flt_ot_stream_stop, NULL), + .detach = flt_ot_detach, + .check_timeouts = flt_ot_check_timeouts, + + /* Channel callbacks. */ + .channel_start_analyze = flt_ot_channel_start_analyze, + .channel_pre_analyze = flt_ot_channel_pre_analyze, + .channel_post_analyze = flt_ot_channel_post_analyze, + .channel_end_analyze = flt_ot_channel_end_analyze, + + /* HTTP callbacks. */ + .http_headers = FLT_OT_DBG_IFDEF(flt_ot_http_headers, NULL), + .http_payload = FLT_OT_DBG_IFDEF(flt_ot_http_payload, NULL), + .http_end = FLT_OT_DBG_IFDEF(flt_ot_http_end, NULL), + .http_reset = FLT_OT_DBG_IFDEF(flt_ot_http_reset, NULL), + .http_reply = FLT_OT_DBG_IFDEF(flt_ot_http_reply, NULL), + + /* TCP callbacks. */ + .tcp_payload = FLT_OT_DBG_IFDEF(flt_ot_tcp_payload, NULL) +}; + + +REGISTER_BUILD_OPTS("Built with OpenTracing support."); + +/* + * Local variables: + * c-indent-level: 8 + * c-basic-offset: 8 + * End: + * + * vi: noexpandtab shiftwidth=8 tabstop=8 + */ |