1 /*
2 * pua_dialoginfo module - publish dialog-info from dialo module
3 *
4 * Copyright (C) 2006 Voice Sistem S.R.L.
5 * Copyright (C) 2007-2008 Dan Pascu
6 * Copyright (C) 2008 Klaus Darilion IPCom
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 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <libxml/parser.h>
30 #include <time.h>
31
32 #include "../../core/script_cb.h"
33 #include "../../core/sr_module.h"
34 #include "../../core/parser/parse_expires.h"
35 #include "../../core/dprint.h"
36 #include "../../core/mem/shm_mem.h"
37 #include "../../core/parser/msg_parser.h"
38 #include "../../core/parser/parse_to.h"
39 #include "../../core/parser/contact/parse_contact.h"
40 #include "../../core/str.h"
41 #include "../../core/str_list.h"
42 #include "../../core/mem/mem.h"
43 #include "../../core/pt.h"
44 #include "../dialog/dlg_load.h"
45 #include "../dialog/dlg_hash.h"
46 #include "../pua/pua_bind.h"
47 #include "pua_dialoginfo.h"
48
49 MODULE_VERSION
50
51 /* Default module parameter values */
52 #define DEF_INCLUDE_CALLID 1
53 #define DEF_INCLUDE_LOCALREMOTE 1
54 #define DEF_INCLUDE_TAGS 1
55 #define DEF_OVERRIDE_LIFETIME 0
56 #define DEF_CALLER_ALWAYS_CONFIRMED 0
57 #define DEF_INCLUDE_REQ_URI 0
58 #define DEF_OVERRIDE_LIFETIME 0
59 #define DEF_SEND_PUBLISH_FLAG -1
60 #define DEF_USE_PUBRURI_AVPS 0
61 #define DEF_PUBRURI_CALLER_AVP 0
62 #define DEF_PUBRURI_CALLEE_AVP 0
63 #define DEF_CALLEE_TRYING 0
64 #define DEF_DISABLE_CALLER_PUBLISH_FLAG -1
65 #define DEF_DISABLE_CALLEE_PUBLISH_FLAG -1
66
67 /* define PUA_DIALOGINFO_DEBUG to activate more verbose
68 * logging and dialog info callback debugging
69 */
70 /* #define PUA_DIALOGINFO_DEBUG 1 */
71
72 pua_api_t pua;
73
74 struct dlg_binds dlg_api;
75
76 unsigned short pubruri_caller_avp_type;
77 int_str pubruri_caller_avp_name;
78 unsigned short pubruri_callee_avp_type;
79 int_str pubruri_callee_avp_name;
80
81 static str caller_dlg_var = {0, 0}; /* pubruri_caller */
82 static str callee_dlg_var = {0, 0}; /* pubruri_callee */
83
84 /* Module parameter variables */
85 int include_callid = DEF_INCLUDE_CALLID;
86 int include_localremote = DEF_INCLUDE_LOCALREMOTE;
87 int include_tags = DEF_INCLUDE_TAGS;
88 int override_lifetime = DEF_OVERRIDE_LIFETIME;
89 int caller_confirmed = DEF_CALLER_ALWAYS_CONFIRMED;
90 int include_req_uri = DEF_INCLUDE_REQ_URI;
91 int send_publish_flag = DEF_SEND_PUBLISH_FLAG;
92 int use_pubruri_avps = DEF_USE_PUBRURI_AVPS;
93 int callee_trying = DEF_CALLEE_TRYING;
94 int disable_caller_publish_flag = DEF_DISABLE_CALLER_PUBLISH_FLAG;
95 int disable_callee_publish_flag = DEF_DISABLE_CALLEE_PUBLISH_FLAG;
96 char * pubruri_caller_avp = DEF_PUBRURI_CALLER_AVP;
97 char * pubruri_callee_avp = DEF_PUBRURI_CALLEE_AVP;
98
99
100 send_publish_t pua_send_publish;
101 /** module functions */
102
103 static int mod_init(void);
104
105
106 static cmd_export_t cmds[]={
107 {0, 0, 0, 0, 0, 0}
108 };
109
110 static param_export_t params[]={
111 {"include_callid", INT_PARAM, &include_callid },
112 {"include_localremote", INT_PARAM, &include_localremote },
113 {"include_tags", INT_PARAM, &include_tags },
114 {"override_lifetime", INT_PARAM, &override_lifetime },
115 {"caller_confirmed", INT_PARAM, &caller_confirmed },
116 {"include_req_uri", INT_PARAM, &include_req_uri },
117 {"send_publish_flag", INT_PARAM, &send_publish_flag },
118 {"use_pubruri_avps", INT_PARAM, &use_pubruri_avps },
119 {"pubruri_caller_avp", PARAM_STRING, &pubruri_caller_avp },
120 {"pubruri_callee_avp", PARAM_STRING, &pubruri_callee_avp },
121 {"pubruri_caller_dlg_var", PARAM_STR, &caller_dlg_var },
122 {"pubruri_callee_dlg_var", PARAM_STR, &callee_dlg_var },
123 {"callee_trying", INT_PARAM, &callee_trying },
124 {"disable_caller_publish_flag", INT_PARAM, &disable_caller_publish_flag },
125 {"disable_callee_publish_flag", INT_PARAM, &disable_callee_publish_flag },
126 {0, 0, 0 }
127 };
128
129 struct module_exports exports= {
130 "pua_dialoginfo", /* module name */
131 DEFAULT_DLFLAGS, /* dlopen flags */
132 cmds, /* exported functions */
133 params, /* exported parameters */
134 0, /* RPC method exports */
135 0, /* exported pseudo-variables */
136 0, /* response handling function */
137 mod_init, /* module initialization function */
138 0, /* per-child init function */
139 0 /* module destroy function */
140 };
141
142
143 #ifdef PUA_DIALOGINFO_DEBUG
144 static void
__dialog_cbtest(struct dlg_cell * dlg,int type,struct dlg_cb_params * _params)145 __dialog_cbtest(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
146 {
147 str tag;
148 struct sip_msg *msg;
149 LM_ERR("dialog callback received, from=%.*s, to=%.*s\n",
150 dlg->from_uri.len, dlg->from_uri.s, dlg->to_uri.len,
151 dlg->to_uri.s);
152 if (dlg->tag[0].len && dlg->tag[0].s ) {
153 LM_ERR("dialog callback: tag[0] = %.*s",
154 dlg->tag[0].len, dlg->tag[0].s);
155 }
156 if (dlg->tag[0].len && dlg->tag[1].s ) {
157 LM_ERR("dialog callback: tag[1] = %.*s",
158 dlg->tag[1].len, dlg->tag[1].s);
159 }
160
161 if (type != DLGCB_DESTROY) {
162 msg = dlg_get_valid_msg(_params);
163 if (!msg) {
164 LM_ERR("no SIP message available in callback parameters\n");
165 return;
166 }
167
168 /* get to tag*/
169 if ( !msg->to) {
170 // to header not defined, parse to header
171 LM_ERR("to header not defined, parse to header\n");
172 if (parse_headers(msg, HDR_TO_F,0)<0) {
173 //parser error
174 LM_ERR("parsing of to-header failed\n");
175 tag.s = 0;
176 tag.len = 0;
177 } else if (!msg->to) {
178 // to header still not defined
179 LM_ERR("bad reply or missing TO header\n");
180 tag.s = 0;
181 tag.len = 0;
182 } else {
183 tag = get_to(msg)->tag_value;
184 }
185 } else {
186 tag = get_to(msg)->tag_value;
187 if (tag.s==0 || tag.len==0) {
188 LM_ERR("missing TAG param in TO hdr :-/\n");
189 tag.s = 0;
190 tag.len = 0;
191 }
192 }
193 if (tag.s) {
194 LM_ERR("dialog callback: msg->to->parsed->tag_value = %.*s",
195 tag.len, tag.s);
196 }
197 }
198
199 switch (type) {
200 case DLGCB_FAILED:
201 LM_ERR("dialog callback type 'DLGCB_FAILED' received, from=%.*s\n",
202 dlg->from_uri.len, dlg->from_uri.s);
203 break;
204 case DLGCB_CONFIRMED_NA:
205 LM_ERR("dialog callback type 'DLGCB_CONFIRMED_NA' received, from=%.*s\n",
206 dlg->from_uri.len, dlg->from_uri.s);
207 break;
208 case DLGCB_CONFIRMED:
209 LM_ERR("dialog callback type 'DLGCB_CONFIRMED' received, from=%.*s\n",
210 dlg->from_uri.len, dlg->from_uri.s);
211 break;
212 case DLGCB_REQ_WITHIN:
213 LM_ERR("dialog callback type 'DLGCB_REQ_WITHIN' received, from=%.*s\n",
214 dlg->from_uri.len, dlg->from_uri.s);
215 break;
216 case DLGCB_TERMINATED:
217 LM_ERR("dialog callback type 'DLGCB_TERMINATED' received, from=%.*s\n",
218 dlg->from_uri.len, dlg->from_uri.s);
219 break;
220 case DLGCB_EXPIRED:
221 LM_ERR("dialog callback type 'DLGCB_EXPIRED' received, from=%.*s\n",
222 dlg->from_uri.len, dlg->from_uri.s);
223 break;
224 case DLGCB_EARLY:
225 LM_ERR("dialog callback type 'DLGCB_EARLY' received, from=%.*s\n",
226 dlg->from_uri.len, dlg->from_uri.s);
227 break;
228 case DLGCB_RESPONSE_FWDED:
229 LM_ERR("dialog callback type 'DLGCB_RESPONSE_FWDED' received, from=%.*s\n",
230 dlg->from_uri.len, dlg->from_uri.s);
231 break;
232 case DLGCB_RESPONSE_WITHIN:
233 LM_ERR("dialog callback type 'DLGCB_RESPONSE_WITHIN' received, from=%.*s\n",
234 dlg->from_uri.len, dlg->from_uri.s);
235 break;
236 case DLGCB_DESTROY:
237 LM_ERR("dialog callback type 'DLGCB_DESTROY' received, from=%.*s\n",
238 dlg->from_uri.len, dlg->from_uri.s);
239 break;
240 default:
241 LM_ERR("dialog callback type 'unknown' received, from=%.*s\n",
242 dlg->from_uri.len, dlg->from_uri.s);
243 }
244 }
245 #endif
246
247 static void
__dialog_sendpublish(struct dlg_cell * dlg,int type,struct dlg_cb_params * _params)248 __dialog_sendpublish(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
249 {
250 str tag = {0,0};
251 str uri = {0,0};
252 str target = {0,0};
253 struct dlginfo_cell *dlginfo = NULL;
254
255 struct sip_msg *request = _params->req;
256 dlginfo = (struct dlginfo_cell*)*_params->param;
257
258 if(dlg==NULL || dlginfo==NULL) {
259 LM_WARN("execution with null parameters - type %d, dlg %p, info %p\n",
260 type, dlg, dlginfo);
261 return;
262 }
263
264 /* skip requests that do not control call state */
265 if(request && (request->REQ_METHOD)&(METHOD_PRACK|METHOD_UPDATE)) {
266 return;
267 }
268 if(include_req_uri) {
269 uri = dlginfo->req_uri;
270 } else {
271 uri = dlginfo->to_uri;
272 }
273
274 switch (type) {
275 case DLGCB_FAILED:
276 case DLGCB_TERMINATED:
277 case DLGCB_EXPIRED:
278 LM_DBG("dialog over, from=%.*s\n", dlginfo->from_uri.len,
279 dlginfo->from_uri.s);
280 if (disable_caller_publish_flag == -1 || !(request
281 && (request->flags & (1<<disable_caller_publish_flag))))
282 {
283 dialog_publish_multi("terminated", dlginfo->pubruris_caller,
284 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
285 10, 0, 0, &(dlginfo->from_contact),
286 &target, send_publish_flag==-1?1:0);
287 }
288 if (disable_callee_publish_flag == -1 || !(request
289 && (request->flags & (1<<disable_callee_publish_flag))))
290 {
291 dialog_publish_multi("terminated", dlginfo->pubruris_callee,
292 &uri, &(dlginfo->from_uri), &(dlginfo->callid), 0,
293 10, 0, 0, &target, &(dlginfo->from_contact),
294 send_publish_flag==-1?1:0);
295 }
296 break;
297 case DLGCB_CONFIRMED:
298 case DLGCB_REQ_WITHIN:
299 case DLGCB_CONFIRMED_NA:
300 LM_DBG("dialog confirmed, from=%.*s\n", dlginfo->from_uri.len,
301 dlginfo->from_uri.s);
302 if (disable_caller_publish_flag == -1 || !(request
303 && (request->flags & (1<<disable_caller_publish_flag))))
304 {
305 dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
306 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
307 dlginfo->lifetime, 0, 0, &(dlginfo->from_contact), &target,
308 send_publish_flag==-1?1:0);
309 }
310 if (disable_callee_publish_flag == -1 || !(request
311 && (request->flags & (1<<disable_callee_publish_flag))))
312 {
313 dialog_publish_multi("confirmed", dlginfo->pubruris_callee, &uri,
314 &(dlginfo->from_uri), &(dlginfo->callid), 0,
315 dlginfo->lifetime, 0, 0, &target, &(dlginfo->from_contact),
316 send_publish_flag==-1?1:0);
317 }
318 break;
319 case DLGCB_EARLY:
320 LM_DBG("dialog is early, from=%.*s\n", dlginfo->from_uri.len,
321 dlginfo->from_uri.s);
322 if (include_tags) {
323 /* get remotetarget */
324 if ( !_params->rpl->contact && ((parse_headers(_params->rpl,
325 HDR_CONTACT_F,0)<0) || !_params->rpl->contact) ) {
326 LM_ERR("bad reply or missing CONTACT hdr\n");
327 } else {
328 if ( parse_contact(_params->rpl->contact)<0 ||
329 ((contact_body_t *)_params->rpl->contact->parsed)->contacts==NULL ||
330 ((contact_body_t *)_params->rpl->contact->parsed)->contacts->next!=NULL ) {
331 LM_ERR("Malformed CONTACT hdr\n");
332 } else {
333 target = ((contact_body_t *)_params->rpl->contact->parsed)->contacts->uri;
334 }
335 }
336 /* get to tag*/
337 if ( !_params->rpl->to && ((parse_headers(_params->rpl, HDR_TO_F,0)<0)
338 || !_params->rpl->to) ) {
339 LM_ERR("bad reply or missing TO hdr :-/\n");
340 tag.s = 0;
341 tag.len = 0;
342 } else {
343 tag = get_to(_params->rpl)->tag_value;
344 if (tag.s==0 || tag.len==0) {
345 LM_ERR("missing TAG param in TO hdr :-/\n");
346 tag.s = 0;
347 tag.len = 0;
348 }
349 }
350 if (disable_caller_publish_flag == -1 || !(request
351 && (request->flags & (1<<disable_caller_publish_flag))))
352 {
353 if (caller_confirmed) {
354 dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
355 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
356 dlginfo->lifetime, &(dlginfo->from_tag), &tag,
357 &(dlginfo->from_contact), &target,
358 send_publish_flag==-1?1:0);
359 } else {
360 dialog_publish_multi("early", dlginfo->pubruris_caller,
361 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
362 dlginfo->lifetime, &(dlginfo->from_tag), &tag,
363 &(dlginfo->from_contact), &target,
364 send_publish_flag==-1?1:0);
365 }
366 }
367 if (disable_callee_publish_flag == -1 || !(request &&
368 (request->flags & (1<<disable_callee_publish_flag))))
369 {
370 dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
371 &(dlginfo->from_uri), &(dlginfo->callid), 0,
372 dlginfo->lifetime, &tag, &(dlginfo->from_tag), &target,
373 &(dlginfo->from_contact), send_publish_flag==-1?1:0);
374 }
375
376 } else {
377 if (disable_caller_publish_flag == -1 || !(request &&
378 (request->flags & (1<<disable_caller_publish_flag))))
379 {
380 if (caller_confirmed) {
381 dialog_publish_multi("confirmed", dlginfo->pubruris_caller,
382 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
383 dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
384 &target, send_publish_flag==-1?1:0);
385
386 } else {
387 dialog_publish_multi("early", dlginfo->pubruris_caller,
388 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
389 dlginfo->lifetime, 0, 0, &(dlginfo->from_contact),
390 &target, send_publish_flag==-1?1:0);
391 }
392 }
393 if (disable_callee_publish_flag == -1 || !(request
394 && (request->flags & (1<<disable_callee_publish_flag))))
395 {
396 dialog_publish_multi("early", dlginfo->pubruris_callee, &uri,
397 &(dlginfo->from_uri), &(dlginfo->callid), 0,
398 dlginfo->lifetime, 0, 0, &target,
399 &(dlginfo->from_contact), send_publish_flag==-1?1:0);
400 }
401 }
402 break;
403 default:
404 LM_ERR("unhandled dialog callback type %d received, from=%.*s\n",
405 type, dlginfo->from_uri.len, dlginfo->from_uri.s);
406 if (disable_caller_publish_flag == -1 || !(request &&
407 (request->flags & (1<<disable_caller_publish_flag))))
408 {
409 dialog_publish_multi("terminated", dlginfo->pubruris_caller,
410 &(dlginfo->from_uri), &uri, &(dlginfo->callid), 1,
411 10, 0, 0, &(dlginfo->from_contact), &target,
412 send_publish_flag==-1?1:0);
413 }
414 if (disable_callee_publish_flag == -1 || !(request &&
415 (request->flags & (1<<disable_callee_publish_flag))))
416 {
417 dialog_publish_multi("terminated", dlginfo->pubruris_callee, &uri,
418 &(dlginfo->from_uri), &(dlginfo->callid), 0,
419 10, 0, 0, &target, &(dlginfo->from_contact),
420 send_publish_flag==-1?1:0);
421 }
422 }
423 }
424
425 /*
426 * Writes all avps with name avp_name to new str_list (shm mem)
427 * Be careful: returns NULL pointer if no avp present!
428 *
429 */
get_str_list(unsigned short avp_flags,int_str avp_name)430 struct str_list* get_str_list(unsigned short avp_flags, int_str avp_name) {
431
432 int_str avp_value;
433 unsigned int len;
434 struct str_list* list_first = 0;
435 struct str_list* list_current = 0 ;
436 struct search_state st;
437
438 if(!search_first_avp(avp_flags, avp_name, &avp_value, &st)) {
439 return NULL;
440 }
441
442 do {
443
444 LM_DBG("AVP found '%.*s'\n", avp_value.s.len, avp_value.s.s);
445
446 len = sizeof(struct str_list) + avp_value.s.len;
447
448 if(list_current) {
449 list_current->next = (struct str_list*) shm_malloc( len);
450 list_current=list_current->next;
451 } else {
452 list_current=list_first= (struct str_list*) shm_malloc( len);
453 }
454
455 if (list_current==0) {
456 SHM_MEM_ERROR;
457 return 0;
458 }
459
460 memset( list_current, 0, len);
461
462 list_current->s.s = (char*)list_current + sizeof(struct str_list);
463 list_current->s.len = avp_value.s.len;
464 memcpy(list_current->s.s,avp_value.s.s,avp_value.s.len);
465
466
467
468 } while(search_next_avp(&st, &avp_value));
469
470 return list_first;
471
472 }
473
get_dialog_data(struct dlg_cell * dlg,int type)474 struct dlginfo_cell* get_dialog_data(struct dlg_cell *dlg, int type)
475 {
476 struct dlginfo_cell *dlginfo;
477 int len;
478 str* s=NULL;
479
480 /* create dlginfo structure to store important data inside the module*/
481 len = sizeof(struct dlginfo_cell)
482 + dlg->from_uri.len
483 + dlg->to_uri.len
484 + dlg->callid.len
485 + dlg->tag[0].len
486 + dlg->req_uri.len
487 + dlg->contact[0].len;
488
489 dlginfo = (struct dlginfo_cell*)shm_malloc( len );
490 if (dlginfo==0) {
491 SHM_MEM_ERROR;
492 return NULL;
493 }
494 memset( dlginfo, 0, len);
495
496 /* copy from dlg structure to dlginfo structure */
497 dlginfo->lifetime = override_lifetime ? override_lifetime : dlg->lifetime;
498 dlginfo->from_uri.s = (char*)dlginfo + sizeof(struct dlginfo_cell);
499 dlginfo->from_uri.len = dlg->from_uri.len;
500 dlginfo->to_uri.s = dlginfo->from_uri.s + dlg->from_uri.len;
501 dlginfo->to_uri.len = dlg->to_uri.len;
502 dlginfo->callid.s = dlginfo->to_uri.s + dlg->to_uri.len;
503 dlginfo->callid.len = dlg->callid.len;
504 dlginfo->from_tag.s = dlginfo->callid.s + dlg->callid.len;
505 dlginfo->from_tag.len = dlg->tag[0].len;
506 dlginfo->req_uri.s = dlginfo->from_tag.s + dlginfo->from_tag.len;
507 dlginfo->req_uri.len = dlg->req_uri.len;
508 dlginfo->from_contact.s = dlginfo->req_uri.s + dlginfo->req_uri.len;
509 dlginfo->from_contact.len = dlg->contact[0].len;
510
511 memcpy(dlginfo->from_uri.s, dlg->from_uri.s, dlg->from_uri.len);
512 memcpy(dlginfo->to_uri.s, dlg->to_uri.s, dlg->to_uri.len);
513 memcpy(dlginfo->callid.s, dlg->callid.s, dlg->callid.len);
514 memcpy(dlginfo->from_tag.s, dlg->tag[0].s, dlg->tag[0].len);
515 memcpy(dlginfo->req_uri.s, dlg->req_uri.s, dlg->req_uri.len);
516 memcpy(dlginfo->from_contact.s, dlg->contact[0].s, dlg->contact[0].len);
517
518 if (use_pubruri_avps) {
519 if(type==DLGCB_CREATED) {
520 dlginfo->pubruris_caller = get_str_list(pubruri_caller_avp_type,
521 pubruri_caller_avp_name);
522 dlginfo->pubruris_callee = get_str_list(pubruri_callee_avp_type,
523 pubruri_callee_avp_name);
524
525 if(dlginfo->pubruris_callee!=NULL && callee_dlg_var.len>0)
526 dlg_api.set_dlg_var(dlg, &callee_dlg_var,
527 &dlginfo->pubruris_callee->s);
528
529 if(dlginfo->pubruris_caller!=NULL && caller_dlg_var.len>0)
530 dlg_api.set_dlg_var(dlg, &caller_dlg_var,
531 &dlginfo->pubruris_caller->s);
532
533 } else {
534 if(caller_dlg_var.len>0
535 && (s = dlg_api.get_dlg_var(dlg, &caller_dlg_var))!=0) {
536 dlginfo->pubruris_caller =
537 (struct str_list*)shm_malloc( sizeof(struct str_list) );
538 if (dlginfo->pubruris_caller==0) {
539 SHM_MEM_ERROR;
540 free_dlginfo_cell(dlginfo);
541 return NULL;
542 }
543 memset( dlginfo->pubruris_caller, 0, sizeof(struct str_list));
544 dlginfo->pubruris_caller->s=*s;
545 LM_DBG("Found pubruris_caller in dialog '%.*s'\n",
546 dlginfo->pubruris_caller->s.len, dlginfo->pubruris_caller->s.s);
547 }
548
549 if(callee_dlg_var.len>0
550 && (s = dlg_api.get_dlg_var(dlg, &callee_dlg_var))!=0) {
551 dlginfo->pubruris_callee =
552 (struct str_list*)shm_malloc( sizeof(struct str_list) );
553 if (dlginfo->pubruris_callee==0) {
554 SHM_MEM_ERROR;
555 free_dlginfo_cell(dlginfo);
556 return NULL;
557 }
558 memset( dlginfo->pubruris_callee, 0, sizeof(struct str_list));
559 dlginfo->pubruris_callee->s=*s;
560 LM_DBG("Found pubruris_callee in dialog '%.*s'\n",
561 dlginfo->pubruris_callee->s.len, dlginfo->pubruris_callee->s.s);
562 }
563 }
564
565 if(dlginfo->pubruris_caller == 0 && dlginfo->pubruris_callee == 0 ) {
566 /* No reason to save dlginfo, we have nobody to publish to */
567 LM_DBG("Neither pubruris_caller nor pubruris_callee found.\n");
568 free_dlginfo_cell(dlginfo);
569 return NULL;
570 }
571 } else {
572 dlginfo->pubruris_caller =
573 (struct str_list*)shm_malloc( sizeof(struct str_list) );
574 if (dlginfo->pubruris_caller==0) {
575 SHM_MEM_ERROR;
576 free_dlginfo_cell(dlginfo);
577 return NULL;
578 }
579 memset( dlginfo->pubruris_caller, 0, sizeof(struct str_list));
580 dlginfo->pubruris_caller->s=dlginfo->from_uri;
581
582 dlginfo->pubruris_callee =
583 (struct str_list*)shm_malloc( sizeof(struct str_list) );
584 if (dlginfo->pubruris_callee==0) {
585 SHM_MEM_ERROR;
586 free_dlginfo_cell(dlginfo);
587 return NULL;
588 }
589 memset( dlginfo->pubruris_callee, 0, sizeof(struct str_list));
590
591 if(include_req_uri) {
592 dlginfo->pubruris_callee->s = dlginfo->req_uri;
593 } else {
594 dlginfo->pubruris_callee->s = dlginfo->to_uri;
595 }
596 }
597
598 /* register dialog callbacks which triggers sending PUBLISH */
599 if (dlg_api.register_dlgcb(dlg,
600 DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_TERMINATED
601 | DLGCB_EXPIRED | DLGCB_REQ_WITHIN | DLGCB_EARLY,
602 __dialog_sendpublish, dlginfo, free_dlginfo_cell) != 0) {
603 LM_ERR("cannot register callback for interesting dialog types\n");
604 free_dlginfo_cell(dlginfo);
605 return NULL;
606 }
607
608 #ifdef PUA_DIALOGINFO_DEBUG
609 /* dialog callback testing (registered last to be executed frist) */
610 if (dlg_api.register_dlgcb(dlg,
611 DLGCB_FAILED| DLGCB_CONFIRMED_NA | DLGCB_CONFIRMED
612 | DLGCB_REQ_WITHIN | DLGCB_TERMINATED | DLGCB_EXPIRED
613 | DLGCB_EARLY | DLGCB_RESPONSE_FWDED | DLGCB_RESPONSE_WITHIN
614 | DLGCB_DESTROY,
615 __dialog_cbtest, NULL, NULL) != 0) {
616 LM_ERR("cannot register callback for all dialog types\n");
617 free_dlginfo_cell(dlginfo);
618 return NULL;
619 }
620 #endif
621
622 return(dlginfo);
623 }
624
625 static void
__dialog_created(struct dlg_cell * dlg,int type,struct dlg_cb_params * _params)626 __dialog_created(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
627 {
628 struct sip_msg *request = _params->req;
629 struct dlginfo_cell *dlginfo;
630
631 if (request==NULL || request->REQ_METHOD != METHOD_INVITE)
632 return;
633
634 if(send_publish_flag > -1 && !(request->flags & (1<<send_publish_flag)))
635 return;
636
637 LM_DBG("new INVITE dialog created: from=%.*s\n",
638 dlg->from_uri.len, dlg->from_uri.s);
639
640 dlginfo=get_dialog_data(dlg, type);
641 if(dlginfo==NULL)
642 return;
643
644 if (disable_caller_publish_flag == -1 || !(request && (request->flags
645 & (1<<disable_caller_publish_flag))))
646 {
647 dialog_publish_multi("Trying", dlginfo->pubruris_caller,
648 &(dlg->from_uri),
649 (include_req_uri)?&(dlg->req_uri):&(dlg->to_uri),
650 &(dlg->callid), 1, dlginfo->lifetime,
651 0, 0, 0, 0, (send_publish_flag==-1)?1:0);
652 }
653
654 if (callee_trying && (disable_callee_publish_flag == -1 || !(request
655 && (request->flags & (1<<disable_callee_publish_flag)))))
656 {
657 dialog_publish_multi("Trying", dlginfo->pubruris_callee,
658 (include_req_uri)?&(dlg->req_uri):&(dlg->to_uri),
659 &(dlg->from_uri),
660 &(dlg->callid), 0, dlginfo->lifetime,
661 0, 0, 0, 0, (send_publish_flag==-1)?1:0);
662 }
663 }
664
665 static void
__dialog_loaded(struct dlg_cell * dlg,int type,struct dlg_cb_params * _params)666 __dialog_loaded(struct dlg_cell *dlg, int type, struct dlg_cb_params *_params)
667 {
668 struct dlginfo_cell *dlginfo;
669
670 LM_DBG("INVITE dialog loaded: from=%.*s\n",
671 dlg->from_uri.len, dlg->from_uri.s);
672
673 dlginfo=get_dialog_data(dlg, type);
674 if(dlginfo!=NULL) {
675 LM_DBG("dialog info initialized (from=%.*s)\n",
676 dlg->from_uri.len, dlg->from_uri.s);
677 /* free_dlginfo_cell(dlginfo); */
678 }
679 }
680
681
682 /**
683 * init module function
684 */
mod_init(void)685 static int mod_init(void)
686 {
687 bind_pua_t bind_pua;
688
689 str s;
690 pv_spec_t avp_spec;
691
692 if(caller_dlg_var.len<=0) {
693 LM_WARN("pubruri_caller_dlg_var is not set"
694 " - restore on restart disabled\n");
695 }
696
697 if(callee_dlg_var.len<=0) {
698 LM_WARN("pubruri_callee_dlg_var is not set"
699 " - restore on restart disabled\n");
700 }
701
702 bind_pua= (bind_pua_t)find_export("bind_pua", 1,0);
703 if (!bind_pua)
704 {
705 LM_ERR("Can't bind pua\n");
706 return -1;
707 }
708
709 if (bind_pua(&pua) < 0)
710 {
711 LM_ERR("Can't bind pua\n");
712 return -1;
713 }
714 if(pua.send_publish == NULL)
715 {
716 LM_ERR("Could not import send_publish\n");
717 return -1;
718 }
719 pua_send_publish= pua.send_publish;
720
721 /* bind to the dialog API */
722 if (load_dlg_api(&dlg_api)!=0) {
723 LM_ERR("failed to find dialog API - is dialog module loaded?\n");
724 return -1;
725 }
726 /* register dialog creation callback */
727 if (dlg_api.register_dlgcb(NULL, DLGCB_CREATED, __dialog_created, NULL, NULL) != 0) {
728 LM_ERR("cannot register callback for dialog creation\n");
729 return -1;
730 }
731 /* register dialog loaded callback */
732 if (dlg_api.register_dlgcb(NULL, DLGCB_LOADED, __dialog_loaded, NULL, NULL) != 0) {
733 LM_ERR("cannot register callback for dialog loaded\n");
734 return -1;
735 }
736
737 if(use_pubruri_avps) {
738 LM_DBG("configured to use avps for uri values\n");
739 if((pubruri_caller_avp==NULL || *pubruri_caller_avp==0)
740 || (pubruri_callee_avp==NULL || *pubruri_callee_avp==0)) {
741 LM_ERR("pubruri_caller_avp and pubruri_callee_avp must be set,"
742 " if use_pubruri_avps is enabled\n");
743 return -1;
744 }
745
746 s.s = pubruri_caller_avp; s.len = strlen(s.s);
747 if (pv_parse_spec(&s, &avp_spec)==0 || avp_spec.type!=PVT_AVP) {
748 LM_ERR("malformed or non AVP %s AVP definition\n", pubruri_caller_avp);
749 return -1;
750 }
751 if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_caller_avp_name,
752 &pubruri_caller_avp_type)!=0) {
753 LM_ERR("[%s]- invalid AVP definition\n", pubruri_caller_avp);
754 return -1;
755 }
756
757 s.s = pubruri_callee_avp; s.len = strlen(s.s);
758 if (pv_parse_spec(&s, &avp_spec)==0 || avp_spec.type!=PVT_AVP) {
759 LM_ERR("malformed or non AVP %s AVP definition\n", pubruri_callee_avp);
760 return -1;
761 }
762 if(pv_get_avp_name(0, &avp_spec.pvp, &pubruri_callee_avp_name,
763 &pubruri_callee_avp_type)!=0) {
764 LM_ERR("[%s]- invalid AVP definition\n", pubruri_callee_avp);
765 return -1;
766 }
767 } else {
768 LM_DBG("configured to use headers for uri values\n");
769 }
770
771 return 0;
772 }
773
free_dlginfo_cell(void * param)774 void free_dlginfo_cell(void *param) {
775
776 struct dlginfo_cell *cell = NULL;
777
778 if(param==NULL)
779 return;
780
781 cell = param;
782 free_str_list_all(cell->pubruris_caller);
783 free_str_list_all(cell->pubruris_callee);
784
785 /*if (cell->to_tag) {
786 shm_free(cell->to_tag);
787 }*/
788 shm_free(param);
789 }
790
791
free_str_list_all(struct str_list * del_current)792 void free_str_list_all(struct str_list * del_current) {
793
794 struct str_list* del_next;
795
796 while(del_current) {
797
798 del_next = del_current->next;
799 shm_free(del_current);
800
801 del_current=del_next;
802 }
803
804 }
805