[sr-dev] git:master: core: route(): added support for rvalue expressions parameters

Andrei Pelinescu-Onciul andrei at iptel.org
Thu Mar 25 23:30:20 CET 2010


Module: sip-router
Branch: master
Commit: d75db62dc2c859165fc3f72b256393678fcd00f5
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=d75db62dc2c859165fc3f72b256393678fcd00f5

Author: Andrei Pelinescu-Onciul <andrei at iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei at iptel.org>
Date:   Thu Mar 25 23:20:17 2010 +0100

core: route(): added support for  rvalue expressions parameters

route($foo+$bar+"test") will work now. Constant values (e.g.
route("foo"+"bar") are optimized to the simple string case
(route("foobar")).

Closes FlySpray#52.

---

 NEWS     |    1 +
 action.c |   35 ++++++++++++++++++++++++++++++-----
 cfg.y    |   11 ++++++++++-
 route.c  |   34 ++++++++++++++++++++++++++++++++--
 4 files changed, 73 insertions(+), 8 deletions(-)

diff --git a/NEWS b/NEWS
index 1e5d4b5..de353af 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ core:
   - global, per protocol blacklist ignore masks (via extended send_flags).
     See dst_blacklist_udp_imask a.s.o (dst_blacklist_*_imask).
   - per message blacklist ignore masks
+  - route() now supports rvalue expressions (e.g. route("test"+$i))
 
 new config variables:
   - dst_blacklist_udp_imask - global blacklist events ignore mask for udp
diff --git a/action.c b/action.c
index c4823e6..70cec69 100644
--- a/action.c
+++ b/action.c
@@ -481,20 +481,45 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg)
 			ret=1;
 			break;
 		case ROUTE_T:
-			if (a->val[0].type!=NUMBER_ST){
+			if (likely(a->val[0].type == NUMBER_ST))
+				i = a->val[0].u.number;
+			else if (a->val[0].type == RVE_ST) {
+				rv = rval_expr_eval(h, msg, a->val[0].u.data);
+				rval_cache_init(&c1);
+				if (unlikely(rv == 0 ||
+						rval_get_tmp_str(h, msg, &s, rv, 0, &c1) < 0)) {
+					rval_destroy(rv);
+					rval_cache_clean(&c1);
+					ERR("failed to convert RVE to string\n");
+					ret = E_UNSPEC;
+					goto error;
+				}
+				i = route_lookup(&main_rt, s.s);
+				if (unlikely(i < 0)) {
+					ERR("route \"%s\" not found at %s:%d\n",
+							s.s, (a->cfile)?a->cfile:"line", a->cline);
+					rval_cache_clean(&c1);
+					s.s = 0;
+					ret = E_SCRIPT;
+					goto error;
+				}
+				rval_cache_clean(&c1);
+				s.s = 0;
+			} else {
 				LOG(L_CRIT, "BUG: do_action: bad route() type %d\n",
 						a->val[0].type);
 				ret=E_BUG;
 				goto error;
 			}
-			if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
+			if (unlikely((i>=main_rt.idx)||(i<0))){
 				LOG(L_ERR, "ERROR: invalid routing table number in"
-							"route(%lu)\n", a->val[0].u.number);
+							"route(%lu) at %s:%d\n", a->val[0].u.number,
+							(a->cfile)?a->cfile:"line", a->cline);
 				ret=E_CFG;
 				goto error;
 			}
-			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
-			ret=run_actions(h, main_rt.rlist[a->val[0].u.number], msg);
+			/*ret=((ret=run_actions(rlist[a->val[0].u.number],msg))<0)?ret:1;*/
+			ret=run_actions(h, main_rt.rlist[i], msg);
 			h->last_retcode=ret;
 			_last_returned_code = h->last_retcode;
 			h->run_flags&=~(RETURN_R_F|BREAK_R_F); /* absorb return & break */
diff --git a/cfg.y b/cfg.y
index 2b12b67..4769ae1 100644
--- a/cfg.y
+++ b/cfg.y
@@ -3042,7 +3042,16 @@ cmd:
 	}
 	| ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
 	| ERROR LPAREN error RPAREN { $$=0; yyerror("bad error argument"); }
-	| ROUTE LPAREN route_name RPAREN	{
+	| ROUTE LPAREN rval_expr RPAREN	{
+		if ($3) {
+			$$ = mk_action(ROUTE_T, 1, RVE_ST, (void*)$3);
+			set_cfg_pos($$);
+		} else {
+			$$ = 0;
+			YYERROR;
+		}
+	}
+	| ROUTE LPAREN ID RPAREN	{
 		if ($3) {
 			$$ = mk_action(ROUTE_T, 1, STRING_ST, (void*)$3);
 			set_cfg_pos($$);
diff --git a/route.c b/route.c
index 729860e..b1cd14c 100644
--- a/route.c
+++ b/route.c
@@ -639,6 +639,7 @@ int fix_actions(struct action* a)
 	struct lvalue* lval;
 	struct rval_expr* rve;
 	struct rval_expr* err_rve;
+	struct rvalue* rv;
 	enum rval_type rve_type, err_type, expected_type;
 
 	
@@ -1022,10 +1023,38 @@ int fix_actions(struct action* a)
 				t->val[0].type=STR_ST;
 				break;
 			case ROUTE_T:
+				if (t->val[0].type == RVE_ST) {
+					rve=(struct rval_expr*)t->val[0].u.data;
+					if (!rve_is_constant(rve)) {
+						if ((ret=fix_rval_expr(&t->val[0].u.data)) < 0){
+							ERR("route() failed to fix rve at %s:%d\n",
+								(t->cfile)?t->cfile:"line", t->cline);
+							ret = E_BUG;
+							goto error;
+						}
+					} else {
+						/* rve is constant => replace it with a string */
+						if ((rv = rval_expr_eval(0, 0, rve)) == 0 ||
+								rval_get_str(0, 0, &s, rv, 0) < 0) {
+							/* out of mem. or bug ? */
+							rval_destroy(rv);
+							ERR("route() failed to fix ct. rve at %s:%d\n",
+								(t->cfile)?t->cfile:"line", t->cline);
+							ret = E_BUG;
+							goto error;
+						}
+						rval_destroy(rv);
+						rve_destroy(rve);
+						t->val[0].type = STRING_ST;
+						t->val[0].u.string = s.s;
+						t->val[0].u.str.len = s.len; /* not used */
+						/* fall-through the STRING_ST if */
+					}
+				}
 				if (t->val[0].type == STRING_ST) {
 					i=route_lookup(&main_rt, t->val[0].u.string);
 					if (i < 0) {
-						ERR("route \"%s\" not found at %s:%d\n", 
+						ERR("route \"%s\" not found at %s:%d\n",
 								t->val[0].u.string,
 								(t->cfile)?t->cfile:"line", t->cline);
 						ret = E_SCRIPT;
@@ -1034,7 +1063,8 @@ int fix_actions(struct action* a)
 					t->val[0].type = NUMBER_ST;
 					pkg_free(t->val[0].u.string);
 					t->val[0].u.number = i;
-				} else if (t->val[0].type != NUMBER_ST) {
+				} else if (t->val[0].type != NUMBER_ST &&
+							t->val[0].type != RVE_ST) {
 					BUG("invalid subtype %d for route()\n",
 								t->val[0].type);
 					ret = E_BUG;




More information about the sr-dev mailing list