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 70
 #include <arpa/inet.h>
71 71
 #include <string.h>
72 72
 
73
+#define USE_LONGJMP
74
+
75
+#ifdef USE_LONGJMP
76
+#include <setjmp.h>
77
+#endif
78
+
73 79
 #ifdef DEBUG_DMALLOC
74 80
 #include <dmalloc.h>
75 81
 #endif
76 82
 
77 83
 
78 84
 struct onsend_info* p_onsend=0; /* onsend route send info */
85
+static unsigned int run_flags=0;
86
+int last_retcode=0; /* last return from a route() */
79 87
 
80 88
 /* ret= 0! if action -> end of list(e.g DROP), 
81 89
       > 0 to continue processing next actions
... ...
@@ -108,7 +117,11 @@ int do_action(struct action* a, struct sip_msg* msg)
108 108
 	ret=E_BUG;
109 109
 	switch ((unsigned char)a->type){
110 110
 		case DROP_T:
111
-				ret=0;
111
+				if (a->p1_type==RETCODE_ST)
112
+					ret=last_retcode;
113
+				else
114
+					ret=(int)a->p1.number;
115
+				run_flags|=(unsigned int)a->p2.number;
112 116
 			break;
113 117
 		case FORWARD_T:
114 118
 #ifdef USE_TCP
... ...
@@ -385,7 +398,10 @@ int do_action(struct action* a, struct sip_msg* msg)
385 385
 				ret=E_CFG;
386 386
 				break;
387 387
 			}
388
-			ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;
388
+			/*ret=((ret=run_actions(rlist[a->p1.number], msg))<0)?ret:1;*/
389
+			ret=run_actions(rlist[a->p1.number], msg);
390
+			last_retcode=ret;
391
+			run_flags&=~RETURN_R_F; /* absorb returns */
389 392
 			break;
390 393
 		case EXEC_T:
391 394
 			if (a->p1_type!=STRING_ST){
... ...
@@ -597,6 +613,7 @@ int do_action(struct action* a, struct sip_msg* msg)
597 597
 				/* if null expr => ignore if? */
598 598
 				if ((a->p1_type==EXPR_ST)&&a->p1.data){
599 599
 					v=eval_expr((struct expr*)a->p1.data, msg);
600
+#if 0
600 601
 					if (v<0){
601 602
 						if (v==EXPR_DROP){ /* hack to quit on DROP*/
602 603
 							ret=0;
... ...
@@ -606,7 +623,12 @@ int do_action(struct action* a, struct sip_msg* msg)
606 606
 										"error in expression\n");
607 607
 						}
608 608
 					}
609
-					
609
+#endif
610
+					if (run_flags & EXIT_R_F){
611
+						ret=0;
612
+						break;
613
+					}
614
+					run_flags &= ~RETURN_R_F; /* catch returns in expr */
610 615
 					ret=1;  /*default is continue */
611 616
 					if (v>0) {
612 617
 						if ((a->p2_type==ACTIONS_ST)&&a->p2.data){
... ...
@@ -622,6 +644,7 @@ int do_action(struct action* a, struct sip_msg* msg)
622 622
 					((a->p2_type==STRING_ST)&&a->p2.data)*/ ){
623 623
 				ret=((cmd_function)(a->p1.data))(msg, (char*)a->p2.data,
624 624
 													  (char*)a->p3.data);
625
+				if (ret==0) run_flags|=EXIT_R_F;
625 626
 			}else{
626 627
 				LOG(L_CRIT,"BUG: do_action: bad module call\n");
627 628
 			}
... ...
@@ -787,6 +810,7 @@ int run_actions(struct action* a, struct sip_msg* msg)
787 787
 	struct action* t;
788 788
 	int ret=E_UNSPEC;
789 789
 	static int rec_lev=0;
790
+	static jmp_buf jmp_env;
790 791
 	struct sr_module *mod;
791 792
 
792 793
 	rec_lev++;
... ...
@@ -796,6 +820,15 @@ int run_actions(struct action* a, struct sip_msg* msg)
796 796
 		ret=E_UNSPEC;
797 797
 		goto error;
798 798
 	}
799
+	if (rec_lev==1){
800
+		run_flags=0;
801
+		last_retcode=0;
802
+		if (setjmp(jmp_env)){
803
+			rec_lev=0;
804
+			ret=last_retcode;
805
+			goto end;
806
+		}
807
+	}
799 808
 		
800 809
 	if (a==0){
801 810
 		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 805
 
806 806
 	for (t=a; t!=0; t=t->next){
807 807
 		ret=do_action(t, msg);
808
-		if(ret==0) break;
809
-		/* ignore errors */
810
-		/*else if (ret<0){ ret=-1; goto error; }*/
808
+		if (run_flags & (RETURN_R_F|EXIT_R_F)){
809
+			if (run_flags & EXIT_R_F){
810
+				last_retcode=ret;
811
+				longjmp(jmp_env, ret);
812
+			}
813
+			break;
814
+		}
815
+		/* ignore error returns */
811 816
 	}
812 817
 	
813 818
 	rec_lev--;
819
+end:
814 820
 	/* process module onbreak handlers if present */
815 821
 	if (rec_lev==0 && ret==0) 
816 822
 		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 108
 FORWARD_TCP	forward_tcp
109 109
 FORWARD_UDP	forward_udp
110 110
 FORWARD_TLS	forward_tls
111
-DROP	"drop"|"break"
111
+DROP	"drop"|"exit"
112
+RETURN	"return"
113
+BREAK	"break"
112 114
 SEND	send
113 115
 SEND_TCP	send_tcp
114 116
 LOG		log
... ...
@@ -171,6 +174,7 @@ PROTO	proto
171 171
 AF		af
172 172
 MYSELF	myself
173 173
 MSGLEN			"msg:len"
174
+RETCODE	\$\?|\$retcode
174 175
 /* operators */
175 176
 EQUAL	=
176 177
 EQUAL_T	==
... ...
@@ -323,6 +327,8 @@ EAT_ABLE	[\ \t\b\r]
323 323
 <INITIAL>{FORWARD_TLS}	{count(); yylval.strval=yytext; return FORWARD_TLS; }
324 324
 <INITIAL>{FORWARD_UDP}	{count(); yylval.strval=yytext; return FORWARD_UDP; }
325 325
 <INITIAL>{DROP}	{ count(); yylval.strval=yytext; return DROP; }
326
+<INITIAL>{RETURN}	{ count(); yylval.strval=yytext; return RETURN; }
327
+<INITIAL>{BREAK}	{ count(); yylval.strval=yytext; return BREAK; }
326 328
 <INITIAL>{SEND}	{ count(); yylval.strval=yytext; return SEND; }
327 329
 <INITIAL>{SEND_TCP}	{ count(); yylval.strval=yytext; return SEND_TCP; }
328 330
 <INITIAL>{LOG}	{ count(); yylval.strval=yytext; return LOG_TOK; }
... ...
@@ -331,6 +337,7 @@ EAT_ABLE	[\ \t\b\r]
331 331
 <INITIAL>{RESETFLAG}	{ count(); yylval.strval=yytext; return RESETFLAG; }
332 332
 <INITIAL>{ISFLAGSET}	{ count(); yylval.strval=yytext; return ISFLAGSET; }
333 333
 <INITIAL>{MSGLEN}	{ count(); yylval.strval=yytext; return MSGLEN; }
334
+<INITIAL>{RETCODE}	{ count(); yylval.strval=yytext; return RETCODE; }
334 335
 <INITIAL>{ROUTE}	{ count(); yylval.strval=yytext; return ROUTE; }
335 336
 <INITIAL>{ROUTE_ONREPLY}	{ count(); yylval.strval=yytext;
336 337
 								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 200
 %token AF
201 201
 %token MYSELF
202 202
 %token MSGLEN 
203
+%token RETCODE 
203 204
 %token UDP
204 205
 %token TCP
205 206
 %token TLS
... ...
@@ -1055,6 +1058,13 @@ exp_elem:	METHOD strop STRING	{$$= mk_elem($2, METHOD_O, 0, STRING_ST, $3);}
1055 1055
 		| MSGLEN intop error { $$=0; yyerror("number expected"); }
1056 1056
 		| MSGLEN error { $$=0; yyerror("equal/!= operator expected"); }
1057 1057
 
1058
+		| RETCODE intop NUMBER	{ $$=mk_elem($2, RETCODE_O, 0,
1059
+												NUMBER_ST, (void *) $3 ); }
1060
+		| RETCODE intop attr_id	{ $$=mk_elem($2, RETCODE_O, 0,
1061
+												AVP_ST, (void *) $3 ); }
1062
+		| RETCODE intop error { $$=0; yyerror("number expected"); }
1063
+		| RETCODE error { $$=0; yyerror("equal/!= operator expected"); }
1064
+
1058 1065
 		| SRCIP equalop ipnet	{ $$=mk_elem($2, SRCIP_O, 0, NET_ST, $3); }
1059 1066
 		| SRCIP strop STRING	{	s_tmp.s=$3;
1060 1067
 									s_tmp.len=strlen($3);
... ...
@@ -1742,8 +1752,24 @@ cmd:		FORWARD LPAREN host RPAREN	{ $$=mk_action(	FORWARD_T,
1742 1742
 		| SEND_TCP error { $$=0; yyerror("missing '(' or ')' ?"); }
1743 1743
 		| SEND_TCP LPAREN error RPAREN { $$=0; yyerror("bad send_tcp"
1744 1744
 													"argument"); }
1745
-		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0, 0, 0); }
1746
-		| DROP					{$$=mk_action(DROP_T,0, 0, 0, 0); }
1745
+		| DROP LPAREN RPAREN	{$$=mk_action(DROP_T,0, 0,
1746
+												0, (void*)EXIT_R_F); }
1747
+		| DROP LPAREN NUMBER RPAREN	{$$=mk_action(DROP_T,0, 0,
1748
+												(void*)$3, (void*)EXIT_R_F); }
1749
+		| DROP NUMBER 			{$$=mk_action(DROP_T,0, 0,
1750
+												(void*)$2, (void*)EXIT_R_F); }
1751
+		| DROP RETCODE 			{$$=mk_action(DROP_T, RETCODE_ST, 0,
1752
+													0, (void*)EXIT_R_F); }
1753
+		| DROP					{$$=mk_action(DROP_T,0, 0,
1754
+												0, (void*)EXIT_R_F); }
1755
+		| RETURN				{$$=mk_action(DROP_T,0, 0,
1756
+												(void*)1, (void*)RETURN_R_F); }
1757
+		| RETURN NUMBER			{$$=mk_action(DROP_T,0, 0, 
1758
+												(void*)$2, (void*)RETURN_R_F);}
1759
+		| RETURN RETCODE		{$$=mk_action(DROP_T, RETCODE_ST, 0, 
1760
+														0, (void*)RETURN_R_F);}
1761
+		| BREAK					{$$=mk_action(DROP_T,0, 0,
1762
+												0, (void*)RETURN_R_F); }
1747 1763
 		| LOG_TOK LPAREN STRING RPAREN	{$$=mk_action(	LOG_T, NUMBER_ST, 
1748 1764
 													STRING_ST,(void*)4,$3);
1749 1765
 									}
... ...
@@ -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 640
 }
641 641
 
642 642
 
643
-/* returns: 0/1 (false/true) or -1 on error, -127 EXPR_DROP */
643
+/* returns: 0/1 (false/true) or -1 on error */
644 644
 static int eval_elem(struct expr* e, struct sip_msg* msg)
645 645
 {
646 646
 	struct sip_uri uri;
... ...
@@ -757,7 +758,7 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
757 757
 
758 758
 	case ACTION_O:
759 759
 		ret=run_actions( (struct action*)e->r.param, msg);
760
-		if (ret<=0) ret=(ret==0)?EXPR_DROP:0;
760
+		if (ret<=0) ret=0;
761 761
 		else ret=1;
762 762
 		break;
763 763
 		
... ...
@@ -831,6 +832,10 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
831 831
 		}
832 832
 		break;
833 833
 
834
+	case RETCODE_O:
835
+		ret=comp_num(e->op, last_retcode, e->r_type, &e->r);
836
+		break;
837
+
834 838
 	case AVP_O:
835 839
 		ret = comp_avp(e->op, e->l.attr, e->r_type, &e->r);
836 840
 		break;
... ...
@@ -846,7 +851,7 @@ error:
846 846
 
847 847
 
848 848
 
849
-/* ret= 0/1 (true/false) ,  -1 on error or EXPR_DROP (-127)  */
849
+/* ret= 0/1 (true/false) ,  -1 on error */
850 850
 int eval_expr(struct expr* e, struct sip_msg* msg)
851 851
 {
852 852
 	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 */