mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-11 17:46:57 +02:00
Since commit 3a4bedccc
("MEDIUM: vars: replace the global name index with
a hash") the names of HAProxy variables are no longer saved, ie their
64-bit hashes are saved instead.
This is very convenient for the HAProxy itself, but for the OpenTracing
module it is a problem because the names of the variables are important
when transferring the OpenTracing context. Namely, this context consists
of an unknown amount of data stored in a key-value format. The number
of these data (and the name of the variable used for this purpose) is
determined with the configuration of the OpenTracing filter, as well as
with the tracer used. The two previous sentences seem to be in conflict,
but that is only so at first glance. The function in the OpenTracing
filter used to read the context does not really know this, neither their
number nor its name. The only thing that function actually knows is the
prefix of the variable names used for context transfer, and by that it
could find all the necessary data. Of course, until the application of
the above-mentioned commit.
The problem is solved in a very simple way: in a common variable that
the filter always knows its name, the names of all variables that are the
product of the OpenTracing context are saved. The names of these context
variables can only be added to that common variable. When that variable
is no longer needed (when we no longer need context), it is deleted.
The format for saving data to this common variable is as follows:
+-----+---------------+-- .. --+-----+---------------+
| len | variable name | | len | variable name |
+-----+---------------+-- .. --+-----+---------------+
The amount of memory space used to store the length of the name is 1 byte,
with a sign (the minus sign is provided for inactive records, but this is
not currently used). This means that the maximum length of the variable
name to be saved is 127 characters, which is quite enough for use in the
filter. The buffer size for such data storage is global.tune.bufsize.
This patch must be backported in 2.5.
835 lines
20 KiB
C
835 lines
20 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"
|
|
|
|
|
|
#ifdef DEBUG_OT
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_scope_dump -
|
|
*
|
|
* ARGUMENTS
|
|
* vars -
|
|
* scope -
|
|
*
|
|
* DESCRIPTION
|
|
* Function prints the contents of all variables defined for a particular
|
|
* scope.
|
|
*
|
|
* RETURN VALUE
|
|
* This function does not return a value.
|
|
*/
|
|
static void flt_ot_vars_scope_dump(struct vars *vars, const char *scope)
|
|
{
|
|
const struct var *var;
|
|
|
|
if (vars == NULL)
|
|
return;
|
|
|
|
vars_rdlock(vars);
|
|
list_for_each_entry(var, &(vars->head), l)
|
|
FLT_OT_DBG(2, "'%s.%016" PRIx64 "' -> '%.*s'", scope, var->name_hash, (int)b_data(&(var->data.u.str)), b_orig(&(var->data.u.str)));
|
|
vars_rdunlock(vars);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_dump -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
*
|
|
* DESCRIPTION
|
|
* Function prints the contents of all variables grouped by individual
|
|
* scope.
|
|
*
|
|
* RETURN VALUE
|
|
* This function does not return a value.
|
|
*/
|
|
void flt_ot_vars_dump(struct stream *s)
|
|
{
|
|
FLT_OT_FUNC("%p", s);
|
|
|
|
/*
|
|
* It would be nice if we could use the get_vars() function from HAProxy
|
|
* source here to get the value of the 'vars' pointer, but it is defined
|
|
* as 'static inline', so unfortunately none of this is possible.
|
|
*/
|
|
flt_ot_vars_scope_dump(&(proc_vars), "PROC");
|
|
flt_ot_vars_scope_dump(&(s->sess->vars), "SESS");
|
|
flt_ot_vars_scope_dump(&(s->vars_txn), "TXN");
|
|
flt_ot_vars_scope_dump(&(s->vars_reqres), "REQ/RES");
|
|
|
|
FLT_OT_RETURN();
|
|
}
|
|
|
|
#endif /* DEBUG_OT */
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_smp_init -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* smp -
|
|
* opt -
|
|
* type -
|
|
* data -
|
|
*
|
|
* DESCRIPTION
|
|
* The function initializes the value of the 'smp' structure. If the 'data'
|
|
* argument is set, then the 'sample_data' member of the 'smp' structure is
|
|
* also initialized.
|
|
*
|
|
* RETURN VALUE
|
|
* This function does not return a value.
|
|
*/
|
|
static inline void flt_ot_smp_init(struct stream *s, struct sample *smp, uint opt, int type, const char *data)
|
|
{
|
|
(void)memset(smp, 0, sizeof(*smp));
|
|
(void)smp_set_owner(smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
|
|
|
if (data != NULL) {
|
|
smp->data.type = type;
|
|
|
|
chunk_initstr(&(smp->data.u.str), data);
|
|
}
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_smp_add -
|
|
*
|
|
* ARGUMENTS
|
|
* data -
|
|
* blk -
|
|
* len -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_smp_add(struct sample_data *data, const char *name, size_t len, char **err)
|
|
{
|
|
bool flag_alloc = 0;
|
|
int retval = FLT_OT_RET_ERROR;
|
|
|
|
FLT_OT_FUNC("%p, \"%.*s\", %zu, %p:%p", data, (int)len, name, len, FLT_OT_DPTR_ARGS(err));
|
|
|
|
FLT_OT_DBG_BUF(2, &(data->u.str));
|
|
|
|
if (b_orig(&(data->u.str)) == NULL) {
|
|
data->type = SMP_T_BIN;
|
|
chunk_init(&(data->u.str), FLT_OT_MALLOC(global.tune.bufsize), global.tune.bufsize);
|
|
|
|
flag_alloc = (b_orig(&(data->u.str)) != NULL);
|
|
}
|
|
|
|
if (b_orig(&(data->u.str)) == NULL) {
|
|
FLT_OT_ERR("failed to add ctx '%.*s', not enough memory", (int)len, name);
|
|
}
|
|
else if (len > ((UINT64_C(1) << ((sizeof(FLT_OT_VAR_CTX_SIZE) << 3) - 1)) - 1)) {
|
|
FLT_OT_ERR("failed to add ctx '%.*s', too long name", (int)len, name);
|
|
}
|
|
else if ((len + sizeof(FLT_OT_VAR_CTX_SIZE)) > b_room(&(data->u.str))) {
|
|
FLT_OT_ERR("failed to add ctx '%.*s', too many names", (int)len, name);
|
|
}
|
|
else {
|
|
retval = b_data(&(data->u.str));
|
|
|
|
b_putchr(&(data->u.str), len);
|
|
(void)__b_putblk(&(data->u.str), name, len);
|
|
|
|
FLT_OT_DBG_BUF(2, &(data->u.str));
|
|
}
|
|
|
|
if ((retval == FLT_OT_RET_ERROR) && flag_alloc)
|
|
FLT_OT_FREE(b_orig(&(data->u.str)));
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_normalize_name -
|
|
*
|
|
* ARGUMENTS
|
|
* var_name -
|
|
* size -
|
|
* len -
|
|
* name -
|
|
* flag_cpy -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_normalize_name(char *var_name, size_t size, int *len, const char *name, bool flag_cpy, char **err)
|
|
{
|
|
int retval = 0;
|
|
|
|
FLT_OT_FUNC("%p, %zu, %p, \"%s\", %hhu, %p:%p", var_name, size, len, name, flag_cpy, FLT_OT_DPTR_ARGS(err));
|
|
|
|
if (!FLT_OT_STR_ISVALID(name))
|
|
FLT_OT_RETURN_INT(retval);
|
|
|
|
/*
|
|
* In case the name of the variable consists of several elements,
|
|
* the character '.' is added between them.
|
|
*/
|
|
if ((*len == 0) || (var_name[*len - 1] == '.'))
|
|
/* Do nothing. */;
|
|
else if (*len < (size - 1))
|
|
var_name[(*len)++] = '.';
|
|
else {
|
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
|
|
|
retval = -1;
|
|
}
|
|
|
|
if (flag_cpy) {
|
|
/* Copy variable name without modification. */
|
|
retval = strlen(name);
|
|
if ((*len + retval + 1) > size) {
|
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
|
|
|
retval = -1;
|
|
} else {
|
|
(void)memcpy(var_name + *len, name, retval + 1);
|
|
|
|
*len += retval;
|
|
}
|
|
} else {
|
|
/*
|
|
* HAProxy does not allow the use of variable names containing '-'
|
|
* or ' '. This of course applies to HTTP header names as well.
|
|
* Also, here the capital letters are converted to lowercase.
|
|
*/
|
|
while (retval != -1)
|
|
if (*len >= (size - 1)) {
|
|
FLT_OT_ERR("failed to normalize variable name, buffer too small");
|
|
|
|
retval = -1;
|
|
} else {
|
|
uint8_t ch = name[retval];
|
|
|
|
if (ch == '\0')
|
|
break;
|
|
else if (ch == '-')
|
|
ch = FLT_OT_VAR_CHAR_DASH;
|
|
else if (ch == ' ')
|
|
ch = FLT_OT_VAR_CHAR_SPACE;
|
|
else if (isupper(ch))
|
|
ch = ist_lc[ch];
|
|
|
|
var_name[(*len)++] = ch;
|
|
retval++;
|
|
}
|
|
|
|
var_name[*len] = '\0';
|
|
}
|
|
|
|
FLT_OT_DBG(3, "var_name: \"%s\" %d/%d", var_name, retval, *len);
|
|
|
|
if (retval == -1)
|
|
*len = retval;
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_name -
|
|
*
|
|
* ARGUMENTS
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* flag_cpy -
|
|
* var_name -
|
|
* size -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* The function initializes the value of the 'smp' structure. If the 'data'
|
|
* argument is set, then the 'sample_data' member of the 'smp' structure is
|
|
* also initialized.
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_var_name(const char *scope, const char *prefix, const char *name, bool flag_cpy, char *var_name, size_t size, char **err)
|
|
{
|
|
int retval = 0;
|
|
|
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %hhu, %p, %zu, %p:%p", scope, prefix, name, flag_cpy, var_name, size, FLT_OT_DPTR_ARGS(err));
|
|
|
|
if (flt_ot_normalize_name(var_name, size, &retval, scope, 0, err) >= 0)
|
|
if (flt_ot_normalize_name(var_name, size, &retval, prefix, 0, err) >= 0)
|
|
(void)flt_ot_normalize_name(var_name, size, &retval, name, flag_cpy, err);
|
|
|
|
if (retval == -1)
|
|
FLT_OT_ERR("failed to construct variable name '%s.%s.%s'", scope, prefix, name);
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_ctx_loop -
|
|
*
|
|
* ARGUMENTS
|
|
* smp -
|
|
* scope -
|
|
* prefix -
|
|
* err -
|
|
* func -
|
|
* ptr -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_ctx_loop(struct sample *smp, const char *scope, const char *prefix, char **err, flt_ot_ctx_loop_cb func, void *ptr)
|
|
{
|
|
FLT_OT_VAR_CTX_SIZE var_ctx_size;
|
|
char var_name[BUFSIZ], var_ctx[BUFSIZ];
|
|
int i, var_name_len, var_ctx_len, rc, n = 1, retval = 0;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %p:%p, %p, %p", smp, scope, prefix, FLT_OT_DPTR_ARGS(err), func, ptr);
|
|
|
|
/*
|
|
* The variable in which we will save the name of the OpenTracing
|
|
* context variable.
|
|
*/
|
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
|
if (var_name_len == -1)
|
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
|
|
|
/*
|
|
* Here we will try to find all the previously recorded variables from
|
|
* the currently set OpenTracing context. If we find the required
|
|
* variable and it is marked as deleted, we will mark it as active.
|
|
* If we do not find it, then it is added to the end of the previously
|
|
* saved names.
|
|
*/
|
|
if (vars_get_by_name(var_name, var_name_len, smp, NULL) == 0) {
|
|
FLT_OT_DBG(2, "ctx '%s' no variable found", var_name);
|
|
}
|
|
else if (smp->data.type != SMP_T_BIN) {
|
|
FLT_OT_ERR("ctx '%s' invalid data type %d", var_name, smp->data.type);
|
|
|
|
retval = FLT_OT_RET_ERROR;
|
|
}
|
|
else {
|
|
FLT_OT_DBG_BUF(2, &(smp->data.u.str));
|
|
|
|
for (i = 0; i < b_data(&(smp->data.u.str)); i += sizeof(var_ctx_size) + var_ctx_len, n++) {
|
|
var_ctx_size = *((typeof(var_ctx_size) *)(b_orig(&(smp->data.u.str)) + i));
|
|
var_ctx_len = abs(var_ctx_size);
|
|
|
|
if ((i + sizeof(var_ctx_size) + var_ctx_len) > b_data(&(smp->data.u.str))) {
|
|
FLT_OT_ERR("ctx '%s' invalid data size", var_name);
|
|
|
|
retval = FLT_OT_RET_ERROR;
|
|
|
|
break;
|
|
}
|
|
|
|
(void)memcpy(var_ctx, b_orig(&(smp->data.u.str)) + i + sizeof(var_ctx_size), var_ctx_len);
|
|
var_ctx[var_ctx_len] = '\0';
|
|
|
|
rc = func(smp, i, scope, prefix, var_ctx, var_ctx_size, err, ptr);
|
|
if (rc == FLT_OT_RET_ERROR) {
|
|
retval = FLT_OT_RET_ERROR;
|
|
|
|
break;
|
|
}
|
|
else if (rc > 0) {
|
|
retval = n;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_ctx_set_cb -
|
|
*
|
|
* ARGUMENTS
|
|
* smp -
|
|
* idx -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* name_len -
|
|
* err -
|
|
* ptr -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_ctx_set_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
|
{
|
|
struct flt_ot_ctx *ctx = ptr;
|
|
int retval = 0;
|
|
|
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
|
|
|
if ((name_len == ctx->value_len) && (strncmp(name, ctx->value, name_len) == 0)) {
|
|
FLT_OT_DBG(2, "ctx '%s' found\n", name);
|
|
|
|
retval = 1;
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_ctx_set -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_ctx_set(struct stream *s, const char *scope, const char *prefix, const char *name, uint opt, char **err)
|
|
{
|
|
struct flt_ot_ctx ctx;
|
|
struct sample smp_ctx;
|
|
char var_name[BUFSIZ];
|
|
bool flag_alloc = 0;
|
|
int rc, var_name_len, retval = FLT_OT_RET_ERROR;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
/*
|
|
* The variable in which we will save the name of the OpenTracing
|
|
* context variable.
|
|
*/
|
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
|
if (var_name_len == -1)
|
|
FLT_OT_RETURN_INT(retval);
|
|
|
|
/* Normalized name of the OpenTracing context variable. */
|
|
ctx.value_len = flt_ot_var_name(name, NULL, NULL, 0, ctx.value, sizeof(ctx.value), err);
|
|
if (ctx.value_len == -1)
|
|
FLT_OT_RETURN_INT(retval);
|
|
|
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
|
|
|
retval = flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_ctx_set_cb, &ctx);
|
|
if (retval == 0) {
|
|
rc = flt_ot_smp_add(&(smp_ctx.data), ctx.value, ctx.value_len, err);
|
|
if (rc == FLT_OT_RET_ERROR)
|
|
retval = FLT_OT_RET_ERROR;
|
|
|
|
flag_alloc = (rc == 0);
|
|
}
|
|
|
|
if (retval == FLT_OT_RET_ERROR) {
|
|
/* Do nothing. */
|
|
}
|
|
else if (retval > 0) {
|
|
FLT_OT_DBG(2, "ctx '%s' data found", ctx.value);
|
|
}
|
|
else if (vars_set_by_name_ifexist(var_name, var_name_len, &smp_ctx) == 0) {
|
|
FLT_OT_ERR("failed to set ctx '%s'", var_name);
|
|
|
|
retval = FLT_OT_RET_ERROR;
|
|
}
|
|
else {
|
|
FLT_OT_DBG(2, "ctx '%s' -> '%.*s' set", var_name, (int)b_data(&(smp_ctx.data.u.str)), b_orig(&(smp_ctx.data.u.str)));
|
|
|
|
retval = b_data(&(smp_ctx.data.u.str));
|
|
}
|
|
|
|
if (flag_alloc)
|
|
FLT_OT_FREE(b_orig(&(smp_ctx.data.u.str)));
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_register -
|
|
*
|
|
* ARGUMENTS
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
int flt_ot_var_register(const char *scope, const char *prefix, const char *name, char **err)
|
|
{
|
|
struct arg arg;
|
|
char var_name[BUFSIZ];
|
|
int retval = -1, var_name_len;
|
|
|
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %p:%p", scope, prefix, name, FLT_OT_DPTR_ARGS(err));
|
|
|
|
var_name_len = flt_ot_var_name(scope, prefix, name, 0, var_name, sizeof(var_name), err);
|
|
if (var_name_len == -1)
|
|
FLT_OT_RETURN_INT(retval);
|
|
|
|
/* Set <size> to 0 to not release var_name memory in vars_check_arg(). */
|
|
(void)memset(&arg, 0, sizeof(arg));
|
|
arg.type = ARGT_STR;
|
|
arg.data.str.area = var_name;
|
|
arg.data.str.data = var_name_len;
|
|
|
|
if (vars_check_arg(&arg, err) == 0) {
|
|
FLT_OT_ERR_APPEND("failed to register variable '%s': %s", var_name, *err);
|
|
} else {
|
|
FLT_OT_DBG(2, "variable '%s' registered", var_name);
|
|
|
|
retval = var_name_len;
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_set -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* value -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
int flt_ot_var_set(struct stream *s, const char *scope, const char *prefix, const char *name, const char *value, uint opt, char **err)
|
|
{
|
|
struct sample smp;
|
|
char var_name[BUFSIZ];
|
|
int retval = -1, var_name_len;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, value, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
var_name_len = flt_ot_var_name(scope, prefix, name, 0, var_name, sizeof(var_name), err);
|
|
if (var_name_len == -1)
|
|
FLT_OT_RETURN_INT(retval);
|
|
|
|
flt_ot_smp_init(s, &smp, opt, SMP_T_STR, value);
|
|
|
|
if (vars_set_by_name_ifexist(var_name, var_name_len, &smp) == 0) {
|
|
FLT_OT_ERR("failed to set variable '%s'", var_name);
|
|
} else {
|
|
FLT_OT_DBG(2, "variable '%s' set", var_name);
|
|
|
|
retval = var_name_len;
|
|
|
|
if (strcmp(scope, FLT_OT_VARS_SCOPE) == 0)
|
|
retval = flt_ot_ctx_set(s, scope, prefix, name, opt, err);
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_unset_cb -
|
|
*
|
|
* ARGUMENTS
|
|
* smp -
|
|
* idx -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* name_len -
|
|
* err -
|
|
* ptr -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_vars_unset_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
|
{
|
|
struct sample smp_ctx;
|
|
char var_ctx[BUFSIZ];
|
|
int var_ctx_len, retval = FLT_OT_RET_ERROR;
|
|
|
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
|
|
|
var_ctx_len = flt_ot_var_name(scope, prefix, name, 1, var_ctx, sizeof(var_ctx), err);
|
|
if (var_ctx_len == -1) {
|
|
FLT_OT_ERR("ctx '%s' invalid", name);
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
flt_ot_smp_init(smp->strm, &smp_ctx, smp->opt, 0, NULL);
|
|
|
|
if (vars_unset_by_name_ifexist(var_ctx, var_ctx_len, &smp_ctx) == 0) {
|
|
FLT_OT_ERR("ctx '%s' no variable found", var_ctx);
|
|
} else {
|
|
FLT_OT_DBG(2, "ctx '%s' unset", var_ctx);
|
|
|
|
retval = 0;
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_unset -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
int flt_ot_vars_unset(struct stream *s, const char *scope, const char *prefix, uint opt, char **err)
|
|
{
|
|
struct sample smp_ctx;
|
|
char var_name[BUFSIZ];
|
|
int var_name_len, retval;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
|
|
|
retval = flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_vars_unset_cb, NULL);
|
|
if (retval != FLT_OT_RET_ERROR) {
|
|
/*
|
|
* After all ctx variables have been unset, the variable used
|
|
* to store their names should also be unset.
|
|
*/
|
|
var_name_len = flt_ot_var_name(scope, prefix, NULL, 0, var_name, sizeof(var_name), err);
|
|
if (var_name_len == -1)
|
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
|
|
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
|
|
|
if (vars_unset_by_name_ifexist(var_name, var_name_len, &smp_ctx) == 0) {
|
|
FLT_OT_DBG(2, "variable '%s' not found", var_name);
|
|
} else {
|
|
FLT_OT_DBG(2, "variable '%s' unset", var_name);
|
|
|
|
retval = 1;
|
|
}
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_get_cb -
|
|
*
|
|
* ARGUMENTS
|
|
* smp -
|
|
* idx -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* name_len -
|
|
* err -
|
|
* ptr -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_vars_get_cb(struct sample *smp, size_t idx, const char *scope, const char *prefix, const char *name, FLT_OT_VAR_CTX_SIZE name_len, char **err, void *ptr)
|
|
{
|
|
struct otc_text_map **map = ptr;
|
|
struct sample smp_ctx;
|
|
char var_ctx[BUFSIZ], ot_var_name[BUFSIZ], ch;
|
|
int var_ctx_len, ot_var_name_len, retval = FLT_OT_RET_ERROR;
|
|
|
|
FLT_OT_FUNC("%p, %zu, \"%s\", \"%s\", \"%s\", %hhd, %p:%p, %p", smp, idx, scope, prefix, name, name_len, FLT_OT_DPTR_ARGS(err), ptr);
|
|
|
|
var_ctx_len = flt_ot_var_name(scope, prefix, name, 1, var_ctx, sizeof(var_ctx), err);
|
|
if (var_ctx_len == -1) {
|
|
FLT_OT_ERR("ctx '%s' invalid", name);
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
flt_ot_smp_init(smp->strm, &smp_ctx, smp->opt, 0, NULL);
|
|
|
|
if (vars_get_by_name(var_ctx, var_ctx_len, &smp_ctx, NULL) != 0) {
|
|
FLT_OT_DBG(2, "'%s' -> '%.*s'", var_ctx, (int)b_data(&(smp_ctx.data.u.str)), b_orig(&(smp_ctx.data.u.str)));
|
|
|
|
if (*map == NULL) {
|
|
*map = otc_text_map_new(NULL, 8);
|
|
if (*map == NULL) {
|
|
FLT_OT_ERR("failed to create map data");
|
|
|
|
FLT_OT_RETURN_INT(FLT_OT_RET_ERROR);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Eh, because the use of some characters is not allowed
|
|
* in the variable name, the conversion of the replaced
|
|
* characters to the original is performed here.
|
|
*/
|
|
for (ot_var_name_len = 0; (ch = name[ot_var_name_len]) != '\0'; ot_var_name_len++)
|
|
if (ot_var_name_len >= (FLT_OT_TABLESIZE(ot_var_name) - 1)) {
|
|
FLT_OT_ERR("failed to reverse variable name, buffer too small");
|
|
|
|
otc_text_map_destroy(map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
|
|
|
break;
|
|
} else {
|
|
ot_var_name[ot_var_name_len] = (ch == FLT_OT_VAR_CHAR_DASH) ? '-' : ((ch == FLT_OT_VAR_CHAR_SPACE) ? ' ' : ch);
|
|
}
|
|
ot_var_name[ot_var_name_len] = '\0';
|
|
|
|
if (*map == NULL) {
|
|
retval = FLT_OT_RET_ERROR;
|
|
}
|
|
else if (otc_text_map_add(*map, ot_var_name, ot_var_name_len, b_orig(&(smp_ctx.data.u.str)), b_data(&(smp_ctx.data.u.str)), OTC_TEXT_MAP_DUP_KEY | OTC_TEXT_MAP_DUP_VALUE) == -1) {
|
|
FLT_OT_ERR("failed to add map data");
|
|
|
|
otc_text_map_destroy(map, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
|
|
|
retval = FLT_OT_RET_ERROR;
|
|
}
|
|
else {
|
|
retval = 0;
|
|
}
|
|
} else {
|
|
FLT_OT_DBG(2, "ctx '%s' no variable found", var_ctx);
|
|
}
|
|
|
|
FLT_OT_RETURN_INT(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_get -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
struct otc_text_map *flt_ot_vars_get(struct stream *s, const char *scope, const char *prefix, uint opt, char **err)
|
|
{
|
|
struct sample smp_ctx;
|
|
struct otc_text_map *retptr = NULL;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
flt_ot_smp_init(s, &smp_ctx, opt, 0, NULL);
|
|
|
|
(void)flt_ot_ctx_loop(&smp_ctx, scope, prefix, err, flt_ot_vars_get_cb, &retptr);
|
|
|
|
ot_text_map_show(retptr);
|
|
|
|
if ((retptr != NULL) && (retptr->count == 0)) {
|
|
FLT_OT_DBG(2, "WARNING: no variables found");
|
|
|
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
|
}
|
|
|
|
FLT_OT_RETURN_PTR(retptr);
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*
|
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
|
*/
|