prefix_tree.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2005-2009 Voice Sistem SRL
  5. *
  6. * This file is part of Kamailio, a free SIP server.
  7. *
  8. * Kamailio 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. * Kamailio is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21. *
  22. * History:
  23. * ---------
  24. * 2005-02-20 first version (cristian)
  25. * 2005-02-27 ported to 0.9.0 (bogdan)
  26. */
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include "../../str.h"
  30. #include "../../mem/shm_mem.h"
  31. #include "prefix_tree.h"
  32. #include "routing.h"
  33. #include "dr_time.h"
  34. extern int inode;
  35. extern int unode;
  36. static inline int
  37. check_time(
  38. tmrec_t *time_rec
  39. )
  40. {
  41. ac_tm_t att;
  42. /* shortcut: if there is no dstart, timerec is valid */
  43. if (time_rec->dtstart==0)
  44. return 1;
  45. memset( &att, 0, sizeof(att));
  46. /* set current time */
  47. if ( ac_tm_set_time( &att, time(0) ) )
  48. return 0;
  49. /* does the recv_time match the specified interval? */
  50. if (check_tmrec( time_rec, &att, 0)!=0)
  51. return 0;
  52. return 1;
  53. }
  54. static inline rt_info_t*
  55. internal_check_rt(
  56. ptree_node_t *ptn,
  57. unsigned int rgid
  58. )
  59. {
  60. int i;
  61. int rg_pos=0;
  62. rg_entry_t* rg=NULL;
  63. rt_info_wrp_t* rtlw=NULL;
  64. if((NULL==ptn) || (NULL==ptn->rg))
  65. goto err_exit;
  66. rg_pos = ptn->rg_pos;
  67. rg=ptn->rg;
  68. for(i=0;(i<rg_pos) && (rg[i].rgid!=rgid);i++);
  69. if(i<rg_pos) {
  70. LM_DBG("found rgid %d (rule list %p)\n",
  71. rgid, rg[i].rtlw);
  72. rtlw=rg[i].rtlw;
  73. while(rtlw!=NULL) {
  74. if(check_time(rtlw->rtl->time_rec))
  75. goto ok_exit;
  76. rtlw=rtlw->next;
  77. }
  78. }
  79. err_exit:
  80. return NULL;
  81. ok_exit:
  82. return rtlw?rtlw->rtl:0;
  83. }
  84. rt_info_t*
  85. check_rt(
  86. ptree_node_t *ptn,
  87. unsigned int rgid
  88. )
  89. {
  90. return internal_check_rt( ptn, rgid);
  91. }
  92. rt_info_t*
  93. get_prefix(
  94. ptree_t *ptree,
  95. str* prefix,
  96. unsigned int rgid
  97. )
  98. {
  99. rt_info_t *rt = NULL;
  100. char *tmp=NULL;
  101. char local=0;
  102. int idx=0;
  103. if(NULL == ptree)
  104. goto err_exit;
  105. if(NULL == prefix)
  106. goto err_exit;
  107. tmp = prefix->s;
  108. /* go the tree down to the last digit in the
  109. * prefix string or down to a leaf */
  110. while(tmp< (prefix->s+prefix->len)) {
  111. if(NULL == tmp)
  112. goto err_exit;
  113. local=*tmp;
  114. if( !IS_DECIMAL_DIGIT(local) ) {
  115. /* unknown character in the prefix string */
  116. goto err_exit;
  117. }
  118. if( tmp == (prefix->s+prefix->len-1) ) {
  119. /* last digit in the prefix string */
  120. break;
  121. }
  122. idx = local -'0';
  123. if( NULL == ptree->ptnode[idx].next) {
  124. /* this is a leaf */
  125. break;
  126. }
  127. ptree = ptree->ptnode[idx].next;
  128. tmp++;
  129. }
  130. /* go in the tree up to the root trying to match the
  131. * prefix */
  132. while(ptree !=NULL ) {
  133. if(NULL == tmp)
  134. goto err_exit;
  135. /* is it a real node or an intermediate one */
  136. idx = *tmp-'0';
  137. if(NULL != ptree->ptnode[idx].rg) {
  138. /* real node; check the constraints on the routing info*/
  139. if( NULL != (rt = internal_check_rt( &(ptree->ptnode[idx]), rgid)))
  140. break;
  141. }
  142. tmp--;
  143. ptree = ptree->bp;
  144. }
  145. return rt;
  146. err_exit:
  147. return NULL;
  148. }
  149. pgw_t*
  150. get_pgw(
  151. pgw_t* pgw_l,
  152. long id
  153. )
  154. {
  155. if(NULL==pgw_l)
  156. goto err_exit;
  157. while(NULL != pgw_l) {
  158. if(id == pgw_l->id) {
  159. return pgw_l;
  160. }
  161. pgw_l = pgw_l->next;
  162. }
  163. err_exit:
  164. return NULL;
  165. }
  166. int
  167. add_prefix(
  168. ptree_t *ptree,
  169. str* prefix,
  170. rt_info_t *r,
  171. unsigned int rg
  172. )
  173. {
  174. char* tmp=NULL;
  175. int res = 0;
  176. if(NULL==ptree)
  177. goto err_exit;
  178. tmp = prefix->s;
  179. while(tmp < (prefix->s+prefix->len)) {
  180. if(NULL == tmp)
  181. goto err_exit;
  182. if( !IS_DECIMAL_DIGIT(*tmp) ) {
  183. /* unknown character in the prefix string */
  184. goto err_exit;
  185. }
  186. if( tmp == (prefix->s+prefix->len-1) ) {
  187. /* last digit in the prefix string */
  188. LM_DBG("adding info %p, %d at: "
  189. "%p (%d)\n", r, rg, &(ptree->ptnode[*tmp-'0']), *tmp-'0');
  190. res = add_rt_info(&(ptree->ptnode[*tmp-'0']), r,rg);
  191. if(res < 0 )
  192. goto err_exit;
  193. unode++;
  194. res = 1;
  195. goto ok_exit;
  196. }
  197. /* process the current digit in the prefix */
  198. if(NULL == ptree->ptnode[*tmp - '0'].next) {
  199. /* allocate new node */
  200. INIT_PTREE_NODE(ptree, ptree->ptnode[*tmp - '0'].next);
  201. inode+=10;
  202. #if 0
  203. printf("new tree node: %p (bp: %p)\n",
  204. ptree->ptnode[*tmp - '0'].next,
  205. ptree->ptnode[*tmp - '0'].next->bp
  206. );
  207. #endif
  208. }
  209. ptree = ptree->ptnode[*tmp-'0'].next;
  210. tmp++;
  211. }
  212. ok_exit:
  213. return 0;
  214. err_exit:
  215. return -1;
  216. }
  217. int
  218. del_tree(
  219. ptree_t* t
  220. )
  221. {
  222. int i,j;
  223. if(NULL == t)
  224. goto exit;
  225. /* delete all the children */
  226. for(i=0; i< PTREE_CHILDREN; i++) {
  227. /* shm_free the rg array of rt_info */
  228. if(NULL!=t->ptnode[i].rg) {
  229. for(j=0;j<t->ptnode[i].rg_pos;j++) {
  230. /* if non intermediate delete the routing info */
  231. if(t->ptnode[i].rg[j].rtlw !=NULL)
  232. del_rt_list(t->ptnode[i].rg[j].rtlw);
  233. }
  234. shm_free(t->ptnode[i].rg);
  235. }
  236. /* if non leaf delete all the children */
  237. if(t->ptnode[i].next != NULL)
  238. del_tree(t->ptnode[i].next);
  239. }
  240. shm_free(t);
  241. exit:
  242. return 0;
  243. }
  244. void
  245. del_rt_list(
  246. rt_info_wrp_t *rwl
  247. )
  248. {
  249. rt_info_wrp_t* t=rwl;
  250. while(rwl!=NULL) {
  251. t=rwl;
  252. rwl=rwl->next;
  253. if ( (--t->rtl->ref_cnt)==0)
  254. free_rt_info(t->rtl);
  255. shm_free(t);
  256. }
  257. }
  258. void
  259. free_rt_info(
  260. rt_info_t *rl
  261. )
  262. {
  263. if(NULL == rl)
  264. return;
  265. if(NULL!=rl->pgwl)
  266. shm_free(rl->pgwl);
  267. if(NULL!=rl->time_rec)
  268. tmrec_free(rl->time_rec);
  269. shm_free(rl);
  270. return;
  271. }
  272. void
  273. print_rt(
  274. rt_info_t*rt
  275. )
  276. {
  277. int i=0;
  278. if(NULL==rt)
  279. return;
  280. printf("priority:%d list of gw:\n", rt->priority);
  281. for(i=0;i<rt->pgwa_len;i++)
  282. if(NULL!=rt->pgwl[i].pgw)
  283. printf(" id:%ld pri:%.*s ip:%.*s \n",
  284. rt->pgwl[i].pgw->id,
  285. rt->pgwl[i].pgw->pri.len, rt->pgwl[i].pgw->pri.s,
  286. rt->pgwl[i].pgw->ip.len, rt->pgwl[i].pgw->ip.s);
  287. }