presence_xml.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006 Voice Sistem S.R.L.
00003  *
00004  * This file is part of Kamailio, a free SIP server.
00005  *
00006  * Kamailio 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  * Kamailio 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, write to the Free Software 
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  * History:
00021  * --------
00022  *  2007-04-12  initial version (anca)
00023  */
00024 
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <libxml/parser.h>
00040 #include <time.h>
00041 
00042 #include "../../sr_module.h"
00043 #include "../../dprint.h"
00044 #include "../../str.h"
00045 #include "../../ut.h"
00046 #include "../../parser/msg_parser.h"
00047 #include "../../parser/parse_uri.h"
00048 #include "../../mem/mem.h"
00049 #include "../presence/bind_presence.h"
00050 #include "../presence/hash.h"
00051 #include "../presence/notify.h"
00052 #include "../xcap_client/xcap_functions.h"
00053 #include "../../modules/sl/sl.h"
00054 #include "../../lib/kmi/mi.h"
00055 #include "../../mod_fix.h"
00056 #include "pidf.h"
00057 #include "add_events.h"
00058 #include "presence_xml.h"
00059 #include "pres_check.h"
00060 #include "api.h"
00061 
00062 MODULE_VERSION
00063 #define S_TABLE_VERSION 4
00064 
00067 static int mod_init(void);
00068 static int child_init(int);
00069 static void destroy(void);
00070 static int pxml_add_xcap_server( modparam_t type, void* val);
00071 static int shm_copy_xcap_list(void);
00072 static void free_xs_list(xcap_serv_t* xs_list, int mem_type);
00073 static int xcap_doc_updated(int doc_type, str xid, char* doc);
00074 static int mi_child_init(void);
00075 static struct mi_root* dum(struct mi_root* cmd, void* param);
00076 
00077 static int fixup_presxml_check(void **param, int param_no);
00078 static int w_presxml_check_basic(struct sip_msg *msg, char *presentity_uri, char *status);
00079 static int w_presxml_check_activities(struct sip_msg *msg, char *presentity_uri, char *activities);
00080 
00082 add_event_t pres_add_event;
00083 update_watchers_t pres_update_watchers;
00084 pres_get_sphere_t pres_get_sphere;
00085 
00086 
00087 /* Module parameter variables */
00088 str xcap_table= str_init("xcap");
00089 str db_url = str_init(DEFAULT_DB_URL);
00090 int force_active= 0;
00091 int pidf_manipulation= 0;
00092 int integrated_xcap_server= 0;
00093 xcap_serv_t* xs_list= NULL;
00094 int disable_presence = 0;
00095 int disable_winfo    = 0;
00096 int disable_bla      = 1;
00097 int passive_mode     = 0;
00098 
00100 sl_api_t slb;
00101 
00102 /* database connection */
00103 db1_con_t *pxml_db = NULL;
00104 db_func_t pxml_dbf;
00105 
00106 /* functions imported from xcap_client module */
00107 
00108 xcapGetNewDoc_t xcap_GetNewDoc;
00109 
00110 static cmd_export_t cmds[]={
00111         { "pres_check_basic",           (cmd_function)w_presxml_check_basic, 2,
00112                 fixup_presxml_check, 0, ANY_ROUTE},
00113         { "pres_check_activities",      (cmd_function)w_presxml_check_activities, 2,
00114                 fixup_presxml_check, 0, ANY_ROUTE},
00115         { "bind_presence_xml",          (cmd_function)bind_presence_xml, 1,
00116                 0, 0, 0},
00117         { 0, 0, 0, 0, 0, 0}
00118 };
00119 
00120 static param_export_t params[]={
00121         { "db_url",             STR_PARAM, &db_url.s},
00122         { "xcap_table",         STR_PARAM, &xcap_table.s},
00123         { "force_active",       INT_PARAM, &force_active },
00124         { "pidf_manipulation",  INT_PARAM, &pidf_manipulation},
00125         { "integrated_xcap_server", INT_PARAM, &integrated_xcap_server},
00126         { "xcap_server",        STR_PARAM|USE_FUNC_PARAM,(void*)pxml_add_xcap_server},
00127         { "disable_presence",   INT_PARAM, &disable_presence },
00128         { "disable_winfo",              INT_PARAM, &disable_winfo },
00129         { "disable_bla",                INT_PARAM, &disable_bla },
00130         { "passive_mode",               INT_PARAM, &passive_mode },
00131         { 0, 0, 0}
00132 };
00133 
00134 static mi_export_t mi_cmds[] = {
00135         { "dum",             dum,          0,  0,  mi_child_init},
00136         {  0,                0,            0,  0,        0      }
00137 };
00138 
00139 
00141 struct module_exports exports= {
00142         "presence_xml",         /* module name */
00143          DEFAULT_DLFLAGS,       /* dlopen flags */
00144          cmds,                  /* exported functions */
00145          params,                /* exported parameters */
00146          0,                             /* exported statistics */
00147          mi_cmds,               /* exported MI functions */
00148          0,                             /* exported pseudo-variables */
00149          0,                             /* extra processes */
00150          mod_init,              /* module initialization function */
00151          0,                             /* response handling function */
00152          destroy,               /* destroy function */
00153          child_init             /* per-child init function */
00154 };
00155         
00159 static int mod_init(void)
00160 {
00161         bind_presence_t bind_presence;
00162         presence_api_t pres;
00163 
00164         if(passive_mode==1)
00165                 return 0;
00166         
00167         if(register_mi_mod(exports.name, mi_cmds)!=0)
00168         {
00169                 LM_ERR("failed to register MI commands\n");
00170                 return -1;
00171         }
00172 
00173         db_url.len = db_url.s ? strlen(db_url.s) : 0;
00174         LM_DBG("db_url=%s/%d/%p\n",ZSW(db_url.s),db_url.len, db_url.s);
00175         xcap_table.len = xcap_table.s ? strlen(xcap_table.s) : 0;
00176         
00177 
00178         /* bind the SL API */
00179         if (sl_load_api(&slb)!=0) {
00180                 LM_ERR("cannot bind to SL API\n");
00181                 return -1;
00182         }
00183 
00184         bind_presence= (bind_presence_t)find_export("bind_presence", 1,0);
00185         if (!bind_presence)
00186         {
00187                 LM_ERR("Can't bind presence\n");
00188                 return -1;
00189         }
00190         if (bind_presence(&pres) < 0)
00191         {
00192                 LM_ERR("Can't bind to presence module\n");
00193                 return -1;
00194         }
00195         
00196         pres_get_sphere= pres.get_sphere;
00197         pres_add_event= pres.add_event;
00198         pres_update_watchers= pres.update_watchers_status;
00199         pres_contains_event= pres.contains_event;
00200         pres_get_presentity= pres.get_presentity;
00201         pres_free_presentity= pres.free_presentity;
00202         if (pres_add_event == NULL || pres_update_watchers== NULL)
00203         {
00204                 LM_ERR("Can't import add_event\n");
00205                 return -1;
00206         }
00207         if(xml_add_events()< 0)
00208         {
00209                 LM_ERR("adding xml events\n");
00210                 return -1;              
00211         }
00212         
00213         if(force_active== 0)
00214         {
00215                 /* binding to mysql module  */
00216                 if (db_bind_mod(&db_url, &pxml_dbf))
00217                 {
00218                         LM_ERR("Database module not found\n");
00219                         return -1;
00220                 }
00221                 
00222                 if (!DB_CAPABILITY(pxml_dbf, DB_CAP_ALL)) {
00223                         LM_ERR("Database module does not implement all functions"
00224                                         " needed by the module\n");
00225                         return -1;
00226                 }
00227 
00228                 pxml_db = pxml_dbf.init(&db_url);
00229                 if (!pxml_db)
00230                 {
00231                         LM_ERR("while connecting to database\n");
00232                         return -1;
00233                 }
00234 
00235                 if(db_check_table_version(&pxml_dbf, pxml_db, &xcap_table, S_TABLE_VERSION) < 0) {
00236                         LM_ERR("error during table version check.\n");
00237                         return -1;
00238                 }
00239                 if(!integrated_xcap_server )
00240                 {
00241                         xcap_api_t xcap_api;
00242                         bind_xcap_t bind_xcap;
00243 
00244                         /* bind xcap */
00245                         bind_xcap= (bind_xcap_t)find_export("bind_xcap", 1, 0);
00246                         if (!bind_xcap)
00247                         {
00248                                 LM_ERR("Can't bind xcap_client\n");
00249                                 return -1;
00250                         }
00251                 
00252                         if (bind_xcap(&xcap_api) < 0)
00253                         {
00254                                 LM_ERR("Can't bind xcap_api\n");
00255                                 return -1;
00256                         }
00257                         xcap_GetNewDoc= xcap_api.getNewDoc;
00258                         if(xcap_GetNewDoc== NULL)
00259                         {
00260                                 LM_ERR("can't import get_elem from xcap_client module\n");
00261                                 return -1;
00262                         }
00263                 
00264                         if(xcap_api.register_xcb(PRES_RULES, xcap_doc_updated)< 0)
00265                         {
00266                                 LM_ERR("registering xcap callback function\n");
00267                                 return -1;
00268                         }
00269                 }
00270         }
00271 
00272         if(shm_copy_xcap_list()< 0)
00273         {
00274                 LM_ERR("copying xcap server list in share memory\n");
00275                 return -1;
00276         }
00277 
00278         if(pxml_db)
00279                 pxml_dbf.close(pxml_db);
00280         pxml_db = NULL;
00281 
00282         return 0;
00283 }
00284 
00285 static int mi_child_init(void)
00286 {
00287         if(passive_mode==1)
00288                 return 0;
00289 
00290         if(force_active== 0)
00291         {
00292                 if(pxml_db)
00293                         return 0;
00294                 pxml_db = pxml_dbf.init(&db_url);
00295                 if (pxml_db== NULL)
00296                 {
00297                         LM_ERR("while connecting database\n");
00298                         return -1;
00299                 }
00300                 if (pxml_dbf.use_table(pxml_db, &xcap_table) < 0)
00301                 {
00302                         LM_ERR("in use_table SQL operation\n");
00303                         return -1;
00304                 }
00305         }
00306 
00307         LM_DBG("Database connection opened successfully\n");
00308 
00309         return 0;
00310 }
00311 
00312 static int child_init(int rank)
00313 {
00314         LM_DBG("[%d]  pid [%d]\n", rank, getpid());
00315         
00316         if(passive_mode==1)
00317                 return 0;
00318 
00319         if (rank==PROC_INIT || rank==PROC_MAIN || rank==PROC_TCP_MAIN)
00320                 return 0; /* do nothing for the main process */
00321 
00322         if(force_active== 0)
00323         {
00324                 if(pxml_db)
00325                         return 0;
00326                 pxml_db = pxml_dbf.init(&db_url);
00327                 if (pxml_db== NULL)
00328                 {
00329                         LM_ERR("while connecting database\n");
00330                         return -1;
00331                 }
00332                 if (pxml_dbf.use_table(pxml_db, &xcap_table) < 0)
00333                 {
00334                         LM_ERR("in use_table SQL operation\n");
00335                         return -1;
00336                 }
00337         }
00338 
00339         LM_DBG("child %d: Database connection opened successfully\n",rank);
00340 
00341         return 0;
00342 }
00343 
00344 static void destroy(void)
00345 {
00346         LM_DBG("start\n");
00347         if(pxml_db && pxml_dbf.close)
00348                 pxml_dbf.close(pxml_db);
00349 
00350         free_xs_list(xs_list, SHM_MEM_TYPE);
00351 
00352         return ;
00353 }
00354 
00355 static int pxml_add_xcap_server( modparam_t type, void* val)
00356 {
00357         xcap_serv_t* xs;
00358         int size;
00359         char* serv_addr= (char*)val;
00360         char* sep= NULL;
00361         unsigned int port= 80;
00362         str serv_addr_str;
00363                 
00364         serv_addr_str.s= serv_addr;
00365         serv_addr_str.len= strlen(serv_addr);
00366 
00367         sep= strchr(serv_addr, ':');
00368         if(sep)
00369         {       
00370                 char* sep2= NULL;
00371                 str port_str;
00372                 
00373                 sep2= strchr(sep+ 1, ':');
00374                 if(sep2)
00375                         sep= sep2;
00376                 
00377 
00378                 port_str.s= sep+ 1;
00379                 port_str.len= serv_addr_str.len- (port_str.s- serv_addr);
00380 
00381                 if(str2int(&port_str, &port)< 0)
00382                 {
00383                         LM_ERR("while converting string to int\n");
00384                         goto error;
00385                 }
00386                 if(port< 0 || port> 65535)
00387                 {
00388                         LM_ERR("wrong port number\n");
00389                         goto error;
00390                 }
00391                 *sep = '\0';
00392                 serv_addr_str.len= sep- serv_addr;
00393         }
00394 
00395         size= sizeof(xcap_serv_t)+ (serv_addr_str.len+ 1)* sizeof(char);
00396         xs= (xcap_serv_t*)pkg_malloc(size);
00397         if(xs== NULL)
00398         {
00399                 ERR_MEM(PKG_MEM_STR);
00400         }
00401         memset(xs, 0, size);
00402         size= sizeof(xcap_serv_t);
00403 
00404         xs->addr= (char*)xs+ size;
00405         strcpy(xs->addr, serv_addr);
00406 
00407         xs->port= port;
00408         /* check for duplicates */
00409         xs->next= xs_list;
00410         xs_list= xs;
00411         return 0;
00412 
00413 error:
00414         free_xs_list(xs_list, PKG_MEM_TYPE);
00415         return -1;
00416 }
00417 
00418 static int shm_copy_xcap_list(void)
00419 {
00420         xcap_serv_t* xs, *shm_xs, *prev_xs;
00421         int size;
00422 
00423         xs= xs_list;
00424         if(xs== NULL)
00425         {
00426                 if(force_active== 0 && !integrated_xcap_server)
00427                 {
00428                         LM_ERR("no xcap_server parameter set\n");
00429                         return -1;
00430                 }
00431                 return 0;
00432         }
00433         xs_list= NULL;
00434         size= sizeof(xcap_serv_t);
00435         
00436         while(xs)
00437         {
00438                 size+= (strlen(xs->addr)+ 1)* sizeof(char);
00439                 shm_xs= (xcap_serv_t*)shm_malloc(size);
00440                 if(shm_xs== NULL)
00441                 {
00442                         ERR_MEM(SHARE_MEM);
00443                 }
00444                 memset(shm_xs, 0, size);
00445                 size= sizeof(xcap_serv_t);
00446 
00447                 shm_xs->addr= (char*)shm_xs+ size;
00448                 strcpy(shm_xs->addr, xs->addr);
00449                 shm_xs->port= xs->port;
00450                 shm_xs->next= xs_list; 
00451                 xs_list= shm_xs;
00452 
00453                 prev_xs= xs;
00454                 xs= xs->next;
00455 
00456                 pkg_free(prev_xs);
00457         }
00458         return 0;
00459 
00460 error:
00461         free_xs_list(xs_list, SHM_MEM_TYPE);
00462         return -1;
00463 }
00464 
00465 static void free_xs_list(xcap_serv_t* xsl, int mem_type)
00466 {
00467         xcap_serv_t* xs, *prev_xs;
00468 
00469         xs= xsl;
00470 
00471         while(xs)
00472         {
00473                 prev_xs= xs;
00474                 xs= xs->next;
00475                 if(mem_type & SHM_MEM_TYPE)
00476                         shm_free(prev_xs);
00477                 else
00478                         pkg_free(prev_xs);
00479         }
00480         xsl= NULL;
00481 }
00482 
00483 static int xcap_doc_updated(int doc_type, str xid, char* doc)
00484 {
00485         pres_ev_t ev;
00486         str rules_doc;
00487 
00488         /* call updating watchers */
00489         ev.name.s= "presence";
00490         ev.name.len= PRES_LEN;
00491 
00492         rules_doc.s= doc;
00493         rules_doc.len= strlen(doc);
00494 
00495         if(pres_update_watchers(xid, &ev, &rules_doc)< 0)
00496         {
00497                 LM_ERR("updating watchers in presence\n");
00498                 return -1;      
00499         }
00500         return 0;
00501 
00502 }
00503 
00504 static struct mi_root* dum(struct mi_root* cmd, void* param)
00505 {
00506         return 0;
00507 }
00508 
00509 int bind_presence_xml(struct presence_xml_binds *pxb)
00510 {
00511         if (pxb == NULL)
00512         {
00513                 LM_WARN("bind_presence_xml: Cannot load presence_xml API into a NULL pointer\n");
00514                 return -1;
00515         }
00516 
00517         pxb->pres_check_basic = presxml_check_basic;
00518         pxb->pres_check_activities = presxml_check_activities;
00519         return 0;
00520 }
00521 
00522 static int fixup_presxml_check(void **param, int param_no)
00523 {
00524         if(param_no==1)
00525         {
00526                 return fixup_spve_null(param, 1);
00527         } else if(param_no==2) {
00528                 return fixup_spve_null(param, 1);
00529         }
00530         return 0;
00531 }
00532 
00533 static int w_presxml_check_basic(struct sip_msg *msg, char *presentity_uri, char *status)
00534 {
00535         str uri, basic;
00536 
00537         if (fixup_get_svalue(msg, (gparam_p)presentity_uri, &uri) != 0)
00538         {
00539                 LM_ERR("invalid presentity uri parameter\n");
00540                 return -1;
00541         }
00542 
00543         if (fixup_get_svalue(msg, (gparam_p)status, &basic) != 0)
00544         {
00545                 LM_ERR("invalid status parameter\n");
00546                 return -1;
00547         }
00548 
00549         return presxml_check_basic(msg, uri, basic);
00550 }
00551 
00552 static int w_presxml_check_activities(struct sip_msg *msg, char *presentity_uri, char *activity)
00553 {
00554         str uri, act;
00555 
00556         if (fixup_get_svalue(msg, (gparam_p)presentity_uri, &uri) != 0)
00557         {
00558                 LM_ERR("invalid presentity uri parameter\n");
00559                 return -1;
00560         }
00561 
00562         if (fixup_get_svalue(msg, (gparam_p)activity, &act) != 0)
00563         {
00564                 LM_ERR("invalid activity parameter\n");
00565                 return -1;
00566         }
00567 
00568         return presxml_check_activities(msg, uri, act);
00569 }