Browse code

- named routes support in core and tm (t_on_*). 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);

Andrei Pelinescu-Onciul authored on 07/02/2006 01:14:57
Showing 12 changed files
... ...
@@ -394,14 +394,14 @@ int do_action(struct action* a, struct sip_msg* msg)
394 394
 				ret=E_BUG;
395 395
 				break;
396 396
 			}
397
-			if ((a->val[0].u.number>RT_NO)||(a->val[0].u.number<0)){
397
+			if ((a->val[0].u.number>=main_rt.idx)||(a->val[0].u.number<0)){
398 398
 				LOG(L_ERR, "ERROR: invalid routing table number in"
399 399
 							"route(%lu)\n", a->val[0].u.number);
400 400
 				ret=E_CFG;
401 401
 				break;
402 402
 			}
403 403
 			/*ret=((ret=run_actions(rlist[a->val[0].u.number], msg))<0)?ret:1;*/
404
-			ret=run_actions(rlist[a->val[0].u.number], msg);
404
+			ret=run_actions(main_rt.rlist[a->val[0].u.number], msg);
405 405
 			last_retcode=ret;
406 406
 			run_flags&=~RETURN_R_F; /* absorb returns */
407 407
 			break;
... ...
@@ -70,6 +70,7 @@
70 70
  * 2006-01-06  AVP index support (mma)
71 71
  * 2005-01-07  optional semicolon in statement, PARAM_STR&PARAM_STRING
72 72
  * 2006-02-02  named flags support (andrei)
73
+ * 2006-02-06  named routes support (andrei)
73 74
  */
74 75
 
75 76
 %{
... ...
@@ -349,6 +350,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
349 349
 %type <intval> assign_op
350 350
 %type <select> select_id
351 351
 %type <strval>	flag_name;
352
+%type <strval>	route_name;
352 353
 
353 354
 /*%type <route_el> rules;
354 355
   %type <route_el> rule;
... ...
@@ -851,61 +853,106 @@ ipv6:
851 851
 	ipv6addr { $$=$1; }
852 852
 	| LBRACK ipv6addr RBRACK {$$=$2; }
853 853
 ;
854
+
855
+
856
+route_name:		NUMBER	{
857
+					tmp=int2str($1, &i_tmp);
858
+					if (($$=pkg_malloc(i_tmp+1))==0) {
859
+						yyerror("out of  memory");
860
+						YYABORT;
861
+					} else {
862
+						memcpy($$, tmp, i_tmp);
863
+						$$[i_tmp]=0;
864
+					}
865
+						}
866
+			|	ID		{ $$=$1; }
867
+			|	STRING	{ $$=$1; }
868
+;
869
+
854 870
 route_stm:
855
-	ROUTE LBRACE actions RBRACE { push($3, &rlist[DEFAULT_RT]); }
856
-	| ROUTE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
857
-		if (($3<RT_NO) && ($3>=0)) {
858
-			push($6, &rlist[$3]);
859
-		} else {
860
-			yyerror("invalid routing table number");
871
+	ROUTE LBRACE actions RBRACE { push($3, &main_rt.rlist[DEFAULT_RT]); }
872
+	| ROUTE LBRACK route_name RBRACK LBRACE actions RBRACE {
873
+		i_tmp=route_get(&main_rt, $3);
874
+		if (i_tmp==-1){
875
+			yyerror("internal error");
876
+			YYABORT;
877
+		}
878
+		if (main_rt.rlist[i_tmp]){
879
+			yyerror("duplicate route");
861 880
 			YYABORT;
862 881
 		}
882
+		push($6, &main_rt.rlist[i_tmp]);
863 883
 	}
864 884
 	| ROUTE error { yyerror("invalid  route  statement"); }
865 885
 	;
866 886
 failure_route_stm:
867
-	ROUTE_FAILURE LBRACK NUMBER RBRACK LBRACE actions RBRACE {
868
-		if (($3<FAILURE_RT_NO)&&($3>=1)) {
869
-			push($6, &failure_rlist[$3]);
870
-		} else {
871
-			yyerror("invalid reply routing table number");
887
+	ROUTE_FAILURE LBRACE actions RBRACE { 
888
+									push($3, &failure_rt.rlist[DEFAULT_RT]);
889
+										}
890
+	| ROUTE_FAILURE LBRACK route_name RBRACK LBRACE actions RBRACE {
891
+		i_tmp=route_get(&failure_rt, $3);
892
+		if (i_tmp==-1){
893
+			yyerror("internal error");
894
+			YYABORT;
895
+		}
896
+		if (failure_rt.rlist[i_tmp]){
897
+			yyerror("duplicate route");
872 898
 			YYABORT;
873 899
 		}
900
+		push($6, &failure_rt.rlist[i_tmp]);
874 901
 	}
875 902
 	| ROUTE_FAILURE error { yyerror("invalid failure_route statement"); }
876 903
 	;
877 904
 onreply_route_stm:
878
-	ROUTE_ONREPLY LBRACE actions RBRACE { push($3, &onreply_rlist[DEFAULT_RT]); }
879
-	| ROUTE_ONREPLY LBRACK NUMBER RBRACK LBRACE actions RBRACE {
880
-		if (($3<ONREPLY_RT_NO)&&($3>=1)) {
881
-			push($6, &onreply_rlist[$3]);
882
-		} else {
883
-			yyerror("invalid reply routing table number");
905
+	ROUTE_ONREPLY LBRACE actions RBRACE {
906
+									push($3, &onreply_rt.rlist[DEFAULT_RT]);
907
+										}
908
+	| ROUTE_ONREPLY LBRACK route_name RBRACK LBRACE actions RBRACE {
909
+		i_tmp=route_get(&onreply_rt, $3);
910
+		if (i_tmp==-1){
911
+			yyerror("internal error");
912
+			YYABORT;
913
+		}
914
+		if (onreply_rt.rlist[i_tmp]){
915
+			yyerror("duplicate route");
884 916
 			YYABORT;
885 917
 		}
918
+		push($6, &onreply_rt.rlist[i_tmp]);
886 919
 	}
887 920
 	| ROUTE_ONREPLY error { yyerror("invalid onreply_route statement"); }
888 921
 	;
889 922
 branch_route_stm:
890
-	ROUTE_BRANCH LBRACE actions RBRACE { push($3, &branch_rlist[DEFAULT_RT]); }
891
-	| ROUTE_BRANCH LBRACK NUMBER RBRACK LBRACE actions RBRACE {
892
-		if (($3<BRANCH_RT_NO)&&($3>=1)) {
893
-			push($6, &branch_rlist[$3]);
894
-		} else {
895
-			yyerror("invalid branch routing table number");
923
+	ROUTE_BRANCH LBRACE actions RBRACE { 
924
+									push($3, &branch_rt.rlist[DEFAULT_RT]);
925
+										}
926
+	| ROUTE_BRANCH LBRACK route_name RBRACK LBRACE actions RBRACE {
927
+		i_tmp=route_get(&branch_rt, $3);
928
+		if (i_tmp==-1){
929
+			yyerror("internal error");
896 930
 			YYABORT;
897 931
 		}
932
+		if (branch_rt.rlist[i_tmp]){
933
+			yyerror("duplicate route");
934
+			YYABORT;
935
+		}
936
+		push($6, &branch_rt.rlist[i_tmp]);
898 937
 	}
899 938
 	| ROUTE_BRANCH error { yyerror("invalid branch_route statement"); }
900 939
 	;
901
-send_route_stm: ROUTE_SEND LBRACE actions RBRACE {push($3, &onsend_rlist[DEFAULT_RT]); }
902
-	| ROUTE_SEND LBRACK NUMBER RBRACK LBRACE actions RBRACE {
903
-		if (($3<ONSEND_RT_NO)&&($3>=1)) {
904
-			push($6, &onsend_rlist[$3]);
905
-		} else {
906
-			yyerror("invalid onsend routing table number");
940
+send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
941
+									push($3, &onsend_rt.rlist[DEFAULT_RT]);
942
+												}
943
+	| ROUTE_SEND LBRACK route_name RBRACK LBRACE actions RBRACE {
944
+		i_tmp=route_get(&onsend_rt, $3);
945
+		if (i_tmp==-1){
946
+			yyerror("internal error");
947
+			YYABORT;
948
+		}
949
+		if (onsend_rt.rlist[i_tmp]){
950
+			yyerror("duplicate route");
907 951
 			YYABORT;
908 952
 		}
953
+		push($6, &onsend_rt.rlist[i_tmp]);
909 954
 	}
910 955
 	| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
911 956
 	;
... ...
@@ -1544,7 +1591,14 @@ cmd:
1544 1544
 	| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T, 2, STRING_ST, $3, STRING_ST, $5); }
1545 1545
 	| ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
1546 1546
 	| ERROR LPAREN error RPAREN { $$=0; yyerror("bad error argument"); }
1547
-	| ROUTE LPAREN NUMBER RPAREN	{ $$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)$3); }
1547
+	| ROUTE LPAREN route_name RPAREN	{ 
1548
+						i_tmp=route_get(&main_rt, $3);
1549
+						if (i_tmp==-1){
1550
+							yyerror("internal error");
1551
+							YYABORT;
1552
+						}
1553
+						$$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)i_tmp); 
1554
+										}
1548 1555
 	| ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
1549 1556
 	| ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route argument"); }
1550 1557
 	| EXEC LPAREN STRING RPAREN	{ $$=mk_action(EXEC_T, 1, STRING_ST, $3); }
... ...
@@ -165,7 +165,7 @@ inline static struct str_hash_entry* str_hash_get(struct str_hash_table* ht,
165 165
 	int h;
166 166
 	struct str_hash_entry* e;
167 167
 	
168
-	h=get_hash1_raw(e->key.s, e->key.len) % ht->size;
168
+	h=get_hash1_raw(key, len) % ht->size;
169 169
 	clist_foreach(&ht->table[h], e, next){
170 170
 		if ((e->key.len==len) && (memcmp(e->key.s, key, len)==0))
171 171
 			return e;
... ...
@@ -389,6 +389,7 @@ void cleanup(show_status)
389 389
 #endif
390 390
 	destroy_timer();
391 391
 	destroy_script_cb();
392
+	destroy_routes();
392 393
 #ifdef PKG_MALLOC
393 394
 	if (show_status){
394 395
 		LOG(memlog, "Memory status (pkg):\n");
... ...
@@ -1306,7 +1307,8 @@ int main(int argc, char** argv)
1306 1306
 					abort();
1307 1307
 		}
1308 1308
 	}
1309
-
1309
+	
1310
+	if (init_routes()<0) goto error;
1310 1311
 	/* fill missing arguments with the default values*/
1311 1312
 	if (cfg_file==0) cfg_file=CFG_FILE;
1312 1313
 
... ...
@@ -1351,7 +1353,7 @@ try_again:
1351 1351
 		goto error;
1352 1352
 	}
1353 1353
 	if (debug_flag) debug = debug_save;
1354
-	print_rl();
1354
+	print_rls();
1355 1355
 
1356 1356
 	/* options with higher priority than cfg file */
1357 1357
 	optind = 1;  /* reset getopt */
... ...
@@ -47,6 +47,7 @@
47 47
  *  2005-12-11  onsend_route support added for forwarding (andrei)
48 48
  *  2006-01-27  t_forward_no_ack will return error if a forward on an 
49 49
  *              already canceled transaction is attempted (andrei)
50
+ *  2006-02-07  named routes support (andrei)
50 51
  */
51 52
 
52 53
 #include "defs.h"
... ...
@@ -128,7 +129,7 @@ char *print_uac_request( struct cell *t, struct sip_msg *i_req,
128 128
 
129 129
 	if (branch_route) {
130 130
 		     /* run branch_route actions if provided */
131
-		if (run_actions(branch_rlist[branch_route], i_req) < 0) {
131
+		if (run_actions(branch_rt.rlist[branch_route], i_req) < 0) {
132 132
 			LOG(L_ERR, "ERROR: print_uac_request: Error in run_actions\n");
133 133
                }
134 134
 	}
... ...
@@ -67,6 +67,7 @@
67 67
  *  2005-09-01  reverted to the old way of checking response.dst.send_sock
68 68
  *               in t_retransmit_reply & reply_light (andrei)
69 69
  *  2005-11-09  updated to the new timers interface (andrei)
70
+ *  2006-02-07  named routes support (andrei)
70 71
  */
71 72
 
72 73
 
... ...
@@ -653,7 +654,7 @@ static inline int run_failure_handlers(struct cell *t, struct sip_msg *rpl,
653 653
 		on_failure = t->on_negative;
654 654
 		t->on_negative=0;
655 655
 		/* run a reply_route action if some was marked */
656
-		if (run_actions(failure_rlist[on_failure], &faked_req)<0)
656
+		if (run_actions(failure_rt.rlist[on_failure], &faked_req)<0)
657 657
 			LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n");
658 658
 	}
659 659
 
... ...
@@ -1342,7 +1343,7 @@ int reply_received( struct sip_msg  *p_msg )
1342 1342
 		if (t->uas.request) p_msg->flags=t->uas.request->flags;
1343 1343
 		/* set the as avp_list the one from transaction */
1344 1344
 		backup_list = set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps );
1345
-		if (run_actions(onreply_rlist[t->on_reply], p_msg)<0)
1345
+		if (run_actions(onreply_rt.rlist[t->on_reply], p_msg)<0)
1346 1346
 			LOG(L_ERR, "ERROR: on_reply processing failed\n");
1347 1347
 		/* transfer current message context back to t */
1348 1348
 		if (t->uas.request) t->uas.request->flags=p_msg->flags;
... ...
@@ -76,6 +76,7 @@
76 76
  *  2005-12-09  fixup_hostport2proxy uses route_struct to access param #1
77 77
  *              when fixing param #2
78 78
  *  2005-12-09  added t_set_fr() (andrei)
79
+ *  2006-02-07  named routes support (andrei)
79 80
  */
80 81
 
81 82
 
... ...
@@ -94,6 +95,7 @@
94 94
 #include "../../usr_avp.h"
95 95
 #include "../../mem/mem.h"
96 96
 #include "../../route_struct.h"
97
+#include "../../route.h"
97 98
 
98 99
 #include "sip_msg.h"
99 100
 #include "h_table.h"
... ...
@@ -114,6 +116,9 @@ MODULE_VERSION
114 114
 
115 115
 /* fixup functions */
116 116
 static int fixup_hostport2proxy(void** param, int param_no);
117
+static int fixup_on_failure(void** param, int param_no);
118
+static int fixup_on_reply(void** param, int param_no);
119
+static int fixup_on_branch(void** param, int param_no);
117 120
 
118 121
 
119 122
 /* init functions */
... ...
@@ -226,11 +231,11 @@ static cmd_export_t cmds[]={
226 226
 	{T_FORWARD_NONACK_TLS, w_t_forward_nonack_tls,  2, fixup_hostport2proxy,
227 227
 			REQUEST_ROUTE},
228 228
 #endif
229
-	{"t_on_failure",       w_t_on_negative,         1, fixup_int_1,
229
+	{"t_on_failure",       w_t_on_negative,         1, fixup_on_failure,
230 230
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
231
-	{"t_on_reply",         w_t_on_reply,            1, fixup_int_1,
231
+	{"t_on_reply",         w_t_on_reply,            1, fixup_on_reply,
232 232
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
233
-	{"t_on_branch",       w_t_on_branch,         1, fixup_int_1,
233
+	{"t_on_branch",       w_t_on_branch,         1, fixup_on_branch,
234 234
 			REQUEST_ROUTE | FAILURE_ROUTE },
235 235
 	{"t_check_status",     t_check_status,          1, fixup_regex_1,
236 236
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
... ...
@@ -308,6 +313,57 @@ struct module_exports exports= {
308 308
 };
309 309
 
310 310
 
311
+
312
+/* helper for fixup_on_* */
313
+static int fixup_routes(char* r_type, struct route_list* rt, void** param)
314
+{
315
+	int i;
316
+	
317
+	i=route_get(rt, (char*)*param);
318
+	if (i==-1){
319
+		LOG(L_ERR, "ERROR: tm: fixup_routes: route_get failed\n");
320
+		return E_UNSPEC;
321
+	}
322
+	if (rt->rlist[i]==0){
323
+		LOG(L_WARN, "WARNING: %s(\"%s\"): empty/non existing route\n",
324
+				r_type, (char*)*param);
325
+	}
326
+	*param=(void*)(long)i;
327
+	return 0;
328
+}
329
+
330
+
331
+
332
+static int fixup_on_failure(void** param, int param_no)
333
+{
334
+	if (param_no==1){
335
+		return fixup_routes("t_on_failure", &failure_rt, param);
336
+	}
337
+	return 0;
338
+}
339
+
340
+
341
+
342
+static int fixup_on_reply(void** param, int param_no)
343
+{
344
+	if (param_no==1){
345
+		return fixup_routes("t_on_reply", &onreply_rt, param);
346
+	}
347
+	return 0;
348
+}
349
+
350
+
351
+
352
+static int fixup_on_branch(void** param, int param_no)
353
+{
354
+	if (param_no==1){
355
+		return fixup_routes("t_on_branch", &branch_rt, param);
356
+	}
357
+	return 0;
358
+}
359
+
360
+
361
+
311 362
 /* (char *hostname, char *port_nr) ==> (struct proxy_l *, -)  */
312 363
 static int fixup_hostport2proxy(void** param, int param_no)
313 364
 {
... ...
@@ -62,13 +62,13 @@ static inline int run_onsend(struct sip_msg* orig_msg,
62 62
 	int ret;
63 63
 	
64 64
 	ret=1;
65
-	if (onsend_rlist[DEFAULT_RT]){
65
+	if (onsend_rt.rlist[DEFAULT_RT]){
66 66
 		onsnd_info.to=to;
67 67
 		onsnd_info.send_sock=send_sock;
68 68
 		onsnd_info.buf=buf;
69 69
 		onsnd_info.len=len;
70 70
 		p_onsend=&onsnd_info;
71
-		ret=run_actions(onsend_rlist[DEFAULT_RT], orig_msg);
71
+		ret=run_actions(onsend_rt.rlist[DEFAULT_RT], orig_msg);
72 72
 		p_onsend=0; /* reset it */
73 73
 	}
74 74
 	return ret;
... ...
@@ -162,7 +162,7 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
162 162
 			goto end; /* drop the request */
163 163
 
164 164
 		/* exec the routing script */
165
-		if (run_actions(rlist[DEFAULT_RT], msg)<0){
165
+		if (run_actions(main_rt.rlist[DEFAULT_RT], msg)<0){
166 166
 			LOG(L_WARN, "WARNING: receive_msg: "
167 167
 					"error while trying script\n");
168 168
 			goto error_req;
... ...
@@ -202,8 +202,8 @@ int receive_msg(char* buf, unsigned int len, struct receive_info* rcv_info)
202 202
 		if (exec_pre_rpl_cb(msg)==0 )
203 203
 			goto end; /* drop the request */
204 204
 		/* exec the onreply routing script */
205
-		if (onreply_rlist[DEFAULT_RT]){
206
-			ret=run_actions(onreply_rlist[DEFAULT_RT], msg);
205
+		if (onreply_rt.rlist[DEFAULT_RT]){
206
+			ret=run_actions(onreply_rt.rlist[DEFAULT_RT], msg);
207 207
 			if (ret<0){
208 208
 				LOG(L_WARN, "WARNING: receive_msg: "
209 209
 						"error while trying onreply script\n");
... ...
@@ -42,7 +42,8 @@
42 42
  *  2004-10-19  added from_uri & to_uri (andrei)
43 43
  *  2005-12-12  added retcode support (anrei)
44 44
  *  2005-12-19  select framework (mma)
45
- *  2006-01-30 removed rec. protection from eval_expr (andrei)
45
+ *  2006-01-30  removed rec. protection from eval_expr (andrei)
46
+ *  2006-02-06  added named route tables (andrei)
46 47
  */
47 48
 
48 49
 
... ...
@@ -71,14 +72,181 @@
71 71
 #include "mem/mem.h"
72 72
 #include "select.h"
73 73
 #include "onsend.h"
74
+#include "hashes.h"
75
+
76
+
77
+#define RT_HASH_SIZE	8 /* route names hash */
74 78
 
75 79
 /* main routing script table  */
76
-struct action* rlist[RT_NO];
77
-/* reply routing table */
78
-struct action* onreply_rlist[ONREPLY_RT_NO];
79
-struct action* failure_rlist[FAILURE_RT_NO];
80
-struct action* branch_rlist[BRANCH_RT_NO];
81
-struct action* onsend_rlist[ONSEND_RT_NO];
80
+struct route_list main_rt;
81
+struct route_list onreply_rt;
82
+struct route_list failure_rt;
83
+struct route_list branch_rt;
84
+struct route_list onsend_rt;
85
+
86
+
87
+
88
+inline static void destroy_rlist(struct route_list* rt)
89
+{
90
+	struct str_hash_entry* e;
91
+	struct str_hash_entry* tmp;
92
+
93
+	if (rt->rlist){
94
+		pkg_free(rt->rlist);
95
+		rt->rlist=0;
96
+		rt->entries=0;
97
+	}
98
+	if (rt->names.table){
99
+		clist_foreach_safe(rt->names.table, e, tmp, next){
100
+			pkg_free(e);
101
+		}
102
+		pkg_free(rt->names.table);
103
+		rt->names.table=0;
104
+		rt->names.size=0;
105
+	}
106
+}
107
+
108
+
109
+
110
+void destroy_routes()
111
+{
112
+	destroy_rlist(&main_rt);
113
+	destroy_rlist(&onreply_rt);
114
+	destroy_rlist(&failure_rt);
115
+	destroy_rlist(&branch_rt);
116
+}
117
+
118
+
119
+
120
+/* adds route name -> i mapping
121
+ * WARNING: it doesn't check for pre-existing routes 
122
+ * return -1 on error, route index on success
123
+ */
124
+static int route_add(struct route_list* rt, char* name, int i)
125
+{
126
+	struct str_hash_entry* e;
127
+	
128
+	e=pkg_malloc(sizeof(struct str_hash_entry));
129
+	if (e==0){
130
+		LOG(L_CRIT, "ERROR: route_add: out of memory\n");
131
+		goto error;
132
+	}
133
+	e->key.s=name;
134
+	e->key.len=strlen(name);
135
+	e->flags=0;
136
+	e->u.n=i;
137
+	str_hash_add(&rt->names, e);
138
+	return 0;
139
+error:
140
+	return -1;
141
+}
142
+
143
+
144
+
145
+/* returns -1 on error, 0 on success */
146
+inline  static int init_rlist(char* r_name, struct route_list* rt,
147
+								int n_entries, int hash_size)
148
+{
149
+		rt->rlist=pkg_malloc(sizeof(struct action*)*n_entries);
150
+		if (rt->rlist==0){ 
151
+			LOG(L_CRIT, "ERROR: failed to allocate \"%s\" route tables: " 
152
+					"out of memory\n", r_name); 
153
+			goto error; 
154
+		}
155
+		memset(rt->rlist, 0 , sizeof(struct action*)*n_entries);
156
+		rt->idx=1; /* idx=0 == default == reserved */
157
+		rt->entries=n_entries;
158
+		if (str_hash_alloc(&rt->names, hash_size)<0){
159
+			LOG(L_CRIT, "ERROR: \"%s\" route table: failed to alloc hash\n",
160
+					r_name);
161
+			goto error;
162
+		}
163
+		str_hash_init(&rt->names);
164
+		route_add(rt, "0", 0);  /* default route */
165
+		
166
+		return 0;
167
+error:
168
+		return -1;
169
+}
170
+
171
+
172
+
173
+/* init route tables */
174
+int init_routes()
175
+{
176
+	if (init_rlist("main", &main_rt, RT_NO, RT_HASH_SIZE)<0)
177
+		goto error;
178
+	if (init_rlist("on_reply", &onreply_rt, ONREPLY_RT_NO, RT_HASH_SIZE)<0)
179
+		goto error;
180
+	if (init_rlist("failure", &failure_rt, FAILURE_RT_NO, RT_HASH_SIZE)<0)
181
+		goto error;
182
+	if (init_rlist("branch", &branch_rt, BRANCH_RT_NO, RT_HASH_SIZE)<0)
183
+		goto error;
184
+	if (init_rlist("on_send", &onsend_rt, ONSEND_RT_NO, RT_HASH_SIZE)<0)
185
+		goto error;
186
+	return 0;
187
+error:
188
+	destroy_routes();
189
+	return -1;
190
+}
191
+
192
+
193
+
194
+static inline int route_new_list(struct route_list* rt)
195
+{
196
+	int ret;
197
+	struct action** tmp;
198
+	
199
+	ret=-1;
200
+	if (rt->idx >= rt->entries){
201
+		tmp=pkg_realloc(rt->rlist, 2*rt->entries*sizeof(struct action*));
202
+		if (tmp==0){
203
+			LOG(L_CRIT, "ERROR: route_new_list: out of memory\n");
204
+			goto end;
205
+		}
206
+		rt->rlist=tmp;
207
+		rt->entries*=2;
208
+	}
209
+	if (rt->idx<rt->entries){
210
+		ret=rt->idx;
211
+		rt->idx++;
212
+	}
213
+end:
214
+	return ret;
215
+}
216
+
217
+
218
+
219
+
220
+/* 
221
+ * if the "name" route already exists, return its index, else
222
+ * create a new empty route
223
+ * return route index in rt->rlist or -1 on error
224
+ */
225
+int route_get(struct route_list* rt, char* name)
226
+{
227
+	int len;
228
+	struct str_hash_entry* e;
229
+	int i;
230
+	
231
+	len=strlen(name);
232
+	/* check if exists an non empty*/
233
+	e=str_hash_get(&rt->names, name, len);
234
+	if (e){
235
+		i=e->u.n;
236
+	}else{
237
+		i=route_new_list(rt);
238
+		if (i==-1) goto error;
239
+		if (route_add(rt, name, i)<0){
240
+			goto error;
241
+		}
242
+	}
243
+	return i;
244
+error:
245
+	return -1;
246
+}
247
+
248
+
82 249
 
83 250
 static int fix_actions(struct action* a); /*fwd declaration*/
84 251
 
... ...
@@ -983,42 +1151,14 @@ error:
983 983
 
984 984
 
985 985
 
986
-/* fixes all action tables */
987
-/* returns 0 if ok , <0 on error */
988
-int fix_rls()
986
+static int fix_rl(struct route_list* rt)
989 987
 {
990
-	int i,ret;
991
-	for(i=0;i<RT_NO;i++){
992
-		if(rlist[i]){
993
-			if ((ret=fix_actions(rlist[i]))!=0){
994
-				return ret;
995
-			}
996
-		}
997
-	}
998
-	for(i=0;i<ONREPLY_RT_NO;i++){
999
-		if(onreply_rlist[i]){
1000
-			if ((ret=fix_actions(onreply_rlist[i]))!=0){
1001
-				return ret;
1002
-			}
1003
-		}
1004
-	}
1005
-	for(i=0;i<FAILURE_RT_NO;i++){
1006
-		if(failure_rlist[i]){
1007
-			if ((ret=fix_actions(failure_rlist[i]))!=0){
1008
-				return ret;
1009
-			}
1010
-		}
1011
-	}
1012
-	for(i=0;i<BRANCH_RT_NO;i++){
1013
-		if(branch_rlist[i]){
1014
-			if ((ret=fix_actions(branch_rlist[i]))!=0){
1015
-				return ret;
1016
-			}
1017
-		}
1018
-	}
1019
-	for(i=0;i<ONSEND_RT_NO;i++){
1020
-		if(onsend_rlist[i]){
1021
-			if ((ret=fix_actions(onsend_rlist[i]))!=0){
988
+	int i;
989
+	int ret;
990
+	
991
+	for(i=0;i<rt->idx; i++){
992
+		if(rt->rlist[i]){
993
+			if ((ret=fix_actions(rt->rlist[i]))!=0){
1022 994
 				return ret;
1023 995
 			}
1024 996
 		}
... ...
@@ -1027,42 +1167,52 @@ int fix_rls()
1027 1027
 }
1028 1028
 
1029 1029
 
1030
-/* debug function, prints main routing table */
1031
-void print_rl()
1030
+
1031
+/* fixes all action tables */
1032
+/* returns 0 if ok , <0 on error */
1033
+int fix_rls()
1032 1034
 {
1033
-	int j;
1035
+	int ret;
1036
+	
1037
+	if ((ret=fix_rl(&main_rt))!=0)
1038
+		return ret;
1039
+	if ((ret=fix_rl(&onreply_rt))!=0)
1040
+		return ret;
1041
+	if ((ret=fix_rl(&failure_rt))!=0)
1042
+		return ret;
1043
+	if ((ret=fix_rl(&branch_rt))!=0)
1044
+		return ret;
1045
+	if ((ret=fix_rl(&onsend_rt))!=0)
1046
+		return ret;
1034 1047
 
1035
-	for(j=0; j<RT_NO; j++){
1036
-		if (rlist[j]==0){
1037
-			if (j==0) DBG("WARNING: the main routing table is empty\n");
1038
-			continue;
1039
-		}
1040
-		DBG("routing table %d:\n",j);
1041
-		print_actions(rlist[j]);
1042
-		DBG("\n");
1043
-	}
1044
-	for(j=0; j<ONREPLY_RT_NO; j++){
1045
-		if (onreply_rlist[j]==0){
1046
-			continue;
1047
-		}
1048
-		DBG("onreply routing table %d:\n",j);
1049
-		print_actions(onreply_rlist[j]);
1050
-		DBG("\n");
1051
-	}
1052
-	for(j=0; j<FAILURE_RT_NO; j++){
1053
-		if (failure_rlist[j]==0){
1054
-			continue;
1055
-		}
1056
-		DBG("failure routing table %d:\n",j);
1057
-		print_actions(failure_rlist[j]);
1058
-		DBG("\n");
1059
-	}
1060
-	for(j=0; j<BRANCH_RT_NO; j++){
1061
-		if (branch_rlist[j]==0){
1048
+	return 0;
1049
+}
1050
+
1051
+
1052
+
1053
+static void print_rl(struct route_list* rt, char* name)
1054
+{
1055
+	int j;
1056
+	
1057
+	for(j=0; j<rt->entries; j++){
1058
+		if (rt->rlist[j]==0){
1059
+			if ((j==0) && (rt==&main_rt))
1060
+				DBG("WARNING: the main routing table is empty\n");
1062 1061
 			continue;
1063 1062
 		}
1064
-		DBG("branch routing table %d:\n",j);
1065
-		print_actions(branch_rlist[j]);
1063
+		DBG("%s routing table %d:\n", name, j);
1064
+		print_actions(rt->rlist[j]);
1066 1065
 		DBG("\n");
1067 1066
 	}
1068 1067
 }
1068
+
1069
+
1070
+/* debug function, prints routing tables */
1071
+void print_rls()
1072
+{
1073
+	print_rl(&main_rt, "");
1074
+	print_rl(&onreply_rt, "onreply");
1075
+	print_rl(&failure_rt, "failure");
1076
+	print_rl(&branch_rt, "branch");
1077
+	print_rl(&onsend_rt, "onsend");
1078
+}
... ...
@@ -37,22 +37,35 @@
37 37
 #include "error.h"
38 38
 #include "route_struct.h"
39 39
 #include "parser/msg_parser.h"
40
+#include "hashes.h"
40 41
 
41 42
 /*#include "cfg_parser.h" */
42 43
 
43 44
 
45
+struct route_list{
46
+	struct action** rlist;
47
+	int idx; /* first empty entry */ 
48
+	int entries; /* total number if entries */
49
+	struct str_hash_table names; /* name to route index mappings */
50
+};
51
+
52
+
44 53
 /* main "script table" */
45
-extern struct action* rlist[RT_NO];
54
+extern struct route_list main_rt;
46 55
 /* main reply route table */
47
-extern struct action* onreply_rlist[ONREPLY_RT_NO];
48
-extern struct action* failure_rlist[FAILURE_RT_NO];
49
-extern struct action* branch_rlist[BRANCH_RT_NO];
50
-extern struct action* onsend_rlist[ONSEND_RT_NO];
56
+extern struct route_list onreply_rt;
57
+extern struct route_list failure_rt;
58
+extern struct route_list branch_rt;
59
+extern struct route_list onsend_rt;
60
+
51 61
 
62
+int init_routes();
63
+void destroy_routes();
64
+int route_get(struct route_list* rt, char* name);
52 65
 
53 66
 void push(struct action* a, struct action** head);
54 67
 int add_actions(struct action* a, struct action** head);
55
-void print_rl();
68
+void print_rls();
56 69
 int fix_rls();
57 70
 
58 71
 int eval_expr(struct expr* e, struct sip_msg* msg);
... ...
@@ -220,12 +220,30 @@ static inline char* int2str_base(unsigned int l, int* len, int base)
220 220
         return int2str_base_0pad(l, len, base, 0);
221 221
 }
222 222
 
223
+
224
+
223 225
 /* returns a pointer to a static buffer containing l in asciiz & sets len */
224 226
 static inline char* int2str(unsigned int l, int* len)
225 227
 {
226
-     return int2str_base(l, len, 10);
228
+	static char r[INT2STR_MAX_LEN];
229
+	int i;
230
+	
231
+	i=INT2STR_MAX_LEN-2;
232
+	r[INT2STR_MAX_LEN-1]=0; /* null terminate */
233
+	do{
234
+		r[i]=l%10+'0';
235
+		i--;
236
+		l/=10;
237
+	}while(l && (i>=0));
238
+	if (l && (i<0)){
239
+		LOG(L_CRIT, "BUG: int2str: overflow\n");
240
+	}
241
+	if (len) *len=(INT2STR_MAX_LEN-2)-i;
242
+	return &r[i+1];
227 243
 }
228 244
 
245
+
246
+
229 247
 /* faster memchr version */
230 248
 static inline char* q_memchr(char* p, int c, unsigned int size)
231 249
 {