00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00109 #include <stdio.h>
00110 #include <stdlib.h>
00111 #include <errno.h>
00112 #include <string.h>
00113
00114 #include "../../sr_module.h"
00115 #include "../../mem/mem.h"
00116 #include "../../data_lump_rpl.h"
00117 #include "../../parser/msg_parser.h"
00118 #include "../../parser/parse_content.h"
00119 #include "../../parser/parse_from.h"
00120 #include "../../parser/parse_param.h"
00121 #include "../../modules/tm/tm_load.h"
00122 #include "../../cfg/cfg_struct.h"
00123
00124 #include "xode.h"
00125 #include "xmpp.h"
00126 #include "network.h"
00127 #include "xmpp_api.h"
00128
00129 #include <arpa/inet.h>
00130
00131
00132 #define DB_KEY "this-be-a-random-key"
00133
00134 MODULE_VERSION
00135
00136 struct tm_binds tmb;
00137
00138 static int mod_init(void);
00139 static int child_init(int rank);
00140 static void xmpp_process(int rank);
00141 static int cmd_send_message(struct sip_msg* msg, char* _foo, char* _bar);
00142
00143 int xmpp_gwmap_param(modparam_t type, void *val);
00144
00145 static int pipe_fds[2] = {-1,-1};
00146
00147
00148
00149
00150 char *backend = "component";
00151 char *domain_sep_str = NULL;
00152 char domain_separator = '*';
00153 char *gateway_domain = "sip2xmpp.example.net";
00154 char *xmpp_domain = "xmpp2sip.example.net";
00155 char *xmpp_host = "xmpp.example.com";
00156 int xmpp_port = 0;
00157 char *xmpp_password = "secret";
00158 str outbound_proxy= {0, 0};
00159
00160 param_t *_xmpp_gwmap_list = NULL;
00161
00162 #define DEFAULT_COMPONENT_PORT 5347
00163 #define DEFAULT_SERVER_PORT 5269
00164
00165 static proc_export_t procs[] = {
00166 {"XMPP receiver", 0, 0, xmpp_process, 1 },
00167 {0,0,0,0,0}
00168 };
00169
00170
00171
00172
00173
00174 static cmd_export_t cmds[] = {
00175 {"xmpp_send_message", (cmd_function)cmd_send_message, 0, 0, 0, REQUEST_ROUTE},
00176 {"bind_xmpp", (cmd_function)bind_xmpp, 0, 0, 0, 0},
00177 {0, 0, 0, 0, 0, 0}
00178 };
00179
00180
00181
00182
00183 static param_export_t params[] = {
00184 { "backend", STR_PARAM, &backend },
00185 { "domain_separator", STR_PARAM, &domain_sep_str },
00186 { "gateway_domain", STR_PARAM, &gateway_domain },
00187 { "xmpp_domain", STR_PARAM, &xmpp_domain },
00188 { "xmpp_host", STR_PARAM, &xmpp_host },
00189 { "xmpp_port", INT_PARAM, &xmpp_port },
00190 { "xmpp_password", STR_PARAM, &xmpp_password },
00191 { "outbound_proxy", STR_PARAM, &outbound_proxy.s},
00192 { "gwmap", STR_PARAM|USE_FUNC_PARAM, (void*)xmpp_gwmap_param},
00193 {0, 0, 0}
00194 };
00195
00196
00197
00198
00199 struct module_exports exports = {
00200 "xmpp",
00201 DEFAULT_DLFLAGS,
00202 cmds,
00203 params,
00204 0,
00205 0,
00206 0,
00207 procs,
00208 mod_init,
00209 0,
00210 0,
00211 child_init,
00212 };
00213
00214
00215
00216
00217 static int mod_init(void) {
00218
00219 if (load_tm_api(&tmb)) {
00220 LM_ERR("failed to load tm API\n");
00221 return -1;
00222 }
00223
00224 if (strcmp(backend, "component") && strcmp(backend, "server")) {
00225 LM_ERR("invalid backend '%s'\n", backend);
00226 return -1;
00227 }
00228
00229 if (!xmpp_port) {
00230 if (!strcmp(backend, "component"))
00231 xmpp_port = DEFAULT_COMPONENT_PORT;
00232 else if (!strcmp(backend, "server"))
00233 xmpp_port = DEFAULT_SERVER_PORT;
00234 }
00235
00236
00237 if (domain_sep_str && *domain_sep_str)
00238 domain_separator = *domain_sep_str;
00239
00240 if(outbound_proxy.s)
00241 outbound_proxy.len= strlen(outbound_proxy.s);
00242
00243 if(init_xmpp_cb_list()<0){
00244 LM_ERR("failed to init callback list\n");
00245 return -1;
00246 }
00247
00248 if (pipe(pipe_fds) < 0) {
00249 LM_ERR("pipe() failed\n");
00250 return -1;
00251 }
00252
00253
00254 register_procs(1);
00255
00256 cfg_register_child(1);
00257
00258 return 0;
00259 }
00260
00264 static int child_init(int rank)
00265 {
00266 int pid;
00267
00268 if (rank==PROC_MAIN) {
00269 pid=fork_process(PROC_NOCHLDINIT, "XMPP Manager", 1);
00270 if (pid<0)
00271 return -1;
00272 if(pid==0){
00273
00274
00275 if (cfg_child_init())
00276 return -1;
00277
00278 xmpp_process(1);
00279 }
00280 }
00281
00282 return 0;
00283 }
00284
00285
00286 static void xmpp_process(int rank)
00287 {
00288
00289
00290
00291 close(pipe_fds[1]);
00292
00293 LM_DBG("started child connection process\n");
00294 if (!strcmp(backend, "component"))
00295 xmpp_component_child_process(pipe_fds[0]);
00296 else if (!strcmp(backend, "server"))
00297 xmpp_server_child_process(pipe_fds[0]);
00298 }
00299
00300
00301
00302
00308 int xmpp_send_sip_msg(char *from, char *to, char *msg)
00309 {
00310 str msg_type = { "MESSAGE", 7 };
00311 str hdr, fromstr, tostr, msgstr;
00312 char buf[512];
00313 uac_req_t uac_r;
00314
00315 hdr.s = buf;
00316 hdr.len = snprintf(buf, sizeof(buf),
00317 "Content-type: text/plain" CRLF "Contact: %s" CRLF, from);
00318
00319 fromstr.s = from;
00320 fromstr.len = strlen(from);
00321 tostr.s = to;
00322 tostr.len = strlen(to);
00323 msgstr.s = msg;
00324 msgstr.len = strlen(msg);
00325
00326 set_uac_req(&uac_r, &msg_type, &hdr, &msgstr, 0, 0, 0, 0);
00327 return tmb.t_request(
00328 &uac_r,
00329 0,
00330 &tostr,
00331 &fromstr,
00332 (outbound_proxy.s)?&outbound_proxy:NULL
00333 );
00334 }
00335
00336
00337
00338
00339 static char *shm_strdup(str *src)
00340 {
00341 char *res;
00342
00343 if (!src || !src->s)
00344 return NULL;
00345 if (!(res = (char *) shm_malloc(src->len + 1)))
00346 return NULL;
00347 strncpy(res, src->s, src->len);
00348 res[src->len] = 0;
00349 return res;
00350 }
00351
00352 void xmpp_free_pipe_cmd(struct xmpp_pipe_cmd *cmd)
00353 {
00354 if (cmd->from)
00355 shm_free(cmd->from);
00356 if (cmd->to)
00357 shm_free(cmd->to);
00358 if (cmd->body)
00359 shm_free(cmd->body);
00360 if (cmd->id)
00361 shm_free(cmd->id);
00362 shm_free(cmd);
00363 }
00364
00365 static int xmpp_send_pipe_cmd(enum xmpp_pipe_cmd_type type, str *from, str *to,
00366 str *body, str *id)
00367 {
00368 struct xmpp_pipe_cmd *cmd;
00369
00371 cmd = (struct xmpp_pipe_cmd *) shm_malloc(sizeof(struct xmpp_pipe_cmd));
00372 memset(cmd, 0, sizeof(struct xmpp_pipe_cmd));
00373
00374 cmd->type = type;
00375 cmd->from = shm_strdup(from);
00376 cmd->to = shm_strdup(to);
00377 cmd->body = shm_strdup(body);
00378 cmd->id = shm_strdup(id);
00379
00380 if (write(pipe_fds[1], &cmd, sizeof(cmd)) != sizeof(cmd)) {
00381 LM_ERR("failed to write to command pipe: %s\n", strerror(errno));
00382 xmpp_free_pipe_cmd(cmd);
00383 return -1;
00384 }
00385 return 0;
00386 }
00387
00388 static int cmd_send_message(struct sip_msg* msg, char* _foo, char* _bar)
00389 {
00390 str body, from_uri, dst, tagid;
00391 int mime;
00392
00393 LM_DBG("cmd_send_message\n");
00394
00395
00396 if (!(body.s = get_body(msg))) {
00397 LM_ERR("failed to extract body\n");
00398 return -1;
00399 }
00400 if (!msg->content_length) {
00401 LM_ERR("no content-length found\n");
00402 return -1;
00403 }
00404 body.len = get_content_length(msg);
00405 if ((mime = parse_content_type_hdr(msg)) < 1) {
00406 LM_ERR("failed parse content-type\n");
00407 return -1;
00408 }
00409 if (mime != (TYPE_TEXT << 16) + SUBTYPE_PLAIN
00410 && mime != (TYPE_MESSAGE << 16) + SUBTYPE_CPIM) {
00411 LM_ERR("invalid content-type 0x%x\n", mime);
00412 return -1;
00413 }
00414
00415
00416 if (parse_headers(msg, HDR_TO_F | HDR_FROM_F, 0) == -1 || !msg->to
00417 || !msg->from) {
00418 LM_ERR("no To/From headers\n");
00419 return -1;
00420 }
00421 if (parse_from_header(msg) < 0 || !msg->from->parsed) {
00422 LM_ERR("failed to parse From header\n");
00423 return -1;
00424 }
00425 from_uri = ((struct to_body *) msg->from->parsed)->uri;
00426 tagid = ((struct to_body *) msg->from->parsed)->tag_value;
00427 LM_DBG("message from <%.*s>\n", from_uri.len, from_uri.s);
00428
00429
00430 dst.len = 0;
00431 if (msg->new_uri.len > 0) {
00432 LM_DBG("using new URI as destination\n");
00433 dst = msg->new_uri;
00434 } else if (msg->first_line.u.request.uri.s
00435 && msg->first_line.u.request.uri.len > 0) {
00436 LM_DBG("using R-URI as destination\n");
00437 dst = msg->first_line.u.request.uri;
00438 } else if (msg->to->parsed) {
00439 LM_DBG("using TO-URI as destination\n");
00440 dst = ((struct to_body *) msg->to->parsed)->uri;
00441 } else {
00442 LM_ERR("failed to find a valid destination\n");
00443 return -1;
00444 }
00445
00446 if (!xmpp_send_pipe_cmd(XMPP_PIPE_SEND_MESSAGE, &from_uri, &dst, &body,
00447 &tagid))
00448 return 1;
00449 return -1;
00450 }
00451
00452
00456 int xmpp_send_xpacket(str *from, str *to, str *msg, str *id)
00457 {
00458 if(from==NULL || to==NULL || msg==NULL || id==NULL)
00459 return -1;
00460 return xmpp_send_pipe_cmd(XMPP_PIPE_SEND_PACKET, from, to, msg, id);
00461 }
00462
00466 int xmpp_send_xmessage(str *from, str *to, str *msg, str *id)
00467 {
00468 if(from==NULL || to==NULL || msg==NULL || id==NULL)
00469 return -1;
00470 return xmpp_send_pipe_cmd(XMPP_PIPE_SEND_MESSAGE, from, to, msg, id);
00471 }
00472
00476 int xmpp_send_xsubscribe(str *from, str *to, str *msg, str *id)
00477 {
00478 if(from==NULL || to==NULL || msg==NULL || id==NULL)
00479 return -1;
00480 return xmpp_send_pipe_cmd(XMPP_PIPE_SEND_PSUBSCRIBE, from, to, msg, id);
00481 }
00482
00486 int xmpp_send_xnotify(str *from, str *to, str *msg, str *id)
00487 {
00488 if(from==NULL || to==NULL || msg==NULL || id==NULL)
00489 return -1;
00490 return xmpp_send_pipe_cmd(XMPP_PIPE_SEND_PNOTIFY, from, to, msg, id);
00491 }
00492
00496 int xmpp_gwmap_param(modparam_t type, void *val)
00497 {
00498 str inv;
00499 param_hooks_t phooks;
00500 param_t *params = NULL;
00501 param_t *it = NULL;
00502
00503 if(val==NULL)
00504 return -1;
00505 inv.s = (char*)val;
00506 inv.len = strlen(inv.s);
00507 if(inv.len<=0)
00508 return -1;
00509
00510 if(inv.s[inv.len-1]==';')
00511 inv.len--;
00512 if (parse_params(&inv, CLASS_ANY, &phooks, ¶ms)<0)
00513 {
00514 LM_ERR("failed parsing params value\n");
00515 return -1;
00516 }
00517 if(_xmpp_gwmap_list==NULL)
00518 {
00519 _xmpp_gwmap_list = params;
00520 } else {
00521 it = _xmpp_gwmap_list;
00522 while(it->next) it = it->next;
00523 it->next = params;
00524 }
00525 return 0;
00526 }