presence/hash.c

Go to the documentation of this file.
00001 /*
00002  * $Id: hash.c 2583 2007-08-08 11:33:25Z anca_vamanu $
00003  *
00004  * presence module - presence server implementation
00005  *
00006  * Copyright (C) 2007 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  * History:
00025  * --------
00026  *  2007-08-20  initial version (anca)
00027  */
00028 
00029 /*! \file
00030  * \brief Kamailio presence module
00031  * \ingroup presence 
00032  */
00033 
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include "../../mem/shm_mem.h"
00037 #include "../../dprint.h"
00038 #include "../../str.h"
00039 #include "../pua/hash.h"
00040 #include "presence.h"
00041 #include "hash.h"
00042 #include "notify.h"
00043 
00044 shtable_t new_shtable(int hash_size)
00045 {
00046    shtable_t htable= NULL;
00047    int i, j;
00048 
00049    i = 0;
00050    htable= (subs_entry_t*)shm_malloc(hash_size* sizeof(subs_entry_t));
00051    if(htable== NULL)
00052    {
00053       ERR_MEM(SHARE_MEM);
00054    }
00055    memset(htable, 0, hash_size* sizeof(subs_entry_t));
00056    for(i= 0; i< hash_size; i++)
00057    {
00058       if(lock_init(&htable[i].lock)== 0)
00059       {
00060          LM_ERR("initializing lock [%d]\n", i);
00061          goto error;
00062       }
00063       htable[i].entries= (subs_t*)shm_malloc(sizeof(subs_t));
00064       if(htable[i].entries== NULL)
00065       {
00066          lock_destroy(&htable[i].lock);
00067          ERR_MEM(SHARE_MEM);
00068       }
00069       memset(htable[i].entries, 0, sizeof(subs_t));
00070       htable[i].entries->next= NULL;
00071    }
00072 
00073    return htable;
00074 
00075 error:
00076    if(htable)
00077    {
00078       for(j=0; j< i; j++)
00079       {
00080          lock_destroy(&htable[j].lock);
00081          shm_free(htable[j].entries);
00082       }
00083       shm_free(htable);
00084    }
00085    return NULL;
00086 
00087 }
00088 
00089 void destroy_shtable(shtable_t htable, int hash_size)
00090 {
00091    int i;
00092 
00093    if(htable== NULL)
00094       return;
00095 
00096    for(i= 0; i< hash_size; i++)
00097    {
00098       lock_destroy(&htable[i].lock);
00099       free_subs_list(htable[i].entries->next, SHM_MEM_TYPE, 1);
00100       shm_free(htable[i].entries);
00101    }
00102    shm_free(htable);
00103    htable= NULL;
00104 }
00105 
00106 subs_t* search_shtable(shtable_t htable,str callid,str to_tag,
00107       str from_tag,unsigned int hash_code)
00108 {
00109    subs_t* s;
00110 
00111    s= htable[hash_code].entries->next;
00112 
00113    while(s)
00114    {
00115       if(s->callid.len==callid.len &&
00116             strncmp(s->callid.s, callid.s, callid.len)==0 &&
00117          s->to_tag.len== to_tag.len &&
00118             strncmp(s->to_tag.s, to_tag.s, to_tag.len)==0 &&
00119          s->from_tag.len== from_tag.len &&
00120             strncmp(s->from_tag.s, from_tag.s, from_tag.len)== 0)
00121          return s;
00122       s= s->next;
00123    }
00124 
00125    return NULL;
00126 }
00127 
00128 subs_t* mem_copy_subs(subs_t* s, int mem_type)
00129 {
00130    int size;
00131    subs_t* dest;
00132 
00133    size= sizeof(subs_t)+ (s->pres_uri.len+ s->to_user.len
00134       + s->to_domain.len+ s->from_user.len+ s->from_domain.len+ s->callid.len
00135       + s->to_tag.len+ s->from_tag.len+s->sockinfo_str.len+s->event_id.len
00136       + s->local_contact.len+ s->contact.len+ s->record_route.len+
00137       + s->reason.len+ 1)*sizeof(char);
00138 
00139    if(mem_type & PKG_MEM_TYPE)
00140       dest= (subs_t*)pkg_malloc(size);
00141    else
00142       dest= (subs_t*)shm_malloc(size);
00143 
00144    if(dest== NULL)
00145    {
00146       ERR_MEM((mem_type==PKG_MEM_TYPE)?PKG_MEM_STR:SHARE_MEM);
00147    }
00148    memset(dest, 0, size);
00149    size= sizeof(subs_t);
00150 
00151    CONT_COPY(dest, dest->pres_uri, s->pres_uri)
00152    CONT_COPY(dest, dest->to_user, s->to_user)
00153    CONT_COPY(dest, dest->to_domain, s->to_domain)
00154    CONT_COPY(dest, dest->from_user, s->from_user)
00155    CONT_COPY(dest, dest->from_domain, s->from_domain)
00156    CONT_COPY(dest, dest->to_tag, s->to_tag)
00157    CONT_COPY(dest, dest->from_tag, s->from_tag)
00158    CONT_COPY(dest, dest->callid, s->callid)
00159    CONT_COPY(dest, dest->sockinfo_str, s->sockinfo_str)
00160    CONT_COPY(dest, dest->local_contact, s->local_contact)
00161    CONT_COPY(dest, dest->contact, s->contact)
00162    CONT_COPY(dest, dest->record_route, s->record_route)
00163    if(s->event_id.s)
00164       CONT_COPY(dest, dest->event_id, s->event_id)
00165    if(s->reason.s)
00166       CONT_COPY(dest, dest->reason, s->reason)
00167 
00168    dest->event= s->event;
00169    dest->local_cseq= s->local_cseq;
00170    dest->remote_cseq= s->remote_cseq;
00171    dest->status= s->status;
00172    dest->version= s->version;
00173    dest->send_on_cback= s->send_on_cback;
00174    dest->expires= s->expires;
00175    dest->db_flag= s->db_flag;
00176 
00177    return dest;
00178 
00179 error:
00180    if(dest)
00181    {
00182       if(mem_type & PKG_MEM_TYPE)
00183          pkg_free(dest);
00184       else
00185          shm_free(dest);
00186    }
00187    return NULL;
00188 }
00189 
00190 
00191 subs_t* mem_copy_subs_noc(subs_t* s)
00192 {
00193    int size;
00194    subs_t* dest;
00195 
00196    size= sizeof(subs_t)+ (s->pres_uri.len+ s->to_user.len
00197       + s->to_domain.len+ s->from_user.len+ s->from_domain.len+ s->callid.len
00198       + s->to_tag.len+ s->from_tag.len+s->sockinfo_str.len+s->event_id.len
00199       + s->local_contact.len + s->record_route.len+
00200       + s->reason.len+ 1)*sizeof(char);
00201 
00202    dest= (subs_t*)shm_malloc(size);
00203    if(dest== NULL)
00204    {
00205       ERR_MEM(SHARE_MEM);
00206    }
00207    memset(dest, 0, size);
00208    size= sizeof(subs_t);
00209 
00210    CONT_COPY(dest, dest->pres_uri, s->pres_uri)
00211    CONT_COPY(dest, dest->to_user, s->to_user)
00212    CONT_COPY(dest, dest->to_domain, s->to_domain)
00213    CONT_COPY(dest, dest->from_user, s->from_user)
00214    CONT_COPY(dest, dest->from_domain, s->from_domain)
00215    CONT_COPY(dest, dest->to_tag, s->to_tag)
00216    CONT_COPY(dest, dest->from_tag, s->from_tag)
00217    CONT_COPY(dest, dest->callid, s->callid)
00218    CONT_COPY(dest, dest->sockinfo_str, s->sockinfo_str)
00219    CONT_COPY(dest, dest->local_contact, s->local_contact)
00220    CONT_COPY(dest, dest->record_route, s->record_route)
00221    if(s->event_id.s)
00222       CONT_COPY(dest, dest->event_id, s->event_id)
00223    if(s->reason.s)
00224       CONT_COPY(dest, dest->reason, s->reason)
00225 
00226    dest->event= s->event;
00227    dest->local_cseq= s->local_cseq;
00228    dest->remote_cseq= s->remote_cseq;
00229    dest->status= s->status;
00230    dest->version= s->version;
00231    dest->send_on_cback= s->send_on_cback;
00232    dest->expires= s->expires;
00233    dest->db_flag= s->db_flag;
00234 
00235    dest->contact.s= (char*)shm_malloc(s->contact.len* sizeof(char));
00236    if(dest->contact.s== NULL)
00237    {
00238       ERR_MEM(SHARE_MEM);
00239    }
00240    memcpy(dest->contact.s, s->contact.s, s->contact.len);
00241    dest->contact.len= s->contact.len;
00242 
00243    return dest;
00244 
00245 error:
00246    if(dest)
00247          shm_free(dest);
00248    return NULL;
00249 }
00250 
00251 int insert_shtable(shtable_t htable,unsigned int hash_code, subs_t* subs)
00252 {
00253    subs_t* new_rec= NULL;
00254 
00255    new_rec= mem_copy_subs_noc(subs);
00256    if(new_rec== NULL)
00257    {
00258       LM_ERR("copying in share memory a subs_t structure\n");
00259       goto error;
00260    }
00261 
00262    new_rec->expires+= (int)time(NULL);
00263    new_rec->db_flag= INSERTDB_FLAG;
00264 
00265    lock_get(&htable[hash_code].lock);
00266    
00267    new_rec->next= htable[hash_code].entries->next;
00268    
00269    htable[hash_code].entries->next= new_rec;
00270    
00271    lock_release(&htable[hash_code].lock);
00272    
00273    return 0;
00274 
00275 error:
00276    if(new_rec)
00277       shm_free(new_rec);
00278    return -1;
00279 }
00280 
00281 int delete_shtable(shtable_t htable,unsigned int hash_code,str to_tag)
00282 {
00283    subs_t* s= NULL, *ps= NULL;
00284    int found= -1;
00285 
00286    lock_get(&htable[hash_code].lock);
00287    
00288    ps= htable[hash_code].entries;
00289    s= ps->next;
00290       
00291    while(s)
00292    {  
00293       if(s->to_tag.len== to_tag.len &&
00294             strncmp(s->to_tag.s, to_tag.s, to_tag.len)== 0)
00295       {
00296          found= s->local_cseq;
00297          ps->next= s->next;
00298          if(s->contact.s!=NULL)
00299             shm_free(s->contact.s);
00300          shm_free(s);
00301          break;
00302       }
00303       ps= s;
00304       s= s->next;
00305    }
00306    lock_release(&htable[hash_code].lock);
00307    return found;
00308 }
00309 
00310 void free_subs_list(subs_t* s_array, int mem_type, int ic)
00311 {
00312    subs_t* s;
00313 
00314    while(s_array)
00315    {
00316       s= s_array;
00317       s_array= s_array->next;
00318       if(mem_type & PKG_MEM_TYPE)
00319       {
00320          if(ic)
00321             pkg_free(s->contact.s);
00322          pkg_free(s);
00323       }
00324       else
00325       {
00326          if(ic)
00327             shm_free(s->contact.s);
00328          shm_free(s);
00329       }
00330    }
00331    
00332 }
00333 
00334 int update_shtable(shtable_t htable,unsigned int hash_code, 
00335       subs_t* subs, int type)
00336 {
00337    subs_t* s;
00338 
00339    lock_get(&htable[hash_code].lock);
00340 
00341    s= search_shtable(htable,subs->callid, subs->to_tag, subs->from_tag,
00342          hash_code);
00343    if(s== NULL)
00344    {
00345       LM_DBG("record not found in hash table\n");
00346       lock_release(&htable[hash_code].lock);
00347       return -1;
00348    }
00349 
00350    if(type & REMOTE_TYPE)
00351    {
00352       s->expires= subs->expires+ (int)time(NULL);
00353       s->remote_cseq= subs->remote_cseq;
00354    }
00355    else
00356    {
00357       subs->local_cseq= s->local_cseq;
00358       s->local_cseq++;  
00359       s->version= subs->version+ 1;
00360    }
00361    
00362    if(strncmp(s->contact.s, subs->contact.s, subs->contact.len))
00363    {
00364       shm_free(s->contact.s);
00365       s->contact.s= (char*)shm_malloc(subs->contact.len* sizeof(char));
00366       if(s->contact.s== NULL)
00367       {
00368          lock_release(&htable[hash_code].lock);
00369          LM_ERR("no more shared memory\n");
00370          return -1;
00371       }
00372       memcpy(s->contact.s, subs->contact.s, subs->contact.len);
00373       s->contact.len= subs->contact.len;
00374    }
00375 
00376    s->status= subs->status;
00377    s->event= subs->event;
00378    subs->db_flag= s->db_flag;
00379 
00380    if(s->db_flag & NO_UPDATEDB_FLAG)
00381       s->db_flag= UPDATEDB_FLAG;
00382 
00383    lock_release(&htable[hash_code].lock);
00384    
00385    return 0;
00386 }
00387 
00388 phtable_t* new_phtable(void)
00389 {
00390    phtable_t* htable= NULL;
00391    int i, j;
00392 
00393    i = 0;
00394    htable= (phtable_t*)shm_malloc(phtable_size* sizeof(phtable_t));
00395    if(htable== NULL)
00396    {
00397       ERR_MEM(SHARE_MEM);
00398    }
00399    memset(htable, 0, phtable_size* sizeof(phtable_t));
00400 
00401    for(i= 0; i< phtable_size; i++)
00402    {
00403       if(lock_init(&htable[i].lock)== 0)
00404       {
00405          LM_ERR("initializing lock [%d]\n", i);
00406          goto error;
00407       }
00408       htable[i].entries= (pres_entry_t*)shm_malloc(sizeof(pres_entry_t));
00409       if(htable[i].entries== NULL)
00410       {
00411          ERR_MEM(SHARE_MEM);
00412       }
00413       memset(htable[i].entries, 0, sizeof(pres_entry_t));
00414       htable[i].entries->next= NULL;
00415    }
00416 
00417    return htable;
00418 
00419 error:
00420    if(htable)
00421    {
00422       for(j=0; j< i; j++)
00423       {
00424          if(htable[i].entries)
00425             shm_free(htable[i].entries);
00426          else 
00427             break;
00428          lock_destroy(&htable[i].lock);
00429       }
00430       shm_free(htable);
00431    }
00432    return NULL;
00433 
00434 }
00435 
00436 void destroy_phtable(void)
00437 {
00438    int i;
00439    pres_entry_t* p, *prev_p;
00440 
00441    if(pres_htable== NULL)
00442       return;
00443 
00444    for(i= 0; i< phtable_size; i++)
00445    {
00446       lock_destroy(&pres_htable[i].lock);
00447       p= pres_htable[i].entries;
00448       while(p)
00449       {
00450          prev_p= p;
00451          p= p->next;
00452          if(prev_p->sphere)
00453             shm_free(prev_p->sphere);
00454          shm_free(prev_p);
00455       }
00456    }
00457    shm_free(pres_htable);
00458 }
00459 /* entry must be locked before calling this function */
00460 
00461 pres_entry_t* search_phtable(str* pres_uri,int event, unsigned int hash_code)
00462 {
00463    pres_entry_t* p;
00464 
00465    LM_DBG("pres_uri= %.*s\n", pres_uri->len,  pres_uri->s);
00466    p= pres_htable[hash_code].entries->next;
00467    while(p)
00468    {
00469       if(p->event== event && p->pres_uri.len== pres_uri->len &&
00470             strncmp(p->pres_uri.s, pres_uri->s, pres_uri->len)== 0 )
00471          return p;
00472       p= p->next;
00473    }
00474    return NULL;
00475 }
00476 
00477 int insert_phtable(str* pres_uri, int event, char* sphere)
00478 {
00479    unsigned int hash_code;
00480    pres_entry_t* p= NULL;
00481    int size;
00482 
00483    hash_code= core_hash(pres_uri, NULL, phtable_size);
00484 
00485    lock_get(&pres_htable[hash_code].lock);
00486    
00487    p= search_phtable(pres_uri, event, hash_code);
00488    if(p)
00489    {
00490       p->publ_count++;
00491       lock_release(&pres_htable[hash_code].lock);
00492       return 0;
00493    }
00494    size= sizeof(pres_entry_t)+ pres_uri->len* sizeof(char);
00495 
00496    p= (pres_entry_t*)shm_malloc(size);
00497    if(p== NULL)
00498    {
00499       lock_release(&pres_htable[hash_code].lock);
00500       ERR_MEM(SHARE_MEM);
00501    }
00502    memset(p, 0, size);
00503 
00504    size= sizeof(pres_entry_t);
00505    p->pres_uri.s= (char*)p+ size;
00506    memcpy(p->pres_uri.s, pres_uri->s, pres_uri->len);
00507    p->pres_uri.len= pres_uri->len;
00508    
00509    if(sphere)
00510    {
00511       p->sphere= (char*)shm_malloc((strlen(sphere)+ 1)*sizeof(char));
00512       if(p->sphere== NULL)
00513       {
00514          lock_release(&pres_htable[hash_code].lock);
00515          ERR_MEM(SHARE_MEM);
00516       }
00517       strcpy(p->sphere, sphere);
00518    }
00519 
00520    p->event= event;
00521    
00522 
00523    p->next= pres_htable[hash_code].entries->next;
00524    pres_htable[hash_code].entries->next= p;
00525 
00526    lock_release(&pres_htable[hash_code].lock);
00527    
00528    return 0;
00529 
00530 error:
00531    return -1;
00532 }
00533 
00534 int delete_phtable(str* pres_uri, int event)
00535 {
00536    unsigned int hash_code;
00537    pres_entry_t* p= NULL, *prev_p= NULL;
00538 
00539    hash_code= core_hash(pres_uri, NULL, phtable_size);
00540 
00541    lock_get(&pres_htable[hash_code].lock);
00542    
00543    p= search_phtable(pres_uri, event, hash_code);
00544    if(p== NULL)
00545    {
00546       LM_DBG("record not found\n");
00547       lock_release(&pres_htable[hash_code].lock);
00548       return 0;
00549    }
00550    
00551    p->publ_count--;
00552    if(p->publ_count== 0)
00553    {
00554       /* delete record */  
00555       prev_p= pres_htable[hash_code].entries;
00556       while(prev_p->next)
00557       {
00558          if(prev_p->next== p)
00559             break;
00560          prev_p= prev_p->next;
00561       }
00562       if(prev_p->next== NULL)
00563       {
00564          LM_ERR("record not found\n");
00565          lock_release(&pres_htable[hash_code].lock);
00566          return -1;
00567       }
00568       prev_p->next= p->next;
00569       if(p->sphere)
00570          shm_free(p->sphere);
00571 
00572       shm_free(p);
00573    }
00574    lock_release(&pres_htable[hash_code].lock);
00575 
00576    return 0;   
00577 }
00578 
00579 int update_phtable(presentity_t* presentity, str pres_uri, str body)
00580 {
00581    char* sphere= NULL;
00582    unsigned int hash_code;
00583    pres_entry_t* p;
00584    int ret= 0;
00585    str* xcap_doc= NULL;
00586 
00587    /* get new sphere */
00588    sphere= extract_sphere(body);
00589    if(sphere==NULL)
00590    {
00591       LM_DBG("no sphere defined in new body\n");
00592       return 0;
00593    }
00594 
00595    /* search for record in hash table */
00596    hash_code= core_hash(&pres_uri, NULL, phtable_size);
00597    
00598    lock_get(&pres_htable[hash_code].lock);
00599 
00600    p= search_phtable(&pres_uri, presentity->event->evp->parsed, hash_code);
00601    if(p== NULL)
00602    {
00603       lock_release(&pres_htable[hash_code].lock);
00604       goto done;
00605    }
00606    
00607    if(p->sphere)
00608    {
00609       if(strcmp(p->sphere, sphere)!= 0)
00610       {
00611          /* new sphere definition */
00612          shm_free(p->sphere);
00613       }
00614       else
00615       {
00616          /* no change in sphere definition */
00617          lock_release(&pres_htable[hash_code].lock);
00618          pkg_free(sphere);
00619          return 0;
00620       }
00621    
00622    }
00623 
00624 
00625    p->sphere= (char*)shm_malloc((strlen(sphere)+ 1)*sizeof(char));
00626    if(p->sphere== NULL)
00627    {
00628       lock_release(&pres_htable[hash_code].lock);
00629       ret= -1;
00630       goto done;
00631    }
00632    strcpy(p->sphere, sphere);
00633       
00634    lock_release(&pres_htable[hash_code].lock);
00635 
00636    /* call for watchers status update */
00637 
00638    if(presentity->event->get_rules_doc(&presentity->user, &presentity->domain,
00639             &xcap_doc)< 0)
00640    {
00641       LM_ERR("failed to retreive xcap document\n");
00642       ret= -1;
00643       goto done;
00644    }
00645 
00646    update_watchers_status(pres_uri, presentity->event, xcap_doc);
00647 
00648 
00649 done:
00650 
00651    if(xcap_doc)
00652    {
00653       if(xcap_doc->s)
00654          pkg_free(xcap_doc->s);
00655       pkg_free(xcap_doc);
00656    }
00657 
00658    if(sphere)
00659       pkg_free(sphere);
00660    return ret;
00661 }

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