pua/hash.c

Go to the documentation of this file.
00001 /*
00002  * $Id: hash.c 4625 2008-08-07 08:37:04Z henningw $
00003  *
00004  * pua module - presence user agent module
00005  *
00006  * Copyright (C) 2006 Voice Sistem S.R.L.
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  */
00024 
00025 
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 
00030 #include "../../mem/mem.h"
00031 #include "../../mem/shm_mem.h"
00032 #include "../../dprint.h"
00033 #include "../../hash_func.h"
00034 #include "../../parser/msg_parser.h"
00035 #include "../../parser/parse_from.h"
00036 #include "hash.h" 
00037 #include "pua.h"
00038 #include "send_publish.h"
00039 
00040 void print_ua_pres(ua_pres_t* p)
00041 {
00042    LM_DBG("\tpres_uri= %.*s   len= %d\n", p->pres_uri->len, p->pres_uri->s, p->pres_uri->len);
00043    if(p->watcher_uri)
00044    {  
00045       LM_DBG("\twatcher_uri= %.*s  len= %d\n", p->watcher_uri->len, p->watcher_uri->s, p->watcher_uri->len);
00046       LM_DBG("\tcall_id= %.*s   len= %d\n", p->call_id.len, p->call_id.s, p->call_id.len);
00047       LM_DBG("\tfrom_tag= %.*s   len= %d\n", p->from_tag.len, p->from_tag.s, p->from_tag.len);
00048       LM_DBG("\tto_tag= %.*s  len= %d\n", p->to_tag.len, p->to_tag.s, p->to_tag.len);
00049       LM_DBG("\tflag= %d\n", p->flag);
00050       LM_DBG("\tevent= %d\n", p->event);
00051    }  
00052    else
00053    {
00054       LM_DBG("\tetag= %.*s - len= %d\n", p->etag.len, p->etag.s, p->etag.len);
00055       if(p->id.s)
00056          LM_DBG("\tid= %.*s\n", p->id.len, p->id.s);
00057    }
00058    LM_DBG("\texpires= %d\n", p->expires- (int)time(NULL));
00059 }
00060 
00061 htable_t* new_htable(void)
00062 {
00063    htable_t* H= NULL;
00064    int i= 0, j;
00065 
00066    H= (htable_t*)shm_malloc(sizeof(htable_t));
00067    if(H== NULL)
00068    {
00069       LM_ERR("No more memory\n");
00070       return NULL;
00071    }
00072    memset(H, 0, sizeof(htable_t));
00073 
00074    H->p_records= (hash_entry_t*)shm_malloc(HASH_SIZE* sizeof(hash_entry_t));
00075    if(H->p_records== NULL)
00076    {
00077       LM_ERR("No more share memory\n");
00078       goto error;    
00079    }
00080 
00081    for(i=0; i<HASH_SIZE; i++)
00082    {
00083       if(lock_init(&H->p_records[i].lock)== 0)
00084       {
00085          LM_CRIT("initializing lock [%d]\n", i);
00086          goto error;
00087       }
00088       H->p_records[i].entity= (ua_pres_t*)shm_malloc(sizeof(ua_pres_t));
00089       if(H->p_records[i].entity== NULL)
00090       {
00091          LM_ERR("No more share memory\n");
00092          goto error;    
00093       }  
00094       H->p_records[i].entity->next= NULL;
00095    }
00096    return H;
00097 
00098 error:
00099 
00100    if(H->p_records)
00101    {
00102       for(j=0; j< i; j++)
00103       {
00104          if(H->p_records[j].entity)
00105             shm_free(H->p_records[j].entity);
00106          lock_destroy(&H->p_records[j].lock);
00107 
00108       }
00109       shm_free(H->p_records);
00110    }
00111    shm_free(H);
00112    return NULL;
00113 
00114 }
00115 
00116 ua_pres_t* search_htable(ua_pres_t* pres, unsigned int hash_code)
00117 {
00118    ua_pres_t* p= NULL,* L= NULL;
00119 
00120    L= HashT->p_records[hash_code].entity;
00121    LM_DBG("core_hash= %u\n", hash_code);
00122 
00123    for(p= L->next; p; p=p->next)
00124    {
00125       if((p->flag & pres->flag) && (p->event & pres->event))
00126       {
00127          if((p->pres_uri->len==pres->pres_uri->len) &&
00128                (strncmp(p->pres_uri->s, pres->pres_uri->s,pres->pres_uri->len)==0))
00129          {
00130             if(pres->id.s && pres->id.len) 
00131             {  
00132                if(!(pres->id.len== p->id.len &&
00133                   strncmp(p->id.s, pres->id.s,pres->id.len)==0))
00134                      continue;
00135             }           
00136 
00137             if(pres->watcher_uri)
00138             {
00139                if(p->watcher_uri->len==pres->watcher_uri->len &&
00140                   (strncmp(p->watcher_uri->s, pres->watcher_uri->s,
00141                           pres->watcher_uri->len )==0))
00142                {
00143                   if(pres->remote_contact.s)
00144                      if(pres->remote_contact.len== p->remote_contact.len &&
00145                         strncmp(pres->remote_contact.s, p->remote_contact.s,
00146                                p->remote_contact.len)== 0)
00147                         break;
00148                }
00149             }
00150             else
00151             {
00152                if(pres->etag.s)
00153                {
00154                   if(pres->etag.len== p->etag.len &&
00155                      strncmp(p->etag.s, pres->etag.s,pres->etag.len)==0)
00156                      break;      
00157                }
00158                else
00159                {
00160                   LM_DBG("no etag restriction\n");
00161                   break;
00162                }
00163             }
00164          }
00165       }
00166    }
00167 
00168    if(p)
00169       LM_DBG("found record\n");
00170    else
00171       LM_DBG("record not found\n");
00172 
00173    return p;
00174 }
00175 
00176 void update_htable(ua_pres_t* p, time_t desired_expires, int expires,
00177       str* etag, unsigned int hash_code, str* contact)
00178 {
00179    if(etag)
00180    {  
00181       shm_free(p->etag.s);
00182       p->etag.s= (char*)shm_malloc(etag->len);
00183       memcpy(p->etag.s, etag->s, etag->len);
00184       p->etag.len= etag->len;
00185    }
00186 
00187    p->expires= expires+ (int)time(NULL);
00188    p->desired_expires= desired_expires;
00189       
00190    if(p->db_flag & NO_UPDATEDB_FLAG)
00191       p->db_flag= UPDATEDB_FLAG;
00192 
00193    if(p->watcher_uri)
00194       p->cseq ++;
00195 
00196    if(contact)
00197    {
00198       if(!(p->remote_contact.len== contact->len && 
00199             strncmp(p->remote_contact.s, contact->s, contact->len)==0))
00200       {
00201          /* update remote contact */
00202          shm_free(p->remote_contact.s);
00203          p->remote_contact.s= (char*)shm_malloc(contact->len* sizeof(char));
00204          if(p->remote_contact.s== NULL)
00205          {
00206             LM_ERR("no more shared memory\n");
00207             return;
00208          }
00209          memcpy(p->remote_contact.s, contact->s, contact->len);
00210          p->remote_contact.len= contact->len;
00211       }
00212    }
00213 }
00214 /* insert in front; so when searching the most recent result is returned*/
00215 void insert_htable(ua_pres_t* presentity)
00216 {
00217    ua_pres_t* p= NULL;
00218    unsigned int hash_code;
00219 
00220    hash_code= core_hash(presentity->pres_uri,presentity->watcher_uri, 
00221          HASH_SIZE);
00222    
00223    lock_get(&HashT->p_records[hash_code].lock);
00224 
00225 /* 
00226  * useless since always checking before calling insert
00227    if(get_dialog(presentity, hash_code)!= NULL )
00228    {
00229       LM_DBG("Dialog already found- do not insert\n");
00230       return; 
00231    }
00232 */ 
00233    p= HashT->p_records[hash_code].entity;
00234 
00235    presentity->db_flag= INSERTDB_FLAG;
00236    presentity->next= p->next;
00237    
00238    p->next= presentity;
00239 
00240    lock_release(&HashT->p_records[hash_code].lock);
00241 
00242 }
00243 
00244 void delete_htable(ua_pres_t* presentity, unsigned int hash_code)
00245 { 
00246    ua_pres_t* p= NULL, *q= NULL;
00247 
00248    p= search_htable(presentity, hash_code);
00249    if(p== NULL)
00250       return;
00251 
00252    q=HashT->p_records[hash_code].entity;
00253 
00254    while(q->next!=p)
00255       q= q->next;
00256    q->next=p->next;
00257    
00258    if(p->etag.s)
00259       shm_free(p->etag.s);
00260    else
00261       if(p->remote_contact.s)
00262          shm_free(p->remote_contact.s);
00263 
00264    shm_free(p);
00265    p= NULL;
00266 
00267 }
00268    
00269 void destroy_htable(void)
00270 {
00271    ua_pres_t* p= NULL,*q= NULL;
00272    int i;
00273 
00274    for(i=0; i<HASH_SIZE; i++)
00275    {  
00276       lock_destroy(&HashT->p_records[i].lock);
00277       p=HashT->p_records[i].entity;
00278       while(p->next)
00279       {
00280          q=p->next;
00281          p->next=q->next;
00282          if(q->etag.s)
00283             shm_free(q->etag.s);
00284          else
00285             if(q->remote_contact.s)
00286                shm_free(q->remote_contact.s);
00287 
00288          shm_free(q);
00289          q= NULL;
00290       }
00291       shm_free(p);
00292    }
00293     shm_free(HashT->p_records);
00294    shm_free(HashT);
00295   
00296   return;
00297 }
00298 
00299 /* must lock the record line before calling this function*/
00300 ua_pres_t* get_dialog(ua_pres_t* dialog, unsigned int hash_code)
00301 {
00302    ua_pres_t* p= NULL, *L;
00303    LM_DBG("core_hash= %u\n", hash_code);
00304 
00305    L= HashT->p_records[hash_code].entity;
00306    for(p= L->next; p; p=p->next)
00307    {
00308 
00309       if(p->flag& dialog->flag)
00310       {
00311          LM_DBG("pres_uri= %.*s\twatcher_uri=%.*s\n\t"
00312                "callid= %.*s\tto_tag= %.*s\tfrom_tag= %.*s\n",
00313             p->pres_uri->len, p->pres_uri->s, p->watcher_uri->len,
00314             p->watcher_uri->s,p->call_id.len, p->call_id.s,
00315             p->to_tag.len, p->to_tag.s, p->from_tag.len, p->from_tag.s);
00316 
00317          LM_DBG("searched to_tag= %.*s\tfrom_tag= %.*s\n",
00318              p->to_tag.len, p->to_tag.s, p->from_tag.len, p->from_tag.s);
00319        
00320          if((p->pres_uri->len== dialog->pres_uri->len) &&
00321             (strncmp(p->pres_uri->s, dialog->pres_uri->s,p->pres_uri->len)==0)&&
00322             (p->watcher_uri->len== dialog->watcher_uri->len) &&
00323             (strncmp(p->watcher_uri->s,dialog->watcher_uri->s,p->watcher_uri->len )==0)&&
00324             (strncmp(p->call_id.s, dialog->call_id.s, p->call_id.len)== 0) &&
00325             (strncmp(p->to_tag.s, dialog->to_tag.s, p->to_tag.len)== 0) &&
00326             (strncmp(p->from_tag.s, dialog->from_tag.s, p->from_tag.len)== 0) )
00327             {  
00328                LM_DBG("FOUND dialog\n");
00329                break;
00330             }
00331       }  
00332    
00333    }
00334       
00335    return p;
00336 }
00337 
00338 int get_record_id(ua_pres_t* dialog, str** rec_id)
00339 {
00340    unsigned int hash_code;
00341    ua_pres_t* rec;
00342    str* id;
00343 
00344    *rec_id= NULL;
00345 
00346    hash_code= core_hash(dialog->pres_uri, dialog->watcher_uri, HASH_SIZE);
00347    lock_get(&HashT->p_records[hash_code].lock);
00348 
00349    rec= get_dialog(dialog, hash_code);
00350    if(rec== NULL)
00351    {
00352       LM_DBG("Record not found\n");
00353       lock_release(&HashT->p_records[hash_code].lock);
00354       return 0;
00355    }
00356    id= (str*)pkg_malloc(sizeof(str));
00357    if(id== NULL)
00358    {
00359       LM_ERR("No more memory\n");
00360       lock_release(&HashT->p_records[hash_code].lock);
00361       return -1;
00362    }
00363    id->s= (char*)pkg_malloc(rec->id.len* sizeof(char));
00364    if(id->s== NULL)
00365    {
00366       LM_ERR("No more memory\n");
00367       pkg_free(id);
00368       lock_release(&HashT->p_records[hash_code].lock);
00369       return -1;
00370    }
00371    memcpy(id->s, rec->id.s, rec->id.len);
00372    id->len= rec->id.len;
00373 
00374    lock_release(&HashT->p_records[hash_code].lock);
00375 
00376    LM_DBG("rec did= %.*s\n", id->len, id->s);
00377 
00378    *rec_id= id;
00379 
00380    return 0;
00381 }
00382 
00383 int is_dialog(ua_pres_t* dialog)
00384 {
00385    int ret_code= 0;
00386    unsigned int hash_code;
00387    
00388    hash_code= core_hash(dialog->pres_uri, dialog->watcher_uri, HASH_SIZE);
00389    lock_get(&HashT->p_records[hash_code].lock);
00390 
00391    if(get_dialog(dialog, hash_code)== NULL)
00392       ret_code= -1;
00393    else
00394       ret_code= 0;
00395    lock_release(&HashT->p_records[hash_code].lock);
00396    
00397    return ret_code;
00398 
00399 }
00400 
00401 int update_contact(struct sip_msg* msg, char* str1, char* str2)
00402 {
00403    ua_pres_t* p, hentity;
00404    str contact;
00405    struct to_body *pto= NULL, TO, *pfrom = NULL;
00406    unsigned int hash_code;
00407 
00408    if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00409    {
00410       LM_ERR("when parsing headers\n");
00411       return -1;
00412    }
00413 
00414    /* find the record */
00415    if( msg->callid==NULL || msg->callid->body.s==NULL)
00416    {
00417       LM_ERR("cannot parse callid header\n");
00418       return -1;
00419    }     
00420    
00421    if (!msg->from || !msg->from->body.s)
00422    {
00423       LM_ERR("cannot find 'from' header!\n");
00424       return -1;
00425    }
00426    if (msg->from->parsed == NULL)
00427    {
00428       if ( parse_from_header( msg )<0 ) 
00429       {
00430          LM_ERR("cannot parse From header\n");
00431          return -1;
00432       }
00433    }
00434    
00435    pfrom = (struct to_body*)msg->from->parsed;
00436    
00437    if( pfrom->tag_value.s ==NULL || pfrom->tag_value.len == 0)
00438    {
00439       LM_ERR("no from tag value present\n");
00440       return -1;
00441    }     
00442    
00443    if( msg->to==NULL || msg->to->body.s==NULL)
00444    {
00445       LM_ERR("cannot parse TO header\n");
00446       return -1;
00447    }        
00448    
00449    if(msg->to->parsed != NULL)
00450    {
00451       pto = (struct to_body*)msg->to->parsed;
00452       LM_DBG("'To' header ALREADY PARSED: <%.*s>\n",pto->uri.len,pto->uri.s);
00453    }
00454    else
00455    {
00456       memset( &TO , 0, sizeof(TO) );
00457       parse_to(msg->to->body.s,msg->to->body.s +
00458          msg->to->body.len + 1, &TO);
00459       if(TO.uri.len <= 0) 
00460       {
00461          LM_DBG("'To' header NOT parsed\n");
00462          return -1;
00463       }
00464       pto = &TO;
00465    }        
00466    if( pto->tag_value.s ==NULL || pto->tag_value.len == 0)
00467    {
00468       LM_ERR("no from tag value present\n");
00469       return -1;
00470    }
00471    hentity.watcher_uri= &pto->uri;
00472    hentity.pres_uri= &pfrom->uri; 
00473    hentity.call_id=  msg->callid->body;
00474    hentity.to_tag= pto->tag_value;
00475    hentity.from_tag= pfrom->tag_value;
00476    
00477    hash_code= core_hash(hentity.pres_uri,hentity.watcher_uri,
00478             HASH_SIZE);
00479 
00480    /* extract the contact */
00481    if(msg->contact== NULL || msg->contact->body.s== NULL)
00482    {
00483       LM_ERR("no contact header found in 200 OK reply");
00484       return -1;
00485    }
00486    contact= msg->contact->body;
00487 
00488    lock_get(&HashT->p_records[hash_code].lock);
00489 
00490    p= get_dialog(&hentity, hash_code);
00491    if(p== NULL)
00492    {
00493       lock_release(&HashT->p_records[hash_code].lock);
00494       LM_ERR("no record for the dialog found in hash table\n");
00495       return -1;
00496    }
00497 
00498    shm_free(p->remote_contact.s);
00499 
00500    if(!(p->remote_contact.len== contact.len && 
00501             strncmp(p->remote_contact.s, contact.s, contact.len)==0))
00502    {
00503       /* update remote contact */
00504       shm_free(p->remote_contact.s);
00505       p->remote_contact.s= (char*)shm_malloc(contact.len* sizeof(char));
00506       if(p->remote_contact.s== NULL)
00507       {
00508          LM_ERR("no more shared memory\n");
00509          lock_release(&HashT->p_records[hash_code].lock);
00510          return -1;
00511       }
00512       memcpy(p->remote_contact.s, contact.s, contact.len);
00513       p->remote_contact.len= contact.len;
00514    }
00515 
00516    lock_release(&HashT->p_records[hash_code].lock);
00517 
00518    return 1;
00519 
00520 }
00521 

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