... | ... |
@@ -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) |
... | ... |
@@ -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 */ |