presentity.c

Go to the documentation of this file.
00001 /*
00002  * $Id: presentity.c 5619 2009-02-18 18:33:43Z miconda $
00003  *
00004  * presence module - presence server implementation
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  * History:
00025  * --------
00026  *  2006-08-15  initial version (anca)
00027  */
00028 
00029 /*! \file
00030  * \brief Kamailio presence module :: Presentity handling
00031  * \ingroup presence 
00032  */
00033 
00034 
00035 #include <stdio.h>
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <time.h>
00039 
00040 #include "../../db/db.h"
00041 #include "../../dprint.h"
00042 #include "../../mem/shm_mem.h"
00043 #include "../../str.h"
00044 #include "../alias_db/alias_db.h"
00045 #include "../../data_lump_rpl.h"
00046 #include "presentity.h"
00047 #include "presence.h" 
00048 #include "notify.h"
00049 #include "publish.h"
00050 #include "hash.h"
00051 #include "utils_func.h"
00052 
00053 
00054 xmlNodePtr xmlNodeGetNodeByName(xmlNodePtr node, const char *name,
00055                                        const char *ns);
00056 static str pu_200_rpl  = str_init("OK");
00057 static str pu_412_rpl  = str_init("Conditional request failed");
00058 
00059 #define ETAG_LEN  128
00060 
00061 char* generate_ETag(int publ_count)
00062 {
00063    char* etag= NULL;
00064    int size = 0;
00065 
00066    etag = (char*)pkg_malloc(ETAG_LEN*sizeof(char));
00067    if(etag ==NULL)
00068    {
00069       ERR_MEM(PKG_MEM_STR);
00070    }
00071    memset(etag, 0, ETAG_LEN*sizeof(char));
00072    size = snprintf (etag, ETAG_LEN, "%c.%d.%d.%d.%d",prefix, startup_time, pid, counter, publ_count);
00073    if( size <0 )
00074    {
00075       LM_ERR("unsuccessfull snprintf\n ");
00076       pkg_free(etag);
00077       return NULL;
00078    }
00079    if(size >= ETAG_LEN)
00080    {
00081       LM_ERR("buffer size overflown\n");
00082       pkg_free(etag);
00083       return NULL;
00084    }
00085 
00086    etag[size] = '\0';
00087    LM_DBG("etag= %s / %d\n ",etag, size);
00088    return etag;
00089 
00090 error:
00091    return NULL;
00092 
00093 }
00094 
00095 int publ_send200ok(struct sip_msg *msg, int lexpire, str etag)
00096 {
00097    char buf[128];
00098    int buf_len= 128, size;
00099    str hdr_append= {0, 0}, hdr_append2= {0, 0} ;
00100 
00101    LM_DBG("send 200OK reply\n"); 
00102    LM_DBG("etag= %s - len= %d\n", etag.s, etag.len);
00103    
00104    hdr_append.s = buf;
00105    hdr_append.s[0]='\0';
00106    hdr_append.len = snprintf(hdr_append.s, buf_len, "Expires: %d\r\n",
00107          ((lexpire==0)?0:(lexpire-expires_offset)));
00108    if(hdr_append.len < 0)
00109    {
00110       LM_ERR("unsuccessful snprintf\n");
00111       goto error;
00112    }
00113    if(hdr_append.len >= buf_len)
00114    {
00115       LM_ERR("buffer size overflown\n");
00116       goto error;
00117    }
00118    hdr_append.s[hdr_append.len]= '\0';
00119       
00120    if (add_lump_rpl( msg, hdr_append.s, hdr_append.len, LUMP_RPL_HDR)==0 )
00121    {
00122       LM_ERR("unable to add lump_rl\n");
00123       goto error;
00124    }
00125 
00126    size= sizeof(char)*(20+etag.len) ;
00127    hdr_append2.s = (char *)pkg_malloc(size);
00128    if(hdr_append2.s == NULL)
00129    {
00130       ERR_MEM(PKG_MEM_STR);
00131    }
00132    hdr_append2.s[0]='\0';
00133    hdr_append2.len = snprintf(hdr_append2.s, size, "SIP-ETag: %s\r\n", etag.s);
00134    if(hdr_append2.len < 0)
00135    {
00136       LM_ERR("unsuccessful snprintf\n ");
00137       goto error;
00138    }
00139    if(hdr_append2.len >= size)
00140    {
00141       LM_ERR("buffer size overflown\n");
00142       goto error;
00143    }
00144 
00145    hdr_append2.s[hdr_append2.len]= '\0';
00146    if (add_lump_rpl(msg, hdr_append2.s, hdr_append2.len, LUMP_RPL_HDR)==0 )
00147    {
00148       LM_ERR("unable to add lump_rl\n");
00149       goto error;
00150    }
00151 
00152    if( slb.send_reply( msg, 200, &pu_200_rpl)== -1)
00153    {
00154       LM_ERR("sending reply\n");
00155       goto error;
00156    }
00157 
00158    pkg_free(hdr_append2.s);
00159    return 0;
00160 
00161 error:
00162 
00163    if(hdr_append2.s)
00164       pkg_free(hdr_append2.s);
00165 
00166    return -1;
00167 }  
00168 presentity_t* new_presentity( str* domain,str* user,int expires, 
00169       pres_ev_t* event, str* etag, str* sender)
00170 {
00171    presentity_t *presentity= NULL;
00172    int size, init_len;
00173    
00174    /* allocating memory for presentity */
00175    size = sizeof(presentity_t)+ domain->len+ user->len+ etag->len +1;
00176    if(sender)
00177       size+= sizeof(str)+ sender->len* sizeof(char);
00178    
00179    init_len= size;
00180 
00181    presentity = (presentity_t*)pkg_malloc(size);
00182    if(presentity == NULL)
00183    {
00184       ERR_MEM(PKG_MEM_STR);
00185    }
00186    memset(presentity, 0, size);
00187    size= sizeof(presentity_t);
00188 
00189    presentity->domain.s = (char*)presentity+ size;
00190    strncpy(presentity->domain.s, domain->s, domain->len);
00191    presentity->domain.len = domain->len;
00192    size+= domain->len;  
00193    
00194    presentity->user.s = (char*)presentity+size;
00195    strncpy(presentity->user.s, user->s, user->len);
00196    presentity->user.len = user->len;
00197    size+= user->len;
00198 
00199    presentity->etag.s = (char*)presentity+ size;
00200    memcpy(presentity->etag.s, etag->s, etag->len);
00201    presentity->etag.s[etag->len]= '\0';
00202    presentity->etag.len = etag->len;
00203 
00204    size+= etag->len+1;
00205    
00206    if(sender)
00207    {
00208       presentity->sender= (str*)((char*)presentity+ size);
00209       size+= sizeof(str);
00210       presentity->sender->s= (char*)presentity + size;
00211       memcpy(presentity->sender->s, sender->s, sender->len);
00212       presentity->sender->len= sender->len;
00213       size+= sender->len;
00214    }
00215 
00216    if(size> init_len)
00217    {
00218       LM_ERR("buffer size overflow init_len= %d, size= %d\n", init_len, size);
00219       goto error;
00220    }
00221    presentity->event= event;
00222    presentity->expires = expires;
00223    presentity->received_time= (int)time(NULL);
00224    return presentity;
00225     
00226 error:
00227    if(presentity)
00228       pkg_free(presentity);
00229    return NULL;
00230 }
00231 
00232 xmlNodePtr xmlNodeGetChildByName(xmlNodePtr node, const char *name)
00233 {
00234    xmlNodePtr cur = node->children;
00235    while (cur) {
00236       if (xmlStrcasecmp(cur->name, (unsigned char*)name) == 0)
00237          return cur;
00238       cur = cur->next;
00239    }
00240    return NULL;
00241 }
00242 
00243 int check_if_dialog(str body, int *is_dialog)
00244 {
00245    xmlDocPtr doc;
00246    xmlNodePtr node;
00247 
00248    doc = xmlParseMemory(body.s, body.len);
00249    if(doc== NULL)
00250    {
00251       LM_ERR("failed to parse xml document\n");
00252       return -1;
00253    }
00254 
00255    node = doc->children;
00256    node = xmlNodeGetChildByName(node, "dialog");
00257 
00258    if(node == NULL)
00259       *is_dialog = 0;
00260    else
00261       *is_dialog = 1;
00262 
00263    xmlFreeDoc(doc);
00264    return 0;
00265 }
00266 
00267 
00268 int update_presentity(struct sip_msg* msg, presentity_t* presentity, str* body,
00269       int new_t, int* sent_reply, char* sphere)
00270 {
00271    db_key_t query_cols[12], update_keys[8], result_cols[5];
00272    db_op_t  query_ops[12];
00273    db_val_t query_vals[12], update_vals[8];
00274    db_res_t *result= NULL;
00275    int n_query_cols = 0;
00276    int n_update_cols = 0;
00277    char* dot= NULL;
00278    str etag= {0, 0};
00279    str cur_etag= {0, 0};
00280    str* rules_doc= NULL;
00281    str pres_uri= {0, 0};
00282    int rez_body_col, rez_sender_col, n_result_cols= 0;
00283    db_row_t *row = NULL ;
00284    db_val_t *row_vals = NULL;
00285    str old_body, sender;
00286    int is_dialog= 0, bla_update_publish= 1;
00287 
00288    *sent_reply= 0;
00289    if(presentity->event->req_auth)
00290    {
00291       /* get rules_document */
00292       if(presentity->event->get_rules_doc(&presentity->user,
00293                &presentity->domain, &rules_doc))
00294       {
00295          LM_ERR("getting rules doc\n");
00296          goto error;
00297       }
00298    }
00299    
00300    if(uandd_to_uri(presentity->user, presentity->domain, &pres_uri)< 0)
00301    {
00302       LM_ERR("constructing uri from user and domain\n");
00303       goto error;
00304    }
00305 
00306 
00307    query_cols[n_query_cols] = &str_domain_col;
00308    query_ops[n_query_cols] = OP_EQ;
00309    query_vals[n_query_cols].type = DB_STR;
00310    query_vals[n_query_cols].nul = 0;
00311    query_vals[n_query_cols].val.str_val = presentity->domain;
00312    n_query_cols++;
00313    
00314    query_cols[n_query_cols] = &str_username_col;
00315    query_ops[n_query_cols] = OP_EQ;
00316    query_vals[n_query_cols].type = DB_STR;
00317    query_vals[n_query_cols].nul = 0;
00318    query_vals[n_query_cols].val.str_val = presentity->user;
00319    n_query_cols++;
00320 
00321    query_cols[n_query_cols] = &str_event_col;
00322    query_ops[n_query_cols] = OP_EQ;
00323    query_vals[n_query_cols].type = DB_STR;
00324    query_vals[n_query_cols].nul = 0;
00325    query_vals[n_query_cols].val.str_val = presentity->event->name;
00326    n_query_cols++;
00327 
00328    query_cols[n_query_cols] = &str_etag_col;
00329    query_ops[n_query_cols] = OP_EQ;
00330    query_vals[n_query_cols].type = DB_STR;
00331    query_vals[n_query_cols].nul = 0;
00332    query_vals[n_query_cols].val.str_val = presentity->etag;
00333    n_query_cols++;
00334 
00335    result_cols[rez_body_col= n_result_cols++] = &str_body_col;
00336    result_cols[rez_sender_col= n_result_cols++] = &str_sender_col;
00337 
00338    if(new_t) 
00339    {
00340       /* insert new record in hash_table */
00341    
00342       if(insert_phtable(&pres_uri, presentity->event->evp->parsed, sphere)< 0)
00343       {
00344          LM_ERR("inserting record in hash table\n");
00345          goto error;
00346       }
00347       
00348       /* insert new record into database */  
00349       query_cols[n_query_cols] = &str_expires_col;
00350       query_vals[n_query_cols].type = DB_INT;
00351       query_vals[n_query_cols].nul = 0;
00352       query_vals[n_query_cols].val.int_val = presentity->expires+
00353             (int)time(NULL);
00354       n_query_cols++;
00355    
00356       if( presentity->sender)
00357       {
00358          query_cols[n_query_cols] = &str_sender_col;
00359          query_vals[n_query_cols].type = DB_STR;
00360          query_vals[n_query_cols].nul = 0;
00361          query_vals[n_query_cols].val.str_val.s = presentity->sender->s;
00362          query_vals[n_query_cols].val.str_val.len = presentity->sender->len;
00363          n_query_cols++;
00364       }
00365 
00366       query_cols[n_query_cols] = &str_body_col;
00367       query_vals[n_query_cols].type = DB_BLOB;
00368       query_vals[n_query_cols].nul = 0;
00369       query_vals[n_query_cols].val.str_val = *body;
00370       n_query_cols++;
00371       
00372       query_cols[n_query_cols] = &str_received_time_col;
00373       query_vals[n_query_cols].type = DB_INT;
00374       query_vals[n_query_cols].nul = 0;
00375       query_vals[n_query_cols].val.int_val = presentity->received_time;
00376       n_query_cols++;
00377       
00378       if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00379       {
00380          LM_ERR("unsuccessful use_table\n");
00381          goto error;
00382       }
00383 
00384       LM_DBG("inserting %d cols into table\n",n_query_cols);
00385             
00386       if (pa_dbf.insert(pa_db, query_cols, query_vals, n_query_cols) < 0) 
00387       {
00388          LM_ERR("inserting new record in database\n");
00389          goto error;
00390       }
00391       if( publ_send200ok(msg, presentity->expires, presentity->etag)< 0)
00392       {
00393          LM_ERR("sending 200OK\n");
00394          goto error;
00395       }
00396       *sent_reply= 1;
00397       goto send_notify;
00398    }
00399    else
00400    {  
00401       if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00402       {
00403          LM_ERR("unsuccessful sql use table\n");
00404          goto error;
00405       }
00406 
00407       if (pa_dbf.query (pa_db, query_cols, query_ops, query_vals,
00408           result_cols, n_query_cols, n_result_cols, 0, &result) < 0) 
00409       {
00410          LM_ERR("unsuccessful sql query\n");
00411          goto error;
00412       }
00413       if(result== NULL)
00414          goto error;
00415 
00416       if (result->n > 0)
00417       {
00418 
00419          if(presentity->event->evp->parsed == EVENT_DIALOG_SLA)
00420          {
00421             /* analize if previous body has a dialog */
00422             row = &result->rows[0];
00423             row_vals = ROW_VALUES(row);
00424 
00425             old_body.s = (char*)row_vals[rez_body_col].val.string_val;
00426             old_body.len = strlen(old_body.s);
00427             if(check_if_dialog(*body, &is_dialog)< 0)
00428             {
00429                LM_ERR("failed to check if dialog stored\n");
00430                goto error;
00431             }
00432 
00433             if(is_dialog== 1)  /* if the new body has a dialog - overwrite */
00434                goto after_dialog_check;
00435 
00436             if(check_if_dialog(old_body, &is_dialog)< 0)
00437             {
00438                LM_ERR("failed to check if dialog stored\n");
00439                goto error;
00440             }
00441 
00442             if(is_dialog==0 ) /* if the old body has no dialog - overwrite */
00443                goto after_dialog_check;
00444 
00445             sender.s = (char*)row_vals[rez_sender_col].val.string_val;
00446             sender.len= strlen(sender.s);
00447 
00448             LM_DBG("old_sender = %.*s\n", sender.len, sender.s );
00449             if(presentity->sender)
00450             {
00451                if(!(presentity->sender->len == sender.len && 
00452                strncmp(presentity->sender->s, sender.s, sender.len)== 0))
00453                    bla_update_publish= 0;
00454             }
00455          }
00456 after_dialog_check:
00457 
00458          pa_dbf.free_result(pa_db, result);
00459          result= NULL;
00460          if(presentity->expires == 0) 
00461          {
00462             if( publ_send200ok(msg, presentity->expires, presentity->etag)< 0)
00463             {
00464                LM_ERR("sending 200OK reply\n");
00465                goto error;
00466             }
00467             *sent_reply= 1;
00468             if( publ_notify( presentity, pres_uri, body, &presentity->etag, rules_doc)< 0 )
00469             {
00470                LM_ERR("while sending notify\n");
00471                goto error;
00472             }
00473             
00474             if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00475             {
00476                LM_ERR("unsuccessful sql use table\n");
00477                goto error;
00478             }
00479 
00480             LM_DBG("expires =0 -> deleting from database\n");
00481             if(pa_dbf.delete(pa_db,query_cols,0,query_vals,n_query_cols)<0)
00482             {
00483                LM_ERR("unsuccessful sql delete operation");
00484                goto error;
00485             }
00486             LM_DBG("deleted from db %.*s\n", presentity->user.len,
00487                   presentity->user.s);
00488 
00489             /* delete from hash table */
00490    
00491             if(delete_phtable(&pres_uri, presentity->event->evp->parsed)< 0)
00492             {
00493                LM_ERR("deleting record from hash table\n");
00494                goto error;
00495             }
00496             goto done;
00497          }
00498 
00499          n_update_cols= 0;
00500          /* if event dialog and is_dialog -> if sender not the same as
00501           * old sender do not overwrite */
00502          if( (presentity->event->evp->parsed == EVENT_DIALOG_SLA) &&  bla_update_publish==0)
00503          {
00504             LM_DBG("drop Publish for BLA from a different sender that"
00505                   " wants to overwrite an existing dialog\n");
00506             LM_DBG("sender = %.*s\n",  presentity->sender->len, presentity->sender->s );
00507             if( publ_send200ok(msg, presentity->expires, presentity->etag)< 0)
00508             {
00509                LM_ERR("sending 200OK reply\n");
00510                goto error;
00511             }
00512             *sent_reply= 1;
00513             goto done;
00514          }
00515 
00516          if(presentity->event->etag_not_new== 0)
00517          {  
00518             /* generate another etag */
00519             unsigned int publ_nr;
00520             str str_publ_nr= {0, 0};
00521 
00522             dot= presentity->etag.s+ presentity->etag.len;
00523             while(*dot!= '.' && str_publ_nr.len< presentity->etag.len)
00524             {
00525                str_publ_nr.len++;
00526                dot--;
00527             }
00528             if(str_publ_nr.len== presentity->etag.len)
00529             {
00530                LM_ERR("wrong etag\n");
00531                goto error;
00532             }  
00533             str_publ_nr.s= dot+1;
00534             str_publ_nr.len--;
00535    
00536             if( str2int(&str_publ_nr, &publ_nr)< 0)
00537             {
00538                LM_ERR("converting string to int\n");
00539                goto error;
00540             }
00541             etag.s = generate_ETag(publ_nr+1);
00542             if(etag.s == NULL)
00543             {
00544                LM_ERR("while generating etag\n");
00545                goto error;
00546             }
00547             etag.len=(strlen(etag.s));
00548             
00549             cur_etag= etag;
00550 
00551             update_keys[n_update_cols] = &str_etag_col;
00552             update_vals[n_update_cols].type = DB_STR;
00553             update_vals[n_update_cols].nul = 0;
00554             update_vals[n_update_cols].val.str_val = etag;
00555             n_update_cols++;
00556 
00557          }
00558          else
00559             cur_etag= presentity->etag;
00560          
00561          update_keys[n_update_cols] = &str_expires_col;
00562          update_vals[n_update_cols].type = DB_INT;
00563          update_vals[n_update_cols].nul = 0;
00564          update_vals[n_update_cols].val.int_val= presentity->expires +
00565             (int)time(NULL);
00566          n_update_cols++;
00567 
00568          update_keys[n_update_cols] = &str_received_time_col;
00569          update_vals[n_update_cols].type = DB_INT;
00570          update_vals[n_update_cols].nul = 0;
00571          update_vals[n_update_cols].val.int_val= presentity->received_time;
00572          n_update_cols++;
00573 
00574          if(body && body->s)
00575          {
00576             update_keys[n_update_cols] = &str_body_col;
00577             update_vals[n_update_cols].type = DB_BLOB;
00578             update_vals[n_update_cols].nul = 0;
00579             update_vals[n_update_cols].val.str_val = *body;
00580             n_update_cols++;
00581 
00582             /* updated stored sphere */
00583             if(sphere_enable && 
00584                   presentity->event->evp->parsed== EVENT_PRESENCE)
00585             {
00586                if(update_phtable(presentity, pres_uri, *body)< 0)
00587                {
00588                   LM_ERR("failed to update sphere for presentity\n");
00589                   goto error;
00590                }
00591             }
00592          }
00593          
00594          if( presentity->sender)
00595          {
00596             update_keys[n_update_cols] = &str_sender_col;
00597             update_vals[n_update_cols].type = DB_STR;
00598             update_vals[n_update_cols].nul = 0;
00599             update_vals[n_update_cols].val.str_val = *presentity->sender;
00600             n_update_cols++;
00601          }
00602 
00603          if( pa_dbf.update( pa_db,query_cols, query_ops, query_vals,
00604                update_keys, update_vals, n_query_cols, n_update_cols )<0) 
00605          {
00606             LM_ERR("updating published info in database\n");
00607             goto error;
00608          }
00609          
00610          /* send 200OK */
00611          if( publ_send200ok(msg, presentity->expires, cur_etag)< 0)
00612          {
00613             LM_ERR("sending 200OK reply\n");
00614             goto error;
00615          }
00616          *sent_reply= 1;
00617          
00618          if(etag.s)
00619             pkg_free(etag.s);
00620          etag.s= NULL;
00621          
00622          if(!body)
00623             goto done;
00624       
00625          goto send_notify;
00626       }  
00627       else  /* if there isn't no registration with those 3 values */
00628       {
00629          pa_dbf.free_result(pa_db, result);
00630          result= NULL;
00631          LM_ERR("No E_Tag match\n");
00632          if (slb.send_reply(msg, 412, &pu_412_rpl) == -1)
00633          {
00634             LM_ERR("sending '412 Conditional request failed' reply\n");
00635             goto error;
00636          }
00637          *sent_reply= 1;
00638          goto done;
00639       }
00640    }
00641 
00642 send_notify:
00643          
00644    /* send notify with presence information */
00645    if (publ_notify(presentity, pres_uri, body, NULL, rules_doc)<0)
00646    {
00647       LM_ERR("while sending Notify requests to watchers\n");
00648       goto error;
00649    }
00650 
00651 done:
00652    if(rules_doc)
00653    {
00654       if(rules_doc->s)
00655          pkg_free(rules_doc->s);
00656       pkg_free(rules_doc);
00657    }
00658    if(pres_uri.s)
00659       pkg_free(pres_uri.s);
00660 
00661    return 0;
00662 
00663 error:
00664    if(result)
00665       pa_dbf.free_result(pa_db, result);
00666    if(etag.s)
00667       pkg_free(etag.s);
00668    if(rules_doc)
00669    {
00670       if(rules_doc->s)
00671          pkg_free(rules_doc->s);
00672       pkg_free(rules_doc);
00673    }
00674    if(pres_uri.s)
00675       pkg_free(pres_uri.s);
00676 
00677    return -1;
00678 
00679 }
00680 
00681 int pres_htable_restore(void)
00682 {
00683    /* query all records from presentity table and insert records 
00684     * in presentity table */
00685    db_key_t result_cols[6];
00686    db_res_t *result= NULL;
00687    db_row_t *row= NULL ;   
00688    db_val_t *row_vals;
00689    int  i;
00690    str user, domain, ev_str, uri, body;
00691    int n_result_cols= 0;
00692    int user_col, domain_col, event_col, expires_col, body_col = 0;
00693    int event;
00694    event_t ev;
00695    char* sphere= NULL;
00696 
00697    result_cols[user_col= n_result_cols++]= &str_username_col;
00698    result_cols[domain_col= n_result_cols++]= &str_domain_col;
00699    result_cols[event_col= n_result_cols++]= &str_event_col;
00700    result_cols[expires_col= n_result_cols++]= &str_expires_col;
00701    if(sphere_enable)
00702       result_cols[body_col= n_result_cols++]= &str_body_col;
00703 
00704    if (pa_dbf.use_table(pa_db, &presentity_table) < 0)
00705    {
00706       LM_ERR("unsuccessful use table sql operation\n");
00707       goto error;
00708    }
00709    static str query_str = str_init("username");
00710    if (pa_dbf.query (pa_db, 0, 0, 0,result_cols,0, n_result_cols,
00711             &query_str, &result) < 0)
00712    {
00713       LM_ERR("querying presentity\n");
00714       goto error;
00715    }
00716    if(result== NULL)
00717       goto error;
00718 
00719    if(result->n<= 0)
00720    {
00721       pa_dbf.free_result(pa_db, result);
00722       return 0;
00723    }
00724       
00725    for(i= 0; i< result->n; i++)
00726    {
00727       row = &result->rows[i];
00728       row_vals = ROW_VALUES(row);
00729 
00730       if(row_vals[expires_col].val.int_val< (int)time(NULL))
00731          continue;
00732       
00733       sphere= NULL;
00734       user.s= (char*)row_vals[user_col].val.string_val;
00735       user.len= strlen(user.s);
00736       domain.s= (char*)row_vals[domain_col].val.string_val;
00737       domain.len= strlen(domain.s);
00738       ev_str.s= (char*)row_vals[event_col].val.string_val;
00739       ev_str.len= strlen(ev_str.s);
00740 
00741       if(event_parser(ev_str.s, ev_str.len, &ev)< 0)
00742       {
00743          LM_ERR("parsing event\n");
00744          free_event_params(ev.params, PKG_MEM_TYPE);
00745          goto error;
00746       }
00747       event= ev.parsed;
00748       free_event_params(ev.params, PKG_MEM_TYPE);
00749 
00750       if(uandd_to_uri(user, domain, &uri)< 0)
00751       {
00752          LM_ERR("constructing uri\n");
00753          goto error;
00754       }
00755       /* insert in hash_table*/
00756    
00757       if(sphere_enable && event== EVENT_PRESENCE )
00758       {
00759          body.s= (char*)row_vals[body_col].val.string_val;
00760          body.len= strlen(body.s);
00761          sphere= extract_sphere(body);
00762       }
00763 
00764       if(insert_phtable(&uri, event, sphere)< 0)
00765       {
00766          LM_ERR("inserting record in presentity hash table");
00767          pkg_free(uri.s);
00768          if(sphere)
00769             pkg_free(sphere);
00770          goto error;
00771       }
00772       if(sphere)
00773          pkg_free(sphere);
00774       pkg_free(uri.s);
00775    }
00776    pa_dbf.free_result(pa_db, result);
00777 
00778    return 0;
00779 
00780 error:
00781    if(result)
00782       pa_dbf.free_result(pa_db, result);
00783    return -1;  
00784 }
00785 
00786 char* extract_sphere(str body)
00787 {
00788 
00789    /* check for a rpid sphere element */
00790    xmlDocPtr doc= NULL;
00791    xmlNodePtr node;
00792    char* cont, *sphere= NULL;
00793    
00794 
00795    doc= xmlParseMemory(body.s, body.len);
00796    if(doc== NULL)
00797    {
00798       LM_ERR("failed to parse xml body\n");
00799       return NULL;
00800    }
00801 
00802    node= xmlNodeGetNodeByName(doc->children, "sphere", "rpid");
00803    
00804    if(node== NULL)
00805       node= xmlNodeGetNodeByName(doc->children, "sphere", "r");
00806 
00807    if(node)
00808    {
00809       LM_DBG("found sphere definition\n");
00810       cont= (char*)xmlNodeGetContent(node);
00811       if(cont== NULL)
00812       {
00813          LM_ERR("failed to extract sphere node content\n");
00814          goto error;
00815       }
00816       sphere= (char*)pkg_malloc((strlen(cont)+ 1)*sizeof(char));
00817       if(sphere== NULL)
00818       {
00819          xmlFree(cont);
00820          ERR_MEM(PKG_MEM_STR);
00821       }
00822       strcpy(sphere, cont);
00823       xmlFree(cont);
00824    }
00825    else
00826       LM_DBG("didn't find sphere definition\n");
00827 
00828 error:
00829    xmlFreeDoc(doc);
00830 
00831    return sphere;
00832 }
00833 
00834 xmlNodePtr xmlNodeGetNodeByName(xmlNodePtr node, const char *name,
00835                                        const char *ns)
00836 {
00837    xmlNodePtr cur = node;
00838    while (cur) {
00839       xmlNodePtr match = NULL;
00840       if (xmlStrcasecmp(cur->name, (unsigned char*)name) == 0) {
00841          if (!ns || (cur->ns && xmlStrcasecmp(cur->ns->prefix,
00842                      (unsigned char*)ns) == 0))
00843             return cur;
00844       }
00845       match = xmlNodeGetNodeByName(cur->children, name, ns);
00846       if (match)
00847          return match;
00848       cur = cur->next;
00849    }
00850    return NULL;
00851 }
00852 
00853 char* get_sphere(str* pres_uri)
00854 {
00855    unsigned int hash_code;
00856    char* sphere= NULL;
00857    pres_entry_t* p;
00858    db_key_t query_cols[6];
00859    db_val_t query_vals[6];
00860    db_key_t result_cols[6];
00861    db_res_t *result = NULL;
00862    db_row_t *row= NULL ;   
00863    db_val_t *row_vals;
00864    int n_result_cols = 0;
00865    int n_query_cols = 0;
00866    struct sip_uri uri;
00867    str body;
00868 
00869 
00870    if(!sphere_enable)
00871       return NULL;
00872 
00873    /* search in hash table*/
00874    hash_code= core_hash(pres_uri, NULL, phtable_size);
00875 
00876    lock_get(&pres_htable[hash_code].lock);
00877 
00878    p= search_phtable(pres_uri, EVENT_PRESENCE, hash_code);
00879 
00880    if(p)
00881    {
00882       if(p->sphere)
00883       {
00884          sphere= (char*)pkg_malloc(strlen(p->sphere)* sizeof(char));
00885          if(sphere== NULL)
00886          {
00887             lock_release(&pres_htable[hash_code].lock);
00888             ERR_MEM(PKG_MEM_STR);
00889          }
00890          strcpy(sphere, p->sphere);
00891       }
00892       lock_release(&pres_htable[hash_code].lock);
00893       return sphere;
00894    }
00895    lock_release(&pres_htable[hash_code].lock);
00896 
00897 
00898    /* if record not found and fallback2db query database*/
00899    if(!fallback2db)
00900    {
00901       return NULL;
00902    }
00903 
00904    if(parse_uri(pres_uri->s, pres_uri->len, &uri)< 0)
00905    {
00906       LM_ERR("failed to parse presentity uri\n");
00907       goto error;
00908    }
00909 
00910    query_cols[n_query_cols] = &str_domain_col;
00911    query_vals[n_query_cols].type = DB_STR;
00912    query_vals[n_query_cols].nul = 0;
00913    query_vals[n_query_cols].val.str_val = uri.host;
00914    n_query_cols++;
00915 
00916    query_cols[n_query_cols] = &str_username_col;
00917    query_vals[n_query_cols].type = DB_STR;
00918    query_vals[n_query_cols].nul = 0;
00919    query_vals[n_query_cols].val.str_val = uri.user;
00920    n_query_cols++;
00921 
00922    query_cols[n_query_cols] = &str_event_col;
00923    query_vals[n_query_cols].type = DB_STR;
00924    query_vals[n_query_cols].nul = 0;
00925    query_vals[n_query_cols].val.str_val.s= "presence";
00926    query_vals[n_query_cols].val.str_val.len= 8;
00927    n_query_cols++;
00928 
00929    result_cols[n_result_cols++] = &str_body_col;
00930    
00931    if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00932    {
00933       LM_ERR("in use_table\n");
00934       return NULL;
00935    }
00936 
00937    static str query_str = str_init("received_time");
00938    if (pa_dbf.query (pa_db, query_cols, 0, query_vals,
00939        result_cols, n_query_cols, n_result_cols, &query_str ,  &result) < 0) 
00940    {
00941       LM_ERR("failed to query %.*s table\n", presentity_table.len, presentity_table.s);
00942       if(result)
00943          pa_dbf.free_result(pa_db, result);
00944       return NULL;
00945    }
00946    
00947    if(result== NULL)
00948       return NULL;
00949 
00950    if (result->n<=0 )
00951    {
00952       LM_DBG("no published record found in database\n");
00953       pa_dbf.free_result(pa_db, result);
00954       return NULL;
00955    }
00956 
00957    row = &result->rows[result->n-1];
00958    row_vals = ROW_VALUES(row);
00959    if(row_vals[0].val.string_val== NULL)
00960    {
00961       LM_ERR("NULL notify body record\n");
00962       goto error;
00963    }
00964 
00965    body.s= (char*)row_vals[0].val.string_val;
00966    body.len= strlen(body.s);
00967    if(body.len== 0)
00968    {
00969       LM_ERR("Empty notify body record\n");
00970       goto error;
00971    }
00972    
00973    sphere= extract_sphere(body);
00974 
00975    pa_dbf.free_result(pa_db, result);
00976 
00977    return sphere;
00978 
00979 error:
00980    if(result)
00981       pa_dbf.free_result(pa_db, result);
00982    return NULL;
00983 
00984 }
00985 

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