Преглед на файлове

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.).
Andrei Pelinescu-Onciul преди 17 години
родител
ревизия
a2da0c5890
променени са 6 файла, в които са добавени 138 реда и са изтрити 12 реда
  1. 85 5
      action.c
  2. 34 3
      cfg.y
  3. 5 0
      route.c
  4. 5 0
      route_struct.c
  5. 7 3
      route_struct.h
  6. 2 1
      sr_module.c

+ 85 - 5
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 {

+ 34 - 3
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");

+ 5 - 0
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;

+ 5 - 0
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:

+ 7 - 3
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);

+ 2 - 1
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", \