registrar_storage.c

Go to the documentation of this file.
00001 /*
00002  * $Id: registrar_storage.c 591 2008-10-15 12:46:34Z vingarzan $
00003  *  
00004  * Copyright (C) 2004-2006 FhG Fokus
00005  *
00006  * This file is part of Open IMS Core - an open source IMS CSCFs & HSS
00007  * implementation
00008  *
00009  * Open IMS Core is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * For a license to use the Open IMS Core software under conditions
00015  * other than those described here, or to purchase support for this
00016  * software, please contact Fraunhofer FOKUS by e-mail at the following
00017  * addresses:
00018  *     info@open-ims.org
00019  *
00020  * Open IMS Core is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * It has to be noted that this Open Source IMS Core System is not 
00026  * intended to become or act as a product in a commercial context! Its 
00027  * sole purpose is to provide an IMS core reference implementation for 
00028  * IMS technology testing and IMS application prototyping for research 
00029  * purposes, typically performed in IMS test-beds.
00030  * 
00031  * Users of the Open Source IMS Core System have to be aware that IMS
00032  * technology may be subject of patents and licence terms, as being 
00033  * specified within the various IMS-related IETF, ITU-T, ETSI, and 3GPP
00034  * standards. Thus all Open IMS Core users have to take notice of this 
00035  * fact and have to agree to check out carefully before installing, 
00036  * using and extending the Open Source IMS Core System, if related 
00037  * patents and licences may become applicable to the intended usage 
00038  * context.  
00039  *
00040  * You should have received a copy of the GNU General Public License
00041  * along with this program; if not, write to the Free Software
00042  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00043  * 
00044  */
00045  
00056 /*
00057  * 
00058  * Big change done, a new hash slot is added at the end of the table.
00059  * All the wildcarded PSIs will be added there in the r_public format 
00060  * the functions update_r_public, update_r_public_previous_lock are the ones
00061  * that will check that the subscription being saved is a wildcarded PSI and
00062  * will then insert it in the last slot
00063  * 
00064  * The function get_r_public will try to match the aor given with the wildcarded PSIs
00065  * if there is no record for that aor. 
00066  * 
00067  * 
00068  * \Author Alberto Diez  alberto dot diez -at- fokus dot fraunhofer dot de
00069  * 
00070  * 
00071  * r_storage_init changed to add 1 slot more
00072  * r_storage_destroy changed to delete 1 slot more
00073  * new_r_public changed, if its a wpsi then i give the fixed hash number (r_hash_size)
00074  *              and i compile the regexp and save it in the r_public->regexp
00075  * 
00076  * 
00077 */
00078 
00079 
00080 
00081 
00082 
00083 
00084 
00085 
00086 
00087 
00088 
00089 #include <time.h>
00090 
00091 #include "mod.h"
00092 #include "registrar_storage.h"
00093 #include "dlg_state.h"
00094 
00095 
00096 extern struct tm_binds tmb;            
00098 extern int scscf_support_wildcardPSI;
00099 
00100 int r_hash_size;                        
00101 r_hash_slot *registrar=0;               
00104 time_t time_now;                        
00109 inline void r_act_time()
00110 {
00111     time_now=time(0);
00112 }
00113 
00120 inline int r_valid_contact(r_contact *c)
00121 {
00122     return (c->expires>time_now);
00123 }
00124 
00131 inline int r_valid_subscriber(r_subscriber *s)
00132 {
00133     return (s->expires>time_now);
00134 }
00135 
00142 inline unsigned int get_aor_hash(str aor,int hash_size)
00143 {
00144 #define h_inc h+=v^(v>>3)
00145    char* p;
00146    register unsigned v;
00147    register unsigned h;
00148 
00149    h=0;
00150    for (p=aor.s; p<=(aor.s+aor.len-4); p+=4){
00151        v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
00152        h_inc;
00153    }
00154    v=0;
00155    for (;p<(aor.s+aor.len); p++) {
00156        v<<=8;
00157        v+=*p;
00158    }
00159    h_inc;
00160 
00161    h=((h)+(h>>11))+((h>>13)+(h>>23));
00162    return (h)%hash_size;
00163 #undef h_inc 
00164 }
00165 
00171 int r_storage_init(int hash_size)
00172 {
00173     int i;
00174     
00175     r_hash_size = hash_size;
00176     registrar = shm_malloc(sizeof(r_hash_slot)*(r_hash_size+1)); // 1 slot extra for the WildPSI
00177     memset(registrar,0,sizeof(r_hash_slot)*(r_hash_size+1));
00178     
00179     for(i=0;i<r_hash_size+1;i++){
00180         registrar[i].lock = lock_alloc();
00181         if (!registrar[i].lock){
00182             LOG(L_ERR,"ERR:"M_NAME":r_storage_init(): Error creating lock\n");
00183             return 0;
00184         }
00185         registrar[i].lock = lock_init(registrar[i].lock);
00186     }
00187             
00188     if (!registrar) return 0;
00189     
00190     return 1;
00191 }
00192 
00196 void r_storage_destroy()
00197 {
00198     int i;
00199     r_public *p,*np;
00200     for(i=0;i<r_hash_size+1;i++){
00201         r_lock(i);
00202             p = registrar[i].head;
00203             while(p){
00204                 np = p->next;
00205                 free_r_public(p);
00206                 p = np;
00207             }
00208         r_unlock(i);
00209         lock_dealloc(registrar[i].lock);
00210     }
00211     shm_free(registrar);
00212 }
00213 
00214 
00219 inline void r_lock(unsigned int hash)
00220 {
00221     // LOG(L_CRIT,"GET %d\n",hash);
00222     lock_get(registrar[(hash)].lock);
00223     // LOG(L_CRIT,"GOT %d\n",hash); 
00224 }
00225 
00230 inline void r_unlock(unsigned int hash)
00231 {
00232     lock_release(registrar[(hash)].lock);
00233     // LOG(L_CRIT,"RELEASED %d\n",hash);    
00234 }
00235 
00236 
00237 
00238 
00248 r_subscriber* new_r_subscriber(str subscriber,int event,int expires,dlg_t *dialog)
00249 {
00250     r_subscriber *s;
00251     
00252     s = shm_malloc(sizeof(r_subscriber));
00253     if (!s) {
00254         LOG(L_ERR,"ERR:"M_NAME":new_r_subscriber(): Unable to alloc %d bytes\n",
00255             sizeof(r_subscriber));
00256         goto error;
00257     }
00258     memset(s,0,sizeof(r_subscriber));
00259     
00260     STR_SHM_DUP(s->subscriber,subscriber,"new_r_subscriber");
00261     
00262     s->event = event;
00263     
00264     s->expires = expires;
00265 
00266     s->dialog = dialog;
00267                     
00268     return s;
00269 error:
00270 out_of_memory:
00271     if (s){
00272         if (s->subscriber.s) shm_free(s->subscriber.s);
00273         shm_free(s);        
00274     }
00275     return 0;
00276 }
00277 
00278 
00286 r_subscriber* get_r_subscriber(r_public *p, str subscriber,int event)
00287 {
00288     r_subscriber *s=0;
00289     if (!p) return 0;
00290     s = p->shead;
00291     while(s){
00292         if (s->event == event &&
00293             s->subscriber.len == subscriber.len &&
00294             strncasecmp(s->subscriber.s,subscriber.s,subscriber.len)==0) return s;
00295         s = s->next;
00296     }
00297     return 0;
00298 }
00299 
00310 r_subscriber* add_r_subscriber(r_public  *p,str subscriber,int event,int expires,dlg_t *dialog)
00311 {
00312     r_subscriber *s;
00313 
00314     if (!p) return 0;
00315     
00316     s = new_r_subscriber(subscriber,event,expires,dialog);
00317     if (!s) return 0;       
00318     s->next = 0;
00319     s->prev = p->stail;
00320     if (p->stail) p->stail->next = s;
00321     p->stail = s;
00322     if (!p->shead) p->shead=s;
00323     
00324     return s;
00325 }
00326 
00337 r_subscriber* update_r_subscriber(r_public *p,str subscriber,int event,int* expires,dlg_t *dialog)
00338 {
00339     r_subscriber *s;
00340     
00341     if (!p) return 0;
00342     s = get_r_subscriber(p,subscriber,event);
00343     if (!s){
00344         if (expires)
00345             return add_r_subscriber(p,subscriber,event,*expires,dialog);
00346         else return 0;
00347     }else{
00348         if (expires) s->expires = *expires;
00349         if (s->dialog && s->dialog!=dialog) tmb.free_dlg(s->dialog);
00350         s->dialog = dialog;
00351         return s;
00352     }
00353 }
00354 
00361 void del_r_subscriber(r_public *p,r_subscriber *s)
00362 {
00363 //  LOG(L_ERR,"DBG:"M_NAME":del_r_subscriber: LIST: %p --> %p\n",p->shead,p->stail);
00364 //  LOG(L_ERR,"DBG:"M_NAME":del_r_subscriber: %p<- S:%p ->%p\n",s->prev,s,s->next); 
00365     if (p->shead == s) p->shead = s->next;
00366     else s->prev->next = s->next;
00367     if (p->stail == s) p->stail = s->prev;
00368     else s->next->prev = s->prev;
00369     if (s->dialog) tmb.free_dlg(s->dialog);
00370     
00371     free_r_subscriber(s);
00372 }
00373 
00378 void free_r_subscriber(r_subscriber *s)
00379 {
00380     if (!s) return;
00381     if (s->subscriber.s) shm_free(s->subscriber.s);
00382     shm_free(s);
00383 }
00384 
00385 
00392 r_contact* get_r_contact(r_public *p, str uri)
00393 {
00394     r_contact *c=0;
00395     if (!p) return 0;
00396     c = p->head;
00397     while(c){
00398         if (c->uri.len == uri.len &&
00399             strncasecmp(c->uri.s,uri.s,uri.len)==0) return c;
00400         c = c->next;
00401     }
00402     return 0;
00403 }
00404 
00415 r_contact* new_r_contact(str uri,int expires,str ua,str path,qvalue_t qvalue)
00416 {
00417     r_contact *c;
00418     
00419     c = shm_malloc(sizeof(r_contact));
00420     if (!c) {
00421         LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
00422             sizeof(r_contact));
00423         goto error;
00424     }
00425     memset(c,0,sizeof(r_contact));
00426     
00427     c->uri.s = shm_malloc(uri.len);
00428     if (!c->uri.s){
00429         LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
00430             uri.len);
00431         goto error;
00432     }   
00433     c->uri.len = uri.len;
00434     memcpy(c->uri.s,uri.s,uri.len);
00435     
00436     c->expires = expires;
00437     
00438     c->ua.s = shm_malloc(ua.len);
00439     if (!c->ua.s){
00440         LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
00441             ua.len);
00442         goto error;
00443     }
00444     c->ua.len = ua.len;
00445     memcpy(c->ua.s,ua.s,ua.len);    
00446 
00447     if (path.len){
00448         c->path.s = shm_malloc(path.len);
00449         if (!c->path.s){
00450             LOG(L_ERR,"ERR:"M_NAME":new_r_contact(): Unable to alloc %d bytes\n",
00451                 path.len);
00452             goto error;
00453         }
00454         c->path.len = path.len;
00455         memcpy(c->path.s,path.s,path.len);  
00456     }
00457 
00458     c->qvalue = qvalue;
00459         
00460     return c;
00461 error:
00462     if (c){
00463         if (c->uri.s) shm_free(c->uri.s);
00464         if (c->ua.s) shm_free(c->ua.s);
00465         shm_free(c);
00466             
00467     }
00468     return 0;
00469 }
00470 
00482 r_contact* add_r_contact(r_public *p,str uri,int expires,str ua,str path,qvalue_t qvalue)
00483 {
00484     r_contact *c;
00485     if (!p) return 0;
00486     c = new_r_contact(uri,expires,ua,path,qvalue);
00487     if (!c) return 0;
00488     c->next=0;
00489     c->prev=p->tail;
00490     if (p->tail) {
00491         p->tail->next = c;
00492         p->tail = c;
00493     }
00494     else p->tail = c;
00495     if (!p->head) p->head=c;
00496     
00497     return c;
00498 }
00499 
00512 r_contact* update_r_contact(r_public *p,str uri,int *expires, str *ua,str *path,qvalue_t qvalue)
00513 {
00514     r_contact *c;
00515     
00516     if (!p) return 0;
00517     c = get_r_contact(p,uri);
00518     if (!c){
00519         if (expires && ua && path)
00520             return add_r_contact(p,uri,*expires,*ua,*path,qvalue);
00521         else return 0;
00522     }else{
00523         if (expires) c->expires = *expires;
00524         if (ua){
00525             if (c->ua.s) shm_free(c->ua.s);
00526             c->ua.s = shm_malloc(ua->len);
00527             if (!c->ua.s) {
00528                 LOG(L_ERR,"ERR:"M_NAME":update_r_contact(): Error allocating %d bytes\n",
00529                     ua->len);
00530                 c->ua.len=0;
00531                 return 0;
00532             }
00533             c->ua.len = ua->len;
00534             memcpy(c->ua.s,ua->s,ua->len);
00535         }
00536         if (path){
00537             if (c->path.s) shm_free(c->path.s);
00538             c->path.s = shm_malloc(path->len);
00539             if (!c->path.s) {
00540                 LOG(L_ERR,"ERR:"M_NAME":update_r_contact(): Error allocating %d bytes\n",
00541                     path->len);
00542                 c->path.len=0;
00543                 return 0;
00544             }
00545             c->path.len = path->len;
00546             memcpy(c->path.s,path->s,path->len);
00547         }
00548         c->qvalue = qvalue;
00549         return c;
00550     }
00551 }
00552 
00559 void del_r_contact(r_public *p,r_contact *c)
00560 {
00561     if (p->head == c) p->head = c->next;
00562     else c->prev->next = c->next;
00563     if (p->tail == c) p->tail = c->prev;
00564     else c->next->prev = c->prev;
00565     free_r_contact(c);
00566 }
00571 void free_r_contact(r_contact *c)
00572 {
00573     if (!c) return;
00574     if (c->uri.s) shm_free(c->uri.s);
00575     if (c->ua.s) shm_free(c->ua.s);
00576     if (c->path.s) shm_free(c->path.s);
00577     shm_free(c);
00578 }
00579 
00580 
00581 void free_regexp_list(t_regexp_list **regexp);
00582 
00583 /*
00584  * This function just needed because for regexp * by itself has no meaning
00585  * it has to be .* that means any character none or more times
00586  *  * ->.*
00587  *  ? ->.  or .?  we do .? because it is more logical
00588  *  . -> \.
00589  *  and we terminate it with \0 because its for regcomp
00590 */
00591 char *escape_all_wildcards_and_copy(str wpsi)
00592 {
00593     char *res;
00594     int i,j,len;
00595     len=1+wpsi.len; // the \0
00596     j=0;
00597     //first lets see how many wildcards there are to see how much space is needed
00598     for (i=0;i<wpsi.len;i++)
00599     {
00600         switch(wpsi.s[i])
00601         {
00602             case '?': case '*':// case '.':
00603                 len++;
00604                 break;
00605         }
00606     }
00607     res=shm_malloc(len);
00608     // then do the copy
00609     for (i=0;i<wpsi.len;i++)
00610     {
00611         switch(wpsi.s[i]) {
00612             case '.':
00613                 res[j++]='\\';
00614                 res[j++]=wpsi.s[i];
00615                 break;
00616             case '?' : case '*':
00617                 res[j++]='.';
00618             default :
00619                 res[j++]=wpsi.s[i]; 
00620                 break;
00621         }
00622     }
00623     res[j]=0;
00624     return res;
00625 }
00626 
00638 r_public* new_r_public(str aor, enum Reg_States reg_state, ims_subscription *s)
00639 {
00640     r_public *p;
00641     
00642     /*I didn't want to make this so complicated..*/
00643     t_regexp_unit *newwpsi;
00644     char *temp=0;
00645     int i,j;
00646     //int len;
00647     //int errcode;
00648     
00649     p = shm_malloc(sizeof(r_public));
00650     if (!p){
00651         LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
00652             sizeof(r_public));
00653         goto error;
00654     }   
00655     memset(p,0,sizeof(r_public));
00656     if (s->wpsi !=1)
00657     {
00658         //very sensible thing to do...
00659         p->hash = get_aor_hash(aor,r_hash_size);
00660         
00661     } else {
00662         
00663         //here it gets a bit complicated
00664         
00665         /* if its a wildcarded psi....*/
00666         p->hash=r_hash_size;
00667         /*will be in the last slot*/
00668         p->regexp=shm_malloc(sizeof(t_regexp_list));
00669         p->regexp->head=NULL;
00670         p->regexp->tail=NULL;
00671         /*lets compile the regular expression and compile it..*/
00672         for (i=0;i<s->service_profiles_cnt;i++)
00673         {
00674             for (j=0;j<s->service_profiles[i].public_identities_cnt;j++)
00675             {
00676                 if (s->service_profiles[i].public_identities[j].wildcarded_psi.s && s->service_profiles[i].public_identities[j].wildcarded_psi.len>0)
00677                  {
00678                     // for each wildcardpsi we add a member to the regexp list in the r_public
00679                     newwpsi=shm_malloc(sizeof(t_regexp_unit));
00680                     newwpsi->next=NULL;
00681                     newwpsi->prev=NULL;
00682                     // now we have to deal with using an external function that expects
00683                     // some string with a finishing \0 character
00684                     //len=s->service_profiles[i].public_identities[j].wildcarded_psi.len;
00685                     temp=escape_all_wildcards_and_copy(s->service_profiles[i].public_identities[j].wildcarded_psi);
00686                     //temp=shm_malloc(len+1);
00687                     //memcpy(temp,s->service_profiles[i].public_identities[j].wildcarded_psi.s,len);
00688                     //temp[len]=0;
00689                     LOG(L_DBG,"New_r_public : REGULAR EXPRESSION is %s\n\n",temp);
00690                     /*errcode=regcomp(&(newwpsi->exp),temp,REG_ICASE|REG_EXTENDED|REG_NOSUB);
00691                     if(errcode!=0)
00692                     {
00693                         // there was an error
00694                         LOG(L_DBG,"there was at least ONE error in regcomp %i\n",errcode);
00695                         //shm_free(temp); temp=NULL;
00696                         len=regerror(errcode,&(newwpsi->exp),NULL,0);
00697                         temp=shm_malloc(len);
00698                         regerror(errcode,&(newwpsi->exp),temp,len);
00699                         LOG(L_DBG,"and that was %s",temp);
00700                         shm_free(temp); temp=NULL;
00701                         
00702                         shm_free(newwpsi);
00703                         goto error;
00704                     }*/
00705                     newwpsi->s=temp;
00706                     //LOG(L_DBG,"there was NO error in regcomp\n");
00707                     //shm_free(temp); temp=NULL;
00708                     newwpsi->prev=p->regexp->tail;
00709                     if (p->regexp->tail)
00710                     {
00711                         p->regexp->tail->next=newwpsi;
00712                         p->regexp->tail=newwpsi;
00713                     } else {
00714                         // no tail means no head too...
00715                         p->regexp->head=newwpsi;
00716                         p->regexp->tail=newwpsi;
00717                     }
00718                     
00719                 }
00720             }
00721         }
00722         
00723         
00724         
00725             
00726         
00727     }
00728     //LOG(L_DBG,"after the mess inside new_r_public\n");
00729     p->aor.s = shm_malloc(aor.len); // I wonder if this should be done in the case of wildpsi
00730     if (!p->aor.s){
00731         LOG(L_ERR,"ERR:"M_NAME":new_r_public(): Unable to alloc %d bytes\n",
00732             aor.len);
00733         goto error;
00734     }
00735     p->aor.len = aor.len;
00736     memcpy(p->aor.s,aor.s,aor.len);
00737     
00738     p->reg_state = reg_state;
00739     
00740     p->s = s;
00741     if (s) {
00742         lock_get(s->lock);
00743         s->ref_count++;
00744         lock_release(s->lock);
00745     }
00746     //LOG(L_DBG,"new_r_public we are returning %p\n",p);    
00747     return p;
00748 error:
00749     if (p){
00750         if (p->aor.s) shm_free(p->aor.s);
00751         // free the regexp list of shit!    
00752         if (p->regexp) free_regexp_list(&(p->regexp));
00753         //if (temp) shm_free(temp);
00754         shm_free(p);
00755     }
00756     //LOG(L_DBG,"new_r_public we are returning error\n");   
00757     return 0;   
00758 }
00759 
00760 
00761 
00762 
00770 r_public* get_matching_wildcard_psi(str aor)
00771 {
00772     r_public *p=0;
00773     t_regexp_unit *t;
00774     regex_t exp;
00775     char *c,*temp;
00776     int len;
00777     int errcode;
00778     
00779     p = registrar[r_hash_size].head;
00780     
00781     r_lock(r_hash_size);
00782     
00783     while (p)
00784     {
00785         
00786         for(t=p->regexp->head;t;t=t->next)
00787         {
00788             LOG(L_DBG,"get_matching_wildcard_psi match %.*s with %s\n",aor.len,aor.s,t->s);
00789             
00790             c=shm_malloc((aor.len)+1);
00791             memcpy(c,aor.s,aor.len);
00792             c[aor.len]='\0';
00793             
00794             
00795                     errcode=regcomp(&(exp),t->s,REG_ICASE|REG_EXTENDED|REG_NOSUB);
00796                     if(errcode!=0)
00797                     {
00798                         // there was an error
00799                         LOG(L_DBG,"there was at least ONE error in regcomp %i\n",errcode);
00800                         //shm_free(temp); temp=NULL;
00801                         len=regerror(errcode,&(exp),NULL,0);
00802                         temp=shm_malloc(len);
00803                         regerror(errcode,&(exp),temp,len);
00804                         LOG(L_DBG,"and that was %s",temp);
00805                         shm_free(temp); temp=NULL;
00806                         //shm_free(newwpsi);
00807                         r_unlock(r_hash_size);
00808                         return NULL;
00809                     }
00810                     
00811             
00812             if (regexec(&(exp),c,0,NULL,0)==0)
00813             {
00814                 //LOG(L_DBG,"A match has been produced!!!!!\n");
00815                 shm_free(c);
00816                 return p;
00817             } else 
00818             {
00819                 //LOG(L_ERR,"there was no match\n");
00820             }
00821             shm_free(c);                 
00822         }       
00823         p=p->next;
00824     }
00825     LOG(L_ERR,"get_r_public (Trying wildcard PSI) found no match\n");
00826     r_unlock(r_hash_size);
00827     
00828     return 0;
00829 }
00830 
00831 
00832 
00839 r_public* get_r_public(str aor)
00840 {
00841     r_public *p=0;
00842     unsigned int hash;
00843     hash = get_aor_hash(aor,r_hash_size);
00844     r_lock(hash);
00845     p = registrar[hash].head;
00846     while(p){
00847         if (p->aor.len == aor.len &&
00848             strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
00849         p = p->next;
00850     }
00851     r_unlock(hash);
00852     
00853     /*
00854      * Here i plan to put the function that tries to match the aor with the wPSI
00855      * There might be an issue 
00856      * if i return this locked, then i have to wait for the lock in the next one...
00857      * mmmh... might be an issue
00858      * */
00859      if (scscf_support_wildcardPSI)
00860         return(get_matching_wildcard_psi(aor));
00861      else
00862         return 0;
00863      
00864 }
00865 
00866 /* This function gets a r_public record from the Wildcarded PSI slot whose  Public Identity
00867  * is equal to the one given as an argument. 
00868  * Main costumer is update_r_public, because there you dont want to find an AOR to send a message
00869  * but you really want the record..  first of being use check its a WildCardPSI
00870  * \note Aquires the lock of the hash on success, so release it when you are done
00871  * @param pi -the public identity of the WildCardPSI
00872  * @returns - the r_public found, 0 if not found
00873  *
00874 */
00875 
00876 r_public* get_r_public_wpsi(str pi)
00877 {
00878     r_public *p=0;
00879     r_lock(r_hash_size);
00880     p = registrar[r_hash_size].head;
00881     while(p){
00882         if (p->aor.len == pi.len &&
00883             strncasecmp(p->aor.s,pi.s,pi.len)==0) return p;
00884         p = p->next;
00885     }
00886     r_unlock(r_hash_size);
00887     return 0;
00888     
00889 }
00890 
00891 
00892 
00898 int get_r_public_expires(str aor)
00899 {
00900     int max_expires=-999;
00901     r_contact *c;
00902     r_public *p=get_r_public(aor);
00903     if (!p) return -999;
00904     r_act_time();
00905     for(c=p->head;c;c=c->next)
00906         if (c->expires-time_now>max_expires){
00907             max_expires = c->expires - time_now;
00908         }
00909     r_unlock(p->hash);
00910     return max_expires;
00911 }
00912 
00920 r_public* get_r_public_nolock(str aor)
00921 {
00922     r_public *p=0;
00923     unsigned int hash;
00924     hash = get_aor_hash(aor,r_hash_size);
00925     p = registrar[hash].head;
00926     while(p){
00927         if (p->aor.len == aor.len &&
00928             strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
00929         p = p->next;
00930     }
00931     LOG(L_ERR,"no match found but get_r_public_nolock doesn't look in the WildCardedPSI area\n");
00932     return 0;
00933 }
00934 
00943 r_public* get_r_public_previous_lock(str aor,int locked_hash)
00944 {
00945     r_public *p=0;
00946     unsigned int hash;
00947     hash = get_aor_hash(aor,r_hash_size);
00948     if (hash!=locked_hash) r_lock(hash);
00949     p = registrar[hash].head;
00950     while(p){
00951         if (p->aor.len == aor.len &&
00952             strncasecmp(p->aor.s,aor.s,aor.len)==0) return p;
00953         p = p->next;
00954     }
00955     if (hash!=locked_hash) r_unlock(hash);
00956     return 0;
00957 }
00958 
00959 
00969 r_public* add_r_public(str aor,enum Reg_States reg_state,ims_subscription *s)
00970 {
00971     r_public *p;
00972     unsigned int hash;
00973     
00974     p = new_r_public(aor,reg_state,s);
00975     
00976     hash = p->hash;
00977     if (!p) return 0;   
00978     p->next=0;
00979     r_lock(hash);
00980         p->prev=registrar[hash].tail;
00981         if (p->prev) p->prev->next = p;
00982         registrar[hash].tail = p;       
00983         if (!registrar[hash].head) registrar[hash].head=p;
00984     
00985     return p;
00986 }
00987 
00999 r_public* add_r_public_previous_lock(str aor,int locked_hash,enum Reg_States reg_state,ims_subscription *s)
01000 {
01001     r_public *p;
01002     unsigned int hash;
01003 
01004     p = new_r_public(aor,reg_state,s);
01005     hash = p->hash;
01006     if (!p) return 0;   
01007     p->next=0;
01008     if (hash!=locked_hash) 
01009         r_lock(hash);
01010             p->prev=registrar[hash].tail;
01011             if (p->prev) p->prev->next = p;
01012             registrar[hash].tail = p;
01013             if (!registrar[hash].head) registrar[hash].head=p;
01014     return p;
01015 }
01016 
01026 r_public* update_r_public(str aor,enum Reg_States *reg_state,ims_subscription **s,
01027     str *ccf1, str *ccf2, str *ecf1, str *ecf2)
01028 {
01029     r_public *p=0;
01030     //LOG(L_CRIT,"update_r_public():with aor %.*s\n",aor.len,aor.s);
01031     
01032     if ((*s)->wpsi) {
01033         p = get_r_public_wpsi(aor);
01034     } else {
01035         p = get_r_public(aor);
01036     }
01037     
01038     if (!p){
01039         //LOG(L_DBG,"updating a new r_public profile\n");            
01040         if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
01041             p = add_r_public(aor,*reg_state,*s);
01042             
01043             if (!p) return p;           
01044             if (ccf1) {
01045                 if (p->ccf1.s) shm_free(p->ccf1.s);
01046                 STR_SHM_DUP(p->ccf1,*ccf1,"SHM CCF1");
01047             }
01048             if (ccf2) {
01049                 if (p->ccf2.s) shm_free(p->ccf2.s);
01050                 STR_SHM_DUP(p->ccf2,*ccf2,"SHM CCF2");
01051             }
01052             if (ecf1) {
01053                 if (p->ecf1.s) shm_free(p->ecf1.s);
01054                 STR_SHM_DUP(p->ecf1,*ecf1,"SHM ECF1");
01055             }
01056             if (ecf2) {
01057                 if (p->ecf2.s) shm_free(p->ecf2.s);
01058                 STR_SHM_DUP(p->ecf2,*ecf2,"SHM ECF2");
01059             }
01060             //LOG(L_DBG,"update_r_public():  it was actually adding\n");
01061             return p;
01062         }
01063         else return 0;
01064     }else{
01065         //LOG(L_DBG,"updating a not so new r_public profile\n");        
01066         if (reg_state) p->reg_state = *reg_state;
01067         if (*s) {
01068             
01069             if (p->s){
01070                 lock_get(p->s->lock);
01071                 if (p->s->ref_count==1){
01072                     free_user_data(p->s);
01073                 }else{
01074                     p->s->ref_count--;
01075                     lock_release(p->s->lock);
01076                 }
01077             }           
01078             p->s = *s;
01079             lock_get(p->s->lock);
01080                 p->s->ref_count++;
01081             lock_release(p->s->lock);
01082             
01083             
01084              if ((*s)->wpsi)
01085              {  
01086                 
01087                  p->s=NULL; 
01088                                  
01089                  if (p->prev) p->prev->next=p->next;
01090                  else registrar[r_hash_size].head=p->next;  
01091                  if (p->next) p->next->prev=p->prev;
01092                  else registrar[r_hash_size].tail=p->prev;
01093                  
01094                  free_r_public(p);
01095                  r_unlock(r_hash_size);          
01096                  p=add_r_public(aor,0,*s);
01097                  
01098              }
01099             
01100             
01101         }
01102         if (ccf1) {
01103             if (p->ccf1.s) shm_free(p->ccf1.s);
01104             STR_SHM_DUP(p->ccf1,*ccf1,"SHM CCF1");
01105         }
01106         if (ccf2) {
01107             if (p->ccf2.s) shm_free(p->ccf2.s);
01108             STR_SHM_DUP(p->ccf2,*ccf2,"SHM CCF2");
01109         }
01110         if (ecf1) {
01111             if (p->ecf1.s) shm_free(p->ecf1.s);
01112             STR_SHM_DUP(p->ecf1,*ecf1,"SHM ECF1");
01113         }
01114         if (ecf2) {
01115             if (p->ecf2.s) shm_free(p->ecf2.s);
01116             STR_SHM_DUP(p->ecf2,*ecf2,"SHM ECF2");
01117         }
01118         //LOG(L_DBG,"update_r_public():    return normaly\n");
01119         return p;
01120     }
01121 out_of_memory:
01122     return p;   
01123 }
01124 
01136 r_public* update_r_public_previous_lock(str aor,int locked_hash,enum Reg_States *reg_state,ims_subscription **s,
01137     str *ccf1, str *ccf2, str *ecf1, str *ecf2)
01138 {
01139     r_public *p=0;
01140     p = get_r_public_previous_lock(aor,locked_hash);
01141     if (!p){
01142         if (reg_state && *reg_state && *reg_state!=NOT_REGISTERED && s){
01143             p = add_r_public_previous_lock(aor,locked_hash,*reg_state,*s);
01144             if (!p) return p;           
01145             if (ccf1) {
01146                 if (p->ccf1.s) shm_free(p->ccf1.s);
01147                 STR_SHM_DUP(p->ccf1,*ccf1,"SHM CCF1");
01148             }
01149             if (ccf2) {
01150                 if (p->ccf2.s) shm_free(p->ccf2.s);
01151                 STR_SHM_DUP(p->ccf2,*ccf2,"SHM CCF2");
01152             }
01153             if (ecf1) {
01154                 if (p->ecf1.s) shm_free(p->ecf1.s);
01155                 STR_SHM_DUP(p->ecf1,*ecf1,"SHM ECF1");
01156             }
01157             if (ecf2) {
01158                 if (p->ecf2.s) shm_free(p->ecf2.s);
01159