pdtree.c

Go to the documentation of this file.
00001 /**
00002  * $Id: pdtree.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * Copyright (C) 2005 Voice Sistem SRL (Voice-System.RO)
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * This file is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  *
00014  * This file is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  * History:
00024  * -------
00025  * 2005-01-25  first tree version (ramona)
00026  * 2006-01-30 multi domain support added (ramona)
00027  */
00028 
00029 #include <stdio.h>
00030 #include <unistd.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 
00034 #include "../../dprint.h"
00035 #include "../../mem/shm_mem.h"
00036 #include "../../ut.h"
00037 
00038 #include "pdtree.h"
00039 
00040 //extern str pdt_char_list = {"1234567890*",11};
00041 extern str pdt_char_list;
00042 
00043 pdt_tree_t* pdt_init_tree(str* sdomain)
00044 {
00045    pdt_tree_t *pt = NULL;
00046 
00047    pt = (pdt_tree_t*)shm_malloc(sizeof(pdt_tree_t));
00048    if(pt==NULL)
00049    {
00050       LM_ERR("no more shm memory\n");
00051       return NULL;
00052    }
00053    memset(pt, 0, sizeof(pdt_tree_t));
00054 
00055    pt->sdomain.s = (char*)shm_malloc((1+sdomain->len)*sizeof(char));
00056    if(pt->sdomain.s==NULL)
00057    {
00058       shm_free(pt);
00059       LM_ERR("no more shm memory\n");
00060       return NULL;
00061    }
00062    memset(pt->sdomain.s, 0,1+sdomain->len );
00063    memcpy(pt->sdomain.s, sdomain->s, sdomain->len);
00064    pt->sdomain.len = sdomain->len;
00065 // printf("sdomain:%.*s\n", pt->sdomain.len, pt->sdomain.s);
00066    
00067    pt->head = (pdt_node_t*)shm_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t));
00068    if(pt->head == NULL)
00069    {
00070       shm_free(pt->sdomain.s);
00071       shm_free(pt);
00072       LM_ERR("no more shm memory\n");
00073       return NULL;
00074    }
00075    memset(pt->head, 0, PDT_NODE_SIZE*sizeof(pdt_node_t));
00076    
00077    return pt;
00078 }
00079 
00080 int add_to_tree(pdt_tree_t *pt, str *sp, str *sd)
00081 {
00082    int l;
00083    pdt_node_t *itn, *itn0;
00084    
00085    if(pt==NULL || sp==NULL || sp->s==NULL
00086          || sd==NULL || sd->s==NULL)
00087    {
00088       LM_ERR("bad parameters\n");
00089       return -1;
00090    }
00091 
00092    if(sp->len>=PDT_MAX_DEPTH)
00093    {
00094       LM_ERR("max prefix len exceeded\n");
00095       return -1;
00096    }
00097    
00098    l = 0;
00099    itn0 = pt->head;
00100    itn = itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].child;
00101 
00102    while(l < sp->len-1)
00103    {
00104       if(strpos(pdt_char_list.s,sp->s[l]) < 0)
00105       {
00106          LM_ERR("invalid char %d in prefix [%c (0x%x)]\n",
00107             l, sp->s[l], sp->s[l]);
00108          return -1;        
00109       }
00110       
00111       if(itn == NULL)
00112       {
00113          itn = (pdt_node_t*)shm_malloc(PDT_NODE_SIZE*sizeof(pdt_node_t));
00114          if(itn == NULL)
00115          {
00116             LM_ERR("no more shm mem\n");
00117             return -1;
00118          }
00119          memset(itn, 0, PDT_NODE_SIZE*sizeof(pdt_node_t));
00120          itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].child = itn;
00121       }
00122       l++;  
00123       itn0 = itn;
00124       itn = itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].child;
00125    }
00126 
00127    if(itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s!=NULL)
00128    {
00129       LM_ERR("prefix already allocated [%.*s/[%.*s]\n",
00130          sp->len, sp->s, sd->len, sd->s);
00131       return -1;
00132    }
00133 
00134    itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s
00135          = (char*)shm_malloc((sd->len+1)*sizeof(char));
00136    if(itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s==NULL)
00137    {
00138       LM_ERR("no more shm mem!\n");
00139       return -1;
00140    }
00141    strncpy(itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s,
00142          sd->s, sd->len);
00143    itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.len = sd->len;
00144    itn0[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s[sd->len]
00145       = '\0';
00146    
00147    return 0;
00148 }
00149 
00150 pdt_tree_t* pdt_get_tree(pdt_tree_t *pl, str *sdomain)
00151 {
00152    pdt_tree_t *it;
00153             
00154    if(pl==NULL)
00155       return NULL;
00156 
00157    if( sdomain==NULL || sdomain->s==NULL)
00158    {
00159       LM_ERR("bad parameters\n");
00160       return NULL;
00161    }
00162 
00163    it = pl;
00164    /* search the tree for the asked sdomain */
00165    while(it!=NULL && str_strcmp(&it->sdomain, sdomain)<0)
00166       it = it->next;
00167 
00168    if(it==NULL || str_strcmp(&it->sdomain, sdomain)>0)
00169       return NULL;
00170    
00171    return it;
00172 }
00173 
00174 int pdt_add_to_tree(pdt_tree_t **dpt, str *sdomain, str *code, str *domain)
00175 {
00176    pdt_tree_t *ndl, *it, *prev;
00177 
00178    if( sdomain==NULL || sdomain->s==NULL
00179          || code==NULL || code->s==NULL
00180          || domain==NULL || domain->s==NULL)
00181    {
00182       LM_ERR("bad parameters\n");
00183       return -1;
00184    }
00185    
00186    ndl = NULL;
00187    
00188    it = *dpt;
00189    prev = NULL;
00190    /* search the it position before which to insert new domain */
00191    while(it!=NULL && str_strcmp(&it->sdomain, sdomain)<0)
00192    {  
00193       prev = it;
00194       it = it->next;
00195    }
00196 // printf("sdomain:%.*s\n", sdomain->len, sdomain->s);
00197 
00198    /* add new sdomain*/
00199    if(it==NULL || str_strcmp(&it->sdomain, sdomain)>0)
00200    {
00201       ndl = pdt_init_tree(sdomain);
00202       if(ndl==NULL)
00203       {
00204          LM_ERR("no more shm memory\n");
00205          return -1; 
00206       }
00207 
00208       if(add_to_tree(ndl, code, domain)<0)
00209       {
00210          LM_ERR("internal error!\n");
00211          return -1;
00212       }
00213       ndl->next = it;
00214       
00215       /* new domain must be added as first element */
00216       if(prev==NULL)
00217          *dpt = ndl;
00218       else
00219          prev->next=ndl;
00220 
00221    }
00222    else 
00223       /* add (prefix, code) to already present sdomain */
00224       if(add_to_tree(it, code, domain)<0)
00225       {
00226          LM_ERR("internal error!\n");
00227          return -1;
00228       }
00229 
00230    return 0;
00231 }
00232 
00233 str* get_domain(pdt_tree_t *pt, str *sp, int *plen)
00234 {
00235    int l, len;
00236    pdt_node_t *itn;
00237    str *domain;
00238 
00239    if(pt==NULL || sp==NULL || sp->s==NULL)
00240    {
00241       LM_ERR("bad parameters\n");
00242       return NULL;
00243    }
00244    
00245    l = len = 0;
00246    itn = pt->head;
00247    domain = NULL;
00248 
00249    while(itn!=NULL && l < sp->len && l < PDT_MAX_DEPTH)
00250    {
00251       /* check validity */
00252       if(strpos(pdt_char_list.s,sp->s[l]) < 0)
00253       {
00254          LM_ERR("invalid char at %d in [%.*s]\n", l, sp->len, sp->s);
00255          return NULL;
00256       }
00257 
00258       if(itn[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain.s!=NULL)
00259       {
00260          domain = &itn[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].domain;
00261          len = l+1;
00262       }
00263       
00264       itn = itn[strpos(pdt_char_list.s,sp->s[l])%PDT_NODE_SIZE].child;
00265       l++;  
00266    }
00267    
00268    if(plen!=NULL)
00269       *plen = len;
00270    
00271    return domain;
00272    
00273 }
00274 str* pdt_get_domain(pdt_tree_t *pl, str* sdomain, str *code, int *plen)
00275 {
00276    pdt_tree_t *it;
00277    int len;
00278    str *domain=NULL;
00279 
00280    if(pl==NULL || sdomain==NULL || sdomain->s==NULL || code == NULL
00281          || code->s == NULL)
00282    {
00283       LM_ERR("bad parameters\n");
00284       return NULL;
00285    }
00286 
00287    it = pl;
00288    while(it!=NULL && str_strcmp(&it->sdomain, sdomain)<0)
00289       it = it->next;
00290    
00291    if(it==NULL || str_strcmp(&it->sdomain, sdomain)>0)
00292       return NULL;
00293    
00294    domain = get_domain(it, code, &len);
00295    if(plen!=NULL)
00296          *plen = len;
00297    return domain;
00298 }
00299 
00300 void pdt_free_node(pdt_node_t *pn)
00301 {
00302    int i;
00303    if(pn==NULL)
00304       return;
00305 
00306    for(i=0; i<PDT_NODE_SIZE; i++)
00307    {
00308       if(pn[i].domain.s!=NULL)
00309       {
00310          shm_free(pn[i].domain.s);
00311          pn[i].domain.s   = NULL;
00312          pn[i].domain.len = 0;
00313       }
00314       if(pn[i].child!=NULL)
00315       {
00316          pdt_free_node(pn[i].child);
00317          pn[i].child = NULL;
00318       }
00319    }
00320    shm_free(pn);
00321    pn = NULL;
00322    
00323    return;
00324 }
00325 
00326 void pdt_free_tree(pdt_tree_t *pt)
00327 {
00328    if(pt == NULL)
00329       return;
00330 
00331    if(pt->head!=NULL) 
00332       pdt_free_node(pt->head);
00333    if(pt->next!=NULL)
00334       pdt_free_tree(pt->next);
00335    if(pt->sdomain.s!=NULL)
00336       shm_free(pt->sdomain.s);
00337    
00338    shm_free(pt);
00339    pt = NULL;
00340    return;
00341 }
00342 
00343 int pdt_print_node(pdt_node_t *pn, char *code, int len)
00344 {
00345    int i;
00346 
00347    if(pn==NULL || code==NULL || len>=PDT_MAX_DEPTH)
00348       return 0;
00349    
00350    for(i=0; i<PDT_NODE_SIZE; i++)
00351    {
00352       code[len]=pdt_char_list.s[i];
00353       if(pn[i].domain.s!=NULL)
00354          LM_DBG("[%.*s] [%.*s]\n",
00355                len+1, code, pn[i].domain.len, pn[i].domain.s);
00356       pdt_print_node(pn[i].child, code, len+1);
00357    }
00358 
00359    return 0;
00360 }
00361 
00362 static char pdt_code_buf[PDT_MAX_DEPTH+1];
00363 int pdt_print_tree(pdt_tree_t *pt)
00364 {
00365    int len;
00366 
00367    if(pt == NULL)
00368    {
00369       LM_DBG("tree is empty\n");
00370       return 0;
00371    }
00372    
00373    LM_DBG("[%.*s]\n", pt->sdomain.len, pt->sdomain.s);
00374    len = 0;
00375    pdt_print_node(pt->head, pdt_code_buf, len);
00376    return pdt_print_tree(pt->next);
00377 }
00378 
00379 int pdt_check_pd_node(pdt_node_t *pn, str *sp, str *sd,
00380       char *code, int len)
00381 {
00382    int i;
00383    int ret;
00384  
00385    if(pn==NULL || code==NULL || len>=PDT_MAX_DEPTH)
00386       return 0;
00387    ret = 0;
00388    for(i=0; i<PDT_NODE_SIZE; i++)
00389    {
00390       code[len]=pdt_char_list.s[i];
00391       if(pn[i].domain.s!=NULL)
00392       {
00393          /* we have a domain - check for duplicates */
00394          LM_DBG("[%.*s] [%.*s]\n",
00395                len+1, code, pn[i].domain.len, pn[i].domain.s);
00396          if(sp->len == len+1 &&
00397                strncmp(sp->s, code, sp->len)==0)
00398          {
00399             LM_DBG("duplicated prefix\n");
00400             return 1;
00401          }
00402          if(sd->len == pn[i].domain.len &&
00403                strncmp(sd->s, pn[i].domain.s, sd->len)==0)
00404          {
00405             LM_DBG("duplicated domain\n");
00406             return 1;
00407          }
00408       }
00409       ret = pdt_check_pd_node(pn[i].child, sp, sd, code, len+1);
00410       if(ret != 0)
00411          break;
00412    }
00413 
00414    return ret;
00415 }
00416 
00417 /* returns 
00418  * 1 if prefix or domain already exists 
00419  * 0 if prefix or domain does not exist
00420  * -1 if any error
00421  */
00422 int pdt_check_pd(pdt_tree_t *pt, str* sdomain, str *sp, str *sd)
00423 {
00424    int len;
00425    int ret;
00426    pdt_tree_t *it;
00427       
00428    if(pt==NULL || sp==NULL || sd==NULL)
00429    {
00430       LM_ERR("bad parameters\n");
00431       return -1;
00432    }
00433 
00434    it = pt;
00435    while(it!=NULL)
00436    {
00437       if(it->sdomain.len==sdomain->len
00438             && strncasecmp(it->sdomain.s, sdomain->s, sdomain->len)==0)
00439          break;
00440       it = it->next;
00441    }
00442    if(it == NULL)
00443       return 0;
00444 
00445    len = 0;
00446    ret = pdt_check_pd_node(it->head, sp, sd, pdt_code_buf, len);
00447    return ret;
00448 }
00449 

Generated on Thu May 24 02:00:29 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6