From dd717b80be6f8e9519aa4b3d627cb88267b81146 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Mon, 28 Dec 2020 14:08:16 +0100 Subject: [PATCH] core: new core directive modparamx(mod, param, val) - alternative to modparam() where all its parameters are evaluated for config script variables - note that only variables that do not depend on SIP message processing should be used at this stage - example - set a module parameter using the value of an evironment variable: modparamx("dispatcher", "db_url", "$env(DBURL)") --- src/core/cfg.lex | 2 + src/core/cfg.y | 29 +++++++++++++ src/core/modparam.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/core/modparam.h | 5 ++- src/core/sr_module.h | 1 + 5 files changed, 131 insertions(+), 2 deletions(-) diff --git a/src/core/cfg.lex b/src/core/cfg.lex index 743ee0c212e..01e52182855 100644 --- a/src/core/cfg.lex +++ b/src/core/cfg.lex @@ -490,6 +490,7 @@ CFG_DESCRIPTION "description"|"descr"|"desc" LOADMODULE loadmodule LOADPATH "loadpath"|"mpath" MODPARAM modparam +MODPARAMX modparamx CFGENGINE "cfgengine" @@ -1003,6 +1004,7 @@ IMPORTFILE "import_file" {LOADMODULE} { count(); yylval.strval=yytext; return LOADMODULE; } {LOADPATH} { count(); yylval.strval=yytext; return LOADPATH; } {MODPARAM} { count(); yylval.strval=yytext; return MODPARAM; } +{MODPARAMX} { count(); yylval.strval=yytext; return MODPARAMX; } {CFGENGINE} { count(); yylval.strval=yytext; return CFGENGINE; } {URI_HOST_EXTRA_CHARS} { yylval.strval=yytext; return URI_HOST_EXTRA_CHARS; } {HDR_NAME_EXTRA_CHARS} { yylval.strval=yytext; return HDR_NAME_EXTRA_CHARS; } diff --git a/src/core/cfg.y b/src/core/cfg.y index 56d0e75caeb..2a5804c3dd8 100644 --- a/src/core/cfg.y +++ b/src/core/cfg.y @@ -403,6 +403,7 @@ extern char *default_routename; %token LOADMODULE %token LOADPATH %token MODPARAM +%token MODPARAMX %token CFGENGINE %token MAXBUFFER %token SQL_BUFFER_SIZE @@ -1890,6 +1891,34 @@ module_stm: } } | MODPARAM error { yyerror("Invalid arguments"); } + | MODPARAMX LPAREN STRING COMMA STRING COMMA STRING RPAREN { + if (!shm_initialized() && init_shm()<0) { + yyerror("Can't initialize shared memory"); + YYABORT; + } + if (modparamx_set($3, $5, PARAM_STRING, $7) != 0) { + yyerror("Can't set module parameter"); + } + } + | MODPARAMX LPAREN STRING COMMA STRING COMMA intno RPAREN { + if (!shm_initialized() && init_shm()<0) { + yyerror("Can't initialize shared memory"); + YYABORT; + } + if (modparamx_set($3, $5, PARAM_INT, (void*)$7) != 0) { + yyerror("Can't set module parameter"); + } + } + | MODPARAMX LPAREN STRING COMMA STRING COMMA PVAR RPAREN { + if (!shm_initialized() && init_shm()<0) { + yyerror("Can't initialize shared memory"); + YYABORT; + } + if (modparamx_set($3, $5, PARAM_VAR, (void*)$7) != 0) { + yyerror("Can't set module parameter"); + } + } + | MODPARAMX error { yyerror("Invalid arguments"); } | CFGENGINE STRING { if(sr_kemi_eng_setz($2, NULL)) { yyerror("Can't set config routing engine"); diff --git a/src/core/modparam.c b/src/core/modparam.c index e169e651a2c..041ce841c40 100644 --- a/src/core/modparam.c +++ b/src/core/modparam.c @@ -29,6 +29,8 @@ #include "modparam.h" #include "dprint.h" +#include "fmsg.h" +#include "pvar.h" #include "mem/mem.h" #include #include @@ -179,6 +181,100 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val) return 0; } +int modparamx_set(char* mname, char* pname, modparam_t ptype, void* pval) +{ + str seval; + str sfmt; + sip_msg_t *fmsg; + char* emname; + char* epname; + pv_spec_t *pvs; + pv_value_t pvv; + + emname = mname; + if(strchr(mname, '$') != NULL) { + fmsg = faked_msg_get_next(); + sfmt.s = mname; + sfmt.len = strlen(sfmt.s); + if(pv_eval_str(fmsg, &seval, &sfmt)>=0) { + emname = seval.s; + } + } + + epname = pname; + if(strchr(pname, '$') != NULL) { + fmsg = faked_msg_get_next(); + sfmt.s = pname; + sfmt.len = strlen(sfmt.s); + if(pv_eval_str(fmsg, &seval, &sfmt)>=0) { + epname = seval.s; + } + } + + switch(ptype) { + case PARAM_STRING: + if(strchr((char*)pval, '$') != NULL) { + fmsg = faked_msg_get_next(); + sfmt.s = (char*)pval; + sfmt.len = strlen(sfmt.s); + if(pv_eval_str(fmsg, &seval, &sfmt)>=0) { + return set_mod_param_regex(emname, epname, PARAM_STRING, + (void*)seval.s); + } else { + LM_ERR("failed to evaluate parameter [%s]\n", (char*)pval); + return -1; + } + } else { + return set_mod_param_regex(emname, epname, PARAM_STRING, pval); + } + case PARAM_INT: + return set_mod_param_regex(emname, epname, PARAM_INT, pval); + case PARAM_VAR: + sfmt.s = (char*)pval; + sfmt.len = strlen(sfmt.s); + seval.len = pv_locate_name(&sfmt); + if(seval.len != sfmt.len) { + LM_ERR("invalid pv [%.*s] (%d/%d)\n", sfmt.len, sfmt.s, + seval.len, sfmt.len); + return -1; + } + pvs = pv_cache_get(&sfmt); + if(pvs==NULL) { + LM_ERR("cannot get pv spec for [%.*s]\n", sfmt.len, sfmt.s); + return -1; + } + + fmsg = faked_msg_get_next(); + memset(&pvv, 0, sizeof(pv_value_t)); + if(pv_get_spec_value(fmsg, pvs, &pvv) != 0) { + LM_ERR("unable to get pv value for [%.*s]\n", sfmt.len, sfmt.s); + return -1; + } + if(pvv.flags&PV_VAL_NULL) { + LM_ERR("unable to get pv value for [%.*s]\n", sfmt.len, sfmt.s); + return -1; + } + if(pvv.flags&PV_TYPE_INT) { + return set_mod_param_regex(emname, epname, PARAM_INT, + (void*)(long)pvv.ri); + } + if(pvv.rs.len<0) { + LM_ERR("invalid pv string value for [%.*s]\n", sfmt.len, sfmt.s); + return -1; + } + if(pvv.rs.s[pvv.rs.len] != '\0') { + LM_ERR("non 0-terminated pv string value for [%.*s]\n", + sfmt.len, sfmt.s); + return -1; + } + return set_mod_param_regex(emname, epname, PARAM_STRING, + (void*)pvv.rs.s); + default: + LM_ERR("invalid parameter type: %d\n", ptype); + return -1; + } +} + int set_mod_param_serialized(char* mval) { #define MPARAM_MBUF_SIZE 256 diff --git a/src/core/modparam.h b/src/core/modparam.h index 0a4241ad4a0..7619e9ae7e3 100644 --- a/src/core/modparam.h +++ b/src/core/modparam.h @@ -13,8 +13,8 @@ * 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 + * 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 */ /*! @@ -33,6 +33,7 @@ int set_mod_param(char* _mod, char* _name, modparam_t _type, void* _val); int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val); +int modparamx_set(char* regex, char* name, modparam_t type, void* val); int set_mod_param_serialized(char* mval); diff --git a/src/core/sr_module.h b/src/core/sr_module.h index 3014a88dad5..485c732bf7f 100644 --- a/src/core/sr_module.h +++ b/src/core/sr_module.h @@ -109,6 +109,7 @@ typedef int (*child_init_function)(int rank); #define PARAM_STRING (1U<<0) /**< String (char *) parameter type */ #define PARAM_INT (1U<<1) /**< Integer parameter type */ #define PARAM_STR (1U<<2) /**< struct str parameter type */ +#define PARAM_VAR (1U<<3) /**< var parameter type - mdoparamx */ #define PARAM_USE_FUNC (1U<<(8*sizeof(int)-1)) #define PARAM_TYPE_MASK(_x) ((_x)&(~PARAM_USE_FUNC))