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 350
 %type <intval> assign_op
350 351
 %type <select> select_id
351 352
 %type <strval>	flag_name;
353
+%type <strval>	route_name;
352 354
 
353 355
 /*%type <route_el> rules;
354 356
   %type <route_el> rule;
... ...
@@ -851,61 +853,106 @@ ipv6:
851 853
 	ipv6addr { $$=$1; }
852 854
 	| LBRACK ipv6addr RBRACK {$$=$2; }
853 855
 ;
856
+
857
+
858
+route_name:		NUMBER	{
859
+					tmp=int2str($1, &i_tmp);
860
+					if (($$=pkg_malloc(i_tmp+1))==0) {
861
+						yyerror("out of  memory");
862
+						YYABORT;
863
+					} else {
864
+						memcpy($$, tmp, i_tmp);
865
+						$$[i_tmp]=0;
866
+					}
867
+						}
868
+			|	ID		{ $$=$1; }
869
+			|	STRING	{ $$=$1; }
870
+;
871
+
854 872
 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");
873
+	ROUTE LBRACE actions RBRACE { push($3, &main_rt.rlist[DEFAULT_RT]); }
874
+	| ROUTE LBRACK route_name RBRACK LBRACE actions RBRACE {
875
+		i_tmp=route_get(&main_rt, $3);
876
+		if (i_tmp==-1){
877
+			yyerror("internal error");
878
+			YYABORT;
879
+		}
880
+		if (main_rt.rlist[i_tmp]){
881
+			yyerror("duplicate route");
861 882
 			YYABORT;
862 883
 		}
884
+		push($6, &main_rt.rlist[i_tmp]);
863 885
 	}
864 886
 	| ROUTE error { yyerror("invalid  route  statement"); }
865 887
 	;
866 888
 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");
889
+	ROUTE_FAILURE LBRACE actions RBRACE { 
890
+									push($3, &failure_rt.rlist[DEFAULT_RT]);
891
+										}
892
+	| ROUTE_FAILURE LBRACK route_name RBRACK LBRACE actions RBRACE {
893
+		i_tmp=route_get(&failure_rt, $3);
894
+		if (i_tmp==-1){
895
+			yyerror("internal error");
896
+			YYABORT;
897
+		}
898
+		if (failure_rt.rlist[i_tmp]){
899
+			yyerror("duplicate route");
872 900
 			YYABORT;
873 901
 		}
902
+		push($6, &failure_rt.rlist[i_tmp]);
874 903
 	}
875 904
 	| ROUTE_FAILURE error { yyerror("invalid failure_route statement"); }
876 905
 	;
877 906
 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");
907
+	ROUTE_ONREPLY LBRACE actions RBRACE {
908
+									push($3, &onreply_rt.rlist[DEFAULT_RT]);
909
+										}
910
+	| ROUTE_ONREPLY LBRACK route_name RBRACK LBRACE actions RBRACE {
911
+		i_tmp=route_get(&onreply_rt, $3);
912
+		if (i_tmp==-1){
913
+			yyerror("internal error");
914
+			YYABORT;
915
+		}
916
+		if (onreply_rt.rlist[i_tmp]){
917
+			yyerror("duplicate route");
884 918
 			YYABORT;
885 919
 		}
920
+		push($6, &onreply_rt.rlist[i_tmp]);
886 921
 	}
887 922
 	| ROUTE_ONREPLY error { yyerror("invalid onreply_route statement"); }
888 923
 	;
889 924
 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");
925
+	ROUTE_BRANCH LBRACE actions RBRACE { 
926
+									push($3, &branch_rt.rlist[DEFAULT_RT]);
927
+										}
928
+	| ROUTE_BRANCH LBRACK route_name RBRACK LBRACE actions RBRACE {
929
+		i_tmp=route_get(&branch_rt, $3);
930
+		if (i_tmp==-1){
931
+			yyerror("internal error");
896 932
 			YYABORT;
897 933
 		}
934
+		if (branch_rt.rlist[i_tmp]){
935
+			yyerror("duplicate route");
936
+			YYABORT;
937
+		}
938
+		push($6, &branch_rt.rlist[i_tmp]);
898 939
 	}
899 940
 	| ROUTE_BRANCH error { yyerror("invalid branch_route statement"); }
900 941
 	;
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");
942
+send_route_stm: ROUTE_SEND LBRACE actions RBRACE {
943
+									push($3, &onsend_rt.rlist[DEFAULT_RT]);
944
+												}
945
+	| ROUTE_SEND LBRACK route_name RBRACK LBRACE actions RBRACE {
946
+		i_tmp=route_get(&onsend_rt, $3);
947
+		if (i_tmp==-1){
948
+			yyerror("internal error");
949
+			YYABORT;
950
+		}
951
+		if (onsend_rt.rlist[i_tmp]){
952
+			yyerror("duplicate route");
907 953
 			YYABORT;
908 954
 		}
955
+		push($6, &onsend_rt.rlist[i_tmp]);
909 956
 	}
910 957
 	| ROUTE_SEND error { yyerror("invalid onsend_route statement"); }
911 958
 	;
... ...
@@ -1544,7 +1591,14 @@ cmd:
1544 1591
 	| ERROR LPAREN STRING COMMA STRING RPAREN {$$=mk_action(ERROR_T, 2, STRING_ST, $3, STRING_ST, $5); }
1545 1592
 	| ERROR error { $$=0; yyerror("missing '(' or ')' ?"); }
1546 1593
 	| ERROR LPAREN error RPAREN { $$=0; yyerror("bad error argument"); }
1547
-	| ROUTE LPAREN NUMBER RPAREN	{ $$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)$3); }
1594
+	| ROUTE LPAREN route_name RPAREN	{ 
1595
+						i_tmp=route_get(&main_rt, $3);
1596
+						if (i_tmp==-1){
1597
+							yyerror("internal error");
1598
+							YYABORT;
1599
+						}
1600
+						$$=mk_action(ROUTE_T, 1, NUMBER_ST, (void*)i_tmp); 
1601
+										}
1548 1602
 	| ROUTE error { $$=0; yyerror("missing '(' or ')' ?"); }
1549 1603
 	| ROUTE LPAREN error RPAREN { $$=0; yyerror("bad route argument"); }
1550 1604
 	| 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 1307
 					abort();
1307 1308
 		}
1308 1309
 	}
1309
-
1310
+	
1311
+	if (init_routes()<0) goto error;
1310 1312
 	/* fill missing arguments with the default values*/
1311 1313
 	if (cfg_file==0) cfg_file=CFG_FILE;
1312 1314
 
... ...
@@ -1351,7 +1353,7 @@ try_again:
1351 1353
 		goto error;
1352 1354
 	}
1353 1355
 	if (debug_flag) debug = debug_save;
1354
-	print_rl();
1356
+	print_rls();
1355 1357
 
1356 1358
 	/* options with higher priority than cfg file */
1357 1359
 	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 129
 
129 130
 	if (branch_route) {
130 131
 		     /* run branch_route actions if provided */
131
-		if (run_actions(branch_rlist[branch_route], i_req) < 0) {
132
+		if (run_actions(branch_rt.rlist[branch_route], i_req) < 0) {
132 133
 			LOG(L_ERR, "ERROR: print_uac_request: Error in run_actions\n");
133 134
                }
134 135
 	}
... ...
@@ -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 654
 		on_failure = t->on_negative;
654 655
 		t->on_negative=0;
655 656
 		/* run a reply_route action if some was marked */
656
-		if (run_actions(failure_rlist[on_failure], &faked_req)<0)
657
+		if (run_actions(failure_rt.rlist[on_failure], &faked_req)<0)
657 658
 			LOG(L_ERR, "ERROR: run_failure_handlers: Error in do_action\n");
658 659
 	}
659 660
 
... ...
@@ -1342,7 +1343,7 @@ int reply_received( struct sip_msg  *p_msg )
1342 1343
 		if (t->uas.request) p_msg->flags=t->uas.request->flags;
1343 1344
 		/* set the as avp_list the one from transaction */
1344 1345
 		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)
1346
+		if (run_actions(onreply_rt.rlist[t->on_reply], p_msg)<0)
1346 1347
 			LOG(L_ERR, "ERROR: on_reply processing failed\n");
1347 1348
 		/* transfer current message context back to t */
1348 1349
 		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 95
 #include "../../usr_avp.h"
95 96
 #include "../../mem/mem.h"
96 97
 #include "../../route_struct.h"
98
+#include "../../route.h"
97 99
 
98 100
 #include "sip_msg.h"
99 101
 #include "h_table.h"
... ...
@@ -114,6 +116,9 @@ MODULE_VERSION
114 116
 
115 117
 /* fixup functions */
116 118
 static int fixup_hostport2proxy(void** param, int param_no);
119
+static int fixup_on_failure(void** param, int param_no);
120
+static int fixup_on_reply(void** param, int param_no);
121
+static int fixup_on_branch(void** param, int param_no);
117 122
 
118 123
 
119 124
 /* init functions */
... ...
@@ -226,11 +231,11 @@ static cmd_export_t cmds[]={
226 231
 	{T_FORWARD_NONACK_TLS, w_t_forward_nonack_tls,  2, fixup_hostport2proxy,
227 232
 			REQUEST_ROUTE},
228 233
 #endif
229
-	{"t_on_failure",       w_t_on_negative,         1, fixup_int_1,
234
+	{"t_on_failure",       w_t_on_negative,         1, fixup_on_failure,
230 235
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
231
-	{"t_on_reply",         w_t_on_reply,            1, fixup_int_1,
236
+	{"t_on_reply",         w_t_on_reply,            1, fixup_on_reply,
232 237
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
233
-	{"t_on_branch",       w_t_on_branch,         1, fixup_int_1,
238
+	{"t_on_branch",       w_t_on_branch,         1, fixup_on_branch,
234 239
 			REQUEST_ROUTE | FAILURE_ROUTE },
235 240
 	{"t_check_status",     t_check_status,          1, fixup_regex_1,
236 241
 			REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE },
... ...
@@ -308,6 +313,57 @@ struct module_exports exports= {
308 313
 };
309 314
 
310 315
 
316
+
317
+/* helper for fixup_on_* */
318
+static int fixup_routes(char* r_type, struct route_list* rt, void** param)
319
+{
320
+	int i;
321
+	
322
+	i=route_get(rt, (char*)*param);
323
+	if (i==-1){
324
+		LOG(L_ERR, "ERROR: tm: fixup_routes: route_get failed\n");
325
+		return E_UNSPEC;
326
+	}
327
+	if (rt->rlist[i]==0){
328
+		LOG(L_WARN, "WARNING: %s(\"%s\"): empty/non existing route\n",
329
+				r_type, (char*)*param);
330
+	}
331
+	*param=(void*)(long)i;
332
+	return 0;
333
+}
334
+
335
+
336
+
337
+static int fixup_on_failure(void** param, int param_no)
338
+{
339
+	if (param_no==1){
340
+		return fixup_routes("t_on_failure", &failure_rt, param);
341
+	}
342
+	return 0;
343
+}
344
+
345
+
346
+
347
+static int fixup_on_reply(void** param, int param_no)
348
+{
349
+	if (param_no==1){
350
+		return fixup_routes("t_on_reply", &onreply_rt, param);
351
+	}
352
+	return 0;
353
+}
354
+
355
+
356
+
357
+static int fixup_on_branch(void** param, int param_no)
358
+{
359
+	if (param_no==1){
360
+		return fixup_routes("t_on_branch", &branch_rt, param);
361
+	}
362
+	return 0;
363
+}
364
+
365
+
366
+
311 367
 /* (char *hostname, char *port_nr) ==> (struct proxy_l *, -)  */
312 368
 static int fixup_hostport2proxy(void** param, int param_no)
313 369
 {
... ...
@@ -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 72
 #include "mem/mem.h"
72 73
 #include "select.h"
73 74
 #include "onsend.h"
75
+#include "hashes.h"
76
+
77
+
78
+#define RT_HASH_SIZE	8 /* route names hash */
74 79
 
75 80
 /* 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];
81
+struct route_list main_rt;
82
+struct route_list onreply_rt;
83
+struct route_list failure_rt;
84
+struct route_list branch_rt;
85
+struct route_list onsend_rt;
86
+
87
+
88
+
89
+inline static void destroy_rlist(struct route_list* rt)
90
+{
91
+	struct str_hash_entry* e;
92
+	struct str_hash_entry* tmp;
93
+
94
+	if (rt->rlist){
95
+		pkg_free(rt->rlist);
96
+		rt->rlist=0;
97
+		rt->entries=0;
98
+	}
99
+	if (rt->names.table){
100
+		clist_foreach_safe(rt->names.table, e, tmp, next){
101
+			pkg_free(e);
102
+		}
103
+		pkg_free(rt->names.table);
104
+		rt->names.table=0;
105
+		rt->names.size=0;
106
+	}
107
+}
108
+
109
+
110
+
111
+void destroy_routes()
112
+{
113
+	destroy_rlist(&main_rt);
114
+	destroy_rlist(&onreply_rt);
115
+	destroy_rlist(&failure_rt);
116
+	destroy_rlist(&branch_rt);
117
+}
118
+
119
+
120
+
121
+/* adds route name -> i mapping
122
+ * WARNING: it doesn't check for pre-existing routes 
123
+ * return -1 on error, route index on success
124
+ */
125
+static int route_add(struct route_list* rt, char* name, int i)
126
+{
127
+	struct str_hash_entry* e;
128
+	
129
+	e=pkg_malloc(sizeof(struct str_hash_entry));
130
+	if (e==0){
131
+		LOG(L_CRIT, "ERROR: route_add: out of memory\n");
132
+		goto error;
133
+	}
134
+	e->key.s=name;
135
+	e->key.len=strlen(name);
136
+	e->flags=0;
137
+	e->u.n=i;
138
+	str_hash_add(&rt->names, e);
139
+	return 0;
140
+error:
141
+	return -1;
142
+}
143
+
144
+
145
+
146
+/* returns -1 on error, 0 on success */
147
+inline  static int init_rlist(char* r_name, struct route_list* rt,
148
+								int n_entries, int hash_size)
149
+{
150
+		rt->rlist=pkg_malloc(sizeof(struct action*)*n_entries);
151
+		if (rt->rlist==0){ 
152
+			LOG(L_CRIT, "ERROR: failed to allocate \"%s\" route tables: " 
153
+					"out of memory\n", r_name); 
154
+			goto error; 
155
+		}
156
+		memset(rt->rlist, 0 , sizeof(struct action*)*n_entries);
157
+		rt->idx=1; /* idx=0 == default == reserved */
158
+		rt->entries=n_entries;
159
+		if (str_hash_alloc(&rt->names, hash_size)<0){
160
+			LOG(L_CRIT, "ERROR: \"%s\" route table: failed to alloc hash\n",
161
+					r_name);
162
+			goto error;
163
+		}
164
+		str_hash_init(&rt->names);
165
+		route_add(rt, "0", 0);  /* default route */
166
+		
167
+		return 0;
168
+error:
169
+		return -1;
170
+}
171
+
172
+
173
+
174
+/* init route tables */
175
+int init_routes()
176
+{
177
+	if (init_rlist("main", &main_rt, RT_NO, RT_HASH_SIZE)<0)
178
+		goto error;
179
+	if (init_rlist("on_reply", &onreply_rt, ONREPLY_RT_NO, RT_HASH_SIZE)<0)
180
+		goto error;
181
+	if (init_rlist("failure", &failure_rt, FAILURE_RT_NO, RT_HASH_SIZE)<0)
182
+		goto error;
183
+	if (init_rlist("branch", &branch_rt, BRANCH_RT_NO, RT_HASH_SIZE)<0)
184
+		goto error;
185
+	if (init_rlist("on_send", &onsend_rt, ONSEND_RT_NO, RT_HASH_SIZE)<0)
186
+		goto error;
187
+	return 0;
188
+error:
189
+	destroy_routes();
190
+	return -1;
191
+}
192
+
193
+
194
+
195
+static inline int route_new_list(struct route_list* rt)
196
+{
197
+	int ret;
198
+	struct action** tmp;
199
+	
200
+	ret=-1;
201
+	if (rt->idx >= rt->entries){
202
+		tmp=pkg_realloc(rt->rlist, 2*rt->entries*sizeof(struct action*));
203
+		if (tmp==0){
204
+			LOG(L_CRIT, "ERROR: route_new_list: out of memory\n");
205
+			goto end;
206
+		}
207
+		rt->rlist=tmp;
208
+		rt->entries*=2;
209
+	}
210
+	if (rt->idx<rt->entries){
211
+		ret=rt->idx;
212
+		rt->idx++;
213
+	}
214
+end:
215
+	return ret;
216
+}
217
+
218
+
219
+
220
+
221
+/* 
222
+ * if the "name" route already exists, return its index, else
223
+ * create a new empty route
224
+ * return route index in rt->rlist or -1 on error
225
+ */
226
+int route_get(struct route_list* rt, char* name)
227
+{
228
+	int len;
229
+	struct str_hash_entry* e;
230
+	int i;
231
+	
232
+	len=strlen(name);
233
+	/* check if exists an non empty*/
234
+	e=str_hash_get(&rt->names, name, len);
235
+	if (e){
236
+		i=e->u.n;
237
+	}else{
238
+		i=route_new_list(rt);
239
+		if (i==-1) goto error;
240
+		if (route_add(rt, name, i)<0){
241
+			goto error;
242
+		}
243
+	}
244
+	return i;
245
+error:
246
+	return -1;
247
+}
248
+
249
+
82 250
 
83 251
 static int fix_actions(struct action* a); /*fwd declaration*/
84 252
 
... ...
@@ -983,42 +1151,14 @@ error:
983 1151
 
984 1152
 
985 1153
 
986
-/* fixes all action tables */
987
-/* returns 0 if ok , <0 on error */
988
-int fix_rls()
1154
+static int fix_rl(struct route_list* rt)
989 1155
 {
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){
1156
+	int i;
1157
+	int ret;
1158
+	
1159
+	for(i=0;i<rt->idx; i++){
1160
+		if(rt->rlist[i]){
1161
+			if ((ret=fix_actions(rt->rlist[i]))!=0){
1022 1162
 				return ret;
1023 1163
 			}
1024 1164
 		}
... ...
@@ -1027,42 +1167,52 @@ int fix_rls()
1027 1167
 }
1028 1168
 
1029 1169
 
1030
-/* debug function, prints main routing table */
1031
-void print_rl()
1170
+
1171
+/* fixes all action tables */
1172
+/* returns 0 if ok , <0 on error */
1173
+int fix_rls()
1032 1174
 {
1033
-	int j;
1175
+	int ret;
1176
+	
1177
+	if ((ret=fix_rl(&main_rt))!=0)
1178
+		return ret;
1179
+	if ((ret=fix_rl(&onreply_rt))!=0)
1180
+		return ret;
1181
+	if ((ret=fix_rl(&failure_rt))!=0)
1182
+		return ret;
1183
+	if ((ret=fix_rl(&branch_rt))!=0)
1184
+		return ret;
1185
+	if ((ret=fix_rl(&onsend_rt))!=0)
1186
+		return ret;
1034 1187
 
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){
1188
+	return 0;
1189
+}
1190
+
1191
+
1192
+
1193
+static void print_rl(struct route_list* rt, char* name)
1194
+{
1195
+	int j;
1196
+	
1197
+	for(j=0; j<rt->entries; j++){
1198
+		if (rt->rlist[j]==0){
1199
+			if ((j==0) && (rt==&main_rt))
1200
+				DBG("WARNING: the main routing table is empty\n");
1062 1201
 			continue;
1063 1202
 		}
1064
-		DBG("branch routing table %d:\n",j);
1065
-		print_actions(branch_rlist[j]);
1203
+		DBG("%s routing table %d:\n", name, j);
1204
+		print_actions(rt->rlist[j]);
1066 1205
 		DBG("\n");
1067 1206
 	}
1068 1207
 }
1208
+
1209
+
1210
+/* debug function, prints routing tables */
1211
+void print_rls()
1212
+{
1213
+	print_rl(&main_rt, "");
1214
+	print_rl(&onreply_rt, "onreply");
1215
+	print_rl(&failure_rt, "failure");
1216
+	print_rl(&branch_rt, "branch");
1217
+	print_rl(&onsend_rt, "onsend");
1218
+}
... ...
@@ -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
 {