all: updated FSF address in GPL text
[sip-router] / modules / pua_xmpp / pua_xmpp.c
1 /*
2  * $Id: pua_xmpp.c 1666 2007-03-02 13:40:09Z anca_vamanu $
3  *
4  * pua_xmpp module - presence SIP - XMPP Gateway
5  *
6  * Copyright (C) 2007 Voice Sistem S.R.L.
7  *
8  * This file is part of Kamailio, a free SIP server.
9  *
10  * Kamailio is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version
14  *
15  * Kamailio is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License 
21  * along with this program; if not, write to the Free Software 
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  * History:
25  * --------
26  *  2007-03-29  initial version (anca)
27  */
28
29 /*! \file
30  * \brief Kamailio presence gateway: SIP/SIMPLE -- XMPP (pua_xmpp)
31  */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <libxml/parser.h>
37 #include <time.h>
38
39 #include "../../sr_module.h"
40 #include "../../dprint.h"
41 #include "../../str.h"
42 #include "../../pt.h"
43 #include "../../mem/mem.h"
44 #include "../../mem/shm_mem.h"
45 #include "../../parser/parse_expires.h"
46 #include "../../parser/msg_parser.h"
47 #include "../../modules/tm/tm_load.h"
48 #include "../xmpp/xmpp_api.h"
49 #include "../pua/pua_bind.h"
50
51 #include "pua_xmpp.h"
52 #include "xmpp2simple.h"
53 #include "simple2xmpp.h"
54 #include "request_winfo.h"
55
56 MODULE_VERSION
57
58 struct tm_binds tmb;
59
60 /* functions imported from pua module*/
61 pua_api_t pua;
62 send_publish_t pua_send_publish;
63 send_subscribe_t pua_send_subscribe;
64 query_dialog_t pua_is_dialog;
65
66 /* functions imported from xmpp module*/
67 xmpp_api_t xmpp_api;
68 xmpp_send_xsubscribe_f xmpp_subscribe;
69 xmpp_send_xnotify_f xmpp_notify;
70 xmpp_send_xpacket_f xmpp_packet;
71 xmpp_translate_uri_f duri_sip_xmpp;
72 xmpp_translate_uri_f euri_sip_xmpp;
73 xmpp_translate_uri_f duri_xmpp_sip;
74 xmpp_translate_uri_f euri_xmpp_sip;
75
76 /* libxml wrapper functions */
77 xmlNodeGetAttrContentByName_t XMLNodeGetAttrContentByName;
78 xmlDocGetNodeByName_t XMLDocGetNodeByName;
79 xmlNodeGetNodeByName_t XMLNodeGetNodeByName;
80 xmlNodeGetNodeContentByName_t XMLNodeGetNodeContentByName;
81
82 str server_address= {0, 0};
83
84 /** module functions */
85
86 static int mod_init(void);
87 static int child_init(int);
88
89 static int fixup_pua_xmpp(void** param, int param_no);
90
91 static cmd_export_t cmds[]=
92 {
93         {"pua_xmpp_notify", (cmd_function)Notify2Xmpp,  0, 0, 0, REQUEST_ROUTE},
94         {"pua_xmpp_req_winfo", (cmd_function)request_winfo, 2, fixup_pua_xmpp, 0, REQUEST_ROUTE},
95         {0, 0, 0, 0, 0, 0}
96 };
97
98 static param_export_t params[]={
99         {"server_address",     STR_PARAM,       &server_address },
100         {0,                     0,              0       }
101 };
102
103 /*! \brief module exports */
104 struct module_exports exports= {
105         "pua_xmpp",                     /* module name */
106         DEFAULT_DLFLAGS,        /* dlopen flags */
107         cmds,                           /* exported functions */
108         params,                         /* exported  parameters */
109         0,                                      /* exported statistics */
110         0,                                      /* exported MI functions*/
111         0,                                      /* exported pseudo-variables */
112         0,                                      /* extra processes */
113         mod_init,                       /* module initialization function */
114         0,                                      /* response handling function */
115         0,                                      /* destroy function */
116         child_init                      /* per-child init function */
117 };
118
119 /*! \brief
120  * init module function
121  */
122 static int mod_init(void)
123 {
124         load_tm_f  load_tm;
125         bind_pua_t bind_pua;
126         bind_xmpp_t bind_xmpp;
127         bind_libxml_t bind_libxml;
128         libxml_api_t libxml_api;
129
130         /* check if compulsory parameter server_address is set */
131         if(server_address.s== NULL)
132         {
133                 LM_ERR("compulsory 'server_address' parameter not set!");
134                 return -1;
135         }
136         server_address.len= strlen(server_address.s);
137
138         /* import the TM auto-loading function */
139         if((load_tm=(load_tm_f)find_export("load_tm", NO_SCRIPT, 0))==NULL)
140         {
141                 LM_ERR("can't import load_tm\n");
142                 return -1;
143         }
144
145         /* let the auto-loading function load all TM stuff */
146
147         if(load_tm(&tmb)==-1)
148         {
149                 LM_ERR("can't load tm functions\n");
150                 return -1;
151         }
152
153         /* bind libxml wrapper functions */
154         if((bind_libxml= (bind_libxml_t)find_export("bind_libxml_api", 1, 0))== NULL)
155         {
156                 LM_ERR("can't import bind_libxml_api\n");
157                 return -1;
158         }
159         if(bind_libxml(&libxml_api)< 0)
160         {
161                 LM_ERR("can not bind libxml api\n");
162                 return -1;
163         }
164         XMLNodeGetAttrContentByName= libxml_api.xmlNodeGetAttrContentByName;
165         XMLDocGetNodeByName= libxml_api.xmlDocGetNodeByName;
166         XMLNodeGetNodeByName= libxml_api.xmlNodeGetNodeByName;
167         XMLNodeGetNodeContentByName= libxml_api.xmlNodeGetNodeContentByName;
168
169         if(XMLNodeGetAttrContentByName== NULL || XMLDocGetNodeByName== NULL ||
170                 XMLNodeGetNodeByName== NULL || XMLNodeGetNodeContentByName== NULL)
171         {
172                 LM_ERR("libxml wrapper functions could not be bound\n");
173                 return -1;
174         }
175
176
177         /* bind xmpp */
178         bind_xmpp= (bind_xmpp_t)find_export("bind_xmpp", 0,0);
179         if (!bind_xmpp)
180         {
181                 LM_ERR("Can't bind to the XMPP module.\n");
182                 return -1;
183         }
184         if(bind_xmpp(&xmpp_api)< 0)
185         {
186                 LM_ERR("Can't bind to the XMPP module.\n");
187                 return -1;
188         }
189         if(xmpp_api.xsubscribe== NULL)
190         {
191                 LM_ERR("Could not import xsubscribe from the XMPP module. Version mismatch?\n");
192                 return -1;
193         }
194         xmpp_subscribe= xmpp_api.xsubscribe;
195
196         if(xmpp_api.xnotify== NULL)
197         {
198                 LM_ERR("Could not import xnotify from the XMPP module. Version mismatch?\n");
199                 return -1;
200         }
201         xmpp_notify= xmpp_api.xnotify;
202         
203         if(xmpp_api.xpacket== NULL)
204         {
205                 LM_ERR("Could not import xnotify from the XMPP module. Version mismatch?\n");
206                 return -1;
207         }
208         xmpp_packet= xmpp_api.xpacket;
209
210         if(xmpp_api.register_callback== NULL)
211         {
212                 LM_ERR("Could not import register_callback"
213                                 " to xmpp\n");
214                 return -1;
215         }
216         if(xmpp_api.register_callback(XMPP_RCV_PRESENCE, pres_Xmpp2Sip, NULL)< 0)
217         {
218                 LM_ERR("ERROR while registering callback"
219                                 " to xmpp\n");
220                 return -1;
221         }
222         if(xmpp_api.decode_uri_sip_xmpp== NULL)
223         {
224                 LM_ERR("Could not import decode_uri_sip_xmpp"
225                                 " from xmpp\n");
226                 return -1;
227         }
228         duri_sip_xmpp= xmpp_api.decode_uri_sip_xmpp;
229
230         if(xmpp_api.encode_uri_sip_xmpp== NULL)
231         {
232                 LM_ERR("Could not import encode_uri_sip_xmpp"
233                                 " from xmpp\n");
234                 return -1;
235         }
236         euri_sip_xmpp= xmpp_api.encode_uri_sip_xmpp;
237
238         if(xmpp_api.decode_uri_xmpp_sip== NULL)
239         {
240                 LM_ERR("Could not import decode_uri_xmpp_sip"
241                                 " from xmpp\n");
242                 return -1;
243         }
244         duri_xmpp_sip= xmpp_api.decode_uri_xmpp_sip;
245
246         if(xmpp_api.encode_uri_xmpp_sip== NULL)
247         {
248                 LM_ERR("Could not import encode_uri_xmpp_sip"
249                                 " from xmpp\n");
250                 return -1;
251         }
252         euri_xmpp_sip= xmpp_api.encode_uri_xmpp_sip;
253
254         /* bind pua */
255         bind_pua= (bind_pua_t)find_export("bind_pua", 1,0);
256         if (!bind_pua)
257         {
258                 LM_ERR("Can't bind to PUA module\n");
259                 return -1;
260         }
261         
262         if (bind_pua(&pua) < 0)
263         {
264                 LM_ERR("Can't bind to PUA module\n");
265                 return -1;
266         }
267         if(pua.send_publish == NULL)
268         {
269                 LM_ERR("Could not import send_publish() in module PUA. Version mismatch?\n");
270                 return -1;
271         }
272         pua_send_publish= pua.send_publish;
273
274         if(pua.send_subscribe == NULL)
275         {
276                 LM_ERR("Could not import send_publish() in module PUA. Version mismatch?\n");
277                 return -1;
278         }
279         pua_send_subscribe= pua.send_subscribe;
280         
281         if(pua.is_dialog == NULL)
282         {
283                 LM_ERR("Could not import send_subscribe() in module PUA. Version mismatch?\n");
284                 return -1;
285         }
286         pua_is_dialog= pua.is_dialog;
287
288         if(pua.register_puacb(XMPP_INITIAL_SUBS, Sipreply2Xmpp, NULL)< 0)
289         {
290                 LM_ERR("Could not register PUA callback\n");
291                 return -1;
292         }       
293
294         return 0;
295 }
296
297 static int child_init(int rank)
298 {
299         LM_DBG("child [%d]  pid [%d]\n", rank, getpid());
300         return 0;
301 }
302
303 static int fixup_pua_xmpp(void** param, int param_no)
304 {
305         pv_elem_t *model;
306         str s;
307         if(*param)
308         {
309                 s.s = (char*)(*param); s.len = strlen(s.s);
310                 if(pv_parse_format(&s, &model)<0)
311                 {
312                         LM_ERR("wrong format[%s]\n",(char*)(*param));
313                         return E_UNSPEC;
314                 }
315                         
316                 *param = (void*)model;
317                 return 0;
318         }
319         LM_ERR("null format\n");
320         return E_UNSPEC;
321 }
322