[SR-Dev] git:sip-router: script: variable number of params for functions

Andrei Pelinescu-Onciul andrei at iptel.org
Wed Nov 19 00:26:23 CET 2008


Module: sip-router
Branch: andrei/mod_f_params
Commit: a2da0c5890f7c02538f0acb3197e6753dc9708bb
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=a2da0c5890f7c02538f0acb3197e6753dc9708bb

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Wed Nov 19 00:10:46 2008 +0100

script: variable number of params for functions

- support for true variable number of parameters module functions
  ( f(sip_msg, param_no, param_array[]) )
- support for functions with 3-6 parameters using kamailio extended
  interface. The implementation is however different: while in kamailio
  all module functions where called with 6 parameters (even if they
  declared only 2), this version will generate different function
  calls (small performance benefit by avoiding unneeded stack pushes
  and register saving for the most common 2 parameter functions and
  works also with other calling conventions).
  For performance reasons, a separate script engine command is now
  generated for each type of function: module functions calls with 0-2
  parameters (MODULE_T), 3 (MODULE3_T), 4 (MODULE4_T), 5 (MODULE5_T)
  and 6 (MODULE6_T) parameters.
  In case of name conflicts with variable param. number function,
  it's undefined which actual function will get executed (it will be
  the "first" one, but the order depends on the module loading order
  a.s.o.).

---

 action.c       |   90 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 cfg.y          |   37 +++++++++++++++++++++--
 route.c        |    5 +++
 route_struct.c |    5 +++
 route_struct.h |   10 ++++--
 sr_module.c    |    3 +-
 6 files changed, 138 insertions(+), 12 deletions(-)

diff --git a/action.c b/action.c
index 4dc7aba..ea69e3a 100644
--- a/action.c
+++ b/action.c
@@ -46,6 +46,7 @@
  *              (andrei)
  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
  *               static vars (andrei)
+ *  2008-11-18  support for variable parameter module functions (andrei)
  */
 
 
@@ -101,6 +102,7 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 	struct dest_info dst;
 	char* tmp;
 	char *new_uri, *end, *crt;
+	void* f;
 	int len;
 	int user;
 	struct sip_uri uri, next_hop;
@@ -717,11 +719,89 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 			break;
 		case MODULE_T:
 			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
-					((union cmd_export_u*)a->val[0].u.data)->c.function){
-				ret=((union cmd_export_u*)a->val[0].u.data)->c.function(msg,
-					(char*)a->val[2].u.data,
-					(char*)a->val[3].u.data
-				);
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function)f)(msg,
+										(char*)a->val[2].u.data,
+										(char*)a->val[3].u.data
+									);
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
+			} else {
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
+		/* instead of using the parameter number, we use different names
+		 * for calls to functions with 3, 4, 5, 6 or variable number of
+		 * parameters due to performance reasons */
+		case MODULE3_T:
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function3)f)(msg,
+										(char*)a->val[2].u.data,
+										(char*)a->val[3].u.data,
+										(char*)a->val[4].u.data
+									);
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
+			} else {
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
+		case MODULE4_T:
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function4)f)(msg,
+										(char*)a->val[2].u.data,
+										(char*)a->val[3].u.data,
+										(char*)a->val[4].u.data,
+										(char*)a->val[5].u.data
+									);
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
+			} else {
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
+		case MODULE5_T:
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function5)f)(msg,
+										(char*)a->val[2].u.data,
+										(char*)a->val[3].u.data,
+										(char*)a->val[4].u.data,
+										(char*)a->val[5].u.data,
+										(char*)a->val[6].u.data
+									);
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
+			} else {
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
+		case MODULE6_T:
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function6)f)(msg,
+										(char*)a->val[2].u.data,
+										(char*)a->val[3].u.data,
+										(char*)a->val[4].u.data,
+										(char*)a->val[5].u.data,
+										(char*)a->val[6].u.data,
+										(char*)a->val[7].u.data
+									);
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
+			} else {
+				LOG(L_CRIT,"BUG: do_action: bad module call\n");
+			}
+			break;
+		case MODULEX_T:
+			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
+					(f=((union cmd_export_u*)a->val[0].u.data)->c.function)){
+				ret=((cmd_function_var)f)(msg,
+											a->val[1].u.number,
+											&a->val[2]
+										);
 				if (ret==0) h->run_flags|=EXIT_R_F;
 				h->last_retcode=ret;
 			} else {
diff --git a/cfg.y b/cfg.y
index ab485e6..5adc111 100644
--- a/cfg.y
+++ b/cfg.y
@@ -88,6 +88,7 @@
  * 2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
  * 2008-01-24  added cfg_var definition (Miklos)
+ * 2008-11-18  support for variable parameter module functions (andrei)
 */
 
 %{
@@ -2359,7 +2360,8 @@ cmd:
 		$$=0; yyerror("bad argument, [proto:]host[:port] expected");
 	}
 	| FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); }
-	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST, 0); } LPAREN func_params RPAREN	{
+	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST,
+			0); } LPAREN func_params RPAREN	{
 		mod_func_action->val[0].u.data = 
 			find_export_record($1, mod_func_action->val[1].u.number, rt,
 								&u_tmp);
@@ -2372,6 +2374,33 @@ cmd:
 			}
 			pkg_free(mod_func_action);
 			mod_func_action=0;
+		}else{
+			switch( ((union cmd_export_u*)
+						mod_func_action->val[0].u.data)->c.param_no){
+				case 0:
+				case 1:
+				case 2:
+					/* MODULE_T used for 0-2 params */
+					break;
+				case 3:
+					mod_func_action->type=MODULE3_T;
+					break;
+				case 4:
+					mod_func_action->type=MODULE4_T;
+					break;
+				case 5:
+					mod_func_action->type=MODULE5_T;
+					break;
+				case 6:
+					mod_func_action->type=MODULE6_T;
+					break;
+				case VAR_PARAM_NO:
+					mod_func_action->type=MODULEX_T;
+					break;
+				default:
+					yyerror("too many parameters for function\n");
+					break;
+			}
 		}
 		$$ = mod_func_action;
 	}
@@ -2385,8 +2414,10 @@ func_params:
 func_param:
         NUMBER {
 		if (mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
-			mod_func_action->val[mod_func_action->val[1].u.number+2].type = NUMBER_ST;
-			mod_func_action->val[mod_func_action->val[1].u.number+2].u.number = $1;
+			mod_func_action->val[mod_func_action->val[1].u.number+2].type =
+				NUMBER_ST;
+			mod_func_action->val[mod_func_action->val[1].u.number+2].u.number =
+				$1;
 			mod_func_action->val[1].u.number++;
 		} else {
 			yyerror("Too many arguments\n");
diff --git a/route.c b/route.c
index b222bfa..5c39764 100644
--- a/route.c
+++ b/route.c
@@ -503,6 +503,11 @@ static int fix_actions(struct action* a)
 				break;
 
 			case MODULE_T:
+			case MODULE3_T:
+			case MODULE4_T:
+			case MODULE5_T:
+			case MODULE6_T:
+			case MODULEX_T:
 				cmd = t->val[0].u.data;
 				if (cmd && cmd->c.fixup) {
 					int i;
diff --git a/route_struct.c b/route_struct.c
index 0c00c61..c5fb76b 100644
--- a/route_struct.c
+++ b/route_struct.c
@@ -350,6 +350,11 @@ void print_action(struct action* t)
 			DBG("if (");
 			break;
 		case MODULE_T:
+		case MODULE3_T:
+		case MODULE4_T:
+		case MODULE5_T:
+		case MODULE6_T:
+		case MODULEX_T:
 			DBG(" external_module_call(");
 			break;
 		case FORCE_RPORT_T:
diff --git a/route_struct.h b/route_struct.h
index 814517b..22b92d9 100644
--- a/route_struct.h
+++ b/route_struct.h
@@ -70,7 +70,7 @@ enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
 		SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_T,
-		IF_T, MODULE_T,
+		IF_T, MODULE_T, MODULE3_T, MODULE4_T, MODULE5_T, MODULE6_T, MODULEX_T,
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
 		AVPFLAG_OPER_T,
 		LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
@@ -133,13 +133,17 @@ typedef struct {
 	} u;
 } action_u_t;
 
-#define MAX_ACTIONS 4
+/* maximum internal array/params
+ * for module function calls val[0] and val[1] store a pointer to the
+ * function and the number of params, the rest are the function params 
+ */
+#define MAX_ACTIONS (2+6)
 
 struct action{
 	int type;  /* forward, drop, log, send ...*/
 	int count;
-	action_u_t val[MAX_ACTIONS];
 	struct action* next;
+	action_u_t val[MAX_ACTIONS];
 };
 
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
diff --git a/sr_module.c b/sr_module.c
index d59dc6d..21d89ac 100644
--- a/sr_module.c
+++ b/sr_module.c
@@ -353,7 +353,8 @@ union cmd_export_u* find_mod_export_record(char* mod, char* name,
 			for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
 					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
 				if((strcmp(name, cmd->VER.name)==0)&& \
-					(cmd->VER.param_no==param_no) &&  \
+					((cmd->VER.param_no==param_no) || \
+					 (cmd->VER.param_no==VAR_PARAM_NO)) && \
 					((cmd->VER.flags & flags) == flags) \
 				){ \
 					DBG("find_export_record: found <%s> in module %s [%s]\n", \




More information about the sr-dev mailing list