Module: sip-router Branch: andrei/script_vars Commit: 26a886bcdcd5901e87d2b1f1984de457eb9fb4d2 URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=26a886bc...
Author: Andrei Pelinescu-Onciul andrei@iptel.org Committer: Andrei Pelinescu-Onciul andrei@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; }