Module: sip-router
Branch: andrei/script_vars
Commit: 26a886bcdcd5901e87d2b1f1984de457eb9fb4d2
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=26a886b…
Author: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Committer: Andrei Pelinescu-Onciul <andrei(a)iptel.org>
Date: Fri Nov 28 20:24:04 2008 +0100
script: basic support for parsing pvar names
- parse pvar names and try to guess on ambiguous pvar/avps identifiers
(e.g.: $foo)
---
cfg.lex | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++------------
cfg.y | 67 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 122 insertions(+), 15 deletions(-)
diff --git a/cfg.lex b/cfg.lex
index 5af02db..56c51e5 100644
--- a/cfg.lex
+++ b/cfg.lex
@@ -75,6 +75,7 @@
* 2007-11-28 added TCP_OPT_{FD_CACHE, DEFER_ACCEPT, DELAYED_ACK, SYNCNT,
* LINGER2, KEEPALIVE, KEEPIDLE, KEEPINTVL, KEEPCNT} (andrei)
* 2008-01-24 added CFG_DESCRIPTION used by cfg_var (Miklos)
+ * 2008-11-28 added support for kamailio pvars and avp/pvar guessing (andrei)
*/
@@ -94,8 +95,10 @@
#define COMMENT_S 1
#define COMMENT_LN_S 2
#define STRING_S 3
- #define ATTR_S 4
- #define SELECT_S 5
+ #define ATTR_S 4 /* avp/attr */
+ #define SELECT_S 5
+ #define AVP_PVAR_S 6 /* avp or pvar */
+ #define PVAR_P_S 7 /* pvar: $(...) or $foo(...)*/
#define STR_BUF_ALLOC_UNIT 128
struct str_buf{
@@ -106,6 +109,7 @@
static int comment_nest=0;
+ static int p_nest=0;
static int state=0, old_state=0, old_initial=0;
static struct str_buf s_buf;
int line=1;
@@ -120,7 +124,7 @@
%}
/* start conditions */
-%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT
+%x STRING1 STRING2 COMMENT COMMENT_LN ATTR SELECT AVP_PVAR PVAR_P
/* action keywords */
FORWARD forward
@@ -219,7 +223,8 @@ PLUS "+"
MINUS "-"
/* Attribute specification */
-ATTR_MARK "$"|"%"
+ATTR_MARK "%"
+VAR_MARK "$"
SELECT_MARK "@"
ATTR_FROM "f"
ATTR_TO "t"
@@ -231,6 +236,9 @@ ATTR_FROMDOMAIN "fd"
ATTR_TODOMAIN "td"
ATTR_GLOBAL "g"
+/* avp prefix */
+AVP_PREF (([ft][rud]?)|g)\.
+
/* config vars. */
DEBUG debug
FORK fork
@@ -729,7 +737,8 @@ EAT_ABLE [\ \t\b\r]
<SELECT>{BINNUMBER} { count(); yylval.intval=(int)strtol(yytext, 0, 2); return
NUMBER; }
-<INITIAL>{ATTR_MARK} { count(); state = ATTR_S; BEGIN(ATTR); return ATTR_MARK;
}
+<INITIAL>{ATTR_MARK} { count(); state = ATTR_S; BEGIN(ATTR);
+ return ATTR_MARK; }
<ATTR>{ATTR_FROM} { count(); return ATTR_FROM; }
<ATTR>{ATTR_TO} { count(); return ATTR_TO; }
<ATTR>{ATTR_FROMURI} { count(); return ATTR_FROMURI; }
@@ -742,15 +751,48 @@ EAT_ABLE [\ \t\b\r]
<ATTR>{DOT} { count(); return DOT; }
<ATTR>{LBRACK} { count(); return LBRACK; }
<ATTR>{RBRACK} { count(); return RBRACK; }
-<ATTR>{STAR} { count(); return STAR; }
-<ATTR>{DECNUMBER} { count(); yylval.intval=atoi(yytext);return NUMBER; }
-<ATTR>{ID} { count(); addstr(&s_buf, yytext, yyleng);
- yylval.strval=s_buf.s;
- memset(&s_buf, 0, sizeof(s_buf));
- state = INITIAL_S;
- BEGIN(INITIAL);
- return ID;
- }
+<ATTR>{STAR} { count(); return STAR; }
+<ATTR>{DECNUMBER} { count(); yylval.intval=atoi(yytext);return NUMBER; }
+<ATTR>{ID} { count(); addstr(&s_buf, yytext, yyleng);
+ yylval.strval=s_buf.s;
+ memset(&s_buf, 0, sizeof(s_buf));
+ state = INITIAL_S;
+ BEGIN(INITIAL);
+ return ID;
+ }
+
+<INITIAL>{VAR_MARK}{LPAREN} { state = PVAR_P_S; BEGIN(PVAR_P); p_nest=1;
+ yymore();}
+ /* eat everything between 2 () and return PVAR token and a string
+ containing everything (including $ and ()) */
+<PVAR_P>{RPAREN} { p_nest--;
+ if (p_nest==0){
+ count();
+ addstr(&s_buf, yytext, yyleng);
+ yylval.strval=s_buf.s;
+ memset(&s_buf, 0, sizeof(s_buf));
+ state=INITIAL_S;
+ BEGIN(INITIAL);
+ return PVAR;
+ }
+ yymore();
+ }
+<PVAR_P>. { yymore(); }
+
+
+<INITIAL>{VAR_MARK} { state=AVP_PVAR_S; BEGIN(AVP_PVAR); yymore(); }
+ /* avp prefix detected -> go to avp mode */
+<AVP_PVAR>{AVP_PREF} |
+<AVP_PVAR>{ID}{LBRACK} { state = ATTR_S; BEGIN(ATTR); yyless(1);
+ return ATTR_MARK; }
+<AVP_PVAR>{ID}{LPAREN} { state = PVAR_P_S; BEGIN(PVAR_P); yymore(); }
+<AVP_PVAR>{ID} { count(); addstr(&s_buf, yytext, yyleng);
+ yylval.strval=s_buf.s;
+ memset(&s_buf, 0, sizeof(s_buf));
+ state = INITIAL_S;
+ BEGIN(INITIAL);
+ return AVP_OR_PVAR;
+ }
<INITIAL>{IPV6ADDR} { count(); yylval.strval=yytext; return IPV6ADDR; }
<INITIAL>{DECNUMBER} { count(); yylval.intval=atoi(yytext);return NUMBER; }
diff --git a/cfg.y b/cfg.y
index 5adc111..228d909 100644
--- a/cfg.y
+++ b/cfg.y
@@ -185,8 +185,17 @@ static struct ip_addr* ip_tmp;
static struct avp_spec* s_attr;
static select_t sel;
static select_t* sel_ptr;
+static pv_spec_t* pv_spec;
static struct action *mod_func_action;
+static struct avp_pvar_spec{
+ int type;
+ union{
+ struct avp_spec avp;
+ pv_spec_t pv;
+ }u;
+} *apv_spec;
+
static void warn(char* s);
static struct socket_id* mk_listen_id(char*, int, int);
static struct name_lst* mk_name_lst(char* name, int flags);
@@ -207,6 +216,8 @@ static void free_socket_id_lst(struct socket_id* i);
struct socket_id* sockid;
struct name_lst* name_l;
struct avp_spec* attr;
+ struct pv_spec_t* pvar;
+ struct avp_pvar_spec* avp_pvar_s;
select_t* select;
}
@@ -426,6 +437,7 @@ static void free_socket_id_lst(struct socket_id* i);
%token ATTR_GLOBAL
%token ADDEQ
+
%token STUN_REFRESH_INTERVAL
%token STUN_ALLOW_STUN
%token STUN_ALLOW_FP
@@ -452,6 +464,9 @@ static void free_socket_id_lst(struct socket_id* i);
%token <strval> ID
%token <strval> STRING
%token <strval> IPV6ADDR
+%token <strval> PVAR
+/* not clear yet if this is an avp or pvar */
+%token <strval> AVP_OR_PVAR
/* other */
%token COMMA
@@ -492,6 +507,8 @@ static void free_socket_id_lst(struct socket_id* i);
%type <attr> attr_id_val
%type <attr> attr_id_any
%type <attr> attr_id_any_str
+%type <pvar> pvar
+%type <avp_pvar_s> avp_pvar
/* %type <intval> class_id */
%type <intval> assign_op
%type <select> select_id
@@ -1954,7 +1971,7 @@ attr_id_any_str:
s.len = strlen(s.s);
if (parse_avp_name(&s, &type, &avp_spec->name, &idx)) {
yyerror("error when parsing AVP");
- pkg_free(avp_spec);
+ pkg_free(avp_spec);
YYABORT;
}
avp_spec->type = type;
@@ -1962,6 +1979,52 @@ attr_id_any_str:
$$ = avp_spec;
}
;
+
+pvar: PVAR {
+ pv_spec=pkg_malloc(sizeof(*pv_spec));
+ if (!pv_spec) {
+ yyerror("Not enough memory");
+ YYABORT;
+ }
+ s.s=$1; s.len=strlen(s.s);
+ if (pv_parse_spec(&s, pv_spec)==0){
+ yyerror("unknown script pseudo variable");
+ pkg_free(pv_spec);
+ YYABORT;
+ }
+ $$=pv_spec;
+ BUG("parsed pvar \"%.*s\"\n", s.len, s.s);
+ }
+ ;
+
+avp_pvar: AVP_OR_PVAR {
+ apv=pkg_malloc(sizeof(*apv));
+ if (!apv) {
+ yyerror("Not enough memory");
+ YYABORT;
+ }
+ s.s=$1; s.len=strlen(s.s);
+ if (pv_parse_spec(&s, &apv_spec->u.pv)==0){
+ /* not a pvar, try avps */
+ /* TODO: test if in ser or k mode */
+ if (parse_avp_name(&s, &type, &apv_spec->u.avp.name, &idx)) {
+ yyerror("error when parsing AVP");
+ pkg_free(apv_spec);
+ YYABORT;
+ }
+ apv_spec->u.avp.type = type;
+ apv_spec->u.avp.index = idx;
+ apv_spec.type=APV_AVP_T;
+ }else{
+ apv_spec.type=APV_PVAR_T;
+ }
+ $$ = apv_spec;
+ BUG("parsed ambigous avp/pvar \"%.*s\" to %d\n", s.len, s.s,
+ apv_spec.type);
+ }
+ ;
+
+
/*
assign_op:
ADDEQ { $$ = ADD_T; }
@@ -1979,6 +2042,8 @@ assign_action:
| attr_id_ass assign_op select_id { $$=mk_action($2, 2, AVP_ST, (void*)$1, SELECT_ST,
(void*)$3); }
| attr_id_ass assign_op LPAREN exp RPAREN { $$ = mk_action($2, 2, AVP_ST, $1, EXPR_ST,
$4); }
;
+
+
avpflag_oper:
SETAVPFLAG { $$ = 1; }
| RESETAVPFLAG { $$ = 0; }