ul_publish.c

Go to the documentation of this file.
00001 /*
00002  * $Id: ul_publish.c 5771 2009-03-27 00:40:12Z ibc_sf $
00003  *
00004  * pua_usrloc module - usrloc pua 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 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <libxml/parser.h>
00029 #include <time.h>
00030 
00031 #include "../../parser/parse_expires.h"
00032 #include "../../parser/msg_parser.h"
00033 #include "../../str.h"
00034 #include "../usrloc/usrloc.h"
00035 #include "../usrloc/ul_callback.h"
00036 #include "../tm/tm_load.h"
00037 #include "../pua/pua.h"
00038 #include "pua_usrloc.h"
00039 
00040 #define BUF_LEN   256
00041 int pua_set_publish(struct sip_msg* msg , char* s1, char* s2)
00042 {
00043    LM_DBG("set send publish\n");
00044    pua_ul_publish= 1;
00045    return 1;
00046 }
00047 
00048 int pua_unset_publish(struct sip_msg* msg , void* param)
00049 {
00050    pua_ul_publish= 0;
00051    return 1;
00052 }
00053 
00054    
00055 /* for debug purpose only */
00056 void print_publ(publ_info_t* p)
00057 {
00058    LM_DBG("publ:\n");
00059    LM_DBG("uri= %.*s\n", p->pres_uri->len, p->pres_uri->s);
00060    LM_DBG("id= %.*s\n", p->id.len, p->id.s);
00061    LM_DBG("expires= %d\n", p->expires);
00062 }  
00063 
00064 str* build_pidf(ucontact_t* c)
00065 {
00066    xmlDocPtr  doc = NULL; 
00067    xmlNodePtr root_node = NULL;
00068    xmlNodePtr tuple_node = NULL;
00069    xmlNodePtr status_node = NULL;
00070    xmlNodePtr basic_node = NULL;
00071    str *body= NULL;
00072    str pres_uri= {NULL, 0};
00073    char buf[BUF_LEN];
00074    char* at= NULL;
00075 
00076    if(c->expires< (int)time(NULL))
00077    {
00078       LM_DBG("found expired \n\n");
00079       return NULL;
00080    }
00081 
00082    pres_uri.s = buf;
00083    if(pres_prefix.s)
00084    {
00085       memcpy(pres_uri.s, pres_prefix.s, pres_prefix.len);
00086       pres_uri.len+= pres_prefix.len;
00087       memcpy(pres_uri.s+ pres_uri.len, ":", 1);
00088       pres_uri.len+= 1;
00089    }
00090    if(pres_uri.len + c->aor->len+ 1 > BUF_LEN)
00091    {
00092       LM_ERR("buffer size overflown\n");
00093       return NULL;
00094    }
00095 
00096    memcpy(pres_uri.s+ pres_uri.len, c->aor->s, c->aor->len);
00097    pres_uri.len+= c->aor->len;
00098 
00099    at = memchr(c->aor->s, '@', c->aor->len);
00100    if(!at)
00101    {
00102       if(pres_uri.len + 2 + default_domain.len > BUF_LEN)
00103       {
00104          LM_ERR("buffer size overflown\n");
00105          return NULL;
00106       }
00107 
00108       pres_uri.s[pres_uri.len++]= '@';
00109       memcpy(pres_uri.s+ pres_uri.len, default_domain.s, default_domain.len);
00110       pres_uri.len+= default_domain.len;     
00111    }
00112    pres_uri.s[pres_uri.len]= '\0';
00113 
00114    /* create the Publish body  */
00115    doc = xmlNewDoc(BAD_CAST "1.0");
00116    if(doc==0)
00117       return NULL;
00118 
00119     root_node = xmlNewNode(NULL, BAD_CAST "presence");
00120    if(root_node==0)
00121       goto error;
00122     
00123    xmlDocSetRootElement(doc, root_node);
00124 
00125     xmlNewProp(root_node, BAD_CAST "xmlns",
00126          BAD_CAST "urn:ietf:params:xml:ns:pidf");
00127    xmlNewProp(root_node, BAD_CAST "xmlns:dm",
00128          BAD_CAST "urn:ietf:params:xml:ns:pidf:data-model");
00129    xmlNewProp(root_node, BAD_CAST  "xmlns:rpid",
00130          BAD_CAST "urn:ietf:params:xml:ns:pidf:rpid" );
00131    xmlNewProp(root_node, BAD_CAST "xmlns:c",
00132          BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid");
00133    xmlNewProp(root_node, BAD_CAST "entity", BAD_CAST pres_uri.s);
00134 
00135    tuple_node =xmlNewChild(root_node, NULL, BAD_CAST "tuple", NULL) ;
00136    if( tuple_node ==NULL)
00137    {
00138       LM_ERR("while adding child\n");
00139       goto error;
00140    }
00141    
00142    status_node = xmlNewChild(tuple_node, NULL, BAD_CAST "status", NULL) ;
00143    if( status_node ==NULL)
00144    {
00145       LM_ERR("while adding child\n");
00146       goto error;
00147    }
00148    
00149    basic_node = xmlNewChild(status_node, NULL, BAD_CAST "basic",
00150       BAD_CAST "open") ;
00151    
00152    if( basic_node ==NULL)
00153    {
00154       LM_ERR("while adding child\n");
00155       goto error;
00156    }
00157    
00158    body = (str*)pkg_malloc(sizeof(str));
00159    if(body == NULL)
00160    {
00161       LM_ERR("while allocating memory\n");
00162       return NULL;
00163    }
00164    memset(body, 0, sizeof(str));
00165 
00166    xmlDocDumpFormatMemory(doc,(unsigned char**)(void*)&body->s,&body->len,1);
00167 
00168    LM_DBG("new_body:\n%.*s\n",body->len, body->s);
00169 
00170     /*free the document */
00171    xmlFreeDoc(doc);
00172     xmlCleanupParser();
00173 
00174    return body;
00175 
00176 error:
00177    if(body)
00178    {
00179       if(body->s)
00180          xmlFree(body->s);
00181       pkg_free(body);
00182    }
00183    if(doc)
00184       xmlFreeDoc(doc);
00185    return NULL;
00186 }  
00187 
00188 void ul_publish(ucontact_t* c, int type, void* param)
00189 {
00190    str* body= NULL;
00191    str uri= {NULL, 0};
00192    char* at= NULL;
00193    publ_info_t* publ= NULL;
00194    int size= 0;
00195    str content_type;
00196    int error;
00197 
00198    content_type.s= "application/pidf+xml";
00199    content_type.len= 20;
00200 
00201    if(pua_ul_publish== 0)
00202    {
00203       LM_INFO("should not send ul publish\n");
00204       return;
00205    }  
00206 
00207    if(type & UL_CONTACT_DELETE)
00208       LM_DBG("\nDELETE type\n");
00209    else
00210       if(type & UL_CONTACT_INSERT)
00211          LM_DBG("\nINSERT type\n");
00212       else
00213          if(type & UL_CONTACT_UPDATE)
00214             LM_DBG("\nUPDATE type\n");
00215          else
00216             if(type & UL_CONTACT_EXPIRE)
00217                LM_DBG("\nEXPIRE type\n");
00218 
00219    if(type & UL_CONTACT_INSERT)
00220    {
00221       body= build_pidf(c);
00222       if(body == NULL || body->s == NULL)
00223          goto error;
00224    }
00225    else
00226       body = NULL;
00227    
00228    uri.s = (char*)pkg_malloc(sizeof(char)*(c->aor->len+default_domain.len+6));
00229    if(uri.s == NULL)
00230       goto error;
00231 
00232    memcpy(uri.s, "sip:", 4);
00233    uri.len = 4;
00234    memcpy(uri.s+ uri.len, c->aor->s, c->aor->len);
00235    uri.len+= c->aor->len;
00236    at = memchr(c->aor->s, '@', c->aor->len);
00237    if(!at)
00238    {
00239       uri.s[uri.len++]= '@';
00240       memcpy(uri.s+ uri.len, default_domain.s, default_domain.len);
00241       uri.len+= default_domain.len;    
00242    }
00243    LM_DBG("uri= %.*s\n", uri.len, uri.s);
00244    
00245    size= sizeof(publ_info_t)+ sizeof(str)+( uri.len 
00246          +c->callid.len+ 12 + content_type.len)*sizeof(char); 
00247    
00248    if(body)
00249       size+= sizeof(str)+ body->len* sizeof(char);
00250 
00251    publ= (publ_info_t*)pkg_malloc(size);
00252    if(publ== NULL)
00253    {
00254       LM_ERR("no more share memory\n");
00255       goto error;
00256    }
00257    memset(publ, 0, size);
00258    size= sizeof(publ_info_t);
00259 
00260    publ->pres_uri= (str*)((char*)publ + size);
00261    size+= sizeof(str);
00262    publ->pres_uri->s= (char*)publ+ size;
00263    memcpy(publ->pres_uri->s, uri.s, uri.len);
00264    publ->pres_uri->len= uri.len;
00265    size+= uri.len;
00266 
00267    if(body)
00268    {
00269       publ->body= (str*)( (char*)publ + size);
00270       size+= sizeof(str);
00271 
00272       publ->body->s= (char*)publ + size;
00273       memcpy(publ->body->s, body->s, body->len);
00274       publ->body->len= body->len;
00275       size+= body->len;
00276    }
00277    publ->id.s= (char*)publ+ size;
00278    memcpy(publ->id.s, "UL_PUBLISH.", 11);
00279    memcpy(publ->id.s+11, c->callid.s, c->callid.len);
00280    publ->id.len= 11+ c->callid.len;
00281    size+= publ->id.len;
00282 
00283    publ->content_type.s= (char*)publ+ size;
00284    memcpy(publ->content_type.s, content_type.s, content_type.len);
00285    publ->content_type.len= content_type.len;
00286    size+= content_type.len;
00287 
00288    if(type & UL_CONTACT_EXPIRE || type & UL_CONTACT_DELETE)
00289       publ->expires= 0;
00290    else
00291       publ->expires= c->expires - (int)time(NULL);
00292    
00293    if(type & UL_CONTACT_INSERT)
00294       publ->flag|= INSERT_TYPE;
00295    else
00296       publ->flag|= UPDATE_TYPE;
00297 
00298    publ->source_flag|= UL_PUBLISH;
00299    publ->event|= PRESENCE_EVENT;
00300    publ->extra_headers= NULL;
00301    print_publ(publ);
00302    if((error=pua_send_publish(publ))< 0)
00303    {
00304       LM_ERR("while sending publish\n");
00305       if(type & UL_CONTACT_UPDATE && error == ERR_PUBLISH_NO_BODY) {
00306          /* This error can occur if Kamailio was restarted/stopped and for any reason couldn't store a pua
00307           * entry in 'pua' DB table. It can also occur if 'pua' table is cleaned externally while Kamailio
00308           * is stopped so cannot retrieve these entries from DB when restarting.
00309           * In these cases, when a refresh registration for that user creates an UPDATE action in pua_usrloc,
00310           * pua 'ul_publish()' would fail since the appropiate entry doesn't exist in pua hast table ("New 
00311           * PUBLISH and no body found - invalid request").
00312           * This code solves this problem by invoking an INSERT action if an UPDATE action failed due to the 
00313           * above error. It will however generate a new presentity entry in the presence server (until the
00314           * previous one expires), but this is a minor issue. */
00315          LM_ERR("UPDATE action generated a PUBLISH without body -> invoking INSERT action\n");
00316          ul_publish(c, UL_CONTACT_INSERT, param);
00317          return;
00318       }
00319    }
00320 
00321    pua_ul_publish= 0;
00322 
00323 error:
00324 
00325    if(publ)
00326       pkg_free(publ);
00327 
00328    if(body)
00329    {
00330       if(body->s)
00331          xmlFree(body->s);
00332       pkg_free(body);
00333    }
00334    
00335    if(uri.s)
00336       pkg_free(uri.s);
00337    pua_ul_publish= 0;
00338 
00339    return;
00340 
00341 }
00342 
00343 

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