publish.c

Go to the documentation of this file.
00001 /*
00002  * $Id: publish.c 5405 2008-12-31 09:17:34Z 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 :: Support for PUBLISH handling
00031  * \ingroup presence 
00032  */
00033 
00034 
00035 #include <time.h>
00036 
00037 #include "../../ut.h"
00038 #include "../../str.h"
00039 #include "../../parser/parse_to.h"
00040 #include "../../parser/parse_uri.h" 
00041 #include "../../parser/parse_expires.h" 
00042 #include "../../parser/parse_event.h" 
00043 #include "../../parser/parse_content.h" 
00044 #include "../../lock_ops.h"
00045 #include "../../hash_func.h"
00046 #include "../../cmpapi.h"
00047 #include "../../db/db.h"
00048 #include "presence.h"
00049 #include "notify.h"
00050 #include "utils_func.h"
00051 #include "publish.h"
00052 #include "presentity.h"
00053 
00054 extern gen_lock_set_t* set;
00055 
00056 static str pu_400a_rpl = str_init("Bad request");
00057 static str pu_400b_rpl = str_init("Invalid request");
00058 static str pu_500_rpl  = str_init("Server Internal Error");
00059 static str pu_489_rpl  = str_init("Bad Event");
00060 
00061 struct p_modif
00062 {
00063    presentity_t* p;
00064    str uri;
00065 };
00066 
00067 void msg_presentity_clean(unsigned int ticks,void *param)
00068 {
00069    db_key_t db_keys[2];
00070    db_val_t db_vals[2];
00071    db_op_t  db_ops[2] ;
00072    db_key_t result_cols[6];
00073    db_res_t *result = NULL;
00074    db_row_t *row ;   
00075    db_val_t *row_vals ;
00076    int i =0, size= 0;
00077    struct p_modif* p= NULL;
00078    presentity_t* pres= NULL;
00079    int n= 0;
00080    int event_col, etag_col, user_col, domain_col;
00081    event_t ev;
00082    str user, domain, etag, event;
00083    int n_result_cols= 0;
00084    str* rules_doc= NULL;
00085 
00086 
00087    if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00088    {
00089       LM_ERR("in use_table\n");
00090       return ;
00091    }
00092    
00093    LM_DBG("cleaning expired presentity information\n");
00094 
00095    db_keys[0] = &str_expires_col;
00096    db_ops[0] = OP_LT;
00097    db_vals[0].type = DB_INT;
00098    db_vals[0].nul = 0;
00099    db_vals[0].val.int_val = (int)time(NULL);
00100       
00101    result_cols[user_col= n_result_cols++] = &str_username_col;
00102    result_cols[domain_col=n_result_cols++] = &str_domain_col;
00103    result_cols[etag_col=n_result_cols++] = &str_etag_col;
00104    result_cols[event_col=n_result_cols++] = &str_event_col;
00105 
00106    static str query_str = str_init("username");
00107    if(pa_dbf.query(pa_db, db_keys, db_ops, db_vals, result_cols,
00108                   1, n_result_cols, &query_str, &result )< 0)
00109    {
00110       LM_ERR("querying database for expired messages\n");
00111       if(result)
00112          pa_dbf.free_result(pa_db, result);
00113       return;
00114    }
00115    if(result== NULL)
00116       return;
00117 
00118    if(result && result->n<= 0)
00119    {
00120       pa_dbf.free_result(pa_db, result);  
00121       return;
00122    }
00123    LM_DBG("found n= %d expires messages\n ",result->n);
00124 
00125    n= result->n;
00126    
00127    p= (struct p_modif*)pkg_malloc(n* sizeof(struct p_modif));
00128    if(p== NULL)
00129    {
00130       ERR_MEM(PKG_MEM_STR);   
00131    }
00132    memset(p, 0, n* sizeof(struct p_modif));
00133 
00134    for(i = 0; i< n; i++)
00135    {  
00136       row = &result->rows[i];
00137       row_vals = ROW_VALUES(row);   
00138    
00139       user.s= (char*)row_vals[user_col].val.string_val;
00140       user.len= strlen(user.s);
00141       
00142       domain.s= (char*)row_vals[domain_col].val.string_val;
00143       domain.len= strlen(domain.s);
00144 
00145       etag.s= (char*)row_vals[etag_col].val.string_val;
00146       etag.len= strlen(etag.s);
00147 
00148       event.s= (char*)row_vals[event_col].val.string_val;
00149       event.len= strlen(event.s);
00150       
00151       size= sizeof(presentity_t)+ (user.len+ domain.len+ etag.len)*
00152          sizeof(char); 
00153       pres= (presentity_t*)pkg_malloc(size);
00154       if(pres== NULL)
00155       {
00156          ERR_MEM(PKG_MEM_STR);
00157       }
00158       memset(pres, 0, size);
00159       size= sizeof(presentity_t);
00160       
00161       pres->user.s= (char*)pres+ size; 
00162       memcpy(pres->user.s, user.s, user.len);
00163       pres->user.len= user.len;
00164       size+= user.len;
00165 
00166       pres->domain.s= (char*)pres+ size;
00167       memcpy(pres->domain.s, domain.s, domain.len);
00168       pres->domain.len= domain.len;
00169       size+= domain.len;
00170 
00171       pres->etag.s= (char*)pres+ size;
00172       memcpy(pres->etag.s, etag.s, etag.len);
00173       pres->etag.len= etag.len;
00174       size+= etag.len;
00175          
00176       pres->event= contains_event(&event, &ev);
00177       if(pres->event== NULL)
00178       {
00179          LM_ERR("event not found\n");
00180          free_event_params(ev.params, PKG_MEM_TYPE);
00181          goto error;
00182       }  
00183    
00184       p[i].p= pres;
00185       if(uandd_to_uri(user, domain, &p[i].uri)< 0)
00186       {
00187          LM_ERR("constructing uri\n");
00188          free_event_params(ev.params, PKG_MEM_TYPE);
00189          goto error;
00190       }
00191       
00192       /* delete from hash table */
00193       if(delete_phtable(&p[i].uri, ev.parsed)< 0)
00194       {
00195          LM_ERR("deleting from pres hash table\n");
00196          free_event_params(ev.params, PKG_MEM_TYPE);
00197          goto error;
00198       }
00199       free_event_params(ev.params, PKG_MEM_TYPE);
00200 
00201    }
00202    pa_dbf.free_result(pa_db, result);
00203    result= NULL;
00204    
00205    for(i= 0; i<n ; i++)
00206    {
00207       LM_DBG("found expired publish for [user]=%.*s  [domanin]=%.*s\n",
00208          p[i].p->user.len,p[i].p->user.s, p[i].p->domain.len, p[i].p->domain.s);
00209       
00210       rules_doc= NULL;
00211       
00212       if(p[i].p->event->get_rules_doc && 
00213       p[i].p->event->get_rules_doc(&p[i].p->user, &p[i].p->domain, &rules_doc)< 0)
00214       {
00215          LM_ERR("getting rules doc\n");
00216          goto error;
00217       }
00218       if(publ_notify( p[i].p, p[i].uri, NULL, &p[i].p->etag, rules_doc)< 0)
00219       {
00220          LM_ERR("sending Notify request\n");
00221          goto error;
00222       }
00223       if(rules_doc)
00224       {
00225          if(rules_doc->s)
00226             pkg_free(rules_doc->s);
00227          pkg_free(rules_doc);
00228       }
00229       rules_doc= NULL;
00230    }
00231 
00232    if (pa_dbf.use_table(pa_db, &presentity_table) < 0) 
00233    {
00234       LM_ERR("in use_table\n");
00235       goto error;
00236    }
00237    
00238    if (pa_dbf.delete(pa_db, db_keys, db_ops, db_vals, 1) < 0) 
00239       LM_ERR("cleaning expired messages\n");
00240    
00241    for(i= 0; i< n; i++)
00242    {
00243       if(p[i].p)
00244          pkg_free(p[i].p);
00245       if(p[i].uri.s)
00246          pkg_free(p[i].uri.s);
00247 
00248    }
00249    pkg_free(p);
00250 
00251    return;
00252 
00253 error:
00254    if(result)
00255       pa_dbf.free_result(pa_db, result);
00256    if(p)
00257    {
00258       for(i= 0; i< n; i++)
00259       {
00260          
00261          if(p[i].p)
00262             pkg_free(p[i].p);
00263          if(p[i].uri.s)
00264             pkg_free(p[i].uri.s);
00265          else
00266             break;
00267       }
00268       pkg_free(p);
00269    }
00270    if(rules_doc)
00271    {
00272       if(rules_doc->s)
00273          pkg_free(rules_doc->s);
00274       pkg_free(rules_doc);
00275    }
00276 
00277    return;  
00278 }
00279 
00280 /**
00281  * PUBLISH request handling
00282  *
00283  */
00284 int handle_publish(struct sip_msg* msg, char* sender_uri, char* str2)
00285 {
00286    struct sip_uri puri;
00287    str body;
00288    int lexpire;
00289    presentity_t* presentity = 0;
00290    struct hdr_field* hdr;
00291    int found= 0, etag_gen = 0;
00292    str etag={0, 0};
00293    str* sender= NULL;
00294    static char buf[256];
00295    int buf_len= 255;
00296    pres_ev_t* event= NULL;
00297    str pres_user;
00298    str pres_domain;
00299    int reply_code;
00300    str reply_str;
00301    int sent_reply= 0;
00302    char* sphere= NULL;
00303 
00304    reply_code= 500;
00305    reply_str= pu_500_rpl;
00306 
00307    counter++;
00308    if ( parse_headers(msg,HDR_EOH_F, 0)==-1 )
00309    {
00310       LM_ERR("parsing headers\n");
00311       reply_code= 400;
00312       reply_str= pu_400a_rpl;
00313       goto error;
00314    }
00315    memset(&body, 0, sizeof(str));
00316    
00317    /* inspecting the Event header field */
00318    
00319    if(msg->event && msg->event->body.len > 0)
00320    {
00321       if (!msg->event->parsed && (parse_event(msg->event) < 0))
00322       {
00323          LM_ERR("cannot parse Event header\n");
00324          reply_code= 400;
00325          reply_str= pu_400a_rpl;
00326          goto error;
00327       }
00328       if(((event_t*)msg->event->parsed)->parsed == EVENT_OTHER)
00329       {  
00330          goto unsupported_event;
00331       }
00332    }
00333    else
00334       goto unsupported_event;
00335 
00336    /* search event in the list */
00337    event= search_event((event_t*)msg->event->parsed);
00338    if(event== NULL)
00339    {
00340       goto unsupported_event;
00341    }
00342    
00343    /* examine the SIP-If-Match header field */
00344    hdr = msg->headers;
00345    while (hdr!= NULL)
00346    {
00347       if(cmp_hdrname_strzn(&hdr->name, "SIP-If-Match", 12)==0)
00348       {
00349          found = 1;
00350          break;
00351       }
00352       hdr = hdr->next;
00353    }
00354    if(found==0 )
00355    {
00356       LM_DBG("SIP-If-Match header not found\n");
00357       etag.s = generate_ETag(0);
00358       if(etag.s == NULL)
00359       {
00360          LM_ERR("when generating etag\n");
00361          goto error;
00362       }
00363       etag.len=(strlen(etag.s));
00364       etag_gen=1;
00365       LM_DBG("new etag  = %.*s \n", etag.len,   etag.s);
00366    }
00367    else
00368    {
00369       LM_DBG("SIP-If-Match header found\n");
00370       etag.s = (char*)pkg_malloc((hdr->body.len+ 1)* sizeof(char));
00371       if(etag.s== NULL)
00372       {
00373          ERR_MEM(PKG_MEM_STR);
00374       }
00375       memcpy(etag.s, hdr->body.s, hdr->body.len );
00376       etag.len = hdr->body.len;   
00377       etag.s[ etag.len] = '\0';
00378       LM_DBG("existing etag  = %.*s \n", etag.len, etag.s);
00379    }
00380 
00381    /* examine the expire header field */
00382    if(msg->expires && msg->expires->body.len > 0)
00383    {
00384       if (!msg->expires->parsed && (parse_expires(msg->expires) < 0))
00385       {
00386          LM_ERR("cannot parse Expires header\n");
00387          goto error;
00388       }
00389       lexpire = ((exp_body_t*)msg->expires->parsed)->val;
00390       LM_DBG("Expires header found, value= %d\n", lexpire);
00391 
00392    }
00393    else 
00394    {
00395       LM_DBG("'expires' not found; default=%d\n",  event->default_expires);
00396       lexpire = event->default_expires;
00397    }
00398    if(lexpire > max_expires)
00399       lexpire = max_expires;
00400 
00401    /* get pres_uri from Request-URI*/
00402    if(parse_sip_msg_uri(msg)< 0)
00403    {
00404       LM_ERR("parsing Request URI\n");
00405       reply_code= 400; 
00406       reply_str= pu_400a_rpl;
00407       goto error;
00408    }
00409    pres_user= msg->parsed_uri.user;
00410    pres_domain= msg->parsed_uri.host;
00411 
00412    if (!msg->content_length) 
00413    {
00414       LM_ERR("no Content-Length header found!\n");
00415       reply_code= 400; 
00416       reply_str= pu_400a_rpl;
00417       goto error;
00418    }  
00419 
00420    /* process the body */
00421    if ( get_content_length(msg) == 0 )
00422    {
00423       body.s = NULL;
00424       if (etag_gen)
00425       {
00426          LM_ERR("No E-Tag and no body found\n");
00427          reply_code= 400;
00428          reply_str= pu_400b_rpl;
00429          goto error;
00430       }
00431    }
00432    else
00433    {
00434       body.s=get_body(msg);
00435       if (body.s== NULL) 
00436       {
00437          LM_ERR("cannot extract body\n");
00438          reply_code= 400; 
00439          reply_str= pu_400a_rpl;
00440          goto error;
00441       }
00442       body.len= get_content_length( msg );
00443 
00444       if(sphere_enable && event->evp->parsed == EVENT_PRESENCE &&
00445             get_content_type(msg)== SUBTYPE_PIDFXML)
00446       {
00447          sphere= extract_sphere(body);       
00448       }
00449 
00450    }  
00451    memset(&puri, 0, sizeof(struct sip_uri));
00452    if(sender_uri)
00453    {
00454       sender=(str*)pkg_malloc(sizeof(str));
00455       if(sender== NULL)
00456       {
00457          ERR_MEM(PKG_MEM_STR);
00458       }  
00459       if(pv_printf(msg, (pv_elem_t*)sender_uri, buf, &buf_len)<0)
00460       {
00461          LM_ERR("cannot print the format\n");
00462          goto error;
00463       }
00464       if(parse_uri(buf, buf_len, &puri)!=0)
00465       {
00466          LM_ERR("bad sender SIP address!\n");
00467          reply_code= 400; 
00468          reply_str= pu_400a_rpl;
00469          goto error;
00470       } 
00471       else 
00472       {
00473          LM_DBG("using user id [%.*s]\n",buf_len,buf);
00474       }
00475       sender->s= buf;
00476       sender->len= buf_len;
00477    }
00478    /* call event specific handling function*/
00479    if(event->evs_publ_handl)
00480    {
00481       if(event->evs_publ_handl(msg)< 0)
00482       {
00483          LM_ERR("in event specific publish handling\n");
00484          goto error;
00485       }
00486    }
00487 
00488    /* now we have all the necessary values */
00489    /* fill in the filds of the structure */
00490 
00491    presentity= new_presentity(&pres_domain, &pres_user, lexpire, event,
00492          &etag, sender);
00493    if(presentity== NULL)
00494    {
00495       LM_ERR("creating presentity structure\n");
00496       goto error;
00497    }
00498 
00499    /* querry the database and update or insert */
00500    if(update_presentity(msg, presentity, &body, etag_gen, &sent_reply, sphere) <0)
00501    {
00502       LM_ERR("when updating presentity\n");
00503       goto error;
00504    }
00505 
00506    if(presentity)
00507       pkg_free(presentity);
00508    if(etag.s)
00509       pkg_free(etag.s);
00510    if(sender)
00511       pkg_free(sender);
00512    if(sphere)
00513       pkg_free(sphere);
00514 
00515    return 1;
00516 
00517 unsupported_event:
00518    
00519    LM_ERR("Missing or unsupported event header field value\n");
00520       
00521    if(msg->event && msg->event->body.s && msg->event->body.len>0)
00522       LM_ERR("\tevent=[%.*s]\n", msg->event->body.len, msg->event->body.s);
00523 
00524    reply_code= BAD_EVENT_CODE;
00525    reply_str=  pu_489_rpl; 
00526 
00527 error:
00528    if(sent_reply== 0)
00529    {
00530       if(send_error_reply(msg, reply_code, reply_str)< 0)
00531       {
00532          LM_ERR("failed to send error reply\n");
00533       }
00534    }
00535    
00536    if(presentity)
00537       pkg_free(presentity);
00538    if(etag.s)
00539       pkg_free(etag.s);
00540    if(sender)
00541       pkg_free(sender);
00542    if(sphere)
00543       pkg_free(sphere);
00544 
00545    return -1;
00546 
00547 }
00548 
00549 

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