Browse code

- return [val] support (returns from the current route with value val, by default 1) - exit [val] support (exits the script with code val, where 0 means drop, >0 means do default actions and <0 means error) - drop is now equivalent to exit 0 - drop should be faster when used to exit deep routes - break is now equivalent with return 1 - the return code can be checked with $?, e.g.: if ($?==1) {...} else if ($?==-1){...} else {...}.

Andrei Pelinescu-Onciul authored on 12/12/2005 23:47:56
Showing 7 changed files
... ...
@@ -41,6 +41,15 @@ modules:
41 41
               Vias a.s.o) and not on the original message
42 42
  
43 43
 core:
44
+ - added return [val] which returns from a route. if no value is specified, or
45
+   a route reaches its end without executing a return statement, it returns 1.
46
+   If return is used in the top level route is equivalent with exit [val].
47
+ - drop /exit [n] now will end the script execution
48
+   exit n will exit with code n (usefull in onreply/onsend routes where
49
+   if script code !=0 a reply is generated/the message is sent or to force
50
+   script errors)
51
+ - added $? which can be used to check the return code of the last executed
52
+   route{} (e.g. route(1); if ($?==1){ /* ... */}else if ($?==2) ... )
44 53
  - onsend_route added: special route executed before a request is sent.
45 54
                        Only a limited number of commands are allowed (drop, if
46 55
                        + all the checks, msg flag manipulations, send(), log(),
... ...
@@ -37,6 +37,7 @@
37 37
  *  2003-10-02  added SET_ADV_ADDR_T & SET_ADV_PORT_T (andrei)
38 38
  *  2003-10-29  added FORCE_TCP_ALIAS_T (andrei)
39 39
  *  2004-11-30  added FORCE_SEND_SOCKET_T (andrei)
40
+ *  2005-12-12  return & drop/exit differentiation (andrei)
40 41
  */
41 42
 
42 43
 
... ...
@@ -70,12 +71,20 @@
70 71
 #include <arpa/inet.h>
71 72
 #include <string.h>
72 73
 
74
+#define USE_LONGJMP
75
+
76
+#ifdef USE_LONGJMP
77
+#include <setjmp.h>
78
+#endif
79
+
73 80
 #ifdef DEBUG_DMALLOC
74 81
 #include <dmalloc.h>
75 82
 #endif
76 83
 
77 84
 
78 85
 struct onsend_info* p_onsend=0; /* onsend route send info */
86
+static unsigned int run_flags=0;
87
+int last_retcode=0; /* last return from a route() */
79 88
 
80 89
 /* ret= 0! if action -> end of list(e.g DROP), 
81 90
       > 0 to continue processing next actions
... ...
@@ -108,7 +117,11 @@ int do_action(struct action* a, struct sip_msg* msg)
108 117
 	ret=E_BUG;
109 118
 	switch ((unsigned char)a->type){
110 119
 		case DROP_T:
111
-				ret=0;
120
+				if (a->p1_type==RETCODE_ST)
121
+					ret=last_retcode;
122
+				else
123
+					ret=(int)a->p1.number;
124
+				run_flags|=(unsigned int)a->p2.number;
112 125
 			break;
113 126
 		case FORWARD_T:
114 127
 #ifdef USE_TCP
... ...
@@ -385,7 +398,10 @@ int do_action(struct action* a, struct sip_msg* msg)
385 398
 				ret=E_CFG;
386 399
 				break;
387 400
 			}
388
-			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
401
+			/*ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;*/
402
+			ret=run_actions(rlist[a->p1.number], msg);
403
+			last_retcode=ret;
404
+			run_flags&=~RETURN_R_F; /* absorb returns */
389 405
 			break;
390 406
 		case EXEC_T:
391 407
 			if (a->p1_type!=STRING_ST){
... ...
@@ -597,6 +613,7 @@ int do_action(struct action* a, struct sip_msg* msg)
597 613
 				/* if null expr => ignore if? */
598 614
 				if ((a->p1_type==EXPR_ST)&&a->p1.data){
599 615
 					v=eval_expr((struct expr*)a->p1.data, msg);
616
+#if 0
600 617
 					if (v<0){
601 618
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
602 619
 							ret=0;
... ...
@@ -606,7 +623,12 @@ int do_action(struct action* a, struct sip_msg* msg)
606 623
 										"error in expression\n");
607 624
 						}
608 625
 					}
609
-					
626
+#endif
627
+					if (run_flags & EXIT_R_F){
628
+						ret=0;
629
+						break;
630
+					}
631
+					run_flags &= ~RETURN_R_F; /* catch returns in expr */
610 632
 					ret=1;  /*default is continue */
611 633
 					if (v>0) {
612 634
 						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
... ...
@@ -622,6 +644,7 @@ int do_action(struct action* a, struct sip_msg* msg)
622 644
 					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
623 645
 				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
624 646
 													  (char*)a->p3.data);
647
+				if (ret==0) run_flags|=EXIT_R_F;
625 648
 			}else{
626 649
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
627 650
 			}
... ...
@@ -787,6 +810,7 @@ int run_actions(struct action* a, struct sip_msg* msg)
787 810
 	struct action* t;
788 811
 	int ret=E_UNSPEC;
789 812
 	static int rec_lev=0;
813
+	static jmp_buf jmp_env;
790 814
 	struct sr_module *mod;
791 815
 
792 816
 	rec_lev++;
... ...
@@ -796,6 +820,15 @@ int run_actions(struct action* a, struct sip_msg* msg)
796 820
 		ret=E_UNSPEC;
797 821
 		goto error;
798 822
 	}
823
+	if (rec_lev==1){
824
+		run_flags=0;
825
+		last_retcode=0;
826
+		if (setjmp(jmp_env)){
827
+			rec_lev=0;
828
+			ret=last_retcode;
829
+			goto end;
830
+		}
831
+	}
799 832
 		
800 833
 	if (a==0){
801 834
 		LOG(L_ERR, "WARNING: run_actions: null action list (rec_level=%d)\n", 
... ...
@@ -805,12 +838,18 @@ int run_actions(struct action* a, struct sip_msg* msg)
805 838
 
806 839
 	for (t=a; t!=0; t=t->next){
807 840
 		ret=do_action(t, msg);
808
-		if(ret==0) break;
809
-		/* ignore errors */
810
-		/*else if (ret<0){ ret=-1; goto error; }*/
841
+		if (run_flags & (RETURN_R_F|EXIT_R_F)){
842
+			if (run_flags & EXIT_R_F){
843
+				last_retcode=ret;
844
+				longjmp(jmp_env, ret);
845
+			}
846
+			break;
847
+		}
848
+		/* ignore error returns */
811 849
 	}
812 850
 	
813 851
 	rec_lev--;
852
+end:
814 853
 	/* process module onbreak handlers if present */
815 854
 	if (rec_lev==0 && ret==0) 
816 855
 		for (mod=modules;mod;mod=mod->next) 
... ...
@@ -33,6 +33,8 @@
33 33
 #include "parser/msg_parser.h"
34 34
 #include "route_struct.h"
35 35
 
36
+extern int last_retcode;
37
+
36 38
 int do_action(struct action* a, struct sip_msg* msg);
37 39
 int run_actions(struct action* a, struct sip_msg* msg);
38 40
 
... ...
@@ -58,6 +58,7 @@
58 58
  *              dns_try_ipv6 (andrei)
59 59
  *  2005-12-11  added onsend_route, snd_{ip,port,proto,af},
60 60
  *              to_{ip,port} (andrei)
61
+ *  2005-12-12  separated drop, exit, break, return, added RETCODE (andrei)
61 62
  */
62 63
 
63 64
 
... ...
@@ -108,7 +109,9 @@ FORWARD	forward
108 109
 FORWARD_TCP	forward_tcp
109 110
 FORWARD_UDP	forward_udp
110 111
 FORWARD_TLS	forward_tls
111
-DROP	"drop"|"break"
112
+DROP	"drop"|"exit"
113
+RETURN	"return"
114
+BREAK	"break"
112 115
 SEND	send
113 116
 SEND_TCP	send_tcp
114 117
 LOG		log
... ...
@@ -171,6 +174,7 @@ PROTO	proto
171 174
 AF		af
172 175
 MYSELF	myself
173 176
 MSGLEN			"msg:len"
177
+RETCODE	\$\?|\$retcode
174 178
 /* operators */
175 179
 EQUAL	=
176 180
 EQUAL_T	==
... ...
@@ -323,6 +327,8 @@ EAT_ABLE	[\ \t\b\r]
323 327
 <INITIAL>{FORWARD_TLS}	{count(); yylval.strval=yytext; return FORWARD_TLS; }
324 328
 <INITIAL>{FORWARD_UDP}	{count(); yylval.strval=yytext; return FORWARD_UDP; }
325 329
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
330
+<INITIAL>{RETURN}	{ count(); yylval.strval=yytext; return RETURN; }
331
+<INITIAL>{BREAK}	{ count(); yylval.strval=yytext; return BREAK; }
326 332
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
327 333
 <INITIAL>{SEND_TCP}	{ count(); yylval.strval=yytext; return SEND_TCP; }
328 334
 <INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG_TOK; }
... ...
@@ -331,6 +337,7 @@ EAT_ABLE	[\ \t\b\r]
331 337
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
332 338
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
333 339
 <INITIAL>{MSGLEN}	{ count(); yylval.strval=yytext; return MSGLEN; }
340
+<INITIAL>{RETCODE}	{ count(); yylval.strval=yytext; return RETCODE; }
334 341
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
335 342
 <INITIAL>{ROUTE_ONREPLY}	{ count(); yylval.strval=yytext;
336 343
 								return ROUTE_ONREPLY; }
... ...
@@ -150,6 +150,8 @@ static struct socket_id* mk_listen_id(char*, int, int);
150 150
 %token SEND
151 151
 %token SEND_TCP
152 152
 %token DROP
153
+%token RETURN 
154
+%token BREAK
153 155
 %token LOG_TOK
154 156
 %token ERROR
155 157
 %token ROUTE
... ...
@@ -200,6 +202,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
200 202
 %token AF
201 203
 %token MYSELF
202 204
 %token MSGLEN 
205
+%token RETCODE 
203 206
 %token UDP
204 207
 %token TCP
205 208
 %token TLS
... ...
@@ -1055,6 +1058,13 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1055 1058
 		| MSGLEN intop error { $$=0; yyerror("number expected"); }
1056 1059
 		| MSGLEN error { $$=0; yyerror("equal/!= operator expected"); }
1057 1060
 
1061
+		| RETCODE intop NUMBER	{ $$=mk_elem($2, RETCODE_O, 0,
1062
+												NUMBER_ST, (void *) $3 ); }
1063
+		| RETCODE intop attr_id	{ $$=mk_elem($2, RETCODE_O, 0,
1064
+												AVP_ST, (void *) $3 ); }
1065
+		| RETCODE intop error { $$=0; yyerror("number expected"); }
1066
+		| RETCODE error { $$=0; yyerror("equal/!= operator expected"); }
1067
+
1058 1068
 		| SRCIP equalop ipnet	{ $$=mk_elem($2, SRCIP_O, 0, NET_ST, $3); }
1059 1069
 		| SRCIP strop STRING	{	s_tmp.s=$3;
1060 1070
 									s_tmp.len=strlen($3);
... ...
@@ -1742,8 +1752,24 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
1742 1752
 		| SEND_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
1743 1753
 		| SEND_TCP LPAREN error RPAREN { $$=0; yyerror("bad send_tcp"
1744 1754
 													"argument"); }
1745
-		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
1746
-		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
1755
+		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0,
1756
+												0, (void*)EXIT_R_F); }
1757
+		| DROP LPAREN NUMBER RPAREN	{$$=mk_action(DROP_T,0, 0,
1758
+												(void*)$3, (void*)EXIT_R_F); }
1759
+		| DROP NUMBER 			{$$=mk_action(DROP_T,0, 0,
1760
+												(void*)$2, (void*)EXIT_R_F); }
1761
+		| DROP RETCODE 			{$$=mk_action(DROP_T, RETCODE_ST, 0,
1762
+													0, (void*)EXIT_R_F); }
1763
+		| DROP					{$$=mk_action(DROP_T,0, 0,
1764
+												0, (void*)EXIT_R_F); }
1765
+		| RETURN				{$$=mk_action(DROP_T,0, 0,
1766
+												(void*)1, (void*)RETURN_R_F); }
1767
+		| RETURN NUMBER			{$$=mk_action(DROP_T,0, 0, 
1768
+												(void*)$2, (void*)RETURN_R_F);}
1769
+		| RETURN RETCODE		{$$=mk_action(DROP_T, RETCODE_ST, 0, 
1770
+														0, (void*)RETURN_R_F);}
1771
+		| BREAK					{$$=mk_action(DROP_T,0, 0,
1772
+												0, (void*)RETURN_R_F); }
1747 1773
 		| LOG_TOK LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
1748 1774
 													STRING_ST,(void*)4,$3);
1749 1775
 									}
... ...
@@ -40,6 +40,7 @@
40 40
  *              the ip with all the addresses (andrei)
41 41
  *  2003-10-10  added more operators support to comp_* (<,>,<=,>=,!=) (andrei)
42 42
  *  2004-10-19  added from_uri & to_uri (andrei)
43
+ *  2005-12-12  added retcode support (anrei)
43 44
  */
44 45
 
45 46
  
... ...
@@ -640,7 +641,7 @@ error_op:
640 641
 }
641 642
 
642 643
 
643
-/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */
644
+/* returns: 0/1 (false/true) or -1 on error */
644 645
 static int eval_elem(struct expr* e, struct sip_msg* msg)
645 646
 {
646 647
 	struct sip_uri uri;
... ...
@@ -757,7 +758,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
757 758
 
758 759
 	case ACTION_O:
759 760
 		ret=run_actions( (struct action*)e->r.param, msg);
760
-		if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
761
+		if (ret<=0) ret=0;
761 762
 		else ret=1;
762 763
 		break;
763 764
 		
... ...
@@ -831,6 +832,10 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
831 832
 		}
832 833
 		break;
833 834
 
835
+	case RETCODE_O:
836
+		ret=comp_num(e->op, last_retcode, e->r_type, &e->r);
837
+		break;
838
+
834 839
 	case AVP_O:
835 840
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r);
836 841
 		break;
... ...
@@ -846,7 +851,7 @@ error:
846 851
 
847 852
 
848 853
 
849
-/* ret= 0/1 (true/false) ,  -1 on error or EXPR_DROP (-127)  */
854
+/* ret= 0/1 (true/false) ,  -1 on error */
850 855
 int eval_expr(struct expr* e, struct sip_msg* msg)
851 856
 {
852 857
 	static int rec_lev=0;
... ...
@@ -62,7 +62,7 @@ enum { EQUAL_OP=10, MATCH_OP, GT_OP, LT_OP, GTE_OP, LTE_OP, DIFF_OP, NO_OP };
62 62
 enum { METHOD_O=1, URI_O, FROM_URI_O, TO_URI_O, SRCIP_O, SRCPORT_O,
63 63
 	   DSTIP_O, DSTPORT_O, PROTO_O, AF_O, MSGLEN_O, DEFAULT_O, ACTION_O,
64 64
 	   NUMBER_O, AVP_O, SNDIP_O, SNDPORT_O, TOIP_O, TOPORT_O, SNDPROTO_O, 
65
-	   SNDAF_O};
65
+	   SNDAF_O, RETCODE_O};
66 66
 
67 67
 enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
68 68
 		SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T, 
... ...
@@ -88,7 +88,12 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
88 88
 };
89 89
 enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST,
90 90
 		EXPR_ST, ACTIONS_ST, CMDF_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST,
91
-		MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST };
91
+		MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST,
92
+		RETCODE_ST};
93
+
94
+/* run flags */
95
+#define EXIT_R_F   1
96
+#define RETURN_R_F 2
92 97
 
93 98
 
94 99
 /* Expression operand */