Browse Source

- fix: run_actions() & friends used some static variables to save some
internal state (run_flags, last_ret a.s.o). Problems would appear when
different routes (e.g. main route and an onsend route) would execute in
the same process (e.g. an onsend route return would exit also the
main route). Now run_actions(), do_action() and eval_expr() take an
extra "context" parameter (which must be initialized before use).

Andrei Pelinescu-Onciul 18 years ago
parent
commit
20fded1fe8
5 changed files with 85 additions and 61 deletions
  1. 44 44
      action.c
  2. 25 5
      action.h
  3. 3 1
      onsend.h
  4. 11 10
      route.c
  5. 2 1
      route.h

+ 44 - 44
action.c

@@ -44,6 +44,8 @@
  *  2006-07-27  dns cache and dns based send address failover support (andrei)
  *  2006-07-27  dns cache and dns based send address failover support (andrei)
  *  2006-12-06  on popular request last_retcode set also by module functions
  *  2006-12-06  on popular request last_retcode set also by module functions
  *              (andrei)
  *              (andrei)
+ *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
+ *               static vars (andrei)
  */
  */
 
 
 
 
@@ -78,11 +80,6 @@
 #include <arpa/inet.h>
 #include <arpa/inet.h>
 #include <string.h>
 #include <string.h>
 
 
-#define USE_LONGJMP
-
-#ifdef USE_LONGJMP
-#include <setjmp.h>
-#endif
 
 
 #ifdef DEBUG_DMALLOC
 #ifdef DEBUG_DMALLOC
 #include <dmalloc.h>
 #include <dmalloc.h>
@@ -90,13 +87,11 @@
 
 
 
 
 struct onsend_info* p_onsend=0; /* onsend route send info */
 struct onsend_info* p_onsend=0; /* onsend route send info */
-unsigned int run_flags=0;
-int last_retcode=0; /* last return from a route() */
 
 
 /* ret= 0! if action -> end of list(e.g DROP),
 /* ret= 0! if action -> end of list(e.g DROP),
       > 0 to continue processing next actions
       > 0 to continue processing next actions
    and <0 on error */
    and <0 on error */
-int do_action(struct action* a, struct sip_msg* msg)
+int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 {
 {
 	int ret;
 	int ret;
 	int v;
 	int v;
@@ -123,10 +118,10 @@ int do_action(struct action* a, struct sip_msg* msg)
 	switch ((unsigned char)a->type){
 	switch ((unsigned char)a->type){
 		case DROP_T:
 		case DROP_T:
 				if (a->val[0].type==RETCODE_ST)
 				if (a->val[0].type==RETCODE_ST)
-					ret=last_retcode;
+					ret=h->last_retcode;
 				else
 				else
 					ret=(int) a->val[0].u.number;
 					ret=(int) a->val[0].u.number;
-				run_flags|=(unsigned int)a->val[1].u.number;
+				h->run_flags|=(unsigned int)a->val[1].u.number;
 			break;
 			break;
 		case FORWARD_T:
 		case FORWARD_T:
 #ifdef USE_TCP
 #ifdef USE_TCP
@@ -436,9 +431,9 @@ int do_action(struct action* a, struct sip_msg* msg)
 				break;
 				break;
 			}
 			}
 			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
 			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
-			ret=run_actions(main_rt.rlist[a->val[0].u.number], msg);
-			last_retcode=ret;
-			run_flags&=~RETURN_R_F; /* absorb returns */
+			ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
+			h->last_retcode=ret;
+			h->run_flags&=~RETURN_R_F; /* absorb returns */
 			break;
 			break;
 		case EXEC_T:
 		case EXEC_T:
 			if (a->val[0].type!=STRING_ST){
 			if (a->val[0].type!=STRING_ST){
@@ -649,7 +644,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 		case IF_T:
 		case IF_T:
 				/* if null expr => ignore if? */
 				/* if null expr => ignore if? */
 				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
 				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
-					v=eval_expr((struct expr*)a->val[0].u.data, msg);
+					v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
 #if 0
 #if 0
 					if (v<0){
 					if (v<0){
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
@@ -661,18 +656,20 @@ int do_action(struct action* a, struct sip_msg* msg)
 						}
 						}
 					}
 					}
 #endif
 #endif
-					if (run_flags & EXIT_R_F){
+					if (h->run_flags & EXIT_R_F){
 						ret=0;
 						ret=0;
 						break;
 						break;
 					}
 					}
-					run_flags &= ~RETURN_R_F; /* catch returns in expr */
+					h->run_flags &= ~RETURN_R_F; /* catch returns in expr */
 					ret=1;  /*default is continue */
 					ret=1;  /*default is continue */
 					if (v>0) {
 					if (v>0) {
 						if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
 						if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
-							ret=run_actions((struct action*)a->val[1].u.data, msg);
+							ret=run_actions(h, 
+										(struct action*)a->val[1].u.data, msg);
 						}
 						}
 					}else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
 					}else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
-							ret=run_actions((struct action*)a->val[2].u.data, msg);
+							ret=run_actions(h, 
+										(struct action*)a->val[2].u.data, msg);
 					}
 					}
 				}
 				}
 			break;
 			break;
@@ -682,8 +679,8 @@ int do_action(struct action* a, struct sip_msg* msg)
 					(char*)a->val[2].u.data,
 					(char*)a->val[2].u.data,
 					(char*)a->val[3].u.data
 					(char*)a->val[3].u.data
 				);
 				);
-				if (ret==0) run_flags|=EXIT_R_F;
-				last_retcode=ret;
+				if (ret==0) h->run_flags|=EXIT_R_F;
+				h->last_retcode=ret;
 			} else {
 			} else {
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
 			}
 			}
@@ -753,7 +750,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 	        case ADD_T:
 	        case ADD_T:
 	        case ASSIGN_T:
 	        case ASSIGN_T:
 
 
-			/* If the left attr was specified withou indexing brackets delete
+			/* If the left attr was specified without indexing brackets delete
 			 * existing AVPs before adding new ones
 			 * existing AVPs before adding new ones
 			 */
 			 */
 			if ((a->val[0].u.attr->type & AVP_INDEX_ALL) != AVP_INDEX_ALL) delete_avp(a->val[0].u.attr->type, a->val[0].u.attr->name);
 			if ((a->val[0].u.attr->type & AVP_INDEX_ALL) != AVP_INDEX_ALL) delete_avp(a->val[0].u.attr->type, a->val[0].u.attr->name);
@@ -772,13 +769,14 @@ int do_action(struct action* a, struct sip_msg* msg)
 				flags = a->val[0].u.attr->type;
 				flags = a->val[0].u.attr->type;
 				name = a->val[0].u.attr->name;
 				name = a->val[0].u.attr->name;
 				if (a->val[1].u.data) {
 				if (a->val[1].u.data) {
-					value.n = run_actions((struct action*)a->val[1].u.data, msg);
+					value.n = run_actions(h, (struct action*)a->val[1].u.data,
+											msg);
 				} else {
 				} else {
 					value.n = -1;
 					value.n = -1;
 				}
 				}
 				ret = value.n;
 				ret = value.n;
 			} else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
 			} else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
-				v = eval_expr((struct expr*)a->val[1].u.data, msg);
+				v = eval_expr(h, (struct expr*)a->val[1].u.data, msg);
 				if (v < 0) {
 				if (v < 0) {
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
 						ret = 0;
 						ret = 0;
@@ -884,54 +882,56 @@ error_fwd_uri:
 
 
 /* returns: 0, or 1 on success, <0 on error */
 /* returns: 0, or 1 on success, <0 on error */
 /* (0 if drop or break encountered, 1 if not ) */
 /* (0 if drop or break encountered, 1 if not ) */
-int run_actions(struct action* a, struct sip_msg* msg)
+int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 {
 {
 	struct action* t;
 	struct action* t;
 	int ret;
 	int ret;
-	static int rec_lev=0;
-	static jmp_buf jmp_env;
 	struct sr_module *mod;
 	struct sr_module *mod;
 
 
 	ret=E_UNSPEC;
 	ret=E_UNSPEC;
-	rec_lev++;
-	if (rec_lev>ROUTE_MAX_REC_LEV){
+	h->rec_lev++;
+	if (h->rec_lev>ROUTE_MAX_REC_LEV){
 		LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
 		LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
-					" giving up!\n", rec_lev);
+					" giving up!\n", h->rec_lev);
 		ret=E_UNSPEC;
 		ret=E_UNSPEC;
 		goto error;
 		goto error;
 	}
 	}
-	if (rec_lev==1){
-		run_flags=0;
-		last_retcode=0;
-		if (setjmp(jmp_env)){
-			rec_lev=0;
-			ret=last_retcode;
+	if (h->rec_lev==1){
+		h->run_flags=0;
+		h->last_retcode=0;
+#ifdef USE_LONGJMP
+		if (setjmp(h->jmp_env)){
+			h->rec_lev=0;
+			ret=h->last_retcode;
 			goto end;
 			goto end;
 		}
 		}
+#endif
 	}
 	}
 
 
 	if (a==0){
 	if (a==0){
 		DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
 		DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
-			rec_lev);
+				h->rec_lev);
 		ret=1;
 		ret=1;
 	}
 	}
 
 
 	for (t=a; t!=0; t=t->next){
 	for (t=a; t!=0; t=t->next){
-		ret=do_action(t, msg);
-		if (run_flags & (RETURN_R_F|EXIT_R_F)){
-			if (run_flags & EXIT_R_F){
-				last_retcode=ret;
-				longjmp(jmp_env, ret);
+		ret=do_action(h, t, msg);
+		if (h->run_flags & (RETURN_R_F|EXIT_R_F)){
+			if (h->run_flags & EXIT_R_F){
+#ifdef USE_LONGJMP
+				h->last_retcode=ret;
+				longjmp(h->jmp_env, ret);
+#endif
 			}
 			}
 			break;
 			break;
 		}
 		}
 		/* ignore error returns */
 		/* ignore error returns */
 	}
 	}
 
 
-	rec_lev--;
+	h->rec_lev--;
 end:
 end:
 	/* process module onbreak handlers if present */
 	/* process module onbreak handlers if present */
-	if (rec_lev==0 && ret==0)
+	if (h->rec_lev==0 && ret==0)
 		for (mod=modules;mod;mod=mod->next)
 		for (mod=modules;mod;mod=mod->next)
 			if (mod->exports && mod->exports->onbreak_f) {
 			if (mod->exports && mod->exports->onbreak_f) {
 				mod->exports->onbreak_f( msg );
 				mod->exports->onbreak_f( msg );
@@ -941,7 +941,7 @@ end:
 
 
 
 
 error:
 error:
-	rec_lev--;
+	h->rec_lev--;
 	return ret;
 	return ret;
 }
 }
 
 

+ 25 - 5
action.h

@@ -30,14 +30,34 @@
 #ifndef action_h
 #ifndef action_h
 #define action_h
 #define action_h
 
 
-#include "parser/msg_parser.h"
+#define USE_LONGJMP
+
 #include "route_struct.h"
 #include "route_struct.h"
 
 
-extern unsigned int run_flags;
-extern int last_retcode;
+#include "parser/msg_parser.h"
+
+#ifdef USE_LONGJMP
+#include <setjmp.h>
+#endif
+
+
+struct run_act_ctx{
+	int rec_lev;
+	int run_flags;
+	int last_retcode; /* return from last route */
+#ifdef USE_LONGJMP
+	jmp_buf jmp_env;
+#endif
+};
+
+
+#define init_run_actions_ctx(ph) \
+	do{\
+		(ph)->rec_lev=(ph)->run_flags=(ph)->last_retcode=0; \
+	}while(0)
 
 
-int do_action(struct action* a, struct sip_msg* msg);
-int run_actions(struct action* a, struct sip_msg* msg);
+int do_action(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
+int run_actions(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
 
 
 
 
 
 

+ 3 - 1
onsend.h

@@ -59,6 +59,7 @@ static inline int run_onsend(struct sip_msg* orig_msg, struct dest_info* dst,
 {
 {
 	struct onsend_info onsnd_info;
 	struct onsend_info onsnd_info;
 	int ret;
 	int ret;
+	struct run_act_ctx ra_ctx;
 	
 	
 	ret=1;
 	ret=1;
 	if (onsend_rt.rlist[DEFAULT_RT]){
 	if (onsend_rt.rlist[DEFAULT_RT]){
@@ -67,7 +68,8 @@ static inline int run_onsend(struct sip_msg* orig_msg, struct dest_info* dst,
 		onsnd_info.buf=buf;
 		onsnd_info.buf=buf;
 		onsnd_info.len=len;
 		onsnd_info.len=len;
 		p_onsend=&onsnd_info;
 		p_onsend=&onsnd_info;
-		ret=run_actions(onsend_rt.rlist[DEFAULT_RT], orig_msg);
+		init_run_actions_ctx(&ra_ctx);
+		ret=run_actions(&ra_ctx, onsend_rt.rlist[DEFAULT_RT], orig_msg);
 		p_onsend=0; /* reset it */
 		p_onsend=0; /* reset it */
 	}
 	}
 	return ret;
 	return ret;

+ 11 - 10
route.c

@@ -933,7 +933,8 @@ error_op:
 
 
 
 
 /* returns: 0/1 (false/true) or -1 on error */
 /* returns: 0/1 (false/true) or -1 on error */
-inline static int eval_elem(struct expr* e, struct sip_msg* msg)
+inline static int eval_elem(struct run_act_ctx* h, struct expr* e, 
+								struct sip_msg* msg)
 {
 {
 	struct sip_uri uri;
 	struct sip_uri uri;
 	int ret;
 	int ret;
@@ -1048,7 +1049,7 @@ inline static int eval_elem(struct expr* e, struct sip_msg* msg)
 		break;
 		break;
 
 
 	case ACTION_O:
 	case ACTION_O:
-		ret=run_actions( (struct action*)e->r.param, msg);
+		ret=run_actions(h, (struct action*)e->r.param, msg);
 		if (ret<=0) ret=0;
 		if (ret<=0) ret=0;
 		else ret=1;
 		else ret=1;
 		break;
 		break;
@@ -1124,7 +1125,7 @@ inline static int eval_elem(struct expr* e, struct sip_msg* msg)
 		break;
 		break;
 
 
 	case RETCODE_O:
 	case RETCODE_O:
-		ret=comp_num(e->op, last_retcode, e->r_type, &e->r);
+		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r);
 		break;
 		break;
 
 
 	case AVP_O:
 	case AVP_O:
@@ -1147,28 +1148,28 @@ error:
 
 
 
 
 /* ret= 0/1 (true/false) ,  -1 on error */
 /* ret= 0/1 (true/false) ,  -1 on error */
-int eval_expr(struct expr* e, struct sip_msg* msg)
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg)
 {
 {
 	int ret;
 	int ret;
 
 
 	if (e->type==ELEM_T){
 	if (e->type==ELEM_T){
-		ret=eval_elem(e, msg);
+		ret=eval_elem(h, e, msg);
 	}else if (e->type==EXP_T){
 	}else if (e->type==EXP_T){
 		switch(e->op){
 		switch(e->op){
 			case LOGAND_OP:
 			case LOGAND_OP:
-				ret=eval_expr(e->l.expr, msg);
+				ret=eval_expr(h, e->l.expr, msg);
 				/* if error or false stop evaluating the rest */
 				/* if error or false stop evaluating the rest */
 				if (ret!=1) break;
 				if (ret!=1) break;
-				ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
+				ret=eval_expr(h, e->r.expr, msg); /*ret1 is 1*/
 				break;
 				break;
 			case LOGOR_OP:
 			case LOGOR_OP:
-				ret=eval_expr(e->l.expr, msg);
+				ret=eval_expr(h, e->l.expr, msg);
 				/* if true or error stop evaluating the rest */
 				/* if true or error stop evaluating the rest */
 				if (ret!=0) break;
 				if (ret!=0) break;
-				ret=eval_expr(e->r.expr, msg); /* ret1 is 0 */
+				ret=eval_expr(h, e->r.expr, msg); /* ret1 is 0 */
 				break;
 				break;
 			case NOT_OP:
 			case NOT_OP:
-				ret=eval_expr(e->l.expr, msg);
+				ret=eval_expr(h, e->l.expr, msg);
 				if (ret<0) break;
 				if (ret<0) break;
 				ret= ! ret;
 				ret= ! ret;
 				break;
 				break;

+ 2 - 1
route.h

@@ -36,6 +36,7 @@
 #include "config.h"
 #include "config.h"
 #include "error.h"
 #include "error.h"
 #include "route_struct.h"
 #include "route_struct.h"
+#include "action.h"
 #include "parser/msg_parser.h"
 #include "parser/msg_parser.h"
 #include "str_hash.h"
 #include "str_hash.h"
 
 
@@ -69,7 +70,7 @@ int add_actions(struct action* a, struct action** head);
 void print_rls();
 void print_rls();
 int fix_rls();
 int fix_rls();
 
 
-int eval_expr(struct expr* e, struct sip_msg* msg);
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg);