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 80
 #include <arpa/inet.h>
79 81
 #include <string.h>
80 82
 
81
-#define USE_LONGJMP
82
-
83
-#ifdef USE_LONGJMP
84
-#include <setjmp.h>
85
-#endif
86 83
 
87 84
 #ifdef DEBUG_DMALLOC
88 85
 #include <dmalloc.h>
... ...
@@ -90,13 +87,11 @@
90 87
 
91 88
 
92 89
 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 90
 
96 91
 /* ret= 0! if action -> end of list(e.g DROP),
97 92
       > 0 to continue processing next actions
98 93
    and <0 on error */
99
-int do_action(struct action* a, struct sip_msg* msg)
94
+int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
100 95
 {
101 96
 	int ret;
102 97
 	int v;
... ...
@@ -123,10 +118,10 @@ int do_action(struct action* a, struct sip_msg* msg)
123 118
 	switch ((unsigned char)a->type){
124 119
 		case DROP_T:
125 120
 				if (a->val[0].type==RETCODE_ST)
126
-					ret=last_retcode;
121
+					ret=h->last_retcode;
127 122
 				else
128 123
 					ret=(int) a->val[0].u.number;
129
-				run_flags|=(unsigned int)a->val[1].u.number;
124
+				h->run_flags|=(unsigned int)a->val[1].u.number;
130 125
 			break;
131 126
 		case FORWARD_T:
132 127
 #ifdef USE_TCP
... ...
@@ -436,9 +431,9 @@ int do_action(struct action* a, struct sip_msg* msg)
436 431
 				break;
437 432
 			}
438 433
 			/*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 */
434
+			ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
435
+			h->last_retcode=ret;
436
+			h->run_flags&=~RETURN_R_F; /* absorb returns */
442 437
 			break;
443 438
 		case EXEC_T:
444 439
 			if (a->val[0].type!=STRING_ST){
... ...
@@ -649,7 +644,7 @@ int do_action(struct action* a, struct sip_msg* msg)
649 644
 		case IF_T:
650 645
 				/* if null expr => ignore if? */
651 646
 				if ((a->val[0].type==EXPR_ST)&&a->val[0].u.data){
652
-					v=eval_expr((struct expr*)a->val[0].u.data, msg);
647
+					v=eval_expr(h, (struct expr*)a->val[0].u.data, msg);
653 648
 #if 0
654 649
 					if (v<0){
655 650
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
... ...
@@ -661,18 +656,20 @@ int do_action(struct action* a, struct sip_msg* msg)
661 656
 						}
662 657
 					}
663 658
 #endif
664
-					if (run_flags & EXIT_R_F){
659
+					if (h->run_flags & EXIT_R_F){
665 660
 						ret=0;
666 661
 						break;
667 662
 					}
668
-					run_flags &= ~RETURN_R_F; /* catch returns in expr */
663
+					h->run_flags &= ~RETURN_R_F; /* catch returns in expr */
669 664
 					ret=1;  /*default is continue */
670 665
 					if (v>0) {
671 666
 						if ((a->val[1].type==ACTIONS_ST)&&a->val[1].u.data){
672
-							ret=run_actions((struct action*)a->val[1].u.data, msg);
667
+							ret=run_actions(h, 
668
+										(struct action*)a->val[1].u.data, msg);
673 669
 						}
674 670
 					}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);
671
+							ret=run_actions(h, 
672
+										(struct action*)a->val[2].u.data, msg);
676 673
 					}
677 674
 				}
678 675
 			break;
... ...
@@ -682,8 +679,8 @@ int do_action(struct action* a, struct sip_msg* msg)
682 679
 					(char*)a->val[2].u.data,
683 680
 					(char*)a->val[3].u.data
684 681
 				);
685
-				if (ret==0) run_flags|=EXIT_R_F;
686
-				last_retcode=ret;
682
+				if (ret==0) h->run_flags|=EXIT_R_F;
683
+				h->last_retcode=ret;
687 684
 			} else {
688 685
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
689 686
 			}
... ...
@@ -753,7 +750,7 @@ int do_action(struct action* a, struct sip_msg* msg)
753 750
 	        case ADD_T:
754 751
 	        case ASSIGN_T:
755 752
 
756
-			/* If the left attr was specified withou indexing brackets delete
753
+			/* If the left attr was specified without indexing brackets delete
757 754
 			 * existing AVPs before adding new ones
758 755
 			 */
759 756
 			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 769
 				flags = a->val[0].u.attr->type;
773 770
 				name = a->val[0].u.attr->name;
774 771
 				if (a->val[1].u.data) {
775
-					value.n = run_actions((struct action*)a->val[1].u.data, msg);
772
+					value.n = run_actions(h, (struct action*)a->val[1].u.data,
773
+											msg);
776 774
 				} else {
777 775
 					value.n = -1;
778 776
 				}
779 777
 				ret = value.n;
780 778
 			} 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);
779
+				v = eval_expr(h, (struct expr*)a->val[1].u.data, msg);
782 780
 				if (v < 0) {
783 781
 					if (v == EXPR_DROP){ /* hack to quit on DROP*/
784 782
 						ret = 0;
... ...
@@ -884,54 +882,56 @@ error_fwd_uri:
884 882
 
885 883
 /* returns: 0, or 1 on success, <0 on error */
886 884
 /* (0 if drop or break encountered, 1 if not ) */
887
-int run_actions(struct action* a, struct sip_msg* msg)
885
+int run_actions(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
888 886
 {
889 887
 	struct action* t;
890 888
 	int ret;
891
-	static int rec_lev=0;
892
-	static jmp_buf jmp_env;
893 889
 	struct sr_module *mod;
894 890
 
895 891
 	ret=E_UNSPEC;
896
-	rec_lev++;
897
-	if (rec_lev>ROUTE_MAX_REC_LEV){
892
+	h->rec_lev++;
893
+	if (h->rec_lev>ROUTE_MAX_REC_LEV){
898 894
 		LOG(L_ERR, "WARNING: too many recursive routing table lookups (%d)"
899
-					" giving up!\n", rec_lev);
895
+					" giving up!\n", h->rec_lev);
900 896
 		ret=E_UNSPEC;
901 897
 		goto error;
902 898
 	}
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;
899
+	if (h->rec_lev==1){
900
+		h->run_flags=0;
901
+		h->last_retcode=0;
902
+#ifdef USE_LONGJMP
903
+		if (setjmp(h->jmp_env)){
904
+			h->rec_lev=0;
905
+			ret=h->last_retcode;
909 906
 			goto end;
910 907
 		}
908
+#endif
911 909
 	}
912 910
 
913 911
 	if (a==0){
914 912
 		DBG("DEBUG: run_actions: null action list (rec_level=%d)\n",
915
-			rec_lev);
913
+				h->rec_lev);
916 914
 		ret=1;
917 915
 	}
918 916
 
919 917
 	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);
918
+		ret=do_action(h, t, msg);
919
+		if (h->run_flags & (RETURN_R_F|EXIT_R_F)){
920
+			if (h->run_flags & EXIT_R_F){
921
+#ifdef USE_LONGJMP
922
+				h->last_retcode=ret;
923
+				longjmp(h->jmp_env, ret);
924
+#endif
925 925
 			}
926 926
 			break;
927 927
 		}
928 928
 		/* ignore error returns */
929 929
 	}
930 930
 
931
-	rec_lev--;
931
+	h->rec_lev--;
932 932
 end:
933 933
 	/* process module onbreak handlers if present */
934
-	if (rec_lev==0 && ret==0)
934
+	if (h->rec_lev==0 && ret==0)
935 935
 		for (mod=modules;mod;mod=mod->next)
936 936
 			if (mod->exports && mod->exports->onbreak_f) {
937 937
 				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 68
 		onsnd_info.buf=buf;
68 69
 		onsnd_info.len=len;
69 70
 		p_onsend=&onsnd_info;
70
-		ret=run_actions(onsend_rt.rlist[DEFAULT_RT], orig_msg);
71
+		init_run_actions_ctx(&ra_ctx);
72
+		ret=run_actions(&ra_ctx, onsend_rt.rlist[DEFAULT_RT], orig_msg);
71 73
 		p_onsend=0; /* reset it */
72 74
 	}
73 75
 	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 1049
 		break;
1049 1050
 
1050 1051
 	case ACTION_O:
1051
-		ret=run_actions( (struct action*)e->r.param, msg);
1052
+		ret=run_actions(h, (struct action*)e->r.param, msg);
1052 1053
 		if (ret<=0) ret=0;
1053 1054
 		else ret=1;
1054 1055
 		break;
... ...
@@ -1124,7 +1125,7 @@ inline static int eval_elem(struct expr* e, struct sip_msg* msg)
1124 1125
 		break;
1125 1126
 
1126 1127
 	case RETCODE_O:
1127
-		ret=comp_num(e->op, last_retcode, e->r_type, &e->r);
1128
+		ret=comp_num(e->op, h->last_retcode, e->r_type, &e->r);
1128 1129
 		break;
1129 1130
 
1130 1131
 	case AVP_O:
... ...
@@ -1147,28 +1148,28 @@ error:
1147 1148
 
1148 1149
 
1149 1150
 /* ret= 0/1 (true/false) ,  -1 on error */
1150
-int eval_expr(struct expr* e, struct sip_msg* msg)
1151
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg)
1151 1152
 {
1152 1153
 	int ret;
1153 1154
 
1154 1155
 	if (e->type==ELEM_T){
1155
-		ret=eval_elem(e, msg);
1156
+		ret=eval_elem(h, e, msg);
1156 1157
 	}else if (e->type==EXP_T){
1157 1158
 		switch(e->op){
1158 1159
 			case LOGAND_OP:
1159
-				ret=eval_expr(e->l.expr, msg);
1160
+				ret=eval_expr(h, e->l.expr, msg);
1160 1161
 				/* if error or false stop evaluating the rest */
1161 1162
 				if (ret!=1) break;
1162
-				ret=eval_expr(e->r.expr, msg); /*ret1 is 1*/
1163
+				ret=eval_expr(h, e->r.expr, msg); /*ret1 is 1*/
1163 1164
 				break;
1164 1165
 			case LOGOR_OP:
1165
-				ret=eval_expr(e->l.expr, msg);
1166
+				ret=eval_expr(h, e->l.expr, msg);
1166 1167
 				/* if true or error stop evaluating the rest */
1167 1168
 				if (ret!=0) break;
1168
-				ret=eval_expr(e->r.expr, msg); /* ret1 is 0 */
1169
+				ret=eval_expr(h, e->r.expr, msg); /* ret1 is 0 */
1169 1170
 				break;
1170 1171
 			case NOT_OP:
1171
-				ret=eval_expr(e->l.expr, msg);
1172
+				ret=eval_expr(h, e->l.expr, msg);
1172 1173
 				if (ret<0) break;
1173 1174
 				ret= ! ret;
1174 1175
 				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 70
 void print_rls();
70 71
 int fix_rls();
71 72
 
72
-int eval_expr(struct expr* e, struct sip_msg* msg);
73
+int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg);
73 74
 
74 75
 
75 76