scscf_list.c

Go to the documentation of this file.
00001 
00062 #include <values.h>
00063  
00064 #include "../../mem/shm_mem.h"
00065 
00066 #include "../../dset.h"
00067 #include "../tm/tm_load.h"
00068 
00069 #include "scscf_list.h"
00070 #include "db.h" 
00071 #include "sip.h"
00072 
00073 
00074 extern struct tm_binds tmb;                             
00076 scscf_capabilities *SCSCF_Capabilities=0;       
00077 int SCSCF_Capabilities_cnt=0;                   
00079 int i_hash_size;                    
00080 i_hash_slot *i_hash_table=0;        
00090 int I_get_capabilities()
00091 {
00092     int i,j,r;
00093     /* free the old cache */
00094     if (SCSCF_Capabilities!=0){
00095         for(i=0;i<SCSCF_Capabilities_cnt;i++){
00096             if (SCSCF_Capabilities[i].capabilities)
00097                 shm_free(SCSCF_Capabilities[i].capabilities);
00098         }
00099         shm_free(SCSCF_Capabilities);
00100     }
00101     
00102     SCSCF_Capabilities_cnt = icscf_db_get_scscf(&SCSCF_Capabilities);
00103     
00104     r = icscf_db_get_capabilities(&SCSCF_Capabilities,SCSCF_Capabilities_cnt);
00105 
00106     LOG(L_DBG,"DBG:"M_NAME":------  S-CSCF Map with Capabilities  begin ------\n");
00107     if (SCSCF_Capabilities!=0){
00108         for(i=0;i<SCSCF_Capabilities_cnt;i++){
00109             LOG(L_DBG,"DBG:"M_NAME":S-CSCF [%d] <%.*s>\n",
00110                 SCSCF_Capabilities[i].id_s_cscf,
00111                 SCSCF_Capabilities[i].scscf_name.len,
00112                 SCSCF_Capabilities[i].scscf_name.s);
00113             for(j=0;j<SCSCF_Capabilities[i].cnt;j++)
00114             LOG(L_DBG,"DBG:"M_NAME":       \t [%d]\n",
00115              SCSCF_Capabilities[i].capabilities[j]);
00116         }
00117     }
00118     LOG(L_DBG,"DBG:"M_NAME":------  S-CSCF Map with Capabilities  end ------\n");
00119     
00120     return r;
00121 }
00122 
00133 int I_get_capab_match(scscf_capabilities *c,int *m,int mcnt,int *o,int ocnt)
00134 {
00135     int r=0,i,j,t=0;
00136     for(i=0;i<mcnt;i++){
00137         t=0;
00138         for(j=0;j<c->cnt;j++)
00139             if (m[i]==c->capabilities[j]) {
00140                 t=1;
00141                 break;
00142             }
00143         if (!t) return -1;
00144     }
00145     for(i=0;i<ocnt;i++){
00146         for(j=0;j<c->cnt;j++)
00147             if (o[i]==c->capabilities[j]) r++;
00148     }   
00149     return r;
00150 }
00151 
00156 static inline scscf_entry* I_add_to_scscf_list(scscf_entry *root,str name,int score, int originating)
00157 {
00158     scscf_entry *x,*i;
00159 
00160     //duplicate?
00161     for(i=root;i;i=i->next)
00162         if (name.len == i->scscf_name.len &&
00163             strncasecmp(name.s,i->scscf_name.s,name.len)==0)
00164                 return root;
00165 
00166     x = new_scscf_entry(name,score, originating);
00167     if (!x) return root;
00168     
00169     if (!root){
00170         return x;
00171     }
00172     if (root->score < x->score){
00173         x->next = root;
00174         return x;
00175     }
00176     i = root;
00177     while(i->next && i->next->score > x->score)
00178         i = i->next;
00179     x->next = i->next;
00180     i->next = x;
00181     return root;
00182 }
00183 
00196 scscf_entry* I_get_capab_ordered(str scscf_name,int *m,int mcnt,int *o,int ocnt, str *p, int pcnt,int orig)
00197 {
00198     scscf_entry *list=0;
00199     int i,r;
00200     
00201     if (scscf_name.len) list = I_add_to_scscf_list(list,scscf_name,MAXINT, orig);
00202 
00203     for(i=0;i<pcnt;i++)
00204         list = I_add_to_scscf_list(list,p[i],MAXINT-i,orig);
00205         
00206     for(i=0;i<SCSCF_Capabilities_cnt;i++){
00207         r = I_get_capab_match(SCSCF_Capabilities+i,m,mcnt,o,ocnt);
00208         if (r!=-1){
00209              list = I_add_to_scscf_list(list,SCSCF_Capabilities[i].scscf_name,r, orig);
00210              LOG(L_DBG,"DBG:"M_NAME":I_get_capab_ordered: <%.*s> Added to the list, orig=%d\n",
00211                 SCSCF_Capabilities[i].scscf_name.len,SCSCF_Capabilities[i].scscf_name.s, orig);
00212         }
00213     }
00214     return list;
00215 }
00216 
00217 
00221 inline unsigned int get_call_id_hash(str callid,int hash_size)
00222 {
00223 #define h_inc h+=v^(v>>3)
00224    char* p;
00225    register unsigned v;
00226    register unsigned h;
00227 
00228    h=0;
00229    for (p=callid.s; p<=(callid.s+callid.len-4); p+=4){
00230        v=(*p<<24)+(p[1]<<16)+(p[2]<<8)+p[3];
00231        h_inc;
00232    }
00233    v=0;
00234    for (;p<(callid.s+callid.len); p++) {
00235        v<<=8;
00236        v+=*p;
00237    }
00238    h_inc;
00239 
00240    h=((h)+(h>>11))+((h>>13)+(h>>23));
00241    return (h)%hash_size;
00242 #undef h_inc 
00243 }
00244 
00248 int i_hash_table_init(int hash_size)
00249 {
00250     int i;
00251     
00252     i_hash_size = hash_size;
00253     i_hash_table = shm_malloc(sizeof(i_hash_slot)*i_hash_size);
00254 
00255     if (!i_hash_table) return 0;
00256     
00257     memset(i_hash_table,0,sizeof(i_hash_slot)*i_hash_size);
00258     
00259     for(i=0;i<i_hash_size;i++){
00260         i_hash_table[i].lock = lock_alloc();
00261         if (!i_hash_table[i].lock){
00262             LOG(L_ERR,"ERR:"M_NAME":i_hash_table_init(): Error creating lock\n");
00263             return 0;
00264         }
00265         i_hash_table[i].lock = lock_init(i_hash_table[i].lock);
00266     }
00267             
00268     return 1;
00269 }
00270 
00274 void i_hash_table_destroy()
00275 {
00276     int i;
00277     scscf_list *sl,*nsl;
00278     for(i=0;i<i_hash_size;i++){
00279         i_lock(i);
00280             sl = i_hash_table[i].head;
00281             while(sl){
00282                 nsl = sl->next;
00283                 free_scscf_list(sl);
00284                 sl = nsl;
00285             }
00286         i_unlock(i);
00287         lock_dealloc(i_hash_table[i].lock);
00288     }
00289     shm_free(i_hash_table);
00290 }
00291 
00295 inline void i_lock(unsigned int hash)
00296 {
00297 //  LOG(L_CRIT,"GET %d\n",hash);
00298     lock_get(i_hash_table[(hash)].lock);
00299 //  LOG(L_CRIT,"GOT %d\n",hash);    
00300 }
00301 
00305 inline void i_unlock(unsigned int hash)
00306 {
00307     lock_release(i_hash_table[(hash)].lock);
00308 //  LOG(L_CRIT,"RELEASED %d\n",hash);   
00309 }
00310 
00311 scscf_entry* new_scscf_entry(str name, int score, int orig)
00312 {
00313     scscf_entry *x=0;
00314     x = shm_malloc(sizeof(scscf_entry));
00315     if (!x) {   
00316         LOG(L_ERR,"ERR:"M_NAME":new_scscf_entry: Error allocating %d bytes\n",
00317             sizeof(scscf_entry));
00318         return 0;
00319     }
00320     /* duplicate always the scscf_name because of possible list reloads and scscf_name coming in LIA/UAA */
00321     if (orig) x->scscf_name.s = shm_malloc(name.len+5);
00322     else x->scscf_name.s = shm_malloc(name.len);
00323     if (!x->scscf_name.s){  
00324         LOG(L_ERR,"ERR:"M_NAME":new_scscf_entry: Error allocating %d bytes\n",
00325             orig?name.len+5:name.len);
00326         shm_free(x);
00327         return 0;
00328     }
00329     memcpy(x->scscf_name.s,name.s,name.len);
00330     x->scscf_name.len = name.len;
00331     if (orig) {
00332         memcpy(x->scscf_name.s+name.len, ";orig", 5);
00333         x->scscf_name.len += 5;
00334     }
00335     
00336     LOG(L_INFO,"INFO:"M_NAME":new_scscf_entry:  <%.*s>\n",x->scscf_name.len,x->scscf_name.s);
00337     
00338     x->score = score;
00339     x->next = 0;
00340     return x;
00341 }
00342 
00343 
00344 scscf_list* new_scscf_list(str call_id,scscf_entry *sl)
00345 {
00346     scscf_list *l;
00347     
00348     l = shm_malloc(sizeof(scscf_list));
00349     if (!l) {
00350         LOG(L_ERR,"ERR:"M_NAME":new_scscf_list(): Unable to alloc %d bytes\n",
00351             sizeof(scscf_list));
00352         goto error;
00353     }
00354     memset(l,0,sizeof(scscf_list));
00355     
00356     STR_SHM_DUP(l->call_id,call_id,"shm");
00357     l->list = sl;
00358                 
00359     return l;
00360 error:
00361 out_of_memory:
00362     if (l){
00363         shm_free(l);        
00364     }
00365     return 0;
00366 }
00367 
00368 int add_scscf_list(str call_id,scscf_entry *sl)
00369 {
00370     scscf_list *l;
00371     unsigned int hash = get_call_id_hash(call_id,i_hash_size);
00372     
00373     l = new_scscf_list(call_id,sl);
00374     if (!l) return 0;       
00375     
00376     i_lock(hash);
00377     l->prev = 0;
00378     l->next = i_hash_table[hash].head;
00379     if (l->next) l->next->prev = l;
00380     i_hash_table[hash].head = l;
00381     if (!i_hash_table[hash].tail) i_hash_table[hash].tail = l;
00382     i_unlock(hash); 
00383     
00384     return 1;
00385 }
00386 
00387 int is_scscf_list(str call_id)
00388 {
00389     scscf_list *l=0;
00390     unsigned int hash = get_call_id_hash(call_id,i_hash_size);
00391 
00392     i_lock(hash);
00393     l = i_hash_table[hash].head;
00394     while(l){
00395         if (l->call_id.len == call_id.len &&
00396             strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) {
00397                 i_unlock(hash);
00398                 return 1;
00399             }
00400         l = l->next;
00401     }
00402     i_unlock(hash);
00403     return 0;
00404 }
00405 
00412 str take_scscf_entry(str call_id)
00413 {
00414     str scscf={0,0};
00415     scscf_list *l=0;
00416     scscf_entry *sl;
00417     unsigned int hash = get_call_id_hash(call_id,i_hash_size);
00418 
00419     i_lock(hash);
00420     l = i_hash_table[hash].head;
00421     while(l){
00422         if (l->call_id.len == call_id.len &&
00423             strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) {
00424                 if (l->list){
00425                     scscf = l->list->scscf_name;
00426                     sl = l->list->next;
00427                     shm_free(l->list);
00428                     l->list = sl;
00429                 }
00430                 break;
00431             }
00432         l = l->next;
00433     }
00434     i_unlock(hash);
00435     return scscf;
00436 }
00437 
00438 void del_scscf_list(str call_id)
00439 {
00440     scscf_list *l=0;
00441     unsigned int hash = get_call_id_hash(call_id,i_hash_size);
00442 
00443     i_lock(hash);
00444     l = i_hash_table[hash].head;
00445     while(l){
00446         if (l->call_id.len == call_id.len &&
00447             strncasecmp(l->call_id.s,call_id.s,call_id.len)==0) {
00448                 if (l->prev) l->prev->next = l->next;
00449                 else i_hash_table[hash].head = l->next;
00450                 if (l->next) l->next->prev = l->prev;
00451                 else i_hash_table[hash].tail = l->prev;                 
00452                 i_unlock(hash);
00453                 free_scscf_list(l);
00454                 return;
00455             }
00456         l = l->next;
00457     }
00458     i_unlock(hash);
00459 }
00460 
00461 void free_scscf_list(scscf_list *sl)
00462 {
00463     scscf_entry *i;
00464     if (!sl) return;
00465     if (sl->call_id.s) shm_free(sl->call_id.s);
00466     while (sl->list) {
00467         i = sl->list->next;
00468         if (sl->list->scscf_name.s) shm_free(sl->list->scscf_name.s);
00469         shm_free(sl->list);
00470         sl->list = i;
00471     }
00472     shm_free(sl);
00473 }
00474 
00475 void print_scscf_list(int log_level)
00476 {
00477     scscf_list *l;
00478     int i;
00479     scscf_entry *sl;
00480     LOG(log_level,"INF:"M_NAME":----------  S-CSCF Lists begin --------------\n");
00481     for(i=0;i<i_hash_size;i++){
00482         i_lock(i);
00483             l = i_hash_table[i].head;
00484             while(l){
00485                 LOG(log_level,"INF:"M_NAME":[%4d] Call-ID: <%.*s> \n",i,
00486                     l->call_id.len,l->call_id.s);
00487                 sl = l->list;
00488                 while(sl){
00489                     LOG(log_level,"INF:"M_NAME":         Score:[%4d] S-CSCF: <%.*s> \n",
00490                         sl->score,
00491                         sl->scscf_name.len,sl->scscf_name.s);                   
00492                     sl = sl->next;
00493                 }
00494                 l = l->next;
00495             }       
00496         i_unlock(i);
00497     }
00498     LOG(log_level,"INF:"M_NAME":----------  S-CSCF Lists end   --------------\n");
00499     
00500 }
00501 
00502 int I_trans_in_processing(struct sip_msg* msg, char* str1, char* str2)
00503 {
00504         unsigned int hash, label;
00505         if (tmb.t_get_trans_ident(msg,&hash,&label)<0)
00506             return CSCF_RETURN_FALSE;
00507         return CSCF_RETURN_TRUE;
00508 }
00509 
00510 static str route_hdr_s={"Route: <",8};
00511 static str route_hdr_e={">\r\n",3};
00512 
00513 int I_scscf_select(struct sip_msg* msg, char* str1, char* str2)
00514 {
00515     str call_id,scscf_name={0,0};
00516     struct sip_msg *req;
00517     int result;
00518     str hdr={0,0};
00519 
00520     //print_scscf_list(L_ERR);
00521         
00522     call_id = cscf_get_call_id(msg,0);
00523     LOG(L_DBG,"DBG:"M_NAME":I_scscf_select(): <%.*s>\n",call_id.len,call_id.s);
00524     if (!call_id.len)
00525         return CSCF_RETURN_FALSE;
00526     
00527     scscf_name = take_scscf_entry(call_id);
00528     if (!scscf_name.len){
00529         I_scscf_drop(msg,str1,str2);
00530         cscf_reply_transactional(msg,600,MSG_600_FORWARDING_FAILED);            
00531         return CSCF_RETURN_BREAK;
00532     }
00533     
00534     if (msg->first_line.u.request.method.len==8 &&
00535         strncasecmp(msg->first_line.u.request.method.s,"REGISTER",8)==0) {
00536         /* REGISTER fwding */           
00537         if (str1&&str1[0]=='0'){
00538             /* first time */    
00539             //LOG(L_CRIT,"rewrite uri\n");
00540             if (rewrite_uri(msg, &(scscf_name)) < 0) {
00541                 LOG(L_ERR,"ERR:"M_NAME":I_UAR_forward: Unable to Rewrite URI\n");
00542                 result = CSCF_RETURN_FALSE;
00543             }else
00544                 result = CSCF_RETURN_TRUE;
00545         }else{
00546             /* subsequent */
00547             //LOG(L_CRIT,"append branch\n");
00548             req = msg;//cscf_get_request_from_reply(msg);
00549             append_branch(req,scscf_name.s,scscf_name.len,0,0,0,0);
00550             result = CSCF_RETURN_TRUE;
00551         }
00552     }else{
00553         /* Another request */
00554         result = CSCF_RETURN_TRUE;
00555         
00556         hdr.len = route_hdr_s.len+scscf_name.len+route_hdr_e.len;
00557         hdr.s = pkg_malloc(hdr.len);
00558         if (!hdr.s){
00559             LOG(L_ERR,"ERR:"M_NAME":Mw_REQUEST_forward: Error allocating %d bytes\n",
00560                 hdr.len);
00561             result = CSCF_RETURN_TRUE;
00562         }
00563         hdr.len=0;
00564         STR_APPEND(hdr,route_hdr_s);
00565         STR_APPEND(hdr,scscf_name);
00566         STR_APPEND(hdr,route_hdr_e);
00567     
00568         if (!cscf_add_header_first(msg,&hdr,HDR_ROUTE_T)){
00569             pkg_free(hdr.s);
00570             result = CSCF_RETURN_TRUE;
00571         }
00572         
00573         if (msg->dst_uri.s) pkg_free(msg->dst_uri.s);   
00574         STR_PKG_DUP(msg->dst_uri,scscf_name,"pkg");
00575     }
00576 
00577     if (scscf_name.s) shm_free(scscf_name.s);
00578     return result;
00579 out_of_memory:  
00580     if (scscf_name.s) shm_free(scscf_name.s);
00581     return CSCF_RETURN_ERROR;
00582 }
00583 
00584 int I_scscf_drop(struct sip_msg* msg, char* str1, char* str2)
00585 {
00586     str call_id;
00587     //print_scscf_list(L_ERR);
00588     call_id = cscf_get_call_id(msg,0);
00589     LOG(L_DBG,"DBG:"M_NAME":I_scscf_drop(): <%.*s>\n",call_id.len,call_id.s);
00590     if (!call_id.len)
00591         return CSCF_RETURN_FALSE;
00592     
00593     del_scscf_list(call_id);
00594     return CSCF_RETURN_TRUE;
00595 }
00596 

Generated on Thu Oct 23 04:14:38 2008 for Open IMS Core CSCFs by  doxygen 1.5.2