summaryrefslogtreecommitdiffstats
path: root/addons/ot/src/group.c
diff options
context:
space:
mode:
Diffstat (limited to 'addons/ot/src/group.c')
-rw-r--r--addons/ot/src/group.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/addons/ot/src/group.c b/addons/ot/src/group.c
new file mode 100644
index 0000000..52b872d
--- /dev/null
+++ b/addons/ot/src/group.c
@@ -0,0 +1,354 @@
+/***
+ * 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"
+
+
+#define FLT_OT_GROUP_DEF(a,b,c) { a, b, c },
+const struct flt_ot_group_data flt_ot_group_data[] = { FLT_OT_GROUP_DEFINES };
+#undef FLT_OT_GROUP_DEF
+
+
+/***
+ * NAME
+ * flt_ot_group_action -
+ *
+ * ARGUMENTS
+ * rule -
+ * px -
+ * sess -
+ * s -
+ * opts -
+ *
+ * DESCRIPTION
+ * This is the action_ptr callback of a rule associated to the
+ * FLT_OT_ACTION_GROUP action.
+ *
+ * RETURN VALUE
+ * The function returns ACT_RET_CONT if processing is finished (with error or
+ * not), otherwise, it returns ACT_RET_YIELD if the action is in progress.
+ */
+static enum act_return flt_ot_group_action(struct act_rule *rule, struct proxy *px, struct session *sess, struct stream *s, int opts)
+{
+ const struct filter *filter;
+ const struct flt_conf *fconf;
+ const struct flt_ot_conf *conf;
+ const struct flt_ot_conf_group *conf_group;
+ const struct flt_ot_runtime_context *rt_ctx = NULL;
+ const struct flt_ot_conf_ph *ph_scope;
+ char *err = NULL;
+ int i, rc;
+
+ FLT_OT_FUNC("%p, %p, %p, %p, %d", rule, px, sess, s, opts);
+
+ FLT_OT_DBG(3, "from: %d, arg.act %p:{ %p %p %p %p }", rule->from, &(rule->arg.act), rule->arg.act.p[0], rule->arg.act.p[1], rule->arg.act.p[2], rule->arg.act.p[3]);
+
+ fconf = rule->arg.act.p[FLT_OT_ARG_FLT_CONF];
+ conf = rule->arg.act.p[FLT_OT_ARG_CONF];
+ conf_group = ((const struct flt_ot_conf_ph *)(rule->arg.act.p[FLT_OT_ARG_GROUP]))->ptr;
+
+ if ((fconf == NULL) || (conf == NULL) || (conf_group == NULL)) {
+ FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid group action");
+
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+ }
+
+ if (conf->tracer->flag_disabled) {
+ FLT_OT_DBG(1, "filter '%s' disabled, group action '%s' ignored", conf->id, conf_group->id);
+
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+ }
+
+ /* Find the OpenTracing filter instance from the current stream. */
+ list_for_each_entry(filter, &(s->strm_flt.filters), list)
+ if (filter->config == fconf) {
+ rt_ctx = filter->ctx;
+
+ break;
+ }
+
+ if (rt_ctx == NULL) {
+ FLT_OT_DBG(1, "cannot find filter, probably not attached to the stream");
+
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+ }
+ else if (flt_ot_is_disabled(filter FLT_OT_DBG_ARGS(, -1))) {
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+ }
+ else {
+ FLT_OT_DBG(3, "run group '%s'", conf_group->id);
+ FLT_OT_DBG_CONF_GROUP("run group ", conf_group);
+ }
+
+ /*
+ * Check the value of rule->from; in case it is incorrect,
+ * report an error.
+ */
+ for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
+ if (flt_ot_group_data[i].act_from == rule->from)
+ break;
+
+ if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
+ FLT_OT_LOG(LOG_ERR, FLT_OT_ACTION_GROUP ": internal error, invalid rule->from=%d", rule->from);
+
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+ }
+
+ list_for_each_entry(ph_scope, &(conf_group->ph_scopes), list) {
+ rc = flt_ot_scope_run(s, rt_ctx->filter, &(s->res), ph_scope->ptr, NULL, SMP_OPT_DIR_RES, &err);
+ if ((rc == FLT_OT_RET_ERROR) && (opts & ACT_OPT_FINAL)) {
+ /* XXX */
+ }
+ }
+
+ FLT_OT_RETURN_EX(ACT_RET_CONT, enum act_return, "%d");
+}
+
+
+/***
+ * NAME
+ * flt_ot_group_check -
+ *
+ * ARGUMENTS
+ * rule -
+ * px -
+ * err -
+ *
+ * DESCRIPTION
+ * This is the check_ptr callback of a rule associated to the
+ * FLT_OT_ACTION_GROUP action.
+ *
+ * RETURN VALUE
+ * The function returns 1 in success case, otherwise,
+ * it returns 0 and err is filled.
+ */
+static int flt_ot_group_check(struct act_rule *rule, struct proxy *px, char **err)
+{
+ struct flt_conf *fconf_tmp, *fconf = NULL;
+ struct flt_ot_conf *conf;
+ struct flt_ot_conf_ph *ph_group;
+ const char *filter_id;
+ const char *group_id;
+ bool flag_found = 0;
+ int i;
+
+ FLT_OT_FUNC("%p, %p, %p:%p", rule, px, FLT_OT_DPTR_ARGS(err));
+
+ filter_id = rule->arg.act.p[FLT_OT_ARG_FILTER_ID];
+ group_id = rule->arg.act.p[FLT_OT_ARG_GROUP_ID];
+
+ FLT_OT_DBG(2, "checking filter_id='%s', group_id='%s'", filter_id, group_id);
+
+ /*
+ * Check the value of rule->from; in case it is incorrect,
+ * report an error.
+ */
+ for (i = 0; i < FLT_OT_TABLESIZE(flt_ot_group_data); i++)
+ if (flt_ot_group_data[i].act_from == rule->from)
+ break;
+
+ if (i >= FLT_OT_TABLESIZE(flt_ot_group_data)) {
+ FLT_OT_ERR("internal error, unexpected rule->from=%d, please report this bug!", rule->from);
+
+ FLT_OT_RETURN_INT(0);
+ }
+
+ /*
+ * Try to find the OpenTracing filter by checking all filters
+ * for the proxy <px>.
+ */
+ list_for_each_entry(fconf_tmp, &(px->filter_configs), list) {
+ conf = fconf_tmp->conf;
+
+ if (fconf_tmp->id != ot_flt_id) {
+ /* This is not an OpenTracing filter. */
+ continue;
+ }
+ else if (strcmp(conf->id, filter_id) == 0) {
+ /* This is the good filter ID. */
+ fconf = fconf_tmp;
+
+ break;
+ }
+ }
+
+ if (fconf == NULL) {
+ FLT_OT_ERR("unable to find the OpenTracing filter '%s' used by the " FLT_OT_ACTION_GROUP " '%s'", filter_id, group_id);
+
+ FLT_OT_RETURN_INT(0);
+ }
+
+ /*
+ * Attempt to find if the group is defined in the OpenTracing filter
+ * configuration.
+ */
+ list_for_each_entry(ph_group, &(conf->tracer->ph_groups), list)
+ if (strcmp(ph_group->id, group_id) == 0) {
+ flag_found = 1;
+
+ break;
+ }
+
+ if (!flag_found) {
+ FLT_OT_ERR("unable to find group '%s' in the OpenTracing filter '%s' configuration", group_id, filter_id);
+
+ FLT_OT_RETURN_INT(0);
+ }
+
+ FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
+ FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_GROUP_ID]);
+
+ rule->arg.act.p[FLT_OT_ARG_FLT_CONF] = fconf;
+ rule->arg.act.p[FLT_OT_ARG_CONF] = conf;
+ rule->arg.act.p[FLT_OT_ARG_GROUP] = ph_group;
+
+ FLT_OT_RETURN_INT(1);
+}
+
+
+/***
+ * NAME
+ * flt_ot_group_release -
+ *
+ * ARGUMENTS
+ * rule -
+ *
+ * DESCRIPTION
+ * This is the release_ptr callback of a rule associated to the
+ * FLT_OT_ACTION_GROUP action.
+ *
+ * RETURN VALUE
+ * This function does not return a value.
+ */
+static void flt_ot_group_release(struct act_rule *rule)
+{
+ FLT_OT_FUNC("%p", rule);
+
+ FLT_OT_RETURN();
+}
+
+
+/***
+ * NAME
+ * flt_ot_group_parse -
+ *
+ * ARGUMENTS
+ * args -
+ * cur_arg -
+ * px -
+ * rule -
+ * err -
+ *
+ * DESCRIPTION
+ * -
+ *
+ * RETURN VALUE
+ * Returns ACT_RET_PRS_ERR if an error occurs, ACT_RET_PRS_OK otherwise.
+ */
+static enum act_parse_ret flt_ot_group_parse(const char **args, int *cur_arg, struct proxy *px, struct act_rule *rule, char **err)
+{
+ FLT_OT_FUNC("%p, %p, %p, %p, %p:%p", args, cur_arg, px, rule, FLT_OT_DPTR_ARGS(err));
+
+ if (!FLT_OT_ARG_ISVALID(*cur_arg) ||
+ !FLT_OT_ARG_ISVALID(*cur_arg + 1) ||
+ (FLT_OT_ARG_ISVALID(*cur_arg + 2) &&
+ (strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_IF) != 0) &&
+ (strcmp(args[*cur_arg + 2], FLT_OT_CONDITION_UNLESS) != 0))) {
+ FLT_OT_ERR("expects: <filter-id> <group-id> [{ if | unless } ...]");
+
+ FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
+ }
+
+ /* Copy the OpenTracing filter id. */
+ rule->arg.act.p[FLT_OT_ARG_FILTER_ID] = FLT_OT_STRDUP(args[*cur_arg]);
+ if (rule->arg.act.p[FLT_OT_ARG_FILTER_ID] == NULL) {
+ FLT_OT_ERR("%s : out of memory", args[*cur_arg]);
+
+ FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
+ }
+
+ /* Copy the OpenTracing group id. */
+ rule->arg.act.p[FLT_OT_ARG_GROUP_ID] = FLT_OT_STRDUP(args[*cur_arg + 1]);
+ if (rule->arg.act.p[FLT_OT_ARG_GROUP_ID] == NULL) {
+ FLT_OT_ERR("%s : out of memory", args[*cur_arg + 1]);
+
+ FLT_OT_FREE_CLEAR(rule->arg.act.p[FLT_OT_ARG_FILTER_ID]);
+
+ FLT_OT_RETURN_EX(ACT_RET_PRS_ERR, enum act_parse_ret, "%d");
+ }
+
+ rule->action = ACT_CUSTOM;
+ rule->action_ptr = flt_ot_group_action;
+ rule->check_ptr = flt_ot_group_check;
+ rule->release_ptr = flt_ot_group_release;
+
+ *cur_arg += 2;
+
+ FLT_OT_RETURN_EX(ACT_RET_PRS_OK, enum act_parse_ret, "%d");
+}
+
+
+static struct action_kw_list tcp_req_action_kws = { ILH, {
+ { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
+ { /* END */ },
+ }
+};
+
+INITCALL1(STG_REGISTER, tcp_req_cont_keywords_register, &tcp_req_action_kws);
+
+static struct action_kw_list tcp_res_action_kws = { ILH, {
+ { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
+ { /* END */ },
+ }
+};
+
+INITCALL1(STG_REGISTER, tcp_res_cont_keywords_register, &tcp_res_action_kws);
+
+static struct action_kw_list http_req_action_kws = { ILH, {
+ { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
+ { /* END */ },
+ }
+};
+
+INITCALL1(STG_REGISTER, http_req_keywords_register, &http_req_action_kws);
+
+static struct action_kw_list http_res_action_kws = { ILH, {
+ { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
+ { /* END */ },
+ }
+};
+
+INITCALL1(STG_REGISTER, http_res_keywords_register, &http_res_action_kws);
+
+static struct action_kw_list http_after_res_actions_kws = { ILH, {
+ { FLT_OT_ACTION_GROUP, flt_ot_group_parse },
+ { /* END */ },
+ }
+};
+
+INITCALL1(STG_REGISTER, http_after_res_keywords_register, &http_after_res_actions_kws);
+
+/*
+ * Local variables:
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * End:
+ *
+ * vi: noexpandtab shiftwidth=8 tabstop=8
+ */