mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-14 02:57:01 +02:00
The presence of this field causes a long dependency chain because almost everyone includes global-t.h, and vars include sample_data which include some system includes as well as HTTP parts. There is absolutely no reason for having the process-wide variables in the global struct, let's just move them into vars.c and vars.h. This reduces from ~190k to ~170k the preprocessed output of version.c.
579 lines
13 KiB
C
579 lines
13 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
|
|
* -
|
|
*
|
|
* 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;
|
|
|
|
HA_RWLOCK_RDLOCK(VARS_LOCK, &(vars->rwlock));
|
|
list_for_each_entry(var, &(vars->head), l)
|
|
FLT_OT_DBG(2, "'%s.%s' -> '%.*s'", scope, var->name, (int)var->data.u.str.data, var->data.u.str.area);
|
|
HA_RWLOCK_RDUNLOCK(VARS_LOCK, &(vars->rwlock));
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_vars_dump -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* 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_get_vars -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static inline struct vars *flt_ot_get_vars(struct stream *s, const char *scope)
|
|
{
|
|
struct vars *retptr = NULL;
|
|
|
|
if (strcasecmp(scope, "proc") == 0)
|
|
retptr = &(proc_vars);
|
|
else if (strcasecmp(scope, "sess") == 0)
|
|
retptr = (&(s->sess->vars));
|
|
else if (strcasecmp(scope, "txn") == 0)
|
|
retptr = (&(s->vars_txn));
|
|
else if ((strcasecmp(scope, "req") == 0) || (strcasecmp(scope, "res") == 0))
|
|
retptr = (&(s->vars_reqres));
|
|
|
|
return retptr;
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_normalize_name -
|
|
*
|
|
* ARGUMENTS
|
|
* var_name -
|
|
* size -
|
|
* len -
|
|
* name -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_normalize_name(char *var_name, size_t size, int *len, const char *name, char **err)
|
|
{
|
|
int retval = 0;
|
|
|
|
FLT_OT_FUNC("%p, %zu, %p, \"%s\", %p:%p", var_name, size, len, name, FLT_OT_DPTR_ARGS(err));
|
|
|
|
if (!FLT_OT_STR_ISVALID(name))
|
|
FLT_OT_RETURN(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
|
|
retval = -1;
|
|
|
|
/*
|
|
* 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(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_name -
|
|
*
|
|
* ARGUMENTS
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* var_name -
|
|
* size -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
static int flt_ot_var_name(const char *scope, const char *prefix, const char *name, char *var_name, size_t size, char **err)
|
|
{
|
|
int retval = 0;
|
|
|
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %p, %zu, %p:%p", scope, prefix, name, var_name, size, FLT_OT_DPTR_ARGS(err));
|
|
|
|
if (flt_ot_normalize_name(var_name, size, &retval, scope, err) >= 0)
|
|
if (flt_ot_normalize_name(var_name, size, &retval, prefix, err) >= 0)
|
|
(void)flt_ot_normalize_name(var_name, size, &retval, name, err);
|
|
|
|
if (retval == -1)
|
|
FLT_OT_ERR("failed to construct variable name '%s.%s.%s'", scope, prefix, name);
|
|
|
|
FLT_OT_RETURN(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;
|
|
|
|
FLT_OT_FUNC("\"%s\", \"%s\", \"%s\", %p:%p", scope, prefix, name, FLT_OT_DPTR_ARGS(err));
|
|
|
|
retval = flt_ot_var_name(scope, prefix, name, var_name, sizeof(var_name), err);
|
|
if (retval == -1)
|
|
FLT_OT_RETURN(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 = retval;
|
|
|
|
if (vars_check_arg(&arg, err) == 0) {
|
|
FLT_OT_ERR_APPEND("failed to register variable '%s': %s", var_name, *err);
|
|
|
|
retval = -1;
|
|
} else {
|
|
FLT_OT_DBG(2, "variable '%s' registered", arg.data.var.name);
|
|
}
|
|
|
|
FLT_OT_RETURN(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;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, value, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
retval = flt_ot_var_name(scope, prefix, name, var_name, sizeof(var_name), err);
|
|
if (retval == -1)
|
|
FLT_OT_RETURN(retval);
|
|
|
|
(void)memset(&smp, 0, sizeof(smp));
|
|
(void)smp_set_owner(&smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
|
smp.data.type = SMP_T_STR;
|
|
smp.data.u.str.area = (char *)value;
|
|
smp.data.u.str.data = strlen(value);
|
|
|
|
vars_set_by_name_ifexist(var_name, retval, &smp);
|
|
|
|
FLT_OT_RETURN(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_unset -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
int flt_ot_var_unset(struct stream *s, const char *scope, const char *prefix, const char *name, uint opt, char **err)
|
|
{
|
|
struct sample smp;
|
|
char var_name[BUFSIZ];
|
|
int retval;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, name, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
retval = flt_ot_var_name(scope, prefix, name, var_name, sizeof(var_name), err);
|
|
if (retval == -1)
|
|
FLT_OT_RETURN(retval);
|
|
|
|
(void)memset(&smp, 0, sizeof(smp));
|
|
(void)smp_set_owner(&smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
|
|
|
vars_unset_by_name_ifexist(var_name, retval, &smp);
|
|
|
|
FLT_OT_RETURN(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;
|
|
struct vars *vars;
|
|
struct var *var, *var_back;
|
|
char var_prefix[BUFSIZ], var_name[BUFSIZ];
|
|
uint size;
|
|
int var_prefix_len, var_name_len, retval = -1;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
vars = flt_ot_get_vars(s, scope);
|
|
if (vars == NULL)
|
|
FLT_OT_RETURN(retval);
|
|
|
|
var_prefix_len = flt_ot_var_name(NULL, prefix, NULL, var_prefix, sizeof(var_prefix), err);
|
|
if (var_prefix_len == -1)
|
|
FLT_OT_RETURN(retval);
|
|
|
|
retval = 0;
|
|
|
|
HA_RWLOCK_WRLOCK(VARS_LOCK, &(vars->rwlock));
|
|
list_for_each_entry_safe(var, var_back, &(vars->head), l) {
|
|
FLT_OT_DBG(3, "variable cmp '%s' '%s' %d", var_prefix, var->name, var_prefix_len);
|
|
|
|
if (strncmp(var_prefix, var->name, var_prefix_len) == 0) {
|
|
var_name_len = snprintf(var_name, sizeof(var_name), "%s.%s", scope, var->name);
|
|
if ((var_name_len == -1) || (var_name_len >= sizeof(var_name))) {
|
|
FLT_OT_DBG(2, "'%s.%s' variable name too long", scope, var->name);
|
|
|
|
break;
|
|
}
|
|
|
|
FLT_OT_DBG(2, "- '%s' -> '%.*s'", var_name, (int)var->data.u.str.data, var->data.u.str.area);
|
|
|
|
(void)memset(&smp, 0, sizeof(smp));
|
|
(void)smp_set_owner(&smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
|
|
|
size = var_clear(var);
|
|
var_accounting_diff(vars, smp.sess, smp.strm, -size);
|
|
|
|
retval++;
|
|
}
|
|
}
|
|
HA_RWLOCK_WRUNLOCK(VARS_LOCK, &(vars->rwlock));
|
|
|
|
FLT_OT_RETURN(retval);
|
|
}
|
|
|
|
|
|
/***
|
|
* NAME
|
|
* flt_ot_var_get -
|
|
*
|
|
* ARGUMENTS
|
|
* s -
|
|
* scope -
|
|
* prefix -
|
|
* name -
|
|
* value -
|
|
* opt -
|
|
* err -
|
|
*
|
|
* DESCRIPTION
|
|
* -
|
|
*
|
|
* RETURN VALUE
|
|
* -
|
|
*/
|
|
int flt_ot_var_get(struct stream *s, const char *scope, const char *prefix, const char *name, char **value, uint opt, char **err)
|
|
{
|
|
struct sample smp;
|
|
char var_name[BUFSIZ], var_value[BUFSIZ];
|
|
int retval;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", \"%s\", %p:%p, %u, %p:%p", s, scope, prefix, name, FLT_OT_DPTR_ARGS(value), opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
retval = flt_ot_var_name(scope, prefix, name, var_name, sizeof(var_name), err);
|
|
if (retval == -1)
|
|
FLT_OT_RETURN(retval);
|
|
|
|
(void)memset(&smp, 0, sizeof(smp));
|
|
(void)smp_set_owner(&smp, s->be, s->sess, s, opt | SMP_OPT_FINAL);
|
|
|
|
if (vars_get_by_name(var_name, retval, &smp)) {
|
|
retval = flt_ot_sample_to_str(&(smp.data), var_value, sizeof(var_value), err);
|
|
if (retval != -1)
|
|
FLT_OT_DBG(3, "data type %d: '%s' = '%s'", smp.data.type, var_name, var_value);
|
|
} else {
|
|
FLT_OT_ERR("failed to get variable '%s'", var_name);
|
|
|
|
retval = -1;
|
|
}
|
|
|
|
FLT_OT_RETURN(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 vars *vars;
|
|
const struct var *var;
|
|
char var_name[BUFSIZ], ot_var_name[BUFSIZ];
|
|
int rc, i;
|
|
struct otc_text_map *retptr = NULL;
|
|
|
|
FLT_OT_FUNC("%p, \"%s\", \"%s\", %u, %p:%p", s, scope, prefix, opt, FLT_OT_DPTR_ARGS(err));
|
|
|
|
vars = flt_ot_get_vars(s, scope);
|
|
if (vars == NULL)
|
|
FLT_OT_RETURN(retptr);
|
|
|
|
rc = flt_ot_var_name(NULL, prefix, NULL, var_name, sizeof(var_name), err);
|
|
if (rc == -1)
|
|
FLT_OT_RETURN(retptr);
|
|
|
|
HA_RWLOCK_RDLOCK(VARS_LOCK, &(vars->rwlock));
|
|
list_for_each_entry(var, &(vars->head), l) {
|
|
FLT_OT_DBG(3, "variable cmp '%s' '%s' %d", var_name, var->name, rc);
|
|
|
|
if (strncmp(var_name, var->name, rc) == 0) {
|
|
FLT_OT_DBG(2, "'%s.%s' -> '%.*s'", scope, var->name, (int)var->data.u.str.data, var->data.u.str.area);
|
|
|
|
if (retptr == NULL) {
|
|
retptr = otc_text_map_new(NULL, 8);
|
|
if (retptr == NULL) {
|
|
FLT_OT_ERR("failed to create data");
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* 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 (i = 0; ; )
|
|
if (i >= (FLT_OT_TABLESIZE(ot_var_name) - 1)) {
|
|
FLT_OT_ERR("failed to reverse variable name, buffer too small");
|
|
|
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
|
|
|
break;
|
|
} else {
|
|
char ch = var->name[rc + i + 1];
|
|
|
|
if (ch == '\0')
|
|
break;
|
|
else if (ch == FLT_OT_VAR_CHAR_DASH)
|
|
ch = '-';
|
|
else if (ch == FLT_OT_VAR_CHAR_SPACE)
|
|
ch = ' ';
|
|
|
|
ot_var_name[i++] = ch;
|
|
}
|
|
ot_var_name[i] = '\0';
|
|
|
|
if (retptr == NULL) {
|
|
break;
|
|
}
|
|
else if (otc_text_map_add(retptr, ot_var_name, i, var->data.u.str.area, var->data.u.str.data, OTC_TEXT_MAP_DUP_KEY | OTC_TEXT_MAP_DUP_VALUE) == -1) {
|
|
FLT_OT_ERR("failed to add map data");
|
|
|
|
otc_text_map_destroy(&retptr, OTC_TEXT_MAP_FREE_KEY | OTC_TEXT_MAP_FREE_VALUE);
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
HA_RWLOCK_RDUNLOCK(VARS_LOCK, &(vars->rwlock));
|
|
|
|
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(retptr);
|
|
}
|
|
|
|
/*
|
|
* Local variables:
|
|
* c-indent-level: 8
|
|
* c-basic-offset: 8
|
|
* End:
|
|
*
|
|
* vi: noexpandtab shiftwidth=8 tabstop=8
|
|
*/
|