mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-09 08:37:04 +02:00
This one is the last optional module to build with haproxy, so let's move it to addons/. It was renamed to "ot" as it was the only one whose USE_* option did not match the directory name, now this is consistent. Few changes were required, only the Makefile, and doc were adjusted, as the directory was already self-contained and relocatable.
355 lines
9.4 KiB
C
355 lines
9.4 KiB
C
/***
|
|
* 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(ACT_RET_CONT);
|
|
}
|
|
|
|
if (conf->tracer->flag_disabled) {
|
|
FLT_OT_DBG(1, "filter '%s' disabled, group action '%s' ignored", conf->id, conf_group->id);
|
|
|
|
FLT_OT_RETURN(ACT_RET_CONT);
|
|
}
|
|
|
|
/* 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(ACT_RET_CONT);
|
|
}
|
|
else if (flt_ot_is_disabled(filter FLT_OT_DBG_ARGS(, -1))) {
|
|
FLT_OT_RETURN(ACT_RET_CONT);
|
|
}
|
|
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(ACT_RET_CONT);
|
|
}
|
|
|
|
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(ACT_RET_CONT);
|
|
}
|
|
|
|
|
|
/***
|
|
* 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(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(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(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(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(ACT_RET_PRS_ERR);
|
|
}
|
|
|
|
/* 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(ACT_RET_PRS_ERR);
|
|
}
|
|
|
|
/* 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(ACT_RET_PRS_ERR);
|
|
}
|
|
|
|
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(ACT_RET_PRS_OK);
|
|
}
|
|
|
|
|
|
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
|
|
*/
|