1 /**
2  * $Id$
3  *
4  * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * This file is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  *
14  * This file is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24 
25 #include <stdio.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <time.h>
30 
31 #include "../../core/dprint.h"
32 #include "../../core/mem/shm_mem.h"
33 #include "../../core/parser/parse_param.h"
34 #include "../../core/ut.h"
35 #include "../../core/pvar.h"
36 #include "../../core/lvalue.h"
37 #include "../../core/shm_init.h"
38 
39 #include "mtree.h"
40 
41 //extern str mt_char_list = {"1234567890*",11};
42 extern str mt_char_list;
43 extern pv_spec_t pv_value;
44 extern pv_spec_t pv_values;
45 extern pv_spec_t pv_dstid;
46 extern pv_spec_t pv_weight;
47 extern int _mt_tree_type;
48 extern int _mt_ignore_duplicates;
49 extern int _mt_allow_duplicates;
50 
51 /** structures containing prefix-value pairs */
52 static m_tree_t **_ptree = NULL;
53 
54 /* quick translation table */
55 #define MT_CHAR_TABLE_SIZE	256
56 #define MT_CHAR_TABLE_NOTSET 255
57 static unsigned char _mt_char_table[MT_CHAR_TABLE_SIZE];
58 
59 /**
60  *
61  */
mt_char_table_init(void)62 void mt_char_table_init(void)
63 {
64 	unsigned int i;
65 	for(i=0; i<MT_CHAR_TABLE_SIZE; i++) {
66 		_mt_char_table[i] = MT_CHAR_TABLE_NOTSET;
67 	}
68 	for(i=0; i<mt_char_list.len; i++) {
69 		unsigned char ch = mt_char_list.s[i];
70 		_mt_char_table[ch] = (unsigned char)i;
71 	}
72 }
73 
74 
75 /**
76  *
77  */
mt_swap_list_head(m_tree_t * ntree)78 m_tree_t *mt_swap_list_head(m_tree_t *ntree)
79 {
80 	m_tree_t *otree;
81 
82 	otree = *_ptree;
83 	*_ptree = ntree;
84 
85 	return otree;
86 }
87 
88 /**
89  *
90  */
mt_init_list_head(void)91 int mt_init_list_head(void)
92 {
93 	if(_ptree!=NULL)
94 		return 0;
95 	_ptree = (m_tree_t**)shm_malloc( sizeof(m_tree_t*) );
96 	if (_ptree==0) {
97 		LM_ERR("out of shm mem for pdtree\n");
98 		return -1;
99 	}
100 	*_ptree=0;
101 	return 0;
102 }
103 
104 /**
105  *
106  */
mt_init_tree(str * tname,str * dbtable,str * scols,int type,int multi)107 m_tree_t* mt_init_tree(str* tname, str *dbtable, str *scols, int type,
108 		int multi)
109 {
110 	m_tree_t *pt = NULL;
111 	int i;
112 	int c;
113 
114 	pt = (m_tree_t*)shm_malloc(sizeof(m_tree_t));
115 	if(pt==NULL)
116 	{
117 		LM_ERR("no more shm memory\n");
118 		return NULL;
119 	}
120 	memset(pt, 0, sizeof(m_tree_t));
121 
122 	pt->type = type;
123 	pt->multi = multi;
124 	pt->reload_time = (unsigned int)time(NULL);
125 	pt->tname.s = (char*)shm_malloc((1+tname->len)*sizeof(char));
126 	if(pt->tname.s==NULL)
127 	{
128 		shm_free(pt);
129 		LM_ERR("no more shm memory\n");
130 		return NULL;
131 	}
132 	memset(pt->tname.s, 0, 1+tname->len);
133 	memcpy(pt->tname.s, tname->s, tname->len);
134 	pt->tname.len = tname->len;
135 
136 	pt->dbtable.s = (char*)shm_malloc((1+dbtable->len)*sizeof(char));
137 	if(pt->dbtable.s==NULL)
138 	{
139 		shm_free(pt->tname.s);
140 		shm_free(pt);
141 		LM_ERR("no more shm memory\n");
142 		return NULL;
143 	}
144 	memset(pt->dbtable.s, 0, 1+dbtable->len);
145 	memcpy(pt->dbtable.s, dbtable->s, dbtable->len);
146 	pt->dbtable.len = dbtable->len;
147 
148 	if(scols!=NULL && scols->s!=NULL && scols->len>0) {
149 		pt->scols[0].s = (char*)shm_malloc((1+scols->len)*sizeof(char));
150 		if(pt->scols[0].s==NULL) {
151 			shm_free(pt->tname.s);
152 			shm_free(pt->dbtable.s);
153 			shm_free(pt);
154 			LM_ERR("no more shm memory\n");
155 			return NULL;
156 		}
157 		memset(pt->scols[0].s, 0, (1+scols->len)*sizeof(char));
158 		memcpy(pt->scols[0].s, scols->s, scols->len);
159 		pt->scols[0].len = scols->len;
160 		c = 0;
161 		for(i=0; i<scols->len; i++) {
162 			if(pt->scols[0].s[i]==',') {
163 				pt->scols[c].len = (pt->scols[0].s + i - pt->scols[c].s);
164 				LM_DBG("db table column[%d]='%.*s'\n", c,
165 						pt->scols[c].len, pt->scols[c].s);
166 				c++;
167 				if(c>=MT_MAX_COLS) {
168 					LM_ERR("too many columns %d\n", c);
169 					shm_free(pt->scols[0].s);
170 					shm_free(pt->tname.s);
171 					shm_free(pt->dbtable.s);
172 					shm_free(pt);
173 					return NULL;
174 				}
175 				pt->scols[c].s = pt->scols[0].s + i + 1;
176 				pt->scols[c].len = pt->scols[0].s + scols->len - pt->scols[c].s;
177 			}
178 		}
179 		LM_DBG("db table column[%d]='%.*s'\n", c,
180 				pt->scols[c].len, pt->scols[c].s);
181 		if(c==0) {
182 			LM_ERR("there must be at least two columns (prefix, value)\n");
183 			shm_free(pt->scols[0].s);
184 			shm_free(pt->tname.s);
185 			shm_free(pt->dbtable.s);
186 			shm_free(pt);
187 			return NULL;
188 		}
189 		pt->ncols = c + 1;
190 		pt->pack[0] = 'l';
191 		pt->pack[1] = ',';
192 		pt->pack[2] = '*';
193 	}
194 
195 	return pt;
196 }
197 
mt_add_to_tree(m_tree_t * pt,str * sp,str * svalue)198 int mt_add_to_tree(m_tree_t *pt, str *sp, str *svalue)
199 {
200 	int l, ivalue = 0;
201 	mt_node_t *itn, *itn0;
202 	mt_is_t *tvalues;
203 	unsigned char mtch;
204 
205 	if(pt==NULL || sp==NULL || sp->s==NULL
206 			|| svalue==NULL || svalue->s==NULL)
207 	{
208 		LM_ERR("bad parameters\n");
209 		return -1;
210 	}
211 
212 	if(sp->len>=MT_MAX_DEPTH)
213 	{
214 		LM_ERR("max prefix len exceeded\n");
215 		return -1;
216 	}
217 
218 	LM_DBG("adding to tree <%.*s> of type <%d>\n", pt->tname.len,
219 			pt->tname.s, pt->type);
220 
221 	if ((pt->type == MT_TREE_IVAL) && (str2sint(svalue, &ivalue) != 0)) {
222 		LM_ERR("bad integer string <%.*s>\n", svalue->len, svalue->s);
223 		return -1;
224 	}
225 
226 	l = 0;
227 	if(pt->head == NULL)
228 	{
229 		pt->head = (mt_node_t*)shm_malloc(MT_NODE_SIZE*sizeof(mt_node_t));
230 		if(pt->head == NULL)
231 		{
232 			LM_ERR("no more shm memory for tree head\n");
233 			return -1;
234 		}
235 		memset(pt->head, 0, MT_NODE_SIZE*sizeof(mt_node_t));
236 		pt->nrnodes++;
237 		pt->memsize +=  MT_NODE_SIZE*sizeof(mt_node_t);
238 	}
239 
240 	itn0 = pt->head;
241 
242 	mtch = _mt_char_table[(unsigned char)sp->s[l]];
243 	if(mtch==MT_CHAR_TABLE_NOTSET)
244 	{
245 		LM_ERR("invalid char at %d in [%.*s] [%c (0x%x)]\n",
246 				l, sp->len, sp->s, sp->s[l], sp->s[l]);
247 		return -1;
248 	}
249 	itn = itn0[mtch].child;
250 
251 	while(l < sp->len-1)
252 	{
253 		if(itn == NULL)
254 		{
255 			itn = (mt_node_t*)shm_malloc(MT_NODE_SIZE*sizeof(mt_node_t));
256 			if(itn == NULL)
257 			{
258 				LM_ERR("no more shm mem\n");
259 				return -1;
260 			}
261 			memset(itn, 0, MT_NODE_SIZE*sizeof(mt_node_t));
262 			pt->nrnodes++;
263 			pt->memsize +=  MT_NODE_SIZE*sizeof(mt_node_t);
264 			itn0[mtch].child = itn;
265 		}
266 
267 		l++;
268 		mtch = _mt_char_table[(unsigned char)sp->s[l]];
269 		if(mtch==MT_CHAR_TABLE_NOTSET)
270 		{
271 			LM_ERR("invalid char at %d in [%.*s]\n",
272 					l, sp->len, sp->s);
273 			return -1;
274 		}
275 		itn0 = itn;
276 		itn = itn0[mtch].child;
277 	}
278 
279 	if(itn0[mtch].tvalues != NULL) {
280 		if(_mt_ignore_duplicates != 0) {
281 			LM_NOTICE("prefix already allocated [%.*s/%.*s]\n",
282 					sp->len, sp->s, svalue->len, svalue->s);
283 			return 1;
284 		} else if (_mt_allow_duplicates == 0) {
285 			LM_ERR("prefix already allocated [%.*s/%.*s]\n",
286 					sp->len, sp->s, svalue->len, svalue->s);
287 			return -1;
288 		}
289 	}
290 
291 	tvalues = (mt_is_t *)shm_malloc(sizeof(mt_is_t));
292 	if (tvalues == NULL) {
293 		LM_ERR("no more shm mem for tvalue\n");
294 		return -1;
295 	}
296 	memset(tvalues, 0, sizeof(mt_is_t));
297 
298 	if (pt->type == MT_TREE_IVAL) {
299 		tvalues->tvalue.n = ivalue;
300 	} else { /* pt->type == MT_TREE_SVAL or MT_TREE_DW */
301 		tvalues->tvalue.s.s = (char*)shm_malloc((svalue->len+1)*sizeof(char));
302 		if (tvalues->tvalue.s.s == NULL) {
303 			LM_ERR("no more shm mem for string\n");
304 			return -1;
305 		}
306 		tvalues->tvalue.s.len = svalue->len;
307 		pt->memsize +=  (svalue->len+1)*sizeof(char);
308 		pt->nritems++;
309 		strncpy(tvalues->tvalue.s.s, svalue->s, svalue->len);
310 		tvalues->tvalue.s.s[svalue->len] = '\0';
311 	}
312 	tvalues->next = itn0[mtch].tvalues;
313 	itn0[mtch].tvalues = tvalues;
314 	mt_node_set_payload(&itn0[mtch], pt->type);
315 	return 0;
316 }
317 
mt_get_tree(str * tname)318 m_tree_t* mt_get_tree(str *tname)
319 {
320 	m_tree_t *it;
321 	int ret;
322 
323 	if(_ptree==NULL || *_ptree==NULL)
324 		return NULL;
325 
326 	if( tname==NULL || tname->s==NULL)
327 	{
328 		LM_ERR("bad parameters\n");
329 		return NULL;
330 	}
331 
332 	it = *_ptree;
333 	/* search the tree for the asked tname */
334 	while(it!=NULL)
335 	{
336 		ret = str_strcmp(&it->tname, tname);
337 		if(ret>0)
338 			return NULL;
339 		if(ret==0)
340 			return it;
341 		it = it->next;
342 	}
343 
344 	return it;
345 }
346 
mt_get_first_tree()347 m_tree_t* mt_get_first_tree()
348 {
349 	if(_ptree==NULL || *_ptree==NULL)
350 		return NULL;
351 	return *_ptree;
352 }
353 
354 
mt_get_tvalue(m_tree_t * pt,str * tomatch,int * len)355 is_t* mt_get_tvalue(m_tree_t *pt, str *tomatch, int *len)
356 {
357 	int l;
358 	mt_node_t *itn;
359 	is_t *tvalue;
360 
361 	if(pt==NULL || tomatch==NULL || tomatch->s==NULL || len == NULL)
362 	{
363 		LM_ERR("bad parameters\n");
364 		return NULL;
365 	}
366 
367 	l = 0;
368 	itn = pt->head;
369 	tvalue = NULL;
370 
371 	while(itn!=NULL && l < tomatch->len && l < MT_MAX_DEPTH)
372 	{
373 		unsigned char mtch = _mt_char_table[(unsigned char)tomatch->s[l]];
374 
375 		/* check validity */
376 		if(mtch==MT_CHAR_TABLE_NOTSET)
377 		{
378 			LM_DBG("not matching char at %d in [%.*s]\n",
379 					l, tomatch->len, tomatch->s);
380 			return NULL;
381 		}
382 
383 		if(itn[mtch].tvalues!=NULL)
384 		{
385 			tvalue = &itn[mtch].tvalues->tvalue;
386 		}
387 
388 		itn = itn[mtch].child;
389 		l++;
390 	}
391 
392 	*len = l;
393 
394 	return tvalue;
395 }
396 
mt_add_tvalues(struct sip_msg * msg,m_tree_t * pt,str * tomatch)397 int mt_add_tvalues(struct sip_msg *msg, m_tree_t *pt, str *tomatch)
398 {
399 	int l, n;
400 	mt_node_t *itn;
401 	int_str val, values_avp_name;
402 	unsigned short values_name_type;
403 	mt_is_t *tvalues;
404 
405 	if (pt == NULL || tomatch == NULL || tomatch->s == NULL) {
406 		LM_ERR("bad parameters\n");
407 		return -1;
408 	}
409 
410 	if (pv_get_avp_name(msg, &pv_values.pvp, &values_avp_name,
411 				&values_name_type) < 0) {
412 		LM_ERR("cannot get values avp name\n");
413 		return -1;
414 	}
415 
416 	destroy_avps(values_name_type, values_avp_name, 1);
417 
418 	l = n = 0;
419 	itn = pt->head;
420 
421 	while (itn != NULL && l < tomatch->len && l < MT_MAX_DEPTH) {
422 		unsigned char mtch = _mt_char_table[(unsigned char)tomatch->s[l]];
423 
424 		/* check validity */
425 		if(mtch==MT_CHAR_TABLE_NOTSET) {
426 			LM_ERR("invalid char at %d in [%.*s]\n",
427 					l, tomatch->len, tomatch->s);
428 			return -1;
429 		}
430 		tvalues = itn[mtch].tvalues;
431 		while (tvalues != NULL) {
432 			if (pt->type == MT_TREE_IVAL) {
433 				val.n = tvalues->tvalue.n;
434 				LM_DBG("adding avp <%.*s> with value <i:%d>\n",
435 						values_avp_name.s.len, values_avp_name.s.s, val.n);
436 				add_avp(values_name_type, values_avp_name, val);
437 			} else {  /* pt->type == MT_TREE_SVAL */
438 				val.s = tvalues->tvalue.s;
439 				LM_DBG("adding avp <%.*s> with value <s:%.*s>\n",
440 						values_avp_name.s.len, values_avp_name.s.s, val.s.len,
441 						val.s.s);
442 				add_avp(values_name_type|AVP_VAL_STR, values_avp_name, val);
443 			}
444 			n++;
445 			tvalues = tvalues->next;
446 		}
447 
448 		itn = itn[mtch].child;
449 		l++;
450 	}
451 
452 	if (n > 0)
453 		return 0;
454 	else
455 		return -1;
456 }
457 
mt_match_prefix(struct sip_msg * msg,m_tree_t * it,str * tomatch,int mode)458 int mt_match_prefix(struct sip_msg *msg, m_tree_t *it,
459 		str *tomatch, int mode)
460 {
461 	int l, len, n;
462 	int i, j, k = 0;
463 	mt_node_t *itn;
464 	is_t *tvalue;
465 	int_str dstid_avp_name;
466 	unsigned short dstid_name_type;
467 	int_str weight_avp_name;
468 	unsigned short weight_name_type;
469 	int_str avp_value;
470 	mt_dw_t *dw;
471 	pv_value_t val;
472 
473 #define MT_MAX_DST_LIST	64
474 	unsigned int tmp_list[2*(MT_MAX_DST_LIST+1)];
475 
476 	if(it==NULL || tomatch == NULL
477 			|| tomatch->s == NULL)
478 	{
479 		LM_ERR("bad parameters\n");
480 		return -1;
481 	}
482 
483 	l = len = 0;
484 	n = 0;
485 	if ((it->type==MT_TREE_SVAL) || (it->type==MT_TREE_IVAL)) {
486 		if (mode == 2)
487 			return mt_add_tvalues(msg, it, tomatch);
488 		tvalue = mt_get_tvalue(it, tomatch, &k);
489 		if (tvalue == NULL) {
490 			LM_DBG("no match for: %.*s\n", tomatch->len, tomatch->s);
491 			return -1;
492 		}
493 		memset(&val, 0, sizeof(pv_value_t));
494 		if (it->type==MT_TREE_SVAL) {
495 			val.flags = PV_VAL_STR;
496 			val.rs = tvalue->s;
497 			if(pv_value.setf(msg, &pv_value.pvp, (int)EQ_T, &val)<0) {
498 				LM_ERR("setting PV failed\n");
499 				return -2;
500 			}
501 		} else {
502 			val.flags = PV_VAL_INT;
503 			val.ri = tvalue->n;
504 			if(pv_value.setf(msg, &pv_value.pvp, (int)EQ_T, &val)<0) {
505 				LM_ERR("setting PV failed\n");
506 				return -2;
507 			}
508 		}
509 		return 0;
510 	}
511 
512 	if(it->type!=MT_TREE_DW)
513 		return -1; /* wrong tree type */
514 
515 	if(pv_get_avp_name(msg, &pv_dstid.pvp, &dstid_avp_name,
516 				&dstid_name_type)<0)
517 	{
518 		LM_ERR("cannot get dstid avp name\n");
519 		return -1;
520 	}
521 	if(pv_get_avp_name(msg, &pv_weight.pvp, &weight_avp_name,
522 				&weight_name_type)<0)
523 	{
524 		LM_ERR("cannot get weight avp name\n");
525 		return -1;
526 	}
527 
528 	itn = it->head;
529 	memset(tmp_list, 0, sizeof(unsigned int)*2*(MT_MAX_DST_LIST+1));
530 
531 	while(itn!=NULL && l < tomatch->len && l < MT_MAX_DEPTH)
532 	{
533 		unsigned char mtch = _mt_char_table[(unsigned char)tomatch->s[l]];
534 
535 		/* check validity */
536 		if(mtch==MT_CHAR_TABLE_NOTSET)
537 		{
538 			LM_ERR("invalid char at %d in [%.*s]\n",
539 					l, tomatch->len, tomatch->s);
540 			return -1;
541 		}
542 
543 		if(itn[mtch].tvalues!=NULL)
544 		{
545 			dw = (mt_dw_t*)itn[mtch].data;
546 			while(dw) {
547 				tmp_list[2*n]=dw->dstid;
548 				tmp_list[2*n+1]=dw->weight;
549 				n++;
550 				if(n==MT_MAX_DST_LIST)
551 					break;
552 				dw = dw->next;
553 			}
554 			len = l+1;
555 		}
556 		if(n==MT_MAX_DST_LIST)
557 			break;
558 
559 		itn = itn[mtch].child;
560 		l++;
561 	}
562 
563 	if(n==0)
564 		return -1; /* no match */
565 	/* invalidate duplicated dstid, keeping longest match */
566 	for(i=(n-1); i>0; i--)
567 	{
568 		if (tmp_list[2*i]!=0)
569 		{
570 			for(j=0; j<i; j++)
571 				if(tmp_list[2*i]==tmp_list[2*j])
572 					tmp_list[2*j] = 0;
573 		}
574 	}
575 	/* sort the table -- bubble sort -- reverse order */
576 	for (i = (n - 1); i >= 0; i--)
577 	{
578 		for (j = 1; j <= i; j++)
579 		{
580 			if (tmp_list[2*(j-1)+1] < tmp_list[2*j+1])
581 			{
582 				tmp_list[2*MT_MAX_DST_LIST]   = tmp_list[2*(j-1)];
583 				tmp_list[2*MT_MAX_DST_LIST+1] = tmp_list[2*(j-1)+1];
584 				tmp_list[2*(j-1)]   = tmp_list[2*j];
585 				tmp_list[2*(j-1)+1] = tmp_list[2*j+1];
586 				tmp_list[2*j]   = tmp_list[2*MT_MAX_DST_LIST];
587 				tmp_list[2*j+1] = tmp_list[2*MT_MAX_DST_LIST+1];
588 			}
589 		}
590 	}
591 	/* add as avp */
592 	for(i=0; i<n; i++)
593 	{
594 		if(tmp_list[2*i]!=0)
595 		{
596 			avp_value.n = (int)tmp_list[2*i+1];
597 			add_avp(weight_name_type, weight_avp_name, avp_value);
598 			avp_value.n = (int)tmp_list[2*i];
599 			add_avp(dstid_name_type, dstid_avp_name, avp_value);
600 		}
601 	}
602 
603 	return 0;
604 }
605 
mt_free_node(mt_node_t * pn,int type)606 void mt_free_node(mt_node_t *pn, int type)
607 {
608 	int i;
609 	mt_is_t *tvalues, *next;
610 
611 	if(pn==NULL)
612 		return;
613 
614 	for(i=0; i<MT_NODE_SIZE; i++) {
615 		tvalues = pn[i].tvalues;
616 		while (tvalues != NULL) {
617 			if ((type == MT_TREE_SVAL) && (tvalues->tvalue.s.s != NULL)) {
618 				shm_free(tvalues->tvalue.s.s);
619 				tvalues->tvalue.s.s   = NULL;
620 				tvalues->tvalue.s.len = 0;
621 			}
622 			next = tvalues->next;
623 			shm_free(tvalues);
624 			tvalues = next;
625 		}
626 		if(type==MT_TREE_DW)
627 			mt_node_unset_payload(&pn[i], type);
628 		if(pn[i].child!=NULL) {
629 			mt_free_node(pn[i].child, type);
630 			pn[i].child = NULL;
631 		}
632 	}
633 	shm_free(pn);
634 	pn = NULL;
635 
636 	return;
637 }
638 
mt_free_tree(m_tree_t * pt)639 void mt_free_tree(m_tree_t *pt)
640 {
641 	if(pt == NULL)
642 		return;
643 
644 	if(pt->head!=NULL)
645 		mt_free_node(pt->head, pt->type);
646 	if(pt->next!=NULL)
647 		mt_free_tree(pt->next);
648 	if(pt->dbtable.s!=NULL)
649 		shm_free(pt->dbtable.s);
650 	if(pt->tname.s!=NULL)
651 		shm_free(pt->tname.s);
652 
653 	shm_free(pt);
654 	pt = NULL;
655 	return;
656 }
657 
mt_print_node(mt_node_t * pn,char * code,int len,int type)658 int mt_print_node(mt_node_t *pn, char *code, int len, int type)
659 {
660 	int i;
661 	mt_is_t *tvalues;
662 
663 	if(pn==NULL || code==NULL || len>=MT_MAX_DEPTH)
664 		return 0;
665 
666 	for(i=0; i<MT_NODE_SIZE; i++)
667 	{
668 		code[len]=mt_char_list.s[i];
669 		tvalues = pn[i].tvalues;
670 		while (tvalues != NULL) {
671 			if (type == MT_TREE_IVAL) {
672 				LM_INFO("[%.*s] [i:%d]\n",	len+1, code, tvalues->tvalue.n);
673 			} else if (tvalues->tvalue.s.s != NULL) {
674 				LM_INFO("[%.*s] [s:%.*s]\n",
675 						len+1, code, tvalues->tvalue.s.len, tvalues->tvalue.s.s);
676 			}
677 			tvalues = tvalues->next;
678 		}
679 		mt_print_node(pn[i].child, code, len+1, type);
680 	}
681 
682 	return 0;
683 }
684 
685 static char mt_code_buf[MT_MAX_DEPTH+1];
mt_print_tree(m_tree_t * pt)686 int mt_print_tree(m_tree_t *pt)
687 {
688 	int len;
689 
690 	if(pt == NULL)
691 	{
692 		LM_DBG("tree is empty\n");
693 		return 0;
694 	}
695 
696 	LM_INFO("[%.*s]\n", pt->tname.len, pt->tname.s);
697 	len = 0;
698 	mt_print_node(pt->head, mt_code_buf, len, pt->type);
699 	return mt_print_tree(pt->next);
700 }
701 
mt_node_set_payload(mt_node_t * node,int type)702 int mt_node_set_payload(mt_node_t *node, int type)
703 {
704 	param_t *list;
705 	param_t *it;
706 	param_hooks_t hooks;
707 	str s;
708 	mt_dw_t *dwl;
709 	mt_dw_t *dw;
710 
711 	if(type!=MT_TREE_DW)
712 		return 0;
713 	s = node->tvalues->tvalue.s;
714 	if(s.s[s.len-1]==';')
715 		s.len--;
716 	if(parse_params(&s, CLASS_ANY, &hooks, &list)<0)
717 	{
718 		LM_ERR("cannot parse tvalue payload [%.*s]\n", s.len, s.s);
719 		return -1;
720 	}
721 	dwl = NULL;
722 	for(it=list; it; it=it->next)
723 	{
724 		dw = (mt_dw_t*)shm_malloc(sizeof(mt_dw_t));
725 		if(dw==NULL)
726 		{
727 			LM_ERR("no more shm\n");
728 			goto error;
729 		}
730 		memset(dw, 0, sizeof(mt_dw_t));
731 		str2int(&it->name, &dw->dstid);
732 		str2int(&it->body, &dw->weight);
733 		dw->next = dwl;
734 		dwl = dw;
735 	}
736 	node->data = (void*)dwl;
737 	free_params(list);
738 	return 0;
739 error:
740 	while(dwl)
741 	{
742 		dw=dwl;
743 		dwl=dwl->next;
744 		shm_free(dwl);
745 	}
746 	free_params(list);
747 	return -1;
748 }
749 
mt_node_unset_payload(mt_node_t * node,int type)750 int mt_node_unset_payload(mt_node_t *node, int type)
751 {
752 	mt_dw_t *dwl;
753 	mt_dw_t *dw;
754 
755 	if(type!=MT_TREE_DW)
756 		return 0;
757 	dwl = (mt_dw_t*)node->data;
758 	while(dwl)
759 	{
760 		dw=dwl;
761 		dwl=dwl->next;
762 		shm_free(dw);
763 	}
764 	node->data = NULL;
765 	return 0;
766 }
767 
mt_table_spec(char * val)768 int mt_table_spec(char* val)
769 {
770 	param_t* params_list = NULL;
771 	param_hooks_t phooks;
772 	param_t *pit=NULL;
773 	m_tree_t tmp;
774 	m_tree_t *it, *prev, *ndl;
775 	str s;
776 
777 	if(val==NULL)
778 		return -1;
779 
780 	if(!shm_initialized())
781 	{
782 		LM_ERR("shm not initialized - cannot define mtree now\n");
783 		return 0;
784 	}
785 
786 	s.s = val;
787 	s.len = strlen(s.s);
788 	if(s.s[s.len-1]==';')
789 		s.len--;
790 	LM_DBG("parsing [%.*s]\n", s.len, s.s);
791 	if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
792 		return -1;
793 	memset(&tmp, 0, sizeof(m_tree_t));
794 	for (pit = params_list; pit; pit=pit->next)
795 	{
796 		LM_DBG("parm: %.*s=%.*s\n", pit->name.len, pit->name.s,
797 				pit->body.len, pit->body.s);
798 		if (pit->name.len==4
799 				&& strncasecmp(pit->name.s, "name", 4)==0) {
800 			tmp.tname = pit->body;
801 		} else if(pit->name.len==4
802 				&& strncasecmp(pit->name.s, "type", 4)==0) {
803 			str2sint(&pit->body, &tmp.type);
804 		} else if(pit->name.len==5
805 				&& strncasecmp(pit->name.s, "multi", 5)==0) {
806 			str2sint(&pit->body, &tmp.multi);
807 		}  else if(pit->name.len==7
808 				&& strncasecmp(pit->name.s, "dbtable", 7)==0) {
809 			tmp.dbtable = pit->body;
810 		}  else if(pit->name.len==4
811 				&& strncasecmp(pit->name.s, "cols", 4)==0) {
812 			tmp.ncols = 1;
813 			tmp.scols[0] = pit->body;
814 		}
815 	}
816 	if(tmp.tname.s==NULL)
817 	{
818 		LM_ERR("invalid mtree name\n");
819 		goto error;
820 	}
821 	if(tmp.dbtable.s==NULL)
822 	{
823 		LM_INFO("no table name - default mtree\n");
824 		tmp.dbtable.s = "mtree";
825 		tmp.dbtable.len = 5;
826 	}
827 	if ((tmp.type != 0) && (tmp.type != 1) && (tmp.type != 2)) {
828 		LM_ERR("unknown tree type <%d>\n", tmp.type);
829 		goto error;
830 	}
831 	if ((tmp.multi != 0) && (tmp.multi != 1)) {
832 		LM_ERR("unknown multi value <%d>\n", tmp.multi);
833 		goto error;
834 	}
835 
836 	/* check for same tree */
837 	if(_ptree == 0)
838 	{
839 		/* tree list head in shm */
840 		_ptree = (m_tree_t**)shm_malloc( sizeof(m_tree_t*) );
841 		if (_ptree==0)
842 		{
843 			LM_ERR("out of shm mem for ptree\n");
844 			goto error;
845 		}
846 		*_ptree=0;
847 	}
848 	it = *_ptree;
849 	prev = NULL;
850 	/* search the it position before which to insert new tvalue */
851 	while(it!=NULL && str_strcmp(&it->tname, &tmp.tname)<0)
852 	{
853 		prev = it;
854 		it = it->next;
855 	}
856 
857 	/* found */
858 	if(it!=NULL && str_strcmp(&it->tname, &tmp.tname)==0)
859 	{
860 		LM_ERR("duplicate tree with name [%s]\n", tmp.tname.s);
861 		goto error;
862 	}
863 	/* add new tname*/
864 	if(it==NULL || str_strcmp(&it->tname, &tmp.tname)>0)
865 	{
866 		LM_DBG("adding new tname [%s]\n", tmp.tname.s);
867 
868 		ndl = mt_init_tree(&tmp.tname, &tmp.dbtable, &tmp.scols[0], tmp.type,
869 					tmp.multi);
870 		if(ndl==NULL)
871 		{
872 			LM_ERR("cannot init the tree [%.*s]\n",
873 					tmp.tname.len, tmp.tname.s);
874 			goto error;
875 		}
876 
877 		ndl->next = it;
878 
879 		/* new tvalue must be added as first element */
880 		if(prev==NULL)
881 			*_ptree = ndl;
882 		else
883 			prev->next=ndl;
884 
885 	}
886 
887 	free_params(params_list);
888 	return 0;
889 error:
890 	free_params(params_list);
891 	return -1;
892 }
893 
mt_add_tree(m_tree_t ** dpt,str * tname,str * dbtable,str * cols,int type,int multi)894 m_tree_t *mt_add_tree(m_tree_t **dpt, str *tname, str *dbtable, str *cols,
895 		int type, int multi)
896 {
897 	m_tree_t *it = NULL;
898 	m_tree_t *prev = NULL;
899 	m_tree_t *ndl = NULL;
900 
901 	if(dpt==NULL)
902 		return NULL;
903 
904 	it = *dpt;
905 	prev = NULL;
906 	/* search the it position before which to insert new tvalue */
907 	while(it!=NULL && str_strcmp(&it->tname, tname)<0)
908 	{
909 		prev = it;
910 		it = it->next;
911 	}
912 
913 	if(it!=NULL && str_strcmp(&it->tname, tname)==0)
914 	{
915 		return it;
916 	}
917 	/* add new tname*/
918 	if(it==NULL || str_strcmp(&it->tname, tname)>0)
919 	{
920 		LM_DBG("adding new tname [%s]\n", tname->s);
921 
922 		ndl = mt_init_tree(tname, dbtable, cols, type, multi);
923 		if(ndl==NULL)
924 		{
925 			LM_ERR("no more shm memory\n");
926 			return NULL;
927 		}
928 
929 		ndl->next = it;
930 
931 		/* new tvalue must be added as first element */
932 		if(prev==NULL)
933 			*dpt = ndl;
934 		else
935 			prev->next=ndl;
936 	}
937 	return ndl;
938 }
939 
mt_destroy_trees(void)940 void mt_destroy_trees(void)
941 {
942 	if (_ptree!=NULL)
943 	{
944 		if (*_ptree!=NULL)
945 			mt_free_tree(*_ptree);
946 		shm_free(_ptree);
947 		_ptree = NULL;
948 	}
949 }
950 
mt_defined_trees(void)951 int mt_defined_trees(void)
952 {
953 	if (_ptree!=NULL && *_ptree!=NULL)
954 		return 1;
955 	return 0;
956 }
957 
mt_rpc_add_tvalues(rpc_t * rpc,void * ctx,m_tree_t * pt,str * tomatch)958 int mt_rpc_add_tvalues(rpc_t* rpc, void* ctx, m_tree_t *pt, str *tomatch)
959 {
960 	int l;
961 	mt_node_t *itn;
962 	mt_is_t *tvalues;
963 	void *vstruct = NULL;
964 	str prefix = STR_NULL;
965 
966 	if (pt == NULL || tomatch == NULL || tomatch->s == NULL) {
967 		LM_ERR("bad parameters\n");
968 		return -1;
969 	}
970 	prefix = *tomatch;
971 
972 	l = 0;
973 	itn = pt->head;
974 
975 	while (itn != NULL && l < tomatch->len && l < MT_MAX_DEPTH) {
976 		unsigned char mtch = _mt_char_table[(unsigned char)tomatch->s[l]];
977 
978 		/* check validity */
979 		if(mtch==MT_CHAR_TABLE_NOTSET) {
980 			LM_ERR("invalid char at %d in [%.*s]\n",
981 					l, tomatch->len, tomatch->s);
982 			return -1;
983 		}
984 		tvalues = itn[mtch].tvalues;
985 		while (tvalues != NULL) {
986 			prefix.len = l+1;
987 			if (rpc->add(ctx, "{", &vstruct) < 0) {
988 				rpc->fault(ctx, 500, "Internal error adding struct");
989 				return -1;
990 			}
991 			if(rpc->struct_add(vstruct, "S", "PREFIX", &prefix) < 0) {
992 				rpc->fault(ctx, 500, "Internal error adding prefix");
993 				return -1;
994 			}
995 			if (pt->type == MT_TREE_IVAL) {
996 				if(rpc->struct_add(vstruct, "d", "TVALUE", tvalues->tvalue.n) < 0 ) {
997 					rpc->fault(ctx, 500, "Internal error adding tvalue");
998 					return -1;
999 				}
1000 			} else {  /* pt->type == MT_TREE_SVAL */
1001 				if(rpc->struct_add(vstruct, "S", "TVALUE", &tvalues->tvalue.s) < 0 ) {
1002 					rpc->fault(ctx, 500, "Internal error adding tvalue");
1003 					return -1;
1004 				}
1005 			}
1006 			tvalues = tvalues->next;
1007 		}
1008 
1009 		itn = itn[mtch].child;
1010 		l++;
1011 	}
1012 
1013 	if (vstruct == NULL) return -1;
1014 
1015 	return 0;
1016 }
1017 
mt_rpc_match_prefix(rpc_t * rpc,void * ctx,m_tree_t * it,str * tomatch,int mode)1018 int mt_rpc_match_prefix(rpc_t* rpc, void* ctx, m_tree_t *it,
1019 		str *tomatch, int mode)
1020 {
1021 	int l, len, n;
1022 	int i, j;
1023 	mt_node_t *itn;
1024 	is_t *tvalue;
1025 	mt_dw_t *dw;
1026 	int tprefix_len = 0;
1027 	str prefix = STR_NULL;
1028 	void *vstruct = NULL;
1029 
1030 #define MT_MAX_DST_LIST	64
1031 	unsigned int tmp_list[2*(MT_MAX_DST_LIST+1)];
1032 
1033 	if(it==NULL || tomatch == NULL
1034 			|| tomatch->s == NULL)
1035 	{
1036 		LM_ERR("bad parameters\n");
1037 		return -1;
1038 	}
1039 	prefix = *tomatch;
1040 
1041 	if (rpc->add(ctx, "S", &it->tname) < 0) {
1042 		rpc->fault(ctx, 500, "Internal error adding tname");
1043 		return -1;
1044 	}
1045 
1046 	l = len = 0;
1047 	n = 0;
1048 	if ((it->type==MT_TREE_SVAL) || (it->type==MT_TREE_IVAL)) {
1049 		if (mode == 2)
1050 			return mt_rpc_add_tvalues(rpc, ctx, it, tomatch);
1051 		tvalue = mt_get_tvalue(it, tomatch, &tprefix_len);
1052 		if (tvalue == NULL) {
1053 			LM_DBG("no match for: %.*s\n", tomatch->len, tomatch->s);
1054 			return -1;
1055 		}
1056 		if (tvalue) {
1057 			prefix.len = tprefix_len;
1058 			if (rpc->add(ctx, "{", &vstruct) < 0) {
1059 				rpc->fault(ctx, 500, "Internal error adding struct");
1060 				return -1;
1061 			}
1062 			if (rpc->struct_add(vstruct, "S", "PREFIX", &prefix) < 0) {
1063 				rpc->fault(ctx, 500, "Internal error adding prefix");
1064 				return -1;
1065 			}
1066 			if (it->type==MT_TREE_SVAL) {
1067 				if(rpc->struct_add(vstruct, "S", "TVALUE", &tvalue->s) < 0 ) {
1068 					rpc->fault(ctx, 500, "Internal error adding tvalue");
1069 					return -1;
1070 				}
1071 			} else {
1072 				if(rpc->struct_add(vstruct, "d", "TVALUE", tvalue->n) < 0 ) {
1073 					rpc->fault(ctx, 500, "Internal error adding tvalue");
1074 					return -1;
1075 				}
1076 			}
1077 		}
1078 		return 0;
1079 	}
1080 
1081 	if(it->type!=MT_TREE_DW)
1082 		return -1; /* wrong tree type */
1083 
1084 	itn = it->head;
1085 	memset(tmp_list, 0, sizeof(unsigned int)*2*(MT_MAX_DST_LIST+1));
1086 
1087 	while(itn!=NULL && l < tomatch->len && l < MT_MAX_DEPTH)
1088 	{
1089 		unsigned char mtch = _mt_char_table[(unsigned char)tomatch->s[l]];
1090 
1091 		/* check validity */
1092 		if(mtch==MT_CHAR_TABLE_NOTSET)
1093 		{
1094 			LM_ERR("invalid char at %d in [%.*s]\n",
1095 					l, tomatch->len, tomatch->s);
1096 			return -1;
1097 		}
1098 
1099 		if(itn[mtch].tvalues!=NULL)
1100 		{
1101 			dw = (mt_dw_t*)itn[mtch].data;
1102 			while(dw) {
1103 				tmp_list[2*n]=dw->dstid;
1104 				tmp_list[2*n+1]=dw->weight;
1105 				n++;
1106 				if(n==MT_MAX_DST_LIST)
1107 					break;
1108 				dw = dw->next;
1109 			}
1110 			len = l+1;
1111 		}
1112 		if(n==MT_MAX_DST_LIST)
1113 			break;
1114 
1115 		itn = itn[mtch].child;
1116 		l++;
1117 	}
1118 
1119 	if(n==0)
1120 		return -1; /* no match */
1121 	/* invalidate duplicated dstid, keeping longest match */
1122 	for(i=(n-1); i>0; i--)
1123 	{
1124 		if (tmp_list[2*i]!=0)
1125 		{
1126 			for(j=0; j<i; j++)
1127 				if(tmp_list[2*i]==tmp_list[2*j])
1128 					tmp_list[2*j] = 0;
1129 		}
1130 	}
1131 	/* sort the table -- bubble sort -- reverse order */
1132 	for (i = (n - 1); i >= 0; i--)
1133 	{
1134 		for (j = 1; j <= i; j++)
1135 		{
1136 			if (tmp_list[2*(j-1)+1] < tmp_list[2*j+1])
1137 			{
1138 				tmp_list[2*MT_MAX_DST_LIST]   = tmp_list[2*(j-1)];
1139 				tmp_list[2*MT_MAX_DST_LIST+1] = tmp_list[2*(j-1)+1];
1140 				tmp_list[2*(j-1)]   = tmp_list[2*j];
1141 				tmp_list[2*(j-1)+1] = tmp_list[2*j+1];
1142 				tmp_list[2*j]   = tmp_list[2*MT_MAX_DST_LIST];
1143 				tmp_list[2*j+1] = tmp_list[2*MT_MAX_DST_LIST+1];
1144 			}
1145 		}
1146 	}
1147 
1148 	prefix.len = len;
1149 
1150 	/* add as attributes */
1151 	for(i=0; i<n; i++)
1152 	{
1153 		if(tmp_list[2*i]!=0)
1154 		{
1155 			if (rpc->add(ctx, "{", &vstruct) < 0) {
1156 				rpc->fault(ctx, 500, "Internal error adding struct");
1157 				return -1;
1158 			}
1159 			if (rpc->struct_add(vstruct, "S", "PREFIX", &prefix) < 0) {
1160 				rpc->fault(ctx, 500, "Internal error adding prefix");
1161 				return -1;
1162 			}
1163 			if(rpc->add(vstruct, "dd",
1164 					"WEIGHT", tmp_list[2*i+1],
1165 					"DSTID", tmp_list[2*i]) < 0 ) {
1166 				rpc->fault(ctx, 500, "Internal error adding weight/dstid");
1167 				return -1;
1168 			}
1169 		}
1170 	}
1171 
1172 	return 0;
1173 }
1174