- added AVP flags feature.
authorTomas Mandys <tomas.mandys@iptel.org>
Wed, 31 May 2006 23:02:46 +0000 (23:02 +0000)
committerTomas Mandys <tomas.mandys@iptel.org>
Wed, 31 May 2006 23:02:46 +0000 (23:02 +0000)
Every AVP may by flaged from script via setavpflag(avpid, flag) (it's similar like message flags setflags,resetflags,isflagset). AVP flags must be declared using avpflags statement. Flags may be tested via isavpflagset(avpid, flag). Both the setting and testing may also be processed in a module. It's currently used in the "rr" module for dialog_cookies. Such module should register flag using register_avpflag(flag_id).

Example:
avpflags myflag, dialog_cookie;

$a = 123;
setavpflag($a, "myflag");

if (isavpflagset($a, "myflag")) {
....

$dlg_foo = "foo";
$dlg_bar = "bar";
setavpflag("$f./^dlg_", "dialog_cookie");

action.c
cfg.lex
cfg.y
doc/serdev/routing_engine.xml
doc/seruser/reference.xml
route_struct.c
route_struct.h
usr_avp.c
usr_avp.h

index 96cb315..3d72afb 100644 (file)
--- a/action.c
+++ b/action.c
@@ -365,6 +365,45 @@ int do_action(struct action* a, struct sip_msg* msg)
                        break;
                /* jku - end : flag processing */
 
+               case AVPFLAG_OPER_T:  {
+                       struct search_state st;
+                       avp_t* avp;
+                       int flag;
+                       ret = 0;
+                       flag = a->val[1].u.number;
+                       if ((a->val[0].u.attr->type & AVP_INDEX_ALL) == AVP_INDEX_ALL || (a->val[0].u.attr->type & AVP_NAME_RE)!=0) {
+                               for (avp=search_first_avp(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, &st); avp; avp = search_next_avp(&st, NULL)) {
+                                       switch (a->val[2].u.number) {   /* oper: 0..reset, 1..set, -1..no change */
+                                               case 0:
+                                                       avp->flags &= ~(avp_flags_t)a->val[1].u.number;
+                                                       break;
+                                               case 1:
+                                                       avp->flags |= (avp_flags_t)a->val[1].u.number;
+                                                       break;
+                                               default:;
+                                       }
+                                       ret = ret || ((avp->flags & (avp_flags_t)a->val[1].u.number) != 0);
+                               }
+                       }
+                       else {
+                               avp = search_avp_by_index(a->val[0].u.attr->type, a->val[0].u.attr->name, NULL, a->val[0].u.attr->index);
+                               if (avp) {
+                                       switch (a->val[2].u.number) {   /* oper: 0..reset, 1..set, -1..no change */
+                                               case 0:
+                                                       avp->flags &= ~(avp_flags_t)a->val[1].u.number;
+                                                       break;
+                                               case 1:
+                                                       avp->flags |= (avp_flags_t)a->val[1].u.number;
+                                                       break;
+                                               default:;
+                                       }
+                                       ret = (avp->flags & (avp_flags_t)a->val[1].u.number) != 0;
+                               }
+                       }
+                       if (ret==0)
+                               ret = -1;
+                       break;
+               }
                case ERROR_T:
                        if ((a->val[0].type!=STRING_ST)|(a->val[1].type!=STRING_ST)){
                                LOG(L_CRIT, "BUG: do_action: bad error() types %d, %d\n",
diff --git a/cfg.lex b/cfg.lex
index 30fa297..d623fb3 100644 (file)
--- a/cfg.lex
+++ b/cfg.lex
@@ -131,6 +131,10 @@ SETFLAG            setflag
 RESETFLAG      resetflag
 ISFLAGSET      isflagset
 FLAGS_DECL     "flags"|"bool"
+SETAVPFLAG     setavpflag
+RESETAVPFLAG   resetavpflag
+ISAVPFLAGSET   isavpflagset
+AVPFLAGS_DECL  avpflags
 SET_HOST               "rewritehost"|"sethost"|"seth"
 SET_HOSTPORT   "rewritehostport"|"sethostport"|"sethp"
 SET_USER               "rewriteuser"|"setuser"|"setu"
@@ -336,6 +340,10 @@ EAT_ABLE   [\ \t\b\r]
 <INITIAL>{RESETFLAG}   { count(); yylval.strval=yytext; return RESETFLAG; }
 <INITIAL>{ISFLAGSET}   { count(); yylval.strval=yytext; return ISFLAGSET; }
 <INITIAL>{FLAGS_DECL}  { count(); yylval.strval=yytext; return FLAGS_DECL; }
+<INITIAL>{SETAVPFLAG}  { count(); yylval.strval=yytext; return SETAVPFLAG; }
+<INITIAL>{RESETAVPFLAG}        { count(); yylval.strval=yytext; return RESETAVPFLAG; }
+<INITIAL>{ISAVPFLAGSET}        { count(); yylval.strval=yytext; return ISAVPFLAGSET; }
+<INITIAL>{AVPFLAGS_DECL}       { count(); yylval.strval=yytext; return AVPFLAGS_DECL; }
 <INITIAL>{MSGLEN}      { count(); yylval.strval=yytext; return MSGLEN; }
 <INITIAL>{RETCODE}     { count(); yylval.strval=yytext; return RETCODE; }
 <INITIAL>{ROUTE}       { count(); yylval.strval=yytext; return ROUTE; }
diff --git a/cfg.y b/cfg.y
index 634d74d..4184d64 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -71,6 +71,7 @@
  * 2005-01-07  optional semicolon in statement, PARAM_STR&PARAM_STRING
  * 2006-02-02  named flags support (andrei)
  * 2006-02-06  named routes support (andrei)
+ * 2006-05-30  avp flags (tma)
  */
 
 %{
@@ -193,6 +194,9 @@ static struct socket_id* mk_listen_id(char*, int, int);
 %token SETFLAG
 %token RESETFLAG
 %token ISFLAGSET
+%token SETAVPFLAG
+%token RESETAVPFLAG
+%token ISAVPFLAGSET
 %token METHOD
 %token URI
 %token FROM_URI
@@ -280,6 +284,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
 %token TOS
 
 %token FLAGS_DECL
+%token AVPFLAGS_DECL
 
 %token ATTR_MARK
 %token SELECT_MARK
@@ -349,11 +354,13 @@ static struct socket_id* mk_listen_id(char*, int, int);
 %type <attr> attr_id_ass
 %type <attr> attr_id_val
 %type <attr> attr_id_any
+%type <attr> attr_id_any_str
 /* %type <intval> class_id */
 %type <intval> assign_op
 %type <select> select_id
 %type <strval> flag_name;
 %type <strval> route_name;
+%type <intval> avpflag_oper
 
 /*%type <route_el> rules;
   %type <route_el> rule;
@@ -373,6 +380,7 @@ statements:
 statement:
        assign_stm
        | flags_decl
+       | avpflags_decl
        | module_stm
        | {rt=REQUEST_ROUTE;} route_stm
        | {rt=FAILURE_ROUTE;} failure_route_stm
@@ -460,6 +468,20 @@ flag_name:         STRING  { $$=$1; }
                        |       ID              { $$=$1; }
 ;
 
+avpflags_decl:
+       AVPFLAGS_DECL avpflag_list
+       | AVPFLAGS_DECL error { yyerror("avpflag list expected\n"); }
+       ;
+avpflag_list:
+       avpflag_spec
+       | avpflag_spec COMMA avpflag_list
+       ;
+avpflag_spec:
+       flag_name {
+               if (register_avpflag($1)==0)
+                       yyerror("cannot declare avpflag");
+       }
+       ;
 assign_stm:
        DEBUG_V EQUAL NUMBER { debug=$3; }
        | DEBUG_V EQUAL error  { yyerror("number  expected"); }
@@ -891,7 +913,7 @@ route_stm:
        | ROUTE error { yyerror("invalid  route  statement"); }
        ;
 failure_route_stm:
-       ROUTE_FAILURE LBRACE actions RBRACE { 
+       ROUTE_FAILURE LBRACE actions RBRACE {
                                                                        push($3, &failure_rt.rlist[DEFAULT_RT]);
                                                                                }
        | ROUTE_FAILURE LBRACK route_name RBRACK LBRACE actions RBRACE {
@@ -927,7 +949,7 @@ onreply_route_stm:
        | ROUTE_ONREPLY error { yyerror("invalid onreply_route statement"); }
        ;
 branch_route_stm:
-       ROUTE_BRANCH LBRACE actions RBRACE { 
+       ROUTE_BRANCH LBRACE actions RBRACE {
                                                                        push($3, &branch_rt.rlist[DEFAULT_RT]);
                                                                                }
        | ROUTE_BRANCH LBRACK route_name RBRACK LBRACE actions RBRACE {
@@ -1404,6 +1426,29 @@ attr_id_any:
        | attr_id_no_idx
        | attr_id_num_idx
 ;
+attr_id_any_str:
+       attr_id
+       | STRING {
+               avp_spec_t *avp_spec;
+               str s;
+               int type, idx;
+               avp_spec = pkg_malloc(sizeof(*avp_spec));
+               if (!avp_spec) {
+                       yyerror("Not enough memory");
+                       YYABORT;
+               }
+               s.s = $1+1; /* skip $ */
+               s.len = strlen(s.s);
+               if (parse_avp_name(&s, &type, &avp_spec->name, &idx)) {
+                       yyerror("error when parsing AVP");
+                       pkg_free(avp_spec);
+                       YYABORT;
+               }
+               avp_spec->type = type;
+               avp_spec->index = idx;
+               $$ = avp_spec;
+       }
+       ;
 /*
 assign_op:
        ADDEQ { $$ = ADD_T; }
@@ -1421,6 +1466,11 @@ 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; }
+       | ISAVPFLAGSET { $$ = -1; }
+       ;
 cmd:
        FORWARD LPAREN host RPAREN      { $$=mk_action( FORWARD_T, 2, STRING_ST, $3, NUMBER_ST, 0); }
        | FORWARD LPAREN STRING RPAREN  { $$=mk_action( FORWARD_T, 2, STRING_ST, $3, NUMBER_ST, 0); }
@@ -1568,7 +1618,7 @@ cmd:
                                                        i_tmp=get_flag_no($3, strlen($3));
                                                        if (i_tmp<0) yyerror("flag not declared");
                                                        $$=mk_action(SETFLAG_T, 1, NUMBER_ST,
-                                                                               (void*)(long)i_tmp); 
+                                                                               (void*)(long)i_tmp);
                                                                        }
        | SETFLAG error                 { $$=0; yyerror("missing '(' or ')'?"); }
        | RESETFLAG LPAREN NUMBER RPAREN {
@@ -1580,7 +1630,7 @@ cmd:
                                                        i_tmp=get_flag_no($3, strlen($3));
                                                        if (i_tmp<0) yyerror("flag not declared");
                                                        $$=mk_action(RESETFLAG_T, 1, NUMBER_ST,
-                                                                               (void*)(long)i_tmp); 
+                                                                               (void*)(long)i_tmp);
                                                                        }
        | RESETFLAG error               { $$=0; yyerror("missing '(' or ')'?"); }
        | ISFLAGSET LPAREN NUMBER RPAREN {
@@ -1592,13 +1642,19 @@ cmd:
                                                        i_tmp=get_flag_no($3, strlen($3));
                                                        if (i_tmp<0) yyerror("flag not declared");
                                                        $$=mk_action(ISFLAGSET_T, 1, NUMBER_ST,
-                                                                               (void*)(long)i_tmp); 
+                                                                               (void*)(long)i_tmp);
                                                                        }
        | ISFLAGSET error { $$=0; yyerror("missing '(' or ')'?"); }
+       | avpflag_oper LPAREN attr_id_any_str COMMA flag_name RPAREN {
+               i_tmp=get_avpflag_no($5);
+               if (i_tmp==0) yyerror("avpflag not declared");
+               $$=mk_action(AVPFLAG_OPER_T, 3, AVP_ST, $3, NUMBER_ST, (void*)(long)i_tmp, NUMBER_ST, (void*)$1);
+       }
+       | avpflag_oper error { $$=0; yyerror("missing '(' or ')'?"); }
        | ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T, 2, STRING_ST, $3, STRING_ST, $5); }
        | ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
        | ERROR LPAREN error RPAREN { $$=0; yyerror("bad error argument"); }
-       | ROUTE LPAREN route_name RPAREN        { 
+       | ROUTE LPAREN route_name RPAREN        {
                                                i_tmp=route_get(&main_rt, $3);
                                                if (i_tmp==-1){
                                                        yyerror("internal error");
index 41edbb2..fd406ef 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
 <section id="routing_engine" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -69,7 +69,7 @@
        </para>
        <para>
            The following commands are handled by the <acronym>SER</acronym> core
-           itself: 
+           itself:
            <function>drop</function>,
            <function>forward</function>,
            <function>send</function>,
@@ -79,6 +79,9 @@
            <function>setflag</function>,
            <function>resetflag</function>,
            <function>isflagset</function>,
+           <function>setavpflag</function>,
+           <function>resetavpflag</function>,
+           <function>isavpflagset</function>,
            <function>error</function>,
            <function>route</function>,
            <function>exec</function>,
                    function.
                </para>
                <para>
-                   The message will be sent out using 
+                   The message will be sent out using
                    <function>udp_send</function> directly.
                </para>
            </listitem>
                    is set or not.
                </para>
            </listitem>
+           <listitem>
+               <para>
+                   <function>setavpflag(avp, flag_id)</function> - Sets a flag in the
+                   AVP(s). The command simply set custom flag of AVP. The flags
+                   may be used in script using <function>isavpflagset</function>
+                   or in a module to perform specific operation on marked AVPs.
+                   Flag identifier must be declared via <emphasis>avpflags</emphasis>
+                   statement.
+               </para>
+           </listitem>
+           <listitem>
+               <para>
+                   <function>resetavpflag(avp, flag_id)</function> - Same as command
+                   <function>setavpflag</function> - only resetavpflag will be
+                   called instead of setavpflag.
+               </para>
+           </listitem>
+           <listitem>
+               <para>
+                   <function>isavpflagset(avp, flag_id)</function> - Test if the avp flag
+                   is set or not.
+               </para>
+           </listitem>
            <listitem>
                <para>
                    <function>error</function> - Log a message with NOTICE log
index 9d1b446..d825cfd 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN" 
+<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
    "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
 
 <section id="reference" xmlns:xi="http://www.w3.org/2001/XInclude">
@@ -21,9 +21,9 @@
            <itemizedlist>
                <listitem>
                    <para>
-                       <varname>debug</varname> - Set log level, this is number between 0 and 9. Default 
+                       <varname>debug</varname> - Set log level, this is number between 0 and 9. Default
                        is 0.
-                       
+
                    </para>
                </listitem>
                <listitem>
                            <para>
                                Disabling child spawning is useful mainly for
                                debugging. When <varname>fork</varname> is turned off,
-                               some features are unavailable: 
+                               some features are unavailable:
                                there is no attendant process, no pid file is generated,
                                and server listens only at one address. Make sure you
-                               are debugging the same interface at which 
+                               are debugging the same interface at which
                                <application>ser</application> listens.
                                The easiest way to do so is to set the interface using
                                <varname>listen</varname> option explicitly.
@@ -47,8 +47,8 @@
                </listitem>
                <listitem>
                    <para>
-                       <varname>log_stderror</varname> - If set to yes, the server will print its debugging 
-                       information to standard error output. If set to no, <command>syslog</command> 
+                       <varname>log_stderror</varname> - If set to yes, the server will print its debugging
+                       information to standard error output. If set to no, <command>syslog</command>
                        will be used. Default is no (printing to syslog).
                    </para>
                </listitem>
@@ -60,9 +60,9 @@
                                        This parameter may repeat several times, then SER will
                                        listen on all addresses. For example, the following
                                        command-line options (equivalent to "listen" config
-                                       option) may be used: 
+                                       option) may be used:
                                        <command>
-                                               ser -l foo  -l bar -p 5061 -l x -l y 
+                                               ser -l foo  -l bar -p 5061 -l x -l y
                                        </command>
                                        will listen on foo:5060, bar:5061 &amp; x:5061 &amp; y:5061
 
@@ -73,7 +73,7 @@
                <listitem>
                    <para>
                        <varname>alias</varname> - Add IP addresses or hostnames to list of name aliases.
-                       All requests with hostname matching an alias will satisfy the condition 
+                       All requests with hostname matching an alias will satisfy the condition
                        "uri==myself".
                    </para>
                </listitem>
                </listitem>
                <listitem>
                    <para>
-                       <varname>port</varname> - Listens on the specified port (default 5060). It applies to the last 
+                       <varname>port</varname> - Listens on the specified port (default 5060). It applies to the last
                        address specified in listen and to all the following that do not have a corresponding "port" option.
                    </para>
                </listitem>
                <listitem>
                    <para>
-                       <varname>maxbuffer</varname> - Maximum receive buffer size which will not be exceeded by 
+                       <varname>maxbuffer</varname> - Maximum receive buffer size which will not be exceeded by
                        the auto-probing procedure even if the OS allows. Default value is MAX_RECV_BUFFER_SIZE,
                        which is 256k.
                    </para>
                <listitem>
                    <para>
                        <varname>children</varname> - Specifies how many processes should be started
-                       for each transport protocol. 
-                   Running multiple children allows a server to 
+                       for each transport protocol.
+                   Running multiple children allows a server to
                        server multiple requests in parallel when request processing block (e.g., on DNS
                        lookup). Note that <application>ser</application> typically spawns additional
                        processes, such as timer process or FIFO server. If FIFO server is turned on,
                </listitem>
                <listitem>
                    <para>
-                       <varname>syn_branch</varname> - Shall the server use stateful synonym branches? It is faster but not 
+                       <varname>syn_branch</varname> - Shall the server use stateful synonym branches? It is faster but not
                        reboot-safe. Default is yes.
                    </para>
                </listitem>
                        whether they should send reply
                        to IP advertised in Via.
                        Turned off by default, which means that replies are
-                       sent to IP address from which requests came from. 
+                       sent to IP address from which requests came from.
                    </para>
                </listitem>
                <listitem>
                    <para>
-                       <varname>user | uid</varname> - uid to be used by the server. 
+                       <varname>user | uid</varname> - uid to be used by the server.
                    </para>
                </listitem>
                <listitem>
                </listitem>
                <listitem>
                    <para>
-                       <varname>mhomed</varname> -- enable calculation of 
+                       <varname>mhomed</varname> -- enable calculation of
                        outbound interface; useful on multihomed servers,
                        see <xref linkend="mhomed"/>.
                    </para>
                <listitem>
                    <para>
                        <command>route[number]{...}</command> - This marks a "route block" in configuration files.
-                       route blocks are basic building blocks of <application>ser</application> scripts. 
-                       Each route block contains a sequence of 
+                       route blocks are basic building blocks of <application>ser</application> scripts.
+                       Each route block contains a sequence of
                        <application>SER</application> actions enclosed in braces. Multiple route blocks
                        can be included in a configuration file.
-                       When script execution begins on request receipt, 
-                       route block number 0 is entered. Other route blocks serve as a kind of sub-routines and 
-                       may be entered by calling the action <command>route(n)</command>, 
+                       When script execution begins on request receipt,
+                       route block number 0 is entered. Other route blocks serve as a kind of sub-routines and
+                       may be entered by calling the action <command>route(n)</command>,
                        where n is number of the block. The action <command>break</command>
                        exits currently executed route block. It stops script execution for
                        route block number 0 or returns to calling route block otherwise.
@@ -263,7 +263,7 @@ route[2] {
                        <command>t_relay</command>. When a negative reply
                        comes back, the desired <command>failure_route</command>
                        will be entered and processing of the original request may
-                       continue. 
+                       continue.
                        </para>
                    <para>
                        The set of actions applicable from within
@@ -288,14 +288,14 @@ failure_route[1] {
 
                <listitem>
                    <para>
-                       The action <command>break</command> exits currently executed route block. 
-                       It stops script execution for route block number 0 or returns to calling 
+                       The action <command>break</command> exits currently executed route block.
+                       It stops script execution for route block number 0 or returns to calling
                        route block otherwise.
                        <note>
                            <para>
                                We recommend to use <command>break</command>
                                after any request forwarding or replying. This practice
-                               helps to avoid erroneous scripts that 
+                               helps to avoid erroneous scripts that
                                continue execution and mistakenly send another reply or
                                forward a request to another place, resulting in
                                protocol confusion.
@@ -376,6 +376,46 @@ if (isflagset(1)) {
 </programlisting>
                    </example>
                </listitem>
+               <listitem>
+                   <para>
+                       <function>setavpflag(avp, flag_id)</function> - Sets a flag in the
+                       AVP(s). The command simply set custom flag of AVP. The flags
+                       may be used in script using <function>isavpflagset</function>
+                       or in a module to perform specific operation on marked AVPs.
+                       Flag identifier must be declared via <emphasis>avpflags</emphasis>
+                       statement.
+                   </para>
+                   <example>
+                       <title>setavpflag</title>
+                       <programlisting>
+avpflags
+       my_flag,
+       your_flag;
+....
+setavpflag($avp[1], "my_flag");
+....
+if (isavpflagset($avp2, "your_flag")) {
+
+}
+</programlisting>
+                   </example>
+               </listitem>
+               <listitem>
+                   <para>
+                       <function>resetavpflag(avp, flag_id)</function> - Same as command
+                       <function>setavpflag</function> - only resetavpflag will be
+                       called instead of setavpflag.
+                   </para>
+               </listitem>
+               <listitem>
+                   <para>
+                       <function>isavpflagset(avp, flag_id)</function> - Test if the avp flag
+                       is set or not.
+                   </para>
+               </listitem>
+
+
+
            </itemizedlist>
            <itemizedlist>
                <title>Manipulation of URI and Destination Set</title>
@@ -476,8 +516,8 @@ sl_send_reply("300", "redirection");
                <title>Message Forwarding</title>
                <listitem>
                    <para>
-                       <command>forward(uri, port)</command> - Forward the request to given 
-                       destination statelessly.  The uri and port parameters may take special 
+                       <command>forward(uri, port)</command> - Forward the request to given
+                       destination statelessly.  The uri and port parameters may take special
                        values 'uri:host'
                        and 'uri:port' respectively, in which case SER forwards to destination
                        set in current URI. All other elements in a destination set are
@@ -489,7 +529,7 @@ sl_send_reply("300", "redirection");
                </listitem>
                <listitem>
                    <para>
-                       <command>send</command> - Send the message as is to a third party 
+                       <command>send</command> - Send the message as is to a third party
                    </para>
                    <para>
                        <emphasis>Example:</emphasis> send("foo.bar.com");
@@ -498,10 +538,10 @@ sl_send_reply("300", "redirection");
            </itemizedlist>
            <itemizedlist>
                <title>Logging</title>
-               
+
 
                <listitem>
-                   
+
                    <para>
                        <command>log([level], message)</command> - Log a message.
                    </para>
@@ -530,7 +570,7 @@ sl_send_reply("300", "redirection");
                <listitem>
                    <para>
                        <command>len_gt</command> - If length of the message is greater than value given as parameter, the
-                       command will return 1 (indicating true). Otherwise -1 (indicating false) will be returned. It may 
+                       command will return 1 (indicating true). Otherwise -1 (indicating false) will be returned. It may
                        take 'max_len' as parameter, in which case message size is limited
                        to internal buffer size BUF_SIZE (3040 by default).
                    </para>
@@ -608,25 +648,25 @@ if (len_gt(1024)) {
                </listitem>
                <listitem>
                    <para>
-                       <emphasis>-l address</emphasis> - Listens on the specified address. Multiple -l mean listening 
+                       <emphasis>-l address</emphasis> - Listens on the specified address. Multiple -l mean listening
                        on multiple addresses. The default behavior is to listen on all the ipv4 interfaces.
                    </para>
                </listitem>
                <listitem>
                    <para>
-                       <emphasis>-p port</emphasis> - Listens on the specified port (default 5060). It applies to the last 
+                       <emphasis>-p port</emphasis> - Listens on the specified port (default 5060). It applies to the last
                        address specified with -l and to all the following that do not have a corresponding -p.
                    </para>
                </listitem>
                <listitem>
                    <para>
-                       <emphasis>-n processes-no</emphasis> - Specifies the number of children processes forked per 
+                       <emphasis>-n processes-no</emphasis> - Specifies the number of children processes forked per
                        interface (default 8).
                    </para>
                </listitem>
                <listitem>
                    <para>
-                       <emphasis>-b max_rcv_buf_size</emphasis> - Maximum receive buffer size which will not be exceeded by 
+                       <emphasis>-b max_rcv_buf_size</emphasis> - Maximum receive buffer size which will not be exceeded by
                        the auto-probing procedure even if the OS allows.
                    </para>
                </listitem>
@@ -637,7 +677,7 @@ if (len_gt(1024)) {
                </listitem>
                <listitem>
                    <para>
-                       <emphasis>-w working-dir</emphasis> - Specifies the working directory. In the very improbable event 
+                       <emphasis>-w working-dir</emphasis> - Specifies the working directory. In the very improbable event
                        that will crash, the core file will be generated here.
                    </para>
                </listitem>
@@ -770,7 +810,7 @@ if (len_gt(1024)) {
                    <listitem>
                        <para>
                            <emphasis>
-                                       nathelper       
+                                       nathelper
                            </emphasis>
                            -- facilitates NAT traversal for symmetric SIP phones such as ATA.
                            </para>
@@ -823,8 +863,8 @@ if (len_gt(1024)) {
                                <emphasis>textops</emphasis> -- textual database back-end.
                        </para>
                        </listitem>
-                               
-                   <listitem>                  
+
+                   <listitem>
                        <para>
                            <emphasis>
                                tm
@@ -833,7 +873,7 @@ if (len_gt(1024)) {
                        </para>
                    </listitem>
 
-                   <listitem>                  
+                   <listitem>
                        <para>
                            <emphasis>
                                uri, uri_radius
@@ -846,7 +886,7 @@ if (len_gt(1024)) {
            </para>
            <para>
                The most frequently used actions exported by modules are summarized
-               in <xref linkend="moduleactions"/>. For a full explanation of 
+               in <xref linkend="moduleactions"/>. For a full explanation of
                module actions, see documentation in respective module directories
                in source distribution of <application>ser</application>.
            </para>
@@ -854,7 +894,7 @@ if (len_gt(1024)) {
                <title>Frequently Used Module Actions</title>
                <tgroup cols="4">
                    <thead>
-                       <row>                       
+                       <row>
                            <entry>
                                Command
                            </entry>
@@ -1081,7 +1121,7 @@ if (len_gt(1024)) {
                                RegExp, Substitute
                            </entry>
                            <entry>
-                               find the first occurrence of a string matching the regular 
+                               find the first occurrence of a string matching the regular
                                expression in header or body and replace it with a substitute
                            </entry>
                        </row>
@@ -1096,7 +1136,7 @@ if (len_gt(1024)) {
                                RegExp, Substitute
                            </entry>
                            <entry>
-                               find all occurrences of a string matching the regular 
+                               find all occurrences of a string matching the regular
                                expression in header or body and replace it with a substitute
                            </entry>
                        </row>
@@ -1210,7 +1250,7 @@ if (len_gt(1024)) {
                is restarted.
            </para>
            <table>
-               
+
                <title>FIFO Commands</title>
                <tgroup cols="4">
                    <thead>
@@ -1223,7 +1263,7 @@ if (len_gt(1024)) {
                            </entry>
                            <entry>
                                Parameters
-                           </entry>                        
+                           </entry>
                            <entry>
                                Comments
                            </entry>
@@ -1255,7 +1295,7 @@ if (len_gt(1024)) {
                            <entry>arg</entry>
                            <entry>core</entry>
                            <entry>none</entry>
-                           <entry>prints list of command-line arguments with which 
+                           <entry>prints list of command-line arguments with which
                                <application>ser</application> was started</entry>
                        </row>
                        <row>
@@ -1300,9 +1340,9 @@ if (len_gt(1024)) {
                            <entry>tm</entry>
                            <entry>method, request URI, outbound URI (if none, empty line with a single dot),
                                        dot-line-terminated header fields, optionally dot-line terminated message
-                                       body. 
+                                       body.
                                </entry>
-                                       
+
                            <entry>initiate a transaction.
                                        From and To header fields must be present in header field list,
                                        so does Content-Type if body is present. If CSeq, CallId and From-tag
@@ -1463,7 +1503,7 @@ if (len_gt(1024)) {
 
                    <listitem>
                        <para>
-                           server_monitoring-* -- reserved for persistent monitoring of 
+                           server_monitoring-* -- reserved for persistent monitoring of
                                server's operation
                        </para>
                    </listitem>
@@ -1478,7 +1518,7 @@ if (len_gt(1024)) {
 
 
                </itemizedlist>
-               
+
            </para>
        </section>
 </section>
index a1bfbd5..6ca9e09 100644 (file)
@@ -322,6 +322,9 @@ void print_action(struct action* t)
                case ISFLAGSET_T:
                        DBG("isflagset(");
                        break;
+               case AVPFLAG_OPER_T:
+                       DBG("avpflagoper(");
+                       break;
                case SET_HOST_T:
                        DBG("sethost(");
                        break;
index b0ee586..6ffd47c 100644 (file)
@@ -71,6 +71,7 @@ enum { FORWARD_T=1, SEND_T, DROP_T, LOG_T, ERROR_T, ROUTE_T, EXEC_T,
                SET_HOST_T, SET_HOSTPORT_T, SET_USER_T, SET_USERPASS_T,
                SET_PORT_T, SET_URI_T, IF_T, MODULE_T,
                SETFLAG_T, RESETFLAG_T, ISFLAGSET_T ,
+               AVPFLAG_OPER_T,
                LEN_GT_T, PREFIX_T, STRIP_T,STRIP_TAIL_T,
                APPEND_BRANCH_T,
                REVERT_URI_T,
index 99a68dd..af1a731 100644 (file)
--- a/usr_avp.c
+++ b/usr_avp.c
@@ -20,8 +20,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License 
- * along with this program; if not, write to the Free Software 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  * History:
@@ -39,6 +39,8 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include <stdio.h>
+
 #include "sr_module.h"
 #include "dprint.h"
 #include "str.h"
@@ -71,6 +73,9 @@ static avp_list_t* crt_list[IDX_MAX];  /* Pointer to current AVP lists */
 static avp_list_t* def_glist;
 static avp_list_t** crt_glist;
 
+/* AVP flags */
+int registered_avpflags_no = 0;
+static char *registered_avpflags[MAX_AVPFLAG];
 
 /* Initialize AVP lists in private memory and allocate memory
  * for shared lists
@@ -80,7 +85,7 @@ int init_avps(void)
        int i;
             /* Empty default lists */
        memset(def_list, 0, sizeof(avp_list_t) * IDX_MAX);
-       
+
             /* Point current pointers to default lists */
        for(i = 0; i < IDX_MAX; i++) {
                crt_list[i] = &def_list[i];
@@ -144,7 +149,7 @@ avp_t *create_avp (avp_flags_t flags, avp_name_t name, avp_value_t val)
                LOG(L_ERR,"ERROR:avp:add_avp: 0 ID or NULL NAME AVP!");
                goto error;
        }
-       
+
        /* compute the required mem size */
        len = sizeof(struct usr_avp);
        if (flags&AVP_NAME_STR) {
@@ -153,11 +158,11 @@ avp_t *create_avp (avp_flags_t flags, avp_name_t name, avp_value_t val)
                        goto error;
                }
                if (flags&AVP_VAL_STR) {
-                       len += sizeof(struct str_str_data)-sizeof(void*) 
+                       len += sizeof(struct str_str_data)-sizeof(void*)
                                + name.s.len + 1 /* Terminating zero for regex search */
                                + val.s.len + 1; /* Value is zero terminated */
                } else {
-                       len += sizeof(struct str_int_data)-sizeof(void*) 
+                       len += sizeof(struct str_int_data)-sizeof(void*)
                                + name.s.len + 1; /* Terminating zero for regex search */
                }
        } else if (flags&AVP_VAL_STR) {
@@ -226,7 +231,7 @@ int add_avp_list(avp_list_t* list, avp_flags_t flags, avp_name_t name, avp_value
                *list = avp;
                return 0;
        }
-       
+
        return -1;
 }
 
@@ -256,14 +261,14 @@ int add_avp(avp_flags_t flags, avp_name_t name, avp_value_t val)
 int add_avp_before(avp_t *avp, avp_flags_t flags, avp_name_t name, avp_value_t val)
 {
        avp_t *new_avp;
-       
+
        if (!avp) {
                return add_avp(flags, name, val);
        }
 
        if ((flags & AVP_CLASS_ALL) == 0) flags |= (avp->flags & AVP_CLASS_ALL);
        if ((flags & AVP_TRACK_ALL) == 0) flags |= (avp->flags & AVP_TRACK_ALL);
-       
+
        if ((avp->flags & (AVP_CLASS_ALL|AVP_TRACK_ALL)) != (flags & (AVP_CLASS_ALL|AVP_TRACK_ALL))) {
                ERR("add_avp_before:Source and target AVPs have different CLASS/TRACK\n");
                return -1;
@@ -400,7 +405,7 @@ avp_t *search_avp (avp_ident_t ident, avp_value_t* val, struct search_state* sta
                LOG(L_ERR,"ERROR:avp:search_first_avp: 0 ID or NULL NAME AVP!");
                return 0;
        }
-       
+
        switch (ident.flags & AVP_INDEX_ALL) {
                case AVP_INDEX_BACKWARD:
                case AVP_INDEX_FORWARD:
@@ -415,7 +420,7 @@ avp_t *search_avp (avp_ident_t ident, avp_value_t* val, struct search_state* sta
                      * all of them by default
                      */
                ident.flags |= AVP_CLASS_ALL;
-               
+
                if ((ident.flags & AVP_TRACK_ALL) == 0) {
                    /* The caller did not specify even the track to search in, so search
                     * in the track_from
@@ -496,7 +501,7 @@ int search_reverse( avp_t *cur, struct search_state* st,
                      avp_index_t index, avp_list_t *ret)
 {
        avp_index_t lvl;
-       
+
        if (!cur)
                return 0;
        lvl = search_reverse(search_next_avp(st, NULL), st, index, ret)+1;
@@ -504,13 +509,13 @@ int search_reverse( avp_t *cur, struct search_state* st,
                *ret=cur;
        return lvl;
 }
-                            
+
 avp_t *search_avp_by_index( avp_flags_t flags, avp_name_t name,
-                            avp_value_t *val, avp_index_t index)       
+                            avp_value_t *val, avp_index_t index)
 {
        avp_t *ret, *cur;
        struct search_state st;
-       
+
        if (flags & AVP_NAME_RE) {
                BUG("search_by_index not supported for AVP_NAME_RE\n");
                return 0;
@@ -537,9 +542,9 @@ avp_t *search_avp_by_index( avp_flags_t flags, avp_name_t name,
                        for (index--; (ret && index); ret=search_next_avp(&st, val), index--);
                        return ret;
        }
-               
+
        return 0;
-}                            
+}
 
 /* FIXME */
 /********* free functions ********/
@@ -550,7 +555,7 @@ void destroy_avp(avp_t *avp_del)
        avp_t *avp, *avp_prev;
 
        for (i = 0; i < IDX_MAX; i++) {
-               for( avp_prev=0,avp=*crt_list[i] ; avp ; 
+               for( avp_prev=0,avp=*crt_list[i] ; avp ;
                     avp_prev=avp,avp=avp->next ) {
                        if (avp==avp_del) {
                                if (avp_prev) {
@@ -564,7 +569,7 @@ void destroy_avp(avp_t *avp_del)
                }
        }
 
-       for( avp_prev=0,avp=**crt_glist ; avp ; 
+       for( avp_prev=0,avp=**crt_glist ; avp ;
             avp_prev=avp,avp=avp->next ) {
                if (avp==avp_del) {
                        if (avp_prev) {
@@ -766,7 +771,7 @@ int parse_avp_name( str *name, int *type, int_str *avp_name, int *index)
 {
        int ret;
        avp_ident_t attr;
-       
+
        ret=parse_avp_ident(name, &attr);
        if (!ret) {
                if (type) *type = attr.flags;
@@ -866,7 +871,7 @@ int parse_avp_ident( str *name, avp_ident_t* attr)
                        p=memchr(name->s, '[', name->len);
                        if (!p) {
                                ERR("missing '[' for AVP index\n");
-                               goto error; 
+                               goto error;
                        }
                        s.s=p+1;
                        s.len=name->len-(p-name->s)-2; // [ and ]
@@ -878,7 +883,7 @@ int parse_avp_ident( str *name, avp_ident_t* attr)
                                        s.s++;s.len--;
                                } else {
                                        attr->flags |= AVP_INDEX_FORWARD;
-                               }       
+                               }
                                if ((str2int(&s, &id) != 0)||(id==0)) {
                                        ERR("Invalid AVP index '%.*s'\n", s.len, s.s);
                                        goto error;
@@ -956,7 +961,7 @@ int add_avp_galias_str(char *alias_definition)
        str  alias;
        int  type;
        int  index;
-       
+
        s = alias_definition;
        while(*s && isspace((int)*s))
                s++;
@@ -1027,3 +1032,26 @@ void delete_avp(avp_flags_t flags, avp_name_t name)
                avp = search_next_avp(&st, 0);
        }
 }
+
+/* AVP flags functions */
+
+/* name2id conversion is intended to use during fixup (cfg parsing and modinit) only therefore no hash is used */
+avp_flags_t register_avpflag(char* name) {
+       avp_flags_t ret;
+       ret = get_avpflag_no(name);
+       if (ret == 0) {
+               if (registered_avpflags_no >= MAX_AVPFLAG) return -1;
+               ret = 1<<(AVP_CUSTOM_FLAGS+registered_avpflags_no);
+               registered_avpflags[registered_avpflags_no++] = name;
+       }
+       return ret;
+}
+
+avp_flags_t get_avpflag_no(char* name) {
+       int i;
+       for (i=0; i<registered_avpflags_no; i++) {
+               if (strcasecmp(name, registered_avpflags[i])==0)
+                       return 1<<(AVP_CUSTOM_FLAGS+i);
+       }
+       return 0;
+}
index 2eda7c7..6f657de 100644 (file)
--- a/usr_avp.h
+++ b/usr_avp.h
@@ -147,10 +147,11 @@ typedef struct avp_spec {
 #define AVP_INDEX_BACKWARD     (1<<11)
 #define AVP_INDEX_ALL          (AVP_INDEX_FORWARD | AVP_INDEX_BACKWARD)
 
-#define AVP_FLAG_DIALOG         (1<<12)
+#define AVP_CUSTOM_FLAGS       12
 
 #define GALIAS_CHAR_MARKER  '$'
 
+#define AVP_IS_ASSIGNABLE(ident) ( ((ident).flags & AVP_NAME_RE) == 0 && (((ident).flags & AVP_NAME) == 0 || (((ident)->flags & AVP_NAME) && (ident).name.s.len)) )
 /* Initialize memory structures */
 int init_avps(void);
 
@@ -196,4 +197,10 @@ int parse_avp_name( str *name, int *type, int_str *avp_name, int *index);
 int parse_avp_spec( str *name, int *type, int_str *avp_name, int *index);
 void free_avp_name( int *type, int_str *avp_name);
 
+/* AVP flags functions */
+#define MAX_AVPFLAG  ((unsigned int)( sizeof(avp_flags_t) * CHAR_BIT - 1 - AVP_CUSTOM_FLAGS))
+
+avp_flags_t register_avpflag(char* name);
+avp_flags_t get_avpflag_no(char* name);
+
 #endif