Module: sip-router Branch: andrei/script_vars Commit: ab7f82d262e57857722855217c93096303468fab URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ab7f82d2...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@iptel.org Date: Thu Dec 4 01:12:46 2008 +0100
script engine: lvalue/rvalue assignment and fixups
---
action.c | 127 +++++--------------------------------------------------- route.c | 61 +++++++++++++-------------- route.h | 4 +- route_struct.h | 4 +- 4 files changed, 47 insertions(+), 149 deletions(-)
diff --git a/action.c b/action.c index ea69e3a..26edcca 100644 --- a/action.c +++ b/action.c @@ -47,6 +47,7 @@ * 2007-06-14 run_actions & do_action need a ctx or handle now, no more * static vars (andrei) * 2008-11-18 support for variable parameter module functions (andrei) + * 2008-12-03 use lvalues/rvalues for assignments (andrei) */
@@ -63,6 +64,7 @@ #include "parser/msg_parser.h" #include "parser/parse_uri.h" #include "ut.h" +#include "lvalue.h" #include "sr_module.h" #include "mem/mem.h" #include "globals.h" @@ -108,8 +110,6 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) struct sip_uri uri, next_hop; struct sip_uri *u; unsigned short port; - unsigned short flags; - int_str name, value; str* dst_host;
/* reset the value of error to E_UNSPEC so avoid unknowledgable @@ -870,121 +870,16 @@ int do_action(struct run_act_ctx* h, struct action* a, struct sip_msg* msg) ret=1; /* continue processing */ break;
- case ADD_T: - case ASSIGN_T: - - /* If the left attr was specified without indexing brackets delete - * existing AVPs before adding new ones - */ - 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); - - if (a->val[1].type == STRING_ST) { - value.s = a->val[1].u.str; - flags = a->val[0].u.attr->type | AVP_VAL_STR; - name = a->val[0].u.attr->name; - ret = 1; - } else if (a->val[1].type == NUMBER_ST) { - value.n = a->val[1].u.number; - flags = a->val[0].u.attr->type; - name = a->val[0].u.attr->name; + case ADD_T: + case ASSIGN_T: + v=lval_assign(h, msg, (struct lvalue*)a->val[0].u.data, + (struct rval_expr*)a->val[1].u.data); + if (likely(v>=0)) ret = 1; - } else if (a->val[1].type == ACTION_ST) { - flags = a->val[0].u.attr->type; - name = a->val[0].u.attr->name; - if (a->val[1].u.data) { - value.n = run_actions(h, (struct action*)a->val[1].u.data, - msg); - } else { - value.n = -1; - } - ret = value.n; - } else if(a->val[1].type == EXPR_ST && a->val[1].u.data) { - v = eval_expr(h, (struct expr*)a->val[1].u.data, msg); - if (v < 0) { - if (v == EXPR_DROP){ /* hack to quit on DROP*/ - ret = 0; - break; - } else { - LOG(L_WARN,"WARNING: do_action: error in expression\n"); - v = 0; /* error is treated as false (Miklos) */ - } - } - - flags = a->val[0].u.attr->type; - name = a->val[0].u.attr->name; - value.n = v; - } else if (a->val[1].type == AVP_ST) { - struct search_state st; - avp_t* avp; - avp_t* avp_mark; - - avp_mark = NULL; - if ((a->val[1].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL) { - avp = search_first_avp(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, &st); - while(avp) { - /* We take only the type of value and name from the source avp - * and reset class and track flags - */ - flags = (a->val[0].u.attr->type & ~AVP_INDEX_ALL) | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL)); - - if (add_avp_before(avp_mark, flags, a->val[0].u.attr->name, value) < 0) { - LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n"); - ret=E_UNSPEC; - break; - } - - /* move the mark, so the next found AVP will come before the one currently added - * so they will have the same order as in the source list - */ - if (avp_mark) { - avp_mark=avp_mark->next; - } else { - avp_mark=search_first_avp(flags, a->val[0].u.attr->name, NULL, NULL); - } - - avp = search_next_avp(&st, &value); - } - ret = 1; - break; - } else { - avp = search_avp_by_index(a->val[1].u.attr->type, a->val[1].u.attr->name, &value, a->val[1].u.attr->index); - if (avp) { - flags = a->val[0].u.attr->type | (avp->flags & ~(AVP_CLASS_ALL|AVP_TRACK_ALL)); - name = a->val[0].u.attr->name; - ret = 1; - } else { - ret = E_UNSPEC; - break; - } - } - } else if (a->val[1].type == SELECT_ST) { - int r; - r = run_select(&value.s, a->val[1].u.select, msg); - if (r < 0) { - ret=E_UNSPEC; - break; - } else if (r > 0) { - value.s.s = ""; - value.s.len = 0; - } - - flags = a->val[0].u.attr->type | AVP_VAL_STR; - name = a->val[0].u.attr->name; - ret = 1; - } else { - LOG(L_CRIT, "BUG: do_action: Bad right side of avp assignment\n"); - ret=E_BUG; - break; - } - - /* If the action is assign then remove the old avp value - * before adding new ones */ -/* if ((unsigned char)a->type == ASSIGN_T) delete_avp(flags, name); */ - if (add_avp(flags & ~AVP_INDEX_ALL, name, value) < 0) { - LOG(L_CRIT, "ERROR: Failed to assign value to attribute\n"); - ret=E_UNSPEC; - break; - } + else if (unlikely (v == EXPR_DROP)) /* hack to quit on DROP*/ + ret=0; + else + ret=v; break;
default: diff --git a/route.c b/route.c index b57364b..cafe4fa 100644 --- a/route.c +++ b/route.c @@ -48,6 +48,7 @@ * the expressions does not exist (Miklos) * 2008-04-23 errors are treated as false during expression evaluation * unless the operator is DIFF_OP (Miklos) + * 2008-12-03 fixups for rvalues in assignments (andrei) */
@@ -66,6 +67,8 @@ #include "dprint.h" #include "proxy.h" #include "action.h" +#include "lvalue.h" +#include "rvalue.h" #include "sr_module.h" #include "ip_addr.h" #include "resolve.h" @@ -276,12 +279,12 @@ int route_lookup(struct route_list* rt, char* name)
-static int fix_actions(struct action* a); /*fwd declaration*/ +int fix_actions(struct action* a); /*fwd declaration*/
/* traverses an expr tree and compiles the REs where necessary) * returns: 0 for ok, <0 if errors */ -static int fix_expr(struct expr* exp) +int fix_expr(struct expr* exp) { regex_t* re; int ret; @@ -380,7 +383,7 @@ static int fix_expr(struct expr* exp)
/* adds the proxies in the proxy list & resolves the hostnames */ /* returns 0 if ok, <0 on error */ -static int fix_actions(struct action* a) +int fix_actions(struct action* a) { struct action *t; struct proxy_l* p; @@ -391,6 +394,8 @@ static int fix_actions(struct action* a) struct hostent* he; struct ip_addr ip; struct socket_info* si; + struct lvalue* lval; + char buf[30]; /* tmp buffer needed for module param fixups */
if (a==0){ @@ -466,40 +471,34 @@ static int fix_actions(struct action* a) } break;
- case ASSIGN_T: - case ADD_T: - if (t->val[0].type != AVP_ST) { - LOG(L_CRIT, "BUG: fix_actions: Invalid left side of assignment\n"); + case ASSIGN_T: + case ADD_T: + if (t->val[0].type !=LVAL_ST) { + LOG(L_CRIT, "BUG: fix_actions: Invalid left side of" + " assignment\n"); return E_BUG; } - if (t->val[0].u.attr->type & AVP_CLASS_DOMAIN) { - LOG(L_ERR, "ERROR: You cannot change domain attributes from the script, they are read-only\n"); - return E_BUG; - } else if (t->val[0].u.attr->type & AVP_CLASS_GLOBAL) { - LOG(L_ERR, "ERROR: You cannot change global attributes from the script, they are read-only\n"); + if (t->val[1].type !=RVE_ST) { + LOG(L_CRIT, "BUG: fix_actions: Invalid right side of" + " assignment (%d)\n", t->val[1].type); return E_BUG; } - - if (t->val[1].type == ACTION_ST && t->val[1].u.data) { - if ((ret = fix_actions((struct action*)t->val[1].u.data)) < 0) { - return ret; - } - } else if (t->val[1].type == EXPR_ST && t->val[1].u.data) { - if ((ret = fix_expr((struct expr*)t->val[1].u.data)) < 0) { - return ret; - } - } else if (t->val[1].type == STRING_ST) { - int len; - len = strlen(t->val[1].u.data); - t->val[1].u.str.s = t->val[1].u.data; - t->val[1].u.str.len = len; - } else if (t->val[1].type == SELECT_ST) { - if ((ret=resolve_select(t->val[1].u.select)) < 0) { - BUG("Unable to resolve select\n"); - print_select(t->val[1].u.select); - return ret; + lval=t->val[0].u.data; + if (lval->type==LV_AVP){ + if (lval->lv.avps.type & AVP_CLASS_DOMAIN) { + LOG(L_ERR, "ERROR: You cannot change domain" + " attributes from the script, they are" + " read-only\n"); + return E_BUG; + } else if (lval->lv.avps.type & AVP_CLASS_GLOBAL) { + LOG(L_ERR, "ERROR: You cannot change global" + " attributes from the script, they are" + "read-only\n"); + return E_BUG; } } + if ((ret=fix_rval_expr(&t->val[1].u.data))<0) + return ret; break;
case MODULE_T: diff --git a/route.h b/route.h index a1486d3..31c9785 100644 --- a/route.h +++ b/route.h @@ -73,7 +73,9 @@ int fix_rls(); int eval_expr(struct run_act_ctx* h, struct expr* e, struct sip_msg* msg);
- +/* fixup functions*/ +int fix_actions(struct action* a); +int fix_expr(struct expr* exp);
diff --git a/route_struct.h b/route_struct.h index 22b92d9..f3b298a 100644 --- a/route_struct.h +++ b/route_struct.h @@ -93,7 +93,9 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T, }; enum { NOSUBTYPE=0, STRING_ST, NET_ST, NUMBER_ST, IP_ST, RE_ST, PROXY_ST, EXPR_ST, ACTIONS_ST, MODEXP_ST, MODFIXUP_ST, URIHOST_ST, URIPORT_ST, - MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST, SELECT_ST, + MYSELF_ST, STR_ST, SOCKID_ST, SOCKETINFO_ST, ACTION_ST, AVP_ST, + SELECT_ST, /* obsolete */ + LVAL_ST, RVE_ST, RETCODE_ST};
/* run flags */