Forráskód Böngészése

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 éve
szülő
commit
a2da0c5890
6 módosított fájl, 138 hozzáadás és 12 törlés
  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)
  *              (andrei)
  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
  *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
  *               static vars (andrei)
  *               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;
 	struct dest_info dst;
 	char* tmp;
 	char* tmp;
 	char *new_uri, *end, *crt;
 	char *new_uri, *end, *crt;
+	void* f;
 	int len;
 	int len;
 	int user;
 	int user;
 	struct sip_uri uri, next_hop;
 	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;
 			break;
 		case MODULE_T:
 		case MODULE_T:
 			if ( a->val[0].type==MODEXP_ST && a->val[0].u.data && 
 			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;
 				if (ret==0) h->run_flags|=EXIT_R_F;
 				h->last_retcode=ret;
 				h->last_retcode=ret;
 			} else {
 			} else {

+ 34 - 3
cfg.y

@@ -88,6 +88,7 @@
  * 2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
  * 2007-11-28  added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
  *              LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
  * 2008-01-24  added cfg_var definition (Miklos)
  * 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");
 		$$=0; yyerror("bad argument, [proto:]host[:port] expected");
 	}
 	}
 	| FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); }
 	| 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 = 
 		mod_func_action->val[0].u.data = 
 			find_export_record($1, mod_func_action->val[1].u.number, rt,
 			find_export_record($1, mod_func_action->val[1].u.number, rt,
 								&u_tmp);
 								&u_tmp);
@@ -2372,6 +2374,33 @@ cmd:
 			}
 			}
 			pkg_free(mod_func_action);
 			pkg_free(mod_func_action);
 			mod_func_action=0;
 			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;
 		$$ = mod_func_action;
 	}
 	}
@@ -2385,8 +2414,10 @@ func_params:
 func_param:
 func_param:
         NUMBER {
         NUMBER {
 		if (mod_func_action->val[1].u.number < MAX_ACTIONS-2) {
 		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++;
 			mod_func_action->val[1].u.number++;
 		} else {
 		} else {
 			yyerror("Too many arguments\n");
 			yyerror("Too many arguments\n");

+ 5 - 0
route.c

@@ -503,6 +503,11 @@ static int fix_actions(struct action* a)
 				break;
 				break;
 
 
 			case MODULE_T:
 			case MODULE_T:
+			case MODULE3_T:
+			case MODULE4_T:
+			case MODULE5_T:
+			case MODULE6_T:
+			case MODULEX_T:
 				cmd = t->val[0].u.data;
 				cmd = t->val[0].u.data;
 				if (cmd && cmd->c.fixup) {
 				if (cmd && cmd->c.fixup) {
 					int i;
 					int i;

+ 5 - 0
route_struct.c

@@ -350,6 +350,11 @@ void print_action(struct action* t)
 			DBG("if (");
 			DBG("if (");
 			break;
 			break;
 		case MODULE_T:
 		case MODULE_T:
+		case MODULE3_T:
+		case MODULE4_T:
+		case MODULE5_T:
+		case MODULE6_T:
+		case MODULEX_T:
 			DBG(" external_module_call(");
 			DBG(" external_module_call(");
 			break;
 			break;
 		case FORCE_RPORT_T:
 		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,
 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_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
 		SET_PORT_T, SET_URI_T, SET_HOSTPORTTRANS_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 ,
 		SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
 		AVPFLAG_OPER_T,
 		AVPFLAG_OPER_T,
 		LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
 		LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
@@ -133,13 +133,17 @@ typedef struct {
 	} u;
 	} u;
 } action_u_t;
 } 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{
 struct action{
 	int type;  /* forward, drop, log, send ...*/
 	int type;  /* forward, drop, log, send ...*/
 	int count;
 	int count;
-	action_u_t val[MAX_ACTIONS];
 	struct action* next;
 	struct action* next;
+	action_u_t val[MAX_ACTIONS];
 };
 };
 
 
 struct expr* mk_exp(int op, struct expr* left, struct expr* right);
 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; \
 			for(i=0, cmd=(void*)&t->exports->VER.cmds[0]; cmd->VER.name; \
 					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
 					i++, cmd=(void*)&t->exports->VER.cmds[i]){\
 				if((strcmp(name, cmd->VER.name)==0)&& \
 				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) \
 					((cmd->VER.flags & flags) == flags) \
 				){ \
 				){ \
 					DBG("find_export_record: found <%s> in module %s [%s]\n", \
 					DBG("find_export_record: found <%s> in module %s [%s]\n", \