xmpp2simple.c

Go to the documentation of this file.
00001 /*
00002  * $Id: xmpp2simple.c 1666 2007-03-02 13:40:09Z anca_vamanu $
00003  *
00004  * pua_xmpp module - presence SIP - XMPP Gateway
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-03-29  initial version (anca)
00027  */
00028 
00029 /*! \file
00030  * \brief Kamailio presence gateway: SIP/SIMPLE -- XMPP (pua_xmpp)
00031  */
00032 
00033 #include <stdio.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include <libxml/parser.h>
00037 
00038 #include "../../parser/msg_parser.h"
00039 #include "../../parser/parse_from.h"
00040 #include "../../parser/parse_to.h"
00041 #include "../../parser/parse_content.h"
00042 #include "../../mem/mem.h"
00043 #include "../../ut.h"
00044 #include "../pua/pua.h"
00045 #include "pua_xmpp.h"
00046 
00047 int build_publish(xmlNodePtr pres_node, int expire);
00048 int presence_subscribe(xmlNodePtr pres_node, int expires, int flag);
00049 
00050 /*  the function registered as a callback in xmpp,
00051  *  to be called when a new message with presence type is received 
00052  *  */
00053 
00054 void pres_Xmpp2Sip(char *msg, int type, void *param)
00055 {
00056    xmlDocPtr doc= NULL;
00057    xmlNodePtr pres_node= NULL;
00058    char* pres_type= NULL;
00059 
00060    doc= xmlParseMemory(msg, strlen(msg));
00061    if(doc == NULL)
00062    {
00063       LM_ERR("while parsing xml memory\n");
00064       return;
00065    }
00066 
00067    pres_node= XMLDocGetNodeByName(doc, "presence", NULL);
00068    if(pres_node == NULL)
00069    {
00070       LM_ERR("while getting node\n");
00071       goto error;
00072    }
00073    pres_type= XMLNodeGetAttrContentByName(pres_node, "type" );
00074    
00075    if(pres_type== NULL )
00076    {
00077       LM_DBG("type attribut not present\n");
00078       build_publish(pres_node, -1);
00079       if(presence_subscribe(pres_node, 3600, XMPP_SUBSCRIBE)< 0)
00080       {
00081             LM_ERR("when sending subscribe for presence");
00082             xmlFree(pres_type);
00083             goto error;
00084       }
00085 
00086 
00087       /* send subscribe after publish because in xmpp subscribe message
00088        * comes only when a new contact is inserted in buddy list */
00089    }
00090    else
00091    if(strcmp(pres_type, "unavailable")== 0)
00092    {
00093       build_publish(pres_node, 0);
00094       if(presence_subscribe(pres_node, 3600, XMPP_SUBSCRIBE)< 0)
00095             /* else subscribe for one hour*/
00096       {
00097             LM_ERR("when unsubscribing for presence");
00098             xmlFree(pres_type);
00099             goto error;
00100       }
00101 
00102    }     
00103    else
00104    if((strcmp(pres_type, "subscribe")==0)|| 
00105       ( strcmp(pres_type, "unsubscribe")== 0)||
00106        (strcmp(pres_type, "probe")== 0))
00107    {
00108       if(strcmp(pres_type, "subscribe")==0 || 
00109             strcmp(pres_type, "probe")== 0)
00110       {  
00111           LM_DBG("send Subscribe message (no time limit)\n");
00112          if(presence_subscribe(pres_node, -1,
00113                   XMPP_INITIAL_SUBS)< 0)
00114          {
00115             LM_ERR("when sending subscribe for presence");
00116             xmlFree(pres_type);
00117             goto error;
00118          }
00119       }  
00120       if(strcmp(pres_type, "unsubscribe")== 0)
00121       {
00122          if(presence_subscribe(pres_node, 0, 
00123                   XMPP_INITIAL_SUBS)< 0)
00124          {
00125             LM_ERR("when unsubscribing for presence");
00126             xmlFree(pres_type);
00127             goto error;
00128          }
00129       }
00130    }
00131    xmlFree(pres_type);
00132 
00133    // else 
00134    //    send_reply_message(pres_node);
00135 
00136    xmlFreeDoc(doc);
00137    xmlCleanupParser();
00138    xmlMemoryDump();
00139    return ;
00140 
00141 error:
00142 
00143    if(doc)
00144       xmlFreeDoc(doc);
00145    xmlCleanupParser();
00146    xmlMemoryDump();
00147 
00148    return ;
00149 
00150 }  
00151 
00152 str* build_pidf(xmlNodePtr pres_node, char* uri, char* resource)
00153 {
00154    str* body= NULL;
00155    xmlDocPtr doc= NULL;
00156    xmlNodePtr root_node= NULL, status_node= NULL;
00157    xmlNodePtr node= NULL, person_node= NULL;
00158    xmlNodePtr tuple_node= NULL, basic_node= NULL;
00159    char* show_cont= NULL, *status_cont= NULL;
00160    char* entity= NULL;
00161    char* type= NULL;
00162    char* status= NULL;
00163 
00164    LM_DBG("start\n");
00165 
00166    entity=(char*)pkg_malloc(7+ strlen(uri)*sizeof(char));
00167    if(entity== NULL)
00168    {  
00169       LM_ERR("no more memory\n");
00170       goto error;
00171    }
00172    strcpy(entity, "pres:");
00173    memcpy(entity+5, uri+4, strlen(uri)-4);
00174    entity[1+ strlen(uri)]= '\0';
00175    LM_DBG("entity: %s\n", entity);
00176 
00177    doc= xmlNewDoc(BAD_CAST "1.0");
00178    if(doc== NULL)
00179    {
00180       LM_ERR("allocating new xml doc\n");
00181       goto error;
00182    }
00183 
00184    root_node = xmlNewNode(NULL, BAD_CAST "presence");
00185    if(root_node== 0)
00186    {
00187       LM_ERR("extracting presence node\n");
00188       goto error;
00189    }
00190    xmlDocSetRootElement(doc, root_node);
00191 
00192    xmlNewProp(root_node, BAD_CAST "xmlns",
00193          BAD_CAST "urn:ietf:params:xml:ns:pidf");
00194    xmlNewProp(root_node, BAD_CAST "xmlns:dm",
00195          BAD_CAST "urn:ietf:params:xml:ns:pidf:data-model");
00196    xmlNewProp(root_node, BAD_CAST  "xmlns:rpid",
00197          BAD_CAST "urn:ietf:params:xml:ns:pidf:rpid" );
00198    xmlNewProp(root_node, BAD_CAST "xmlns:c",
00199          BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid");
00200    xmlNewProp(root_node, BAD_CAST "entity", BAD_CAST entity);
00201    
00202    tuple_node =xmlNewChild(root_node, NULL, BAD_CAST "tuple", NULL) ;
00203    if( tuple_node ==NULL)
00204    {
00205       LM_ERR("while adding child\n");
00206       goto error;
00207    }
00208 
00209    status_node = xmlNewChild(tuple_node, NULL, BAD_CAST "status", NULL) ;
00210    if( status_node ==NULL)
00211    {
00212       LM_ERR("while adding child\n");
00213       goto error;
00214    }
00215 
00216    type=  XMLNodeGetAttrContentByName(pres_node, "type");
00217    if(type== NULL)
00218    {
00219       basic_node = xmlNewChild(status_node, NULL, BAD_CAST "basic",
00220          BAD_CAST "open") ;
00221       if( basic_node ==NULL)
00222       {
00223          LM_ERR("while adding child\n");
00224          goto error;
00225       }
00226 
00227    }
00228    else
00229    {  
00230       basic_node = xmlNewChild(status_node, NULL, BAD_CAST "basic",
00231             BAD_CAST "closed") ;
00232       if( basic_node ==NULL)
00233       {
00234          LM_ERR("while adding child\n");
00235          goto error;
00236       }
00237       goto done;     
00238    }
00239    /*if no type present search for suplimentary information */
00240    status_cont= XMLNodeGetNodeContentByName(pres_node, "status", NULL);
00241    show_cont= XMLNodeGetNodeContentByName(pres_node, "show", NULL);
00242    
00243    if(show_cont)
00244    {
00245       if(strcmp(show_cont, "xa")== 0)
00246          status= "not available";
00247       else
00248          if(strcmp(show_cont, "chat")== 0)
00249             status= "free for chat";
00250       else
00251          if(strcmp(show_cont, "dnd")== 0)
00252             status= "do not disturb";
00253       else
00254          status= show_cont;
00255    }
00256 
00257    if(status_cont)
00258    {
00259       /*
00260       person_node= xmlNewChild(root_node, NULL, BAD_CAST "person", 0);
00261       if(person_node== NULL)
00262       {
00263          LM_ERR("while adding node\n");
00264          goto error;
00265       }
00266       */
00267       node = xmlNewChild(root_node, NULL, BAD_CAST "note",
00268             BAD_CAST status_cont);
00269       if(node== NULL)
00270       {
00271          LM_ERR("while adding node\n");
00272          goto error;
00273       }
00274    }else
00275       if(show_cont)
00276       {
00277          node = xmlNewChild(root_node, NULL, BAD_CAST "note", 
00278                BAD_CAST status);
00279          if(node== NULL)
00280          {
00281             LM_ERR("while adding node\n");
00282             goto error;
00283          }  
00284       }  
00285 
00286    if(show_cont)
00287    {
00288       LM_DBG("show_cont= %s\n", show_cont);
00289       if(person_node== NULL)
00290       {  
00291          person_node= xmlNewChild(root_node, NULL, BAD_CAST "person",0 );
00292          if(person_node== NULL)
00293          {
00294             LM_ERR("while adding node\n");
00295             goto error;
00296          }
00297       }
00298       node=  xmlNewChild(person_node, NULL, BAD_CAST "activities", 
00299             BAD_CAST 0);
00300       if(node== NULL)
00301       {
00302          LM_ERR("while adding node\n");
00303          goto error;
00304       }
00305 
00306                   
00307       if( xmlNewChild(person_node, NULL, BAD_CAST "note", 
00308                BAD_CAST status )== NULL)
00309       {
00310          LM_ERR("while adding node\n");
00311          goto error;
00312       }
00313 
00314 
00315    }
00316       
00317    
00318 done: 
00319    body= (str* )pkg_malloc(sizeof(str));
00320    if(body== NULL)
00321    {
00322       LM_ERR("no more memory\n");
00323       goto error;
00324    }
00325    xmlDocDumpFormatMemory(doc,(xmlChar**)(void*)&body->s, &body->len, 1);
00326 
00327    if(entity)
00328       pkg_free(entity);
00329    if(status_cont)
00330       xmlFree(status_cont);
00331    if(show_cont)
00332       xmlFree(show_cont);
00333    if(type)
00334       xmlFree(type);
00335    xmlFreeDoc(doc);
00336    
00337    return body;
00338 
00339 error:
00340    if(entity)
00341       pkg_free(entity);
00342    if(body)
00343    {
00344       if(body->s)
00345          xmlFree(body->s);
00346       pkg_free(body);
00347    }
00348    if(status_cont)
00349       xmlFree(status_cont);
00350    if(show_cont)
00351       xmlFree(show_cont);
00352    if(type)
00353       xmlFree(type);
00354    if(doc)
00355       xmlFreeDoc(doc);
00356 
00357    return NULL;
00358 }  
00359 
00360 
00361 int build_publish(xmlNodePtr pres_node, int expires)
00362 {
00363    str* body= NULL;
00364    publ_info_t publ;
00365    char* uri= NULL, *resource= NULL;
00366    char* pres_uri= NULL;
00367    char* slash;
00368    int uri_len;
00369    str uri_str;
00370 
00371    LM_DBG("start... \n");
00372    
00373    uri= XMLNodeGetAttrContentByName(pres_node, "from");
00374    if(uri== NULL)
00375    {
00376       LM_DBG("getting 'from' attribute\n");
00377       return -1;
00378    }
00379    uri_len= strlen(uri);
00380 
00381    slash= memchr(uri, '/', strlen(uri));
00382    if(slash)
00383    {
00384       uri_len= slash- uri;
00385       resource= (char*)pkg_malloc((strlen(uri)-uri_len)*sizeof(char));
00386       if(resource== NULL)
00387       {
00388          LM_ERR("no more memory\n");
00389          return -1;
00390       }
00391       strcpy(resource, slash+1);
00392       slash= '\0';
00393    }  
00394    pres_uri= euri_xmpp_sip(uri);
00395    if(pres_uri== NULL)
00396    {
00397       LM_ERR("while encoding xmpp-sip uri\n");
00398       goto error; 
00399    }  
00400    xmlFree(uri);
00401    uri_str.s= pres_uri;
00402    uri_str.len= strlen(pres_uri);
00403 
00404    body= build_pidf(pres_node, pres_uri, resource);
00405    if(body== NULL)
00406    {
00407       LM_ERR("while constructing PUBLISH body\n");
00408       goto error;
00409    }
00410 
00411    /* construct the publ_info_t structure */
00412 
00413    memset(&publ, 0, sizeof(publ_info_t));
00414    
00415    publ.pres_uri= &uri_str;
00416 
00417    LM_DBG("publ->pres_uri: %.*s  -  %d\n", publ.pres_uri->len, 
00418          publ.pres_uri->s, publ.pres_uri->len );
00419 
00420    publ.body= body;
00421    
00422    LM_DBG("publ->notify body: %.*s - %d\n", publ.body->len,
00423          publ.body->s,  publ.body->len);
00424 
00425    publ.source_flag|= XMPP_PUBLISH;
00426    publ.expires= expires;
00427    publ.event= PRESENCE_EVENT;
00428    publ.extra_headers= NULL;
00429 
00430    if( pua_send_publish(&publ)< 0)
00431    {
00432       LM_ERR("while sending publish\n");
00433       goto error;
00434    }
00435 
00436    if(resource)
00437       pkg_free(resource);
00438    if(body)
00439    {
00440       if(body->s)
00441          xmlFree(body->s);
00442       pkg_free(body);
00443    }
00444 
00445    return 0;
00446 
00447 error:
00448 
00449    if(resource)
00450       pkg_free(resource);
00451 
00452    if(body)
00453    {
00454       if(body->s)
00455          xmlFree(body->s);
00456       pkg_free(body);
00457    }
00458 
00459    return -1;
00460 
00461 }
00462 
00463 int presence_subscribe(xmlNodePtr pres_node, int expires,int  flag)
00464 {
00465    subs_info_t subs;
00466    char* to_uri= NULL, *from_uri= NULL;
00467    char* uri= NULL;
00468    char* type= NULL;
00469    str to_uri_str;
00470    str from_uri_str;
00471 
00472    uri= XMLNodeGetAttrContentByName(pres_node, "to"); 
00473    if(uri== NULL)
00474    {
00475       LM_ERR("while getting attribute from xml doc\n");
00476       return -1;
00477    }
00478    to_uri= duri_xmpp_sip(uri);
00479    if(to_uri== NULL)
00480    {
00481       LM_ERR("while decoding xmpp--sip uri\n");
00482       goto error;
00483    }
00484    xmlFree(uri);
00485    to_uri_str.s= to_uri;
00486    to_uri_str.len= strlen(to_uri);
00487 
00488    uri= XMLNodeGetAttrContentByName(pres_node, "from"); 
00489    if(uri== NULL)
00490    {
00491       LM_ERR("while getting attribute from xml doc\n");
00492       goto error;
00493    }
00494    from_uri= euri_xmpp_sip(uri);
00495    if(from_uri== NULL)
00496    {
00497       LM_ERR("while encoding xmpp-sip uri\n");
00498       goto error; 
00499    }  
00500    xmlFree(uri);
00501    from_uri_str.s= from_uri;
00502    from_uri_str.len= strlen(from_uri);
00503    
00504    memset(&subs, 0, sizeof(subs_info_t));
00505 
00506    subs.pres_uri= &to_uri_str;
00507    subs.watcher_uri= &from_uri_str;
00508    subs.contact= subs.watcher_uri;
00509    /*
00510    type= XMLNodeGetAttrContentByName(pres_node, "type" );
00511    if(strcmp(type, "subscribe")==0 ||strcmp(type, "probe")== 0)
00512       subs->flag|= INSERT_TYPE;
00513    else  
00514       if(strcmp(type, "unsubscribe")== 0)
00515          subs->flag|= UPDATE_TYPE;
00516    xmlFree(type);
00517    type= NULL;
00518    */
00519 
00520    subs.source_flag|= flag;
00521    subs.event= PRESENCE_EVENT;
00522    subs.expires= expires;
00523    
00524    LM_DBG("subs:\n");
00525    LM_DBG("\tpres_uri= %.*s\n", subs.pres_uri->len,  subs.pres_uri->s);
00526    LM_DBG("\twatcher_uri= %.*s\n", subs.watcher_uri->len,  subs.watcher_uri->s);
00527    LM_DBG("\texpires= %d\n", subs.expires);
00528 
00529    if(pua_send_subscribe(&subs)< 0)
00530    {
00531       LM_ERR("while sending SUBSCRIBE\n");
00532       goto error;
00533    }
00534    return 0;
00535 
00536 error:
00537    if(type)
00538       xmlFree(type);
00539 
00540    return -1;
00541 }
00542 

Generated on Fri May 25 00:00:35 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6