Browse code

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)")

Daniel-Constantin Mierla authored on 28/12/2020 13:08:16
Showing 5 changed files
... ...
@@ -490,6 +490,7 @@ CFG_DESCRIPTION		"description"|"descr"|"desc"
490 490
 LOADMODULE	loadmodule
491 491
 LOADPATH	"loadpath"|"mpath"
492 492
 MODPARAM        modparam
493
+MODPARAMX        modparamx
493 494
 
494 495
 CFGENGINE	"cfgengine"
495 496
 
... ...
@@ -1003,6 +1004,7 @@ IMPORTFILE      "import_file"
1003 1004
 <INITIAL>{LOADMODULE}	{ count(); yylval.strval=yytext; return LOADMODULE; }
1004 1005
 <INITIAL>{LOADPATH}		{ count(); yylval.strval=yytext; return LOADPATH; }
1005 1006
 <INITIAL>{MODPARAM}     { count(); yylval.strval=yytext; return MODPARAM; }
1007
+<INITIAL>{MODPARAMX}     { count(); yylval.strval=yytext; return MODPARAMX; }
1006 1008
 <INITIAL>{CFGENGINE}	{ count(); yylval.strval=yytext; return CFGENGINE; }
1007 1009
 <INITIAL>{URI_HOST_EXTRA_CHARS}	{ yylval.strval=yytext; return URI_HOST_EXTRA_CHARS; }
1008 1010
 <INITIAL>{HDR_NAME_EXTRA_CHARS}	{ yylval.strval=yytext; return HDR_NAME_EXTRA_CHARS; }
... ...
@@ -403,6 +403,7 @@ extern char *default_routename;
403 403
 %token LOADMODULE
404 404
 %token LOADPATH
405 405
 %token MODPARAM
406
+%token MODPARAMX
406 407
 %token CFGENGINE
407 408
 %token MAXBUFFER
408 409
 %token SQL_BUFFER_SIZE
... ...
@@ -1890,6 +1891,34 @@ module_stm:
1890 1891
 		}
1891 1892
 	}
1892 1893
 	| MODPARAM error { yyerror("Invalid arguments"); }
1894
+	| MODPARAMX LPAREN STRING COMMA STRING COMMA STRING RPAREN {
1895
+		if (!shm_initialized() && init_shm()<0) {
1896
+			yyerror("Can't initialize shared memory");
1897
+			YYABORT;
1898
+		}
1899
+		if (modparamx_set($3, $5, PARAM_STRING, $7) != 0) {
1900
+			 yyerror("Can't set module parameter");
1901
+		}
1902
+	}
1903
+	| MODPARAMX LPAREN STRING COMMA STRING COMMA intno RPAREN {
1904
+		if (!shm_initialized() && init_shm()<0) {
1905
+			yyerror("Can't initialize shared memory");
1906
+			YYABORT;
1907
+		}
1908
+		if (modparamx_set($3, $5, PARAM_INT, (void*)$7) != 0) {
1909
+			 yyerror("Can't set module parameter");
1910
+		}
1911
+	}
1912
+	| MODPARAMX LPAREN STRING COMMA STRING COMMA PVAR RPAREN {
1913
+		if (!shm_initialized() && init_shm()<0) {
1914
+			yyerror("Can't initialize shared memory");
1915
+			YYABORT;
1916
+		}
1917
+		if (modparamx_set($3, $5, PARAM_VAR, (void*)$7) != 0) {
1918
+			 yyerror("Can't set module parameter");
1919
+		}
1920
+	}
1921
+	| MODPARAMX error { yyerror("Invalid arguments"); }
1893 1922
 	| CFGENGINE STRING {
1894 1923
 		if(sr_kemi_eng_setz($2, NULL)) {
1895 1924
 			yyerror("Can't set config routing engine");
... ...
@@ -29,6 +29,8 @@
29 29
 
30 30
 #include "modparam.h"
31 31
 #include "dprint.h"
32
+#include "fmsg.h"
33
+#include "pvar.h"
32 34
 #include "mem/mem.h"
33 35
 #include <sys/types.h>
34 36
 #include <regex.h>
... ...
@@ -179,6 +181,100 @@ int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val)
179 181
 	return 0;
180 182
 }
181 183
 
184
+int modparamx_set(char* mname, char* pname, modparam_t ptype, void* pval)
185
+{
186
+	str seval;
187
+	str sfmt;
188
+	sip_msg_t *fmsg;
189
+	char* emname;
190
+	char* epname;
191
+	pv_spec_t *pvs;
192
+	pv_value_t pvv;
193
+
194
+	emname = mname;
195
+	if(strchr(mname, '$') != NULL) {
196
+		fmsg = faked_msg_get_next();
197
+		sfmt.s = mname;
198
+		sfmt.len = strlen(sfmt.s);
199
+		if(pv_eval_str(fmsg, &seval, &sfmt)>=0) {
200
+			emname = seval.s;
201
+		}
202
+	}
203
+
204
+	epname = pname;
205
+	if(strchr(pname, '$') != NULL) {
206
+		fmsg = faked_msg_get_next();
207
+		sfmt.s = pname;
208
+		sfmt.len = strlen(sfmt.s);
209
+		if(pv_eval_str(fmsg, &seval, &sfmt)>=0) {
210
+			epname = seval.s;
211
+		}
212
+	}
213
+
214
+	switch(ptype) {
215
+		case PARAM_STRING:
216
+			if(strchr((char*)pval, '$') != NULL) {
217
+				fmsg = faked_msg_get_next();
218
+				sfmt.s = (char*)pval;
219
+				sfmt.len = strlen(sfmt.s);
220
+				if(pv_eval_str(fmsg, &seval, &sfmt)>=0) {
221
+					return set_mod_param_regex(emname, epname, PARAM_STRING,
222
+							(void*)seval.s);
223
+				} else {
224
+					LM_ERR("failed to evaluate parameter [%s]\n", (char*)pval);
225
+					return -1;
226
+				}
227
+			} else {
228
+				return set_mod_param_regex(emname, epname, PARAM_STRING, pval);
229
+			}
230
+		case PARAM_INT:
231
+			return set_mod_param_regex(emname, epname, PARAM_INT, pval);
232
+		case PARAM_VAR:
233
+			sfmt.s = (char*)pval;
234
+			sfmt.len = strlen(sfmt.s);
235
+			seval.len = pv_locate_name(&sfmt);
236
+			if(seval.len != sfmt.len) {
237
+				LM_ERR("invalid pv [%.*s] (%d/%d)\n", sfmt.len, sfmt.s,
238
+						seval.len, sfmt.len);
239
+				return -1;
240
+			}
241
+			pvs = pv_cache_get(&sfmt);
242
+			if(pvs==NULL) {
243
+				LM_ERR("cannot get pv spec for [%.*s]\n", sfmt.len, sfmt.s);
244
+				return -1;
245
+			}
246
+
247
+			fmsg = faked_msg_get_next();
248
+			memset(&pvv, 0, sizeof(pv_value_t));
249
+			if(pv_get_spec_value(fmsg, pvs, &pvv) != 0) {
250
+				LM_ERR("unable to get pv value for [%.*s]\n", sfmt.len, sfmt.s);
251
+				return -1;
252
+			}
253
+			if(pvv.flags&PV_VAL_NULL) {
254
+				LM_ERR("unable to get pv value for [%.*s]\n", sfmt.len, sfmt.s);
255
+				return -1;
256
+			}
257
+			if(pvv.flags&PV_TYPE_INT) {
258
+				return set_mod_param_regex(emname, epname, PARAM_INT,
259
+						(void*)(long)pvv.ri);
260
+			}
261
+			if(pvv.rs.len<0) {
262
+				LM_ERR("invalid pv string value for [%.*s]\n", sfmt.len, sfmt.s);
263
+				return -1;
264
+			}
265
+			if(pvv.rs.s[pvv.rs.len] != '\0') {
266
+				LM_ERR("non 0-terminated pv string value for [%.*s]\n",
267
+						sfmt.len, sfmt.s);
268
+				return -1;
269
+			}
270
+			return set_mod_param_regex(emname, epname, PARAM_STRING,
271
+							(void*)pvv.rs.s);
272
+		default:
273
+			LM_ERR("invalid parameter type: %d\n", ptype);
274
+			return -1;
275
+	}
276
+}
277
+
182 278
 int set_mod_param_serialized(char* mval)
183 279
 {
184 280
 #define MPARAM_MBUF_SIZE 256
... ...
@@ -13,8 +13,8 @@
13 13
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 14
  * GNU General Public License for more details.
15 15
  *
16
- * You should have received a copy of the GNU General Public License 
17
- * along with this program; if not, write to the Free Software 
16
+ * You should have received a copy of the GNU General Public License
17
+ * along with this program; if not, write to the Free Software
18 18
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19 19
  */
20 20
 /*!
... ...
@@ -33,6 +33,7 @@
33 33
 int set_mod_param(char* _mod, char* _name, modparam_t _type, void* _val);
34 34
 
35 35
 int set_mod_param_regex(char* regex, char* name, modparam_t type, void* val);
36
+int modparamx_set(char* regex, char* name, modparam_t type, void* val);
36 37
 
37 38
 int set_mod_param_serialized(char* mval);
38 39
 
... ...
@@ -109,6 +109,7 @@ typedef int (*child_init_function)(int rank);
109 109
 #define PARAM_STRING     (1U<<0)  /**< String (char *) parameter type */
110 110
 #define PARAM_INT        (1U<<1)  /**< Integer parameter type */
111 111
 #define PARAM_STR        (1U<<2)  /**< struct str parameter type */
112
+#define PARAM_VAR        (1U<<3)  /**< var parameter type - mdoparamx */
112 113
 #define PARAM_USE_FUNC   (1U<<(8*sizeof(int)-1))
113 114
 #define PARAM_TYPE_MASK(_x)   ((_x)&(~PARAM_USE_FUNC))
114 115