- named routes support in core and tm (t_on_*).
authorAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 7 Feb 2006 01:14:57 +0000 (01:14 +0000)
committerAndrei Pelinescu-Onciul <andrei@iptel.org>
Tue, 7 Feb 2006 01:14:57 +0000 (01:14 +0000)
e.g.:
route{
route(bar);
t_on_reply("reply_route");
  route(1); # == route("1")
...
}
 route[foo]{
   ...
 }
 route["bar"]{
   ...
 }
 route[1]{
 ...
}
 onreply_route[reply_route]{
  ...
 }

 route(bar);

12 files changed:
action.c
cfg.y
hashes.h
main.c
modules/tm/t_fwd.c
modules/tm/t_reply.c
modules/tm/tm.c
onsend.h
receive.c
route.c
route.h
ut.h

index da7efcc..12bc619 100644 (file)
--- a/action.c
+++ b/action.c
@@ -394,14 +394,14 @@ int do_action(struct action* a, struct sip_msg* msg)
                                ret=E_BUG;
                                break;
                        }
-                       if ((a->val[0].u.number>RT_NO)||(a->val[0].u.number<0)){
+                       if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
                                LOG(L_ERR, "ERROR: invalid routing table number in"
                                                        "route(%lu)\n", a->val[0].u.number);
                                ret=E_CFG;
                                break;
                        }
                        /*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
-                       ret=run_actions(rlist[a->val[0].u.number], msg);
+                       ret=run_actions(main_rt.rlist[a->val[0].u.number], msg);
                        last_retcode=ret;
                        run_flags&=~RETURN_R_F; /* absorb returns */
                        break;
diff --git a/cfg.y b/cfg.y
index fcc536c..03e4457 100644 (file)
--- a/cfg.y
+++ b/cfg.y
@@ -70,6 +70,7 @@
  * 2006-01-06  AVP index support (mma)
  * 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)
  */
 
 %{
@@ -349,6 +350,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
 %type <intval> assign_op
 %type <select> select_id
 %type <strval> flag_name;
+%type <strval> route_name;
 
 /*%type <route_el> rules;
   %type <route_el> rule;
@@ -851,61 +853,106 @@ ipv6:
        ipv6addr { $$=$1; }
        | LBRACK ipv6addr RBRACK {$$=$2; }
 ;
+
+
+route_name:            NUMBER  {
+                                       tmp=int2str($1, &i_tmp);
+                                       if (($$=pkg_malloc(i_tmp+1))==0) {
+                                               yyerror("out of  memory");
+                                               YYABORT;
+                                       } else {
+                                               memcpy($$, tmp, i_tmp);
+                                               $$[i_tmp]=0;
+                                       }
+                                               }
+                       |       ID              { $$=$1; }
+                       |       STRING  { $$=$1; }
+;
+
 route_stm:
-       ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
-       | ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
-               if (($3<RT_NO) && ($3>=0)) {
-                       push($6, &rlist[$3]);
-               } else {
-                       yyerror("invalid routing table number");
+       ROUTE LBRACE actions RBRACE { push($3, &main_rt.rlist[DEFAULT_RT]); }
+       | ROUTE LBRACK route_name RBRACK LBRACE actions RBRACE {
+               i_tmp=route_get(&main_rt, $3);
+               if (i_tmp==-1){
+                       yyerror("internal error");
+                       YYABORT;
+               }
+               if (main_rt.rlist[i_tmp]){
+                       yyerror("duplicate route");
                        YYABORT;
                }
+               push($6, &main_rt.rlist[i_tmp]);
        }
        | ROUTE error { yyerror("invalid  route  statement"); }
        ;
 failure_route_stm:
-       ROUTE_FAILURE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
-               if (($3<FAILURE_RT_NO)&&($3>=1)) {
-                       push($6, &failure_rlist[$3]);
-               } else {
-                       yyerror("invalid reply routing table number");
+       ROUTE_FAILURE LBRACE actions RBRACE { 
+                                                                       push($3, &failure_rt.rlist[DEFAULT_RT]);
+                                                                               }
+       | ROUTE_FAILURE LBRACK route_name RBRACK LBRACE actions RBRACE {
+               i_tmp=route_get(&failure_rt, $3);
+               if (i_tmp==-1){
+                       yyerror("internal error");
+                       YYABORT;
+               }
+               if (failure_rt.rlist[i_tmp]){
+                       yyerror("duplicate route");
                        YYABORT;
                }
+               push($6, &failure_rt.rlist[i_tmp]);
        }
        | ROUTE_FAILURE error { yyerror("invalid failure_route statement"); }
        ;
 onreply_route_stm:
-       ROUTE_ONREPLY LBRACE actions RBRACE { push($3, &onreply_rlist[DEFAULT_RT]); }
-       | ROUTE_ONREPLY LBRACK NUMBER RBRACK LBRACE actions RBRACE {
-               if (($3<ONREPLY_RT_NO)&&($3>=1)) {
-                       push($6, &onreply_rlist[$3]);
-               } else {
-                       yyerror("invalid reply routing table number");
+       ROUTE_ONREPLY LBRACE actions RBRACE {
+                                                                       push($3, &onreply_rt.rlist[DEFAULT_RT]);
+                                                                               }
+       | ROUTE_ONREPLY LBRACK route_name RBRACK LBRACE actions RBRACE {
+               i_tmp=route_get(&onreply_rt, $3);
+               if (i_tmp==-1){
+                       yyerror("internal error");
+                       YYABORT;
+               }
+               if (onreply_rt.rlist[i_tmp]){
+                       yyerror("duplicate route");
                        YYABORT;
                }
+               push($6, &onreply_rt.rlist[i_tmp]);
        }
        | ROUTE_ONREPLY error { yyerror("invalid onreply_route statement"); }
        ;
 branch_route_stm:
-       ROUTE_BRANCH LBRACE actions RBRACE { push($3, &branch_rlist[DEFAULT_RT]); }
-       | ROUTE_BRANCH LBRACK NUMBER RBRACK LBRACE actions RBRACE {
-               if (($3<BRANCH_RT_NO)&&($3>=1)) {
-                       push($6, &branch_rlist[$3]);
-               } else {
-                       yyerror("invalid branch routing table number");
+       ROUTE_BRANCH LBRACE actions RBRACE { 
+                                                                       push($3, &branch_rt.rlist[DEFAULT_RT]);
+                                                                               }
+       | ROUTE_BRANCH LBRACK route_name RBRACK LBRACE actions RBRACE {
+               i_tmp=route_get(&branch_rt, $3);
+               if (i_tmp==-1){
+                       yyerror("internal error");
                        YYABORT;
                }
+               if (branch_rt.rlist[i_tmp]){
+                       yyerror("duplicate route");
+                       YYABORT;
+               }
+               push($6, &branch_rt.rlist[i_tmp]);
        }
        | ROUTE_BRANCH error { yyerror("invalid branch_route statement"); }
        ;
-send_route_stm: ROUTE_SEND LBRACE actions RBRACE {push($3, &onsend_rlist[DEFAULT_RT]); }
-       | ROUTE_SEND LBRACK NUMBER RBRACK LBRACE actions RBRACE {
-               if (($3<ONSEND_RT_NO)&&($3>=1)) {
-                       push($6, &onsend_rlist[$3]);
-               } else {
-                       yyerror("invalid onsend routing table number");
+send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
+                                                                       push($3, &onsend_rt.rlist[DEFAULT_RT]);
+                                                                                               }
+       | ROUTE_SEND LBRACK route_name RBRACK LBRACE actions RBRACE {
+               i_tmp=route_get(&onsend_rt, $3);
+               if (i_tmp==-1){
+                       yyerror("internal error");
+                       YYABORT;
+               }
+               if (onsend_rt.rlist[i_tmp]){
+                       yyerror("duplicate route");
                        YYABORT;
                }
+               push($6, &onsend_rt.rlist[i_tmp]);
        }
        | ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
        ;
@@ -1544,7 +1591,14 @@ cmd:
        | 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 NUMBER RPAREN    { $$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)$3); }
+       | ROUTE LPAREN route_name RPAREN        { 
+                                               i_tmp=route_get(&main_rt, $3);
+                                               if (i_tmp==-1){
+                                                       yyerror("internal error");
+                                                       YYABORT;
+                                               }
+                                               $$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)i_tmp); 
+                                                                               }
        | ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
        | ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route argument"); }
        | EXEC LPAREN STRING RPAREN     { $$=mk_action(EXEC_T, 1, STRING_ST, $3); }
index a0b74bf..285e0b1 100644 (file)
--- a/hashes.h
+++ b/hashes.h
@@ -165,7 +165,7 @@ inline static struct str_hash_entry* str_hash_get(struct str_hash_table* ht,
        int h;
        struct str_hash_entry* e;
        
-       h=get_hash1_raw(e->key.s, e->key.len) % ht->size;
+       h=get_hash1_raw(key, len) % ht->size;
        clist_foreach(&ht->table[h], e, next){
                if ((e->key.len==len) && (memcmp(e->key.s, key, len)==0))
                        return e;
diff --git a/main.c b/main.c
index d053c4c..551a0c4 100644 (file)
--- a/main.c
+++ b/main.c
@@ -389,6 +389,7 @@ void cleanup(show_status)
 #endif
        destroy_timer();
        destroy_script_cb();
+       destroy_routes();
 #ifdef PKG_MALLOC
        if (show_status){
                LOG(memlog, "Memory status (pkg):\n");
@@ -1306,7 +1307,8 @@ int main(int argc, char** argv)
                                        abort();
                }
        }
-
+       
+       if (init_routes()<0) goto error;
        /* fill missing arguments with the default values*/
        if (cfg_file==0) cfg_file=CFG_FILE;
 
@@ -1351,7 +1353,7 @@ try_again:
                goto error;
        }
        if (debug_flag) debug = debug_save;
-       print_rl();
+       print_rls();
 
        /* options with higher priority than cfg file */
        optind = 1;  /* reset getopt */
index 60704d7..eb93683 100644 (file)
@@ -47,6 +47,7 @@
  *  2005-12-11  onsend_route support added for forwarding (andrei)
  *  2006-01-27  t_forward_no_ack will return error if a forward on an 
  *              already canceled transaction is attempted (andrei)
+ *  2006-02-07  named routes support (andrei)
  */
 
 #include "defs.h"
@@ -128,7 +129,7 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req,
 
        if (branch_route) {
                     /* run branch_route actions if provided */
-               if (run_actions(branch_rlist[branch_route], i_req) < 0) {
+               if (run_actions(branch_rt.rlist[branch_route], i_req) < 0) {
                        LOG(L_ERR, "ERROR: print_uac_request: Error in run_actions\n");
                }
        }
index 7fc3135..66c0f6a 100644 (file)
@@ -67,6 +67,7 @@
  *  2005-09-01  reverted to the old way of checking response.dst.send_sock
  *               in t_retransmit_reply & reply_light (andrei)
  *  2005-11-09  updated to the new timers interface (andrei)
+ *  2006-02-07  named routes support (andrei)
  */
 
 
@@ -653,7 +654,7 @@ static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
                on_failure = t->on_negative;
                t->on_negative=0;
                /* run a reply_route action if some was marked */
-               if (run_actions(failure_rlist[on_failure], &faked_req)<0)
+               if (run_actions(failure_rt.rlist[on_failure], &faked_req)<0)
                        LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n");
        }
 
@@ -1342,7 +1343,7 @@ int reply_received( struct sip_msg  *p_msg )
                if (t->uas.request) p_msg->flags=t->uas.request->flags;
                /* set the as avp_list the one from transaction */
                backup_list = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps );
-               if (run_actions(onreply_rlist[t->on_reply], p_msg)<0)
+               if (run_actions(onreply_rt.rlist[t->on_reply], p_msg)<0)
                        LOG(L_ERR, "ERROR: on_reply processing failed\n");
                /* transfer current message context back to t */
                if (t->uas.request) t->uas.request->flags=p_msg->flags;
index c0384e7..95adcec 100644 (file)
@@ -76,6 +76,7 @@
  *  2005-12-09  fixup_hostport2proxy uses route_struct to access param #1
  *              when fixing param #2
  *  2005-12-09  added t_set_fr() (andrei)
+ *  2006-02-07  named routes support (andrei)
  */
 
 
@@ -94,6 +95,7 @@
 #include "../../usr_avp.h"
 #include "../../mem/mem.h"
 #include "../../route_struct.h"
+#include "../../route.h"
 
 #include "sip_msg.h"
 #include "h_table.h"
@@ -114,6 +116,9 @@ MODULE_VERSION
 
 /* fixup functions */
 static int fixup_hostport2proxy(void** param, int param_no);
+static int fixup_on_failure(void** param, int param_no);
+static int fixup_on_reply(void** param, int param_no);
+static int fixup_on_branch(void** param, int param_no);
 
 
 /* init functions */
@@ -226,11 +231,11 @@ static cmd_export_t cmds[]={
        {T_FORWARD_NONACK_TLS, w_t_forward_nonack_tls,  2, fixup_hostport2proxy,
                        REQUEST_ROUTE},
 #endif
-       {"t_on_failure",       w_t_on_negative,         1, fixup_int_1,
+       {"t_on_failure",       w_t_on_negative,         1, fixup_on_failure,
                        REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
-       {"t_on_reply",         w_t_on_reply,            1, fixup_int_1,
+       {"t_on_reply",         w_t_on_reply,            1, fixup_on_reply,
                        REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
-       {"t_on_branch",       w_t_on_branch,         1, fixup_int_1,
+       {"t_on_branch",       w_t_on_branch,         1, fixup_on_branch,
                        REQUEST_ROUTE | FAILURE_ROUTE },
        {"t_check_status",     t_check_status,          1, fixup_regex_1,
                        REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
@@ -308,6 +313,57 @@ struct module_exports exports= {
 };
 
 
+
+/* helper for fixup_on_* */
+static int fixup_routes(char* r_type, struct route_list* rt, void** param)
+{
+       int i;
+       
+       i=route_get(rt, (char*)*param);
+       if (i==-1){
+               LOG(L_ERR, "ERROR: tm: fixup_routes: route_get failed\n");
+               return E_UNSPEC;
+       }
+       if (rt->rlist[i]==0){
+               LOG(L_WARN, "WARNING: %s(\"%s\"): empty/non existing route\n",
+                               r_type, (char*)*param);
+       }
+       *param=(void*)(long)i;
+       return 0;
+}
+
+
+
+static int fixup_on_failure(void** param, int param_no)
+{
+       if (param_no==1){
+               return fixup_routes("t_on_failure", &failure_rt, param);
+       }
+       return 0;
+}
+
+
+
+static int fixup_on_reply(void** param, int param_no)
+{
+       if (param_no==1){
+               return fixup_routes("t_on_reply", &onreply_rt, param);
+       }
+       return 0;
+}
+
+
+
+static int fixup_on_branch(void** param, int param_no)
+{
+       if (param_no==1){
+               return fixup_routes("t_on_branch", &branch_rt, param);
+       }
+       return 0;
+}
+
+
+
 /* (char *hostname, char *port_nr) ==> (struct proxy_l *, -)  */
 static int fixup_hostport2proxy(void** param, int param_no)
 {
index d4987fa..cdc6b1d 100644 (file)
--- a/onsend.h
+++ b/onsend.h
@@ -62,13 +62,13 @@ static inline int run_onsend(struct sip_msg* orig_msg,
        int ret;
        
        ret=1;
-       if (onsend_rlist[DEFAULT_RT]){
+       if (onsend_rt.rlist[DEFAULT_RT]){
                onsnd_info.to=to;
                onsnd_info.send_sock=send_sock;
                onsnd_info.buf=buf;
                onsnd_info.len=len;
                p_onsend=&onsnd_info;
-               ret=run_actions(onsend_rlist[DEFAULT_RT], orig_msg);
+               ret=run_actions(onsend_rt.rlist[DEFAULT_RT], orig_msg);
                p_onsend=0; /* reset it */
        }
        return ret;
index b959df6..11f895c 100644 (file)
--- a/receive.c
+++ b/receive.c
@@ -162,7 +162,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                        goto end; /* drop the request */
 
                /* exec the routing script */
-               if (run_actions(rlist[DEFAULT_RT], msg)<0){
+               if (run_actions(main_rt.rlist[DEFAULT_RT], msg)<0){
                        LOG(L_WARN, "WARNING: receive_msg: "
                                        "error while trying script\n");
                        goto error_req;
@@ -202,8 +202,8 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
                if (exec_pre_rpl_cb(msg)==0 )
                        goto end; /* drop the request */
                /* exec the onreply routing script */
-               if (onreply_rlist[DEFAULT_RT]){
-                       ret=run_actions(onreply_rlist[DEFAULT_RT], msg);
+               if (onreply_rt.rlist[DEFAULT_RT]){
+                       ret=run_actions(onreply_rt.rlist[DEFAULT_RT], msg);
                        if (ret<0){
                                LOG(L_WARN, "WARNING: receive_msg: "
                                                "error while trying onreply script\n");
diff --git a/route.c b/route.c
index f39f8aa..3f37a34 100644 (file)
--- a/route.c
+++ b/route.c
@@ -42,7 +42,8 @@
  *  2004-10-19  added from_uri & to_uri (andrei)
  *  2005-12-12  added retcode support (anrei)
  *  2005-12-19  select framework (mma)
- *  2006-01-30 removed rec. protection from eval_expr (andrei)
+ *  2006-01-30  removed rec. protection from eval_expr (andrei)
+ *  2006-02-06  added named route tables (andrei)
  */
 
 
 #include "mem/mem.h"
 #include "select.h"
 #include "onsend.h"
+#include "hashes.h"
+
+
+#define RT_HASH_SIZE   8 /* route names hash */
 
 /* main routing script table  */
-struct action* rlist[RT_NO];
-/* reply routing table */
-struct action* onreply_rlist[ONREPLY_RT_NO];
-struct action* failure_rlist[FAILURE_RT_NO];
-struct action* branch_rlist[BRANCH_RT_NO];
-struct action* onsend_rlist[ONSEND_RT_NO];
+struct route_list main_rt;
+struct route_list onreply_rt;
+struct route_list failure_rt;
+struct route_list branch_rt;
+struct route_list onsend_rt;
+
+
+
+inline static void destroy_rlist(struct route_list* rt)
+{
+       struct str_hash_entry* e;
+       struct str_hash_entry* tmp;
+
+       if (rt->rlist){
+               pkg_free(rt->rlist);
+               rt->rlist=0;
+               rt->entries=0;
+       }
+       if (rt->names.table){
+               clist_foreach_safe(rt->names.table, e, tmp, next){
+                       pkg_free(e);
+               }
+               pkg_free(rt->names.table);
+               rt->names.table=0;
+               rt->names.size=0;
+       }
+}
+
+
+
+void destroy_routes()
+{
+       destroy_rlist(&main_rt);
+       destroy_rlist(&onreply_rt);
+       destroy_rlist(&failure_rt);
+       destroy_rlist(&branch_rt);
+}
+
+
+
+/* adds route name -> i mapping
+ * WARNING: it doesn't check for pre-existing routes 
+ * return -1 on error, route index on success
+ */
+static int route_add(struct route_list* rt, char* name, int i)
+{
+       struct str_hash_entry* e;
+       
+       e=pkg_malloc(sizeof(struct str_hash_entry));
+       if (e==0){
+               LOG(L_CRIT, "ERROR: route_add: out of memory\n");
+               goto error;
+       }
+       e->key.s=name;
+       e->key.len=strlen(name);
+       e->flags=0;
+       e->u.n=i;
+       str_hash_add(&rt->names, e);
+       return 0;
+error:
+       return -1;
+}
+
+
+
+/* returns -1 on error, 0 on success */
+inline  static int init_rlist(char* r_name, struct route_list* rt,
+                                                               int n_entries, int hash_size)
+{
+               rt->rlist=pkg_malloc(sizeof(struct action*)*n_entries);
+               if (rt->rlist==0){ 
+                       LOG(L_CRIT, "ERROR: failed to allocate \"%s\" route tables: " 
+                                       "out of memory\n", r_name); 
+                       goto error; 
+               }
+               memset(rt->rlist, 0 , sizeof(struct action*)*n_entries);
+               rt->idx=1; /* idx=0 == default == reserved */
+               rt->entries=n_entries;
+               if (str_hash_alloc(&rt->names, hash_size)<0){
+                       LOG(L_CRIT, "ERROR: \"%s\" route table: failed to alloc hash\n",
+                                       r_name);
+                       goto error;
+               }
+               str_hash_init(&rt->names);
+               route_add(rt, "0", 0);  /* default route */
+               
+               return 0;
+error:
+               return -1;
+}
+
+
+
+/* init route tables */
+int init_routes()
+{
+       if (init_rlist("main", &main_rt, RT_NO, RT_HASH_SIZE)<0)
+               goto error;
+       if (init_rlist("on_reply", &onreply_rt, ONREPLY_RT_NO, RT_HASH_SIZE)<0)
+               goto error;
+       if (init_rlist("failure", &failure_rt, FAILURE_RT_NO, RT_HASH_SIZE)<0)
+               goto error;
+       if (init_rlist("branch", &branch_rt, BRANCH_RT_NO, RT_HASH_SIZE)<0)
+               goto error;
+       if (init_rlist("on_send", &onsend_rt, ONSEND_RT_NO, RT_HASH_SIZE)<0)
+               goto error;
+       return 0;
+error:
+       destroy_routes();
+       return -1;
+}
+
+
+
+static inline int route_new_list(struct route_list* rt)
+{
+       int ret;
+       struct action** tmp;
+       
+       ret=-1;
+       if (rt->idx >= rt->entries){
+               tmp=pkg_realloc(rt->rlist, 2*rt->entries*sizeof(struct action*));
+               if (tmp==0){
+                       LOG(L_CRIT, "ERROR: route_new_list: out of memory\n");
+                       goto end;
+               }
+               rt->rlist=tmp;
+               rt->entries*=2;
+       }
+       if (rt->idx<rt->entries){
+               ret=rt->idx;
+               rt->idx++;
+       }
+end:
+       return ret;
+}
+
+
+
+
+/* 
+ * if the "name" route already exists, return its index, else
+ * create a new empty route
+ * return route index in rt->rlist or -1 on error
+ */
+int route_get(struct route_list* rt, char* name)
+{
+       int len;
+       struct str_hash_entry* e;
+       int i;
+       
+       len=strlen(name);
+       /* check if exists an non empty*/
+       e=str_hash_get(&rt->names, name, len);
+       if (e){
+               i=e->u.n;
+       }else{
+               i=route_new_list(rt);
+               if (i==-1) goto error;
+               if (route_add(rt, name, i)<0){
+                       goto error;
+               }
+       }
+       return i;
+error:
+       return -1;
+}
+
+
 
 static int fix_actions(struct action* a); /*fwd declaration*/
 
@@ -983,42 +1151,14 @@ error:
 
 
 
-/* fixes all action tables */
-/* returns 0 if ok , <0 on error */
-int fix_rls()
+static int fix_rl(struct route_list* rt)
 {
-       int i,ret;
-       for(i=0;i<RT_NO;i++){
-               if(rlist[i]){
-                       if ((ret=fix_actions(rlist[i]))!=0){
-                               return ret;
-                       }
-               }
-       }
-       for(i=0;i<ONREPLY_RT_NO;i++){
-               if(onreply_rlist[i]){
-                       if ((ret=fix_actions(onreply_rlist[i]))!=0){
-                               return ret;
-                       }
-               }
-       }
-       for(i=0;i<FAILURE_RT_NO;i++){
-               if(failure_rlist[i]){
-                       if ((ret=fix_actions(failure_rlist[i]))!=0){
-                               return ret;
-                       }
-               }
-       }
-       for(i=0;i<BRANCH_RT_NO;i++){
-               if(branch_rlist[i]){
-                       if ((ret=fix_actions(branch_rlist[i]))!=0){
-                               return ret;
-                       }
-               }
-       }
-       for(i=0;i<ONSEND_RT_NO;i++){
-               if(onsend_rlist[i]){
-                       if ((ret=fix_actions(onsend_rlist[i]))!=0){
+       int i;
+       int ret;
+       
+       for(i=0;i<rt->idx; i++){
+               if(rt->rlist[i]){
+                       if ((ret=fix_actions(rt->rlist[i]))!=0){
                                return ret;
                        }
                }
@@ -1027,42 +1167,52 @@ int fix_rls()
 }
 
 
-/* debug function, prints main routing table */
-void print_rl()
+
+/* fixes all action tables */
+/* returns 0 if ok , <0 on error */
+int fix_rls()
 {
-       int j;
+       int ret;
+       
+       if ((ret=fix_rl(&main_rt))!=0)
+               return ret;
+       if ((ret=fix_rl(&onreply_rt))!=0)
+               return ret;
+       if ((ret=fix_rl(&failure_rt))!=0)
+               return ret;
+       if ((ret=fix_rl(&branch_rt))!=0)
+               return ret;
+       if ((ret=fix_rl(&onsend_rt))!=0)
+               return ret;
 
-       for(j=0; j<RT_NO; j++){
-               if (rlist[j]==0){
-                       if (j==0) DBG("WARNING: the main routing table is empty\n");
-                       continue;
-               }
-               DBG("routing table %d:\n",j);
-               print_actions(rlist[j]);
-               DBG("\n");
-       }
-       for(j=0; j<ONREPLY_RT_NO; j++){
-               if (onreply_rlist[j]==0){
-                       continue;
-               }
-               DBG("onreply routing table %d:\n",j);
-               print_actions(onreply_rlist[j]);
-               DBG("\n");
-       }
-       for(j=0; j<FAILURE_RT_NO; j++){
-               if (failure_rlist[j]==0){
-                       continue;
-               }
-               DBG("failure routing table %d:\n",j);
-               print_actions(failure_rlist[j]);
-               DBG("\n");
-       }
-       for(j=0; j<BRANCH_RT_NO; j++){
-               if (branch_rlist[j]==0){
+       return 0;
+}
+
+
+
+static void print_rl(struct route_list* rt, char* name)
+{
+       int j;
+       
+       for(j=0; j<rt->entries; j++){
+               if (rt->rlist[j]==0){
+                       if ((j==0) && (rt==&main_rt))
+                               DBG("WARNING: the main routing table is empty\n");
                        continue;
                }
-               DBG("branch routing table %d:\n",j);
-               print_actions(branch_rlist[j]);
+               DBG("%s routing table %d:\n", name, j);
+               print_actions(rt->rlist[j]);
                DBG("\n");
        }
 }
+
+
+/* debug function, prints routing tables */
+void print_rls()
+{
+       print_rl(&main_rt, "");
+       print_rl(&onreply_rt, "onreply");
+       print_rl(&failure_rt, "failure");
+       print_rl(&branch_rt, "branch");
+       print_rl(&onsend_rt, "onsend");
+}
diff --git a/route.h b/route.h
index dded8c5..0ce52b0 100644 (file)
--- a/route.h
+++ b/route.h
 #include "error.h"
 #include "route_struct.h"
 #include "parser/msg_parser.h"
+#include "hashes.h"
 
 /*#include "cfg_parser.h" */
 
 
+struct route_list{
+       struct action** rlist;
+       int idx; /* first empty entry */ 
+       int entries; /* total number if entries */
+       struct str_hash_table names; /* name to route index mappings */
+};
+
+
 /* main "script table" */
-extern struct action* rlist[RT_NO];
+extern struct route_list main_rt;
 /* main reply route table */
-extern struct action* onreply_rlist[ONREPLY_RT_NO];
-extern struct action* failure_rlist[FAILURE_RT_NO];
-extern struct action* branch_rlist[BRANCH_RT_NO];
-extern struct action* onsend_rlist[ONSEND_RT_NO];
+extern struct route_list onreply_rt;
+extern struct route_list failure_rt;
+extern struct route_list branch_rt;
+extern struct route_list onsend_rt;
+
 
+int init_routes();
+void destroy_routes();
+int route_get(struct route_list* rt, char* name);
 
 void push(struct action* a, struct action** head);
 int add_actions(struct action* a, struct action** head);
-void print_rl();
+void print_rls();
 int fix_rls();
 
 int eval_expr(struct expr* e, struct sip_msg* msg);
diff --git a/ut.h b/ut.h
index e667bd1..fcde1d8 100644 (file)
--- a/ut.h
+++ b/ut.h
@@ -220,12 +220,30 @@ static inline char* int2str_base(unsigned int l, int* len, int base)
         return int2str_base_0pad(l, len, base, 0);
 }
 
+
+
 /* returns a pointer to a static buffer containing l in asciiz & sets len */
 static inline char* int2str(unsigned int l, int* len)
 {
-     return int2str_base(l, len, 10);
+       static char r[INT2STR_MAX_LEN];
+       int i;
+       
+       i=INT2STR_MAX_LEN-2;
+       r[INT2STR_MAX_LEN-1]=0; /* null terminate */
+       do{
+               r[i]=l%10+'0';
+               i--;
+               l/=10;
+       }while(l && (i>=0));
+       if (l && (i<0)){
+               LOG(L_CRIT, "BUG: int2str: overflow\n");
+       }
+       if (len) *len=(INT2STR_MAX_LEN-2)-i;
+       return &r[i+1];
 }
 
+
+
 /* faster memchr version */
 static inline char* q_memchr(char* p, int c, unsigned int size)
 {