Browse code

- 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 authored on 14/06/2007 23:12:26
Showing 5 changed files
... ...
@@ -44,6 +44,8 @@
44 44
  *  2006-07-27  dns cache and dns based send address failover support (andrei)
45 45
  *  2006-12-06  on popular request last_retcode set also by module functions
46 46
  *              (andrei)
47
+ *  2007-06-14  run_actions & do_action need a ctx or handle now, no more 
48
+ *               static vars (andrei)
47 49
  */
48 50
 
49 51
 
... ...
@@ -78,11 +80,6 @@
78 78
 #include <arpa/inet.h>
79 79
 #include <string.h>
80 80
 
81
-#define USE_LONGJMP
82
-
83
-#ifdef USE_LONGJMP
84
-#include <setjmp.h>
85
-#endif
86 81
 
87 82
 #ifdef DEBUG_DMALLOC
88 83
 #include <dmalloc.h>
... ...
@@ -90,13 +87,11 @@
90 90
 
91 91
 
92 92
 struct onsend_info* p_onsend=0; /* onsend route send info */
93
-unsigned int run_flags=0;
94
-int last_retcode=0; /* last return from a route() */
95 93
 
96 94
 /* ret= 0! if action -> end of list(e.g DROP),
97 95
       > 0 to continue processing next actions
98 96
    and <0 on error */
99
-int do_action(struct action* a, struct sip_msg* msg)
97
+int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
100 98
 {
101 99
 	int ret;
102 100
 	int v;
... ...
@@ -123,10 +118,10 @@ int do_action(struct action* a, struct sip_msg* msg)
123 123
 	switch ((unsigned char)a->type){
124 124
 		case DROP_T:
125 125
 				if (a->val[0].type==RETCODE_ST)
126
-					ret=last_retcode;
126
+					ret=h->last_retcode;
127 127
 				else
128 128
 					ret=(int) a->val[0].u.number;
129
-				run_flags|=(unsigned int)a->val[1].u.number;
129
+				h->run_flags|=(unsigned int)a->val[1].u.number;
130 130
 			break;
131 131
 		case FORWARD_T:
132 132
 #ifdef USE_TCP
... ...
@@ -436,9 +431,9 @@ int do_action(struct action* a, struct sip_msg* msg)
436 436
 				break;
437 437
 			}
438 438
 			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
439
-			ret=run_actions(main_rt.rlist[a->val[0].u.number], msg);
440
-			last_retcode=ret;
441
-			run_flags&=~RETURN_R_F; /* absorb returns */
439
+			ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
440
+			h->last_retcode=ret;
441
+			h->run_flags&=~RETURN_R_F; /* absorb returns */
442 442
 			break;
443 443
 		case EXEC_T:
444 444
 			if (a->val[0].type!=STRING_ST){
... ...
@@ -649,7 +644,7 @@ int do_action(struct action* a, struct sip_msg* msg)
649 649
 		case IF_T:
650 650
 				/* if null expr => ignore if? */
651 651
 				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
652
-					v=eval_expr((struct expr*)a->val[0].u.data, msg);
652
+					v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
653 653
 #if 0
654 654
 					if (v<0){
655 655
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
... ...
@@ -661,18 +656,20 @@ int do_action(struct action* a, struct sip_msg* msg)
661 661
 						}
662 662
 					}
663 663
 #endif
664
-					if (run_flags & EXIT_R_F){
664
+					if (h->run_flags & EXIT_R_F){
665 665
 						ret=0;
666 666
 						break;
667 667
 					}
668
-					run_flags &= ~RETURN_R_F; /* catch returns in expr */
668
+					h->run_flags &= ~RETURN_R_F; /* catch returns in expr */
669 669
 					ret=1;  /*default is continue */
670 670
 					if (v>0) {
671 671
 						if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
672
-							ret=run_actions((struct action*)a->val[1].u.data, msg);
672
+							ret=run_actions(h, 
673
+										(struct action*)a->val[1].u.data, msg);
673 674
 						}
674 675
 					}else if ((a->val[2].type==ACTIONS_ST)&&a->val[2].u.data){
675
-							ret=run_actions((struct action*)a->val[2].u.data, msg);
676
+							ret=run_actions(h, 
677
+										(struct action*)a->val[2].u.data, msg);
676 678
 					}
677 679
 				}
678 680
 			break;
... ...
@@ -682,8 +679,8 @@ int do_action(struct action* a, struct sip_msg* msg)
682 682
 					(char*)a->val[2].u.data,
683 683
 					(char*)a->val[3].u.data
684 684
 				);
685
-				if (ret==0) run_flags|=EXIT_R_F;
686
-				last_retcode=ret;
685
+				if (ret==0) h->run_flags|=EXIT_R_F;
686
+				h->last_retcode=ret;
687 687
 			} else {
688 688
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
689 689
 			}
... ...
@@ -753,7 +750,7 @@ int do_action(struct action* a, struct sip_msg* msg)
753 753
 	        case ADD_T:
754 754
 	        case ASSIGN_T:
755 755
 
756
-			/* If the left attr was specified withou indexing brackets delete
756
+			/* If the left attr was specified without indexing brackets delete
757 757
 			 * existing AVPs before adding new ones
758 758
 			 */
759 759
 			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)
772 772
 				flags = a->val[0].u.attr->type;
773 773
 				name = a->val[0].u.attr->name;
774 774
 				if (a->val[1].u.data) {
775
-					value.n = run_actions((struct action*)a->val[1].u.data, msg);
775
+					value.n = run_actions(h, (struct action*)a->val[1].u.data,
776
+											msg);
776 777
 				} else {
777 778
 					value.n = -1;
778 779
 				}
779 780
 				ret = value.n;
780 781
 			} else if(a->val[1].type == EXPR_ST && a->val[1].u.data) {
781
-				v = eval_expr((struct expr*)a->val[1].u.data, msg);
782
+				v = eval_expr(h, (struct expr*)a->val[1].u.data, msg);
782 783
 				if (v < 0) {
783 784
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
784 785
 						ret = 0;
... ...
@@ -884,54 +882,56 @@ error_fwd_uri:
884 884
 
885 885
 /* returns: 0, or 1 on success, <0 on error */
886 886
 /* (0 if drop or break encountered, 1 if not ) */
887
-int run_actions(struct action* a, struct sip_msg* msg)
887
+int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
888 888
 {
889 889
 	struct action* t;
890 890
 	int ret;
891
-	static int rec_lev=0;
892
-	static jmp_buf jmp_env;
893 891
 	struct sr_module *mod;
894 892
 
895 893
 	ret=E_UNSPEC;
896
-	rec_lev++;
897
-	if (rec_lev>ROUTE_MAX_REC_LEV){
894
+	h->rec_lev++;
895
+	if (h->rec_lev>ROUTE_MAX_REC_LEV){
898 896
 		LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
899
-					" giving up!\n", rec_lev);
897
+					" giving up!\n", h->rec_lev);
900 898
 		ret=E_UNSPEC;
901 899
 		goto error;
902 900
 	}
903
-	if (rec_lev==1){
904
-		run_flags=0;
905
-		last_retcode=0;
906
-		if (setjmp(jmp_env)){
907
-			rec_lev=0;
908
-			ret=last_retcode;
901
+	if (h->rec_lev==1){
902
+		h->run_flags=0;
903
+		h->last_retcode=0;
904
+#ifdef USE_LONGJMP
905
+		if (setjmp(h->jmp_env)){
906
+			h->rec_lev=0;
907
+			ret=h->last_retcode;
909 908
 			goto end;
910 909
 		}
910
+#endif
911 911
 	}
912 912
 
913 913
 	if (a==0){
914 914
 		DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
915
-			rec_lev);
915
+				h->rec_lev);
916 916
 		ret=1;
917 917
 	}
918 918
 
919 919
 	for (t=a; t!=0; t=t->next){
920
-		ret=do_action(t, msg);
921
-		if (run_flags & (RETURN_R_F|EXIT_R_F)){
922
-			if (run_flags & EXIT_R_F){
923
-				last_retcode=ret;
924
-				longjmp(jmp_env, ret);
920
+		ret=do_action(h, t, msg);
921
+		if (h->run_flags & (RETURN_R_F|EXIT_R_F)){
922
+			if (h->run_flags & EXIT_R_F){
923
+#ifdef USE_LONGJMP
924
+				h->last_retcode=ret;
925
+				longjmp(h->jmp_env, ret);
926
+#endif
925 927
 			}
926 928
 			break;
927 929
 		}
928 930
 		/* ignore error returns */
929 931
 	}
930 932
 
931
-	rec_lev--;
933
+	h->rec_lev--;
932 934
 end:
933 935
 	/* process module onbreak handlers if present */
934
-	if (rec_lev==0 && ret==0)
936
+	if (h->rec_lev==0 && ret==0)
935 937
 		for (mod=modules;mod;mod=mod->next)
936 938
 			if (mod->exports && mod->exports->onbreak_f) {
937 939
 				mod->exports->onbreak_f( msg );
... ...
@@ -941,7 +941,7 @@ end:
941 941
 
942 942
 
943 943
 error:
944
-	rec_lev--;
944
+	h->rec_lev--;
945 945
 	return ret;
946 946
 }
947 947
 
... ...
@@ -30,14 +30,34 @@
30 30
 #ifndef action_h
31 31
 #define action_h
32 32
 
33
-#include "parser/msg_parser.h"
33
+#define USE_LONGJMP
34
+
34 35
 #include "route_struct.h"
35 36
 
36
-extern unsigned int run_flags;
37
-extern int last_retcode;
37
+#include "parser/msg_parser.h"
38
+
39
+#ifdef USE_LONGJMP
40
+#include <setjmp.h>
41
+#endif
42
+
43
+
44
+struct run_act_ctx{
45
+	int rec_lev;
46
+	int run_flags;
47
+	int last_retcode; /* return from last route */
48
+#ifdef USE_LONGJMP
49
+	jmp_buf jmp_env;
50
+#endif
51
+};
52
+
53
+
54
+#define init_run_actions_ctx(ph) \
55
+	do{\
56
+		(ph)->rec_lev=(ph)->run_flags=(ph)->last_retcode=0; \
57
+	}while(0)
38 58
 
39
-int do_action(struct action* a, struct sip_msg* msg);
40
-int run_actions(struct action* a, struct sip_msg* msg);
59
+int do_action(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
60
+int run_actions(struct run_act_ctx* c, struct action* a, struct sip_msg* msg);
41 61
 
42 62
 
43 63
 
... ...
@@ -59,6 +59,7 @@ static inline int run_onsend(struct sip_msg* orig_msg, struct dest_info* dst,
59 59
 {
60 60
 	struct onsend_info onsnd_info;
61 61
 	int ret;
62
+	struct run_act_ctx ra_ctx;
62 63
 	
63 64
 	ret=1;
64 65
 	if (onsend_rt.rlist[DEFAULT_RT]){
... ...
@@ -67,7 +68,8 @@ static inline int run_onsend(struct sip_msg* orig_msg, struct dest_info* dst,
67 67
 		onsnd_info.buf=buf;
68 68
 		onsnd_info.len=len;
69 69
 		p_onsend=&onsnd_info;
70
-		ret=run_actions(onsend_rt.rlist[DEFAULT_RT], orig_msg);
70
+		init_run_actions_ctx(&ra_ctx);
71
+		ret=run_actions(&ra_ctx, onsend_rt.rlist[DEFAULT_RT], orig_msg);
71 72
 		p_onsend=0; /* reset it */
72 73
 	}
73 74
 	return ret;
... ...
@@ -933,7 +933,8 @@ error_op:
933 933
 
934 934
 
935 935
 /* returns: 0/1 (false/true) or -1 on error */
936
-inline static int eval_elem(struct expr* e, struct sip_msg* msg)
936
+inline static int eval_elem(struct run_act_ctx* h, struct expr* e, 
937
+								struct sip_msg* msg)
937 938
 {
938 939
 	struct sip_uri uri;
939 940
 	int ret;
... ...
@@ -1048,7 +1049,7 @@ inline static int eval_elem(struct expr* e, struct sip_msg* msg)
1048 1048
 		break;
1049 1049
 
1050 1050
 	case ACTION_O:
1051
-		ret=run_actions( (struct action*)e->r.param, msg);
1051
+		ret=run_actions(h, (struct action*)e->r.param, msg);
1052 1052
 		if (ret<=0) ret=0;
1053 1053
 		else ret=1;
1054 1054
 		break;
... ...
@@ -1124,7 +1125,7 @@ inline static int eval_elem(struct expr* e, struct sip_msg* msg)
1124 1124
 		break;
1125 1125
 
1126 1126
 	case RETCODE_O:
1127
-		ret=comp_num(e->op, last_retcode, e->r_type, &e->r);
1127
+		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r);
1128 1128
 		break;
1129 1129
 
1130 1130
 	case AVP_O:
... ...
@@ -1147,28 +1148,28 @@ error:
1147 1147
 
1148 1148
 
1149 1149
 /* ret= 0/1 (true/false) ,  -1 on error */
1150
-int eval_expr(struct expr* e, struct sip_msg* msg)
1150
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg)
1151 1151
 {
1152 1152
 	int ret;
1153 1153
 
1154 1154
 	if (e->type==ELEM_T){
1155
-		ret=eval_elem(e, msg);
1155
+		ret=eval_elem(h, e, msg);
1156 1156
 	}else if (e->type==EXP_T){
1157 1157
 		switch(e->op){
1158 1158
 			case LOGAND_OP:
1159
-				ret=eval_expr(e->l.expr, msg);
1159
+				ret=eval_expr(h, e->l.expr, msg);
1160 1160
 				/* if error or false stop evaluating the rest */
1161 1161
 				if (ret!=1) break;
1162
-				ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
1162
+				ret=eval_expr(h, e->r.expr, msg); /*ret1 is 1*/
1163 1163
 				break;
1164 1164
 			case LOGOR_OP:
1165
-				ret=eval_expr(e->l.expr, msg);
1165
+				ret=eval_expr(h, e->l.expr, msg);
1166 1166
 				/* if true or error stop evaluating the rest */
1167 1167
 				if (ret!=0) break;
1168
-				ret=eval_expr(e->r.expr, msg); /* ret1 is 0 */
1168
+				ret=eval_expr(h, e->r.expr, msg); /* ret1 is 0 */
1169 1169
 				break;
1170 1170
 			case NOT_OP:
1171
-				ret=eval_expr(e->l.expr, msg);
1171
+				ret=eval_expr(h, e->l.expr, msg);
1172 1172
 				if (ret<0) break;
1173 1173
 				ret= ! ret;
1174 1174
 				break;
... ...
@@ -36,6 +36,7 @@
36 36
 #include "config.h"
37 37
 #include "error.h"
38 38
 #include "route_struct.h"
39
+#include "action.h"
39 40
 #include "parser/msg_parser.h"
40 41
 #include "str_hash.h"
41 42
 
... ...
@@ -69,7 +70,7 @@ int add_actions(struct action* a, struct action** head);
69 69
 void print_rls();
70 70
 int fix_rls();
71 71
 
72
-int eval_expr(struct expr* e, struct sip_msg* msg);
72
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg);
73 73
 
74 74
 
75 75