purple_sip.c

Go to the documentation of this file.
00001 /* OpenSER PURPLE MODULE
00002  * 
00003  * Copyright (C) 2008 Atos Worldline
00004  * Contact: Eric PTAK <eric.ptak@atosorigin.com>
00005  *
00006  * This program is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  *
00019  */
00020 #include <stdlib.h>
00021 #include <string.h>
00022 #include <libxml/parser.h>
00023 
00024 #include "../../dprint.h"
00025 #include "../../str.h"
00026 #include "../tm/tm_load.h"
00027 #include "../pua/pua_bind.h"
00028 #include "../pua/pidf.h"
00029 
00030 #include "purple.h"
00031 #include "purple_sip.h"
00032 
00033 extern struct tm_binds tmb;
00034 extern send_publish_t pua_send_publish;
00035 
00036 /* Relay a MESSAGE to a SIP client */
00037 int purple_send_sip_msg(char *to, char *from, char *msg) {
00038    LM_DBG("sending message from %s to %s\n", from, to);
00039    str msg_type = { "MESSAGE", 7 };
00040    str ruri, hdr, fromstr, tostr, msgstr;
00041    char hdr_buf[512], ruri_buf[512];
00042    
00043    ruri.s = ruri_buf;
00044    ruri.len = snprintf(ruri_buf, sizeof(ruri_buf), "%s;proto=purple", to);
00045    
00046    hdr.s = hdr_buf;
00047    hdr.len = snprintf(hdr_buf, sizeof(hdr_buf), "Content-type: text/plain" CRLF "Contact: %s" CRLF, from);
00048 
00049    fromstr.s = from;
00050    fromstr.len = strlen(from);
00051    tostr.s = to;
00052    tostr.len = strlen(to);
00053    msgstr.s = msg;
00054    msgstr.len = strlen(msg);
00055 
00056    if (tmb.t_request(&msg_type, &ruri, &tostr, &fromstr, &hdr, &msgstr, 0, 0, 0) < 0) {
00057       LM_ERR("error sending request\n");
00058       return -1;
00059    }
00060    LM_DBG("message sent successfully\n");
00061    return 0;
00062 }
00063 
00064 static str* build_pidf(char *uri, char *id, enum purple_publish_basic basic, enum purple_publish_activity activity, const char *note) {
00065    LM_DBG("build pidf : %s, %d, %d, %s\n", uri, basic, activity, note);
00066    str* body = NULL;
00067    xmlDocPtr doc = NULL;
00068    xmlNodePtr root_node = NULL, status_node = NULL;
00069    xmlNodePtr tuple_node = NULL, basic_node = NULL;
00070    xmlNodePtr person_node = NULL, activities_node = NULL;
00071    xmlNsPtr pidf_ns, dm_ns, rpid_ns, cipid_ns;
00072    char* entity = NULL;
00073 
00074    entity = (char*)pkg_malloc(7+ strlen(uri)*sizeof(char));
00075    if(entity == NULL) { 
00076       LM_ERR("no more memory\n");
00077       goto error;
00078    }
00079    strcpy(entity, "pres:");
00080    memcpy(entity+5, uri+4, strlen(uri)-4);
00081    entity[1+ strlen(uri)] = '\0';
00082    LM_DBG("building pidf for entity: %s\n", entity);
00083 
00084    doc = xmlNewDoc(BAD_CAST "1.0");
00085    if(doc == NULL) {
00086       LM_ERR("allocating new xml doc\n");
00087       goto error;
00088    }
00089 
00090    root_node = xmlNewNode(NULL, BAD_CAST "presence");
00091    if(root_node == 0) {
00092       LM_ERR("extracting presence node\n");
00093       goto error;
00094    }
00095    xmlDocSetRootElement(doc, root_node);
00096    xmlNewProp(root_node, BAD_CAST "entity", BAD_CAST entity);
00097 
00098    pidf_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf", NULL);
00099    dm_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:data-model", BAD_CAST "dm");
00100    rpid_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:rpid", BAD_CAST "rpid");
00101    cipid_ns = xmlNewNs(root_node, BAD_CAST "urn:ietf:params:xml:ns:pidf:cipid", BAD_CAST "c");
00102    
00103    tuple_node = xmlNewChild(root_node, NULL, BAD_CAST "tuple", NULL);
00104    if( tuple_node == NULL) {
00105       LM_ERR("while adding child\n");
00106       goto error;
00107    }
00108    xmlNewProp(tuple_node, BAD_CAST "id", BAD_CAST id);
00109    
00110    status_node = xmlNewChild(tuple_node, pidf_ns, BAD_CAST "status", NULL);
00111    if( status_node ==NULL) {
00112       LM_ERR("while adding child\n");
00113       goto error;
00114    }
00115 
00116    switch (basic) {
00117       case PURPLE_BASIC_OPEN:
00118          basic_node = xmlNewChild(status_node, pidf_ns, BAD_CAST "basic", BAD_CAST "open");
00119          if(basic_node == NULL) {
00120             LM_ERR("while adding child\n");
00121             goto error;
00122          }
00123          break;
00124 
00125       case PURPLE_BASIC_CLOSED:  
00126          basic_node = xmlNewChild(status_node, pidf_ns, BAD_CAST "basic", BAD_CAST "closed") ;
00127          if(basic_node == NULL) {
00128             LM_ERR("while adding child\n");
00129             goto error;
00130          }
00131          break;
00132       default:
00133          break;
00134    }
00135       
00136    person_node = xmlNewChild(root_node, dm_ns, BAD_CAST "person", NULL);
00137    if (person_node == NULL) {
00138       LM_ERR("while adding child\n");
00139       goto error;
00140    }
00141    xmlNewProp(person_node, BAD_CAST "id", BAD_CAST id);
00142 
00143    activities_node = xmlNewChild(person_node, rpid_ns, BAD_CAST "activities", NULL);
00144    if (activities_node == NULL) {
00145       LM_ERR("while adding child\n");
00146       goto error;
00147    }
00148    
00149    switch (activity) {
00150       case PURPLE_ACTIVITY_AVAILABLE:
00151          xmlNewChild(activities_node, rpid_ns, BAD_CAST "unknown", NULL);
00152          xmlNewChild(person_node, dm_ns, BAD_CAST "note", (note != NULL) ? BAD_CAST note : NULL);
00153          break;
00154       case PURPLE_ACTIVITY_BUSY:
00155          xmlNewChild(activities_node, rpid_ns, BAD_CAST "busy", NULL);
00156          xmlNewChild(activities_node, rpid_ns, BAD_CAST "unknown", NULL);
00157          if (note == NULL)
00158             xmlNewChild(person_node, dm_ns, BAD_CAST "note", BAD_CAST "Busy");
00159          break;
00160       case PURPLE_ACTIVITY_AWAY:
00161          xmlNewChild(activities_node, rpid_ns, BAD_CAST "away", NULL);
00162          xmlNewChild(activities_node, rpid_ns, BAD_CAST "unknown", NULL);
00163          if (note == NULL)
00164             xmlNewChild(person_node, dm_ns, BAD_CAST "note", BAD_CAST "Away");
00165          break;
00166       default:
00167          break;
00168    }  
00169 
00170    if (note != NULL)
00171       xmlNewChild(person_node, dm_ns, BAD_CAST "note", BAD_CAST note);
00172       
00173       
00174    body = (str*)pkg_malloc(sizeof(str));
00175    if(body == NULL) {
00176       LM_ERR("no more memory\n");
00177       goto error;
00178    }
00179    xmlDocDumpFormatMemory(doc, (xmlChar**)(void*)&body->s, &body->len, 1);
00180       
00181    if(entity)
00182       pkg_free(entity);
00183    xmlFreeDoc(doc);
00184    
00185    return body;
00186 
00187 error:
00188    if(entity)
00189       pkg_free(entity);
00190    if(body) {
00191       if(body->s) {
00192          xmlFree(body->s);
00193       }
00194       pkg_free(body);
00195    }
00196    if(doc) {
00197       xmlFreeDoc(doc);
00198    }
00199 
00200    return NULL;
00201 }  
00202 
00203 
00204 /* Relay a PUBLISH */
00205 int purple_send_sip_publish(char *from, char *tupleid, enum purple_publish_basic basic, enum purple_publish_activity primitive, const char *note) {
00206 
00207    LM_DBG("publishing presence for <%s> with tuple [%s]\n", from, tupleid);
00208    
00209    char pres_buff[512];
00210    publ_info_t publ;
00211 
00212    memset(&publ, 0, sizeof(publ_info_t));
00213    
00214    str pres_uri;
00215    pres_uri.s = pres_buff;
00216    pres_uri.len = sprintf(pres_buff, "%s;proto=purple", from);
00217 
00218    publ.pres_uri = &pres_uri;
00219    publ.source_flag = PURPLE_PUBLISH;
00220    publ.event = PRESENCE_EVENT;
00221 
00222    str *body = NULL;
00223    if (basic == PURPLE_BASIC_OPEN) {
00224       body = build_pidf(from, tupleid, basic, primitive, note);
00225       publ.expires = 3600; 
00226    }
00227    else {
00228       publ.body = NULL;
00229       publ.expires = 0;
00230    }
00231 
00232    publ.body = body; 
00233 
00234    if(pua_send_publish(&publ) < 0) {
00235       LM_ERR("error while sending publish\n");
00236       return -1;
00237    }
00238    LM_DBG("publish sent successfully for <%s>\n", from);
00239    return 0;
00240 }
00241 
00242 

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