Module: sip-router
Branch: andrei/script_vars
Commit: ab7f82d262e57857722855217c93096303468fab
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ab7f82d…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)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 */