1 /*!
2 * \file
3 * \brief Functions related to dialog handling
4 * \ingroup dialog
5 * Module: \ref dialog
6 */
7
8 #include <string.h>
9 #include <time.h>
10
11 #include "../../core/trim.h"
12 #include "../../core/pvar.h"
13 #include "../../core/timer.h"
14 #include "../../core/counters.h"
15 #include "../../core/action.h"
16 #include "../../core/script_cb.h"
17 #include "../../core/fmsg.h"
18 #include "../../core/parser/parse_from.h"
19 #include "../../core/parser/parse_cseq.h"
20 #include "../../core/parser/contact/parse_contact.h"
21 #include "../../core/parser/parse_from.h"
22 #include "../../core/parser/parse_rr.h"
23 #include "../../modules/tm/tm_load.h"
24 #include "../../modules/rr/api.h"
25 #include "dlg_hash.h"
26 #include "dlg_timer.h"
27 #include "dlg_cb.h"
28 #include "dlg_handlers.h"
29 #include "dlg_req_within.h"
30 #include "dlg_profile.h"
31 #include "dlg_var.h"
32 #include "dlg_db_handler.h"
33 #include "dlg_ng_stats.h"
34
35 static str rr_param; /*!< record-route parameter for matching */
36 static int dlg_flag; /*!< flag for dialog tracking */
37 static pv_spec_t *timeout_avp; /*!< AVP for timeout setting */
38 static int default_timeout; /*!< default dialog timeout */
39 static int seq_match_mode; /*!< dlg_match mode */
40 static int shutdown_done = 0; /*!< 1 when destroy_dlg_handlers was called */
41 extern int detect_spirals;
42 int spiral_detected = -1;
43
44 extern struct rr_binds d_rrb; /*!< binding to record-routing module */
45 extern struct tm_binds d_tmb;
46 extern struct dialog_ng_counters_h dialog_ng_cnts_h;
47 time_t act_time;
48
49 extern pv_elem_t *ruri_param_model; /*!< pv-string to get r-uri */
50
51 static unsigned int CURR_DLG_LIFETIME = 0; /*!< current dialog lifetime */
52 static unsigned int CURR_DLG_STATUS = 0; /*!< current dialog state */
53 static unsigned int CURR_DLG_ID = 0xffffffff; /*!< current dialog id */
54
55
56 /*! size of the dialog record-route parameter */
57 #define RR_DLG_PARAM_SIZE (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
58 /*! separator inside the record-route paramter */
59 #define DLG_SEPARATOR '.'
60
61 /*!
62 * \brief Initialize the dialog handlers
63 * \param rr_param_p added record-route parameter
64 * \param dlg_flag_p dialog flag
65 * \param timeout_avp_p AVP for timeout setting
66 * \param default_timeout_p default timeout
67 * \param seq_match_mode_p matching mode
68 */
init_dlg_handlers(char * rr_param_p,int dlg_flag_p,pv_spec_t * timeout_avp_p,int default_timeout_p,int seq_match_mode_p)69 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p, pv_spec_t *timeout_avp_p, int default_timeout_p, int seq_match_mode_p) {
70 rr_param.s = rr_param_p;
71 rr_param.len = strlen(rr_param.s);
72
73 dlg_flag = 1 << dlg_flag_p;
74
75 timeout_avp = timeout_avp_p;
76 default_timeout = default_timeout_p;
77 seq_match_mode = seq_match_mode_p;
78 }
79
80 /*!
81 * \brief Shutdown operation of the module
82 */
destroy_dlg_handlers(void)83 void destroy_dlg_handlers(void) {
84 shutdown_done = 1;
85 }
86
87 /*!
88 * \brief Add record-route parameter for dialog tracking
89 * \param req SIP request
90 * \param entry dialog hash entry
91 * \param id dialog hash id
92 * \return 0 on success, -1 on failure
93 */
add_dlg_rr_param(struct sip_msg * req,unsigned int entry,unsigned int id)94 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry, unsigned int id) {
95 static char buf[RR_DLG_PARAM_SIZE];
96 str s;
97 int n;
98 char *p;
99
100 s.s = p = buf;
101
102 *(p++) = ';';
103 memcpy(p, rr_param.s, rr_param.len);
104 p += rr_param.len;
105 *(p++) = '=';
106
107 n = RR_DLG_PARAM_SIZE - (p - buf);
108 if (int2reverse_hex(&p, &n, entry) == -1)
109 return -1;
110
111 *(p++) = DLG_SEPARATOR;
112
113 n = RR_DLG_PARAM_SIZE - (p - buf);
114 if (int2reverse_hex(&p, &n, id) == -1)
115 return -1;
116
117 s.len = p - buf;
118
119 if (d_rrb.add_rr_param(req, &s) < 0) {
120 LM_ERR("failed to add rr param\n");
121 return -1;
122 }
123
124 return 0;
125 }
126
127 /*!
128 * \brief Unreference a dialog from tm callback (another wrapper)
129 * \param t transaction, unused
130 * \param type type of the entered callback
131 * \param param saved dialog structure in the callback
132 */
unref_dlg_from_cb(struct cell * t,int type,struct tmcb_params * param)133 static void unref_dlg_from_cb(struct cell* t, int type, struct tmcb_params *param) {
134 dlg_cell_t *dlg = NULL;
135 dlg_iuid_t *iuid = NULL;
136
137 LM_DBG("Unref dlg from callback called\n");
138 iuid = (dlg_iuid_t*) (*param->param);
139 if (iuid == NULL)
140 return;
141
142 dlg = dlg_get_by_iuid(iuid);
143 if (dlg == NULL)
144 return;
145 /* unref by 2: 1 set when adding in tm cb, 1 sent by dlg_get_by_iuid() */
146 unref_dlg(dlg, 2);
147 }
148
149 /*!
150 * \brief Parse SIP message and populate leg informations
151 *
152 * Parse SIP message and populate leg informations.
153 * \param dlg the dialog to add cseq, contact & record_route
154 * \param msg sip message
155 * \param t transaction
156 * \param leg type of the call leg
157 * \param tag SIP To tag
158 * \return 0 on success, -1 on failure
159 * \note for a request: get record route in normal order, for a reply get
160 * in reverse order, skipping the ones from the request and the proxies' own
161 */
populate_leg_info(struct dlg_cell * dlg,struct sip_msg * msg,struct cell * t,unsigned int leg,str * tag)162 int populate_leg_info(struct dlg_cell *dlg, struct sip_msg *msg,
163 struct cell* t, unsigned int leg, str *tag) {
164 unsigned int skip_recs;
165 str cseq;
166 str contact;
167 str rr_set;
168 struct socket_info* callee_bind_address = NULL;
169
170 if (leg == DLG_CALLER_LEG)
171 dlg->caller_bind_addr = msg->rcv.bind_address;
172 else
173 callee_bind_address = msg->rcv.bind_address;
174
175
176
177 /* extract the cseq number as string from the request or response*/
178 //TO DO - can pair the cseqs here to make sure that the response and request are in sync
179
180 if ((!msg->cseq && (parse_headers(msg, HDR_CSEQ_F, 0) < 0 || !msg->cseq))
181 || !msg->cseq->parsed) {
182 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
183 goto error0;
184 }
185 cseq = (get_cseq(msg))->number;
186
187
188 /* extract the contact address */
189 if (!msg->contact && (parse_headers(msg, HDR_CONTACT_F, 0) < 0 || !msg->contact)) {
190 if (msg->first_line.type == SIP_REQUEST)
191 LM_ERR("bad sip message or missing Contact hdr for message [%.*s]\n", msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
192 else
193 LM_ERR("bad sip message or missing Contact hdr for message [%.*s]\n", msg->first_line.u.reply.status.len, msg->first_line.u.reply.status.s);
194 goto error0;
195 }
196 if (parse_contact(msg->contact) < 0 ||
197 ((contact_body_t *) msg->contact->parsed)->contacts == NULL ||
198 ((contact_body_t *) msg->contact->parsed)->contacts->next != NULL) {
199 LM_ERR("bad Contact HDR\n");
200 goto error0;
201 }
202 contact = ((contact_body_t *) msg->contact->parsed)->contacts->uri;
203
204 /* extract the RR parts */
205 if (!msg->record_route && (parse_headers(msg, HDR_EOH_F, 0) < 0)) {
206 LM_ERR("failed to parse record route header\n");
207 goto error0;
208 }
209
210 if (leg == DLG_CALLER_LEG) {
211 skip_recs = 0;
212 } else {
213 skip_recs = 0;
214 /* was the 200 OK received or local generated */
215 skip_recs = dlg->from_rr_nb +
216 ((t->relayed_reply_branch >= 0) ?
217 ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_R2) ? 2 :
218 ((t->uac[t->relayed_reply_branch].flags & TM_UAC_FLAG_RR) ? 1 : 0))
219 : 0);
220 }
221
222 if (msg->record_route) {
223 if (print_rr_body(msg->record_route, &rr_set, leg,
224 &skip_recs) != 0) {
225 LM_ERR("failed to print route records \n");
226 goto error0;
227 }
228 } else {
229 rr_set.s = 0;
230 rr_set.len = 0;
231 }
232
233 if (leg == DLG_CALLER_LEG)
234 dlg->from_rr_nb = skip_recs;
235
236 LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s [%p]\n",
237 rr_set.len, rr_set.s, contact.len, contact.s,
238 cseq.len, cseq.s,
239 msg->rcv.bind_address->sock_str.len,
240 msg->rcv.bind_address->sock_str.s, msg->rcv.bind_address);
241
242 if (dlg_set_leg_info(dlg, tag, &rr_set, &contact, &cseq, callee_bind_address, leg) != 0) {
243 LM_ERR("dlg_set_leg_info failed\n");
244 if (rr_set.s) pkg_free(rr_set.s);
245 goto error0;
246 }
247
248 if (rr_set.s) pkg_free(rr_set.s);
249
250 return 0;
251 error0:
252 return -1;
253 }
254
255 /*!
256 * \brief Clone dialog internal unique id to shared memory
257 * \param dlg dialog
258 */
dlg_get_iuid_shm_clone(dlg_cell_t * dlg)259 dlg_iuid_t *dlg_get_iuid_shm_clone(dlg_cell_t *dlg) {
260 dlg_iuid_t *iuid = NULL;
261
262 if (dlg == NULL)
263 return NULL;
264
265 iuid = (dlg_iuid_t*) shm_malloc(sizeof (dlg_iuid_t));
266 if (iuid == NULL) {
267 LM_ERR("failed to clone dialog iuid\n");
268 return NULL;
269 }
270
271 memset(iuid, 0, sizeof (dlg_iuid_t));
272 iuid->h_entry = dlg->h_entry;
273 iuid->h_id = dlg->h_id;
274
275 return iuid;
276 }
277
278 /*!
279 * \brief Free dialog internal unique id stored in shared memory
280 * \param iuid dialog iuid
281 */
dlg_iuid_sfree(void * iuid)282 void dlg_iuid_sfree(void *iuid) {
283 if (iuid) {
284 LM_DBG("freeing dlg iuid [%u:%u] (%p)\n",
285 ((dlg_iuid_t*) iuid)->h_entry,
286 ((dlg_iuid_t*) iuid)->h_id, iuid);
287 shm_free(iuid);
288 }
289 }
290
291 ///*!
292 // * \brief Function that executes BYE reply callbacks
293 // * \param t transaction, unused
294 // * \param type type of the callback, should be TMCB_RESPONSE_FWDED
295 // * \param param saved dialog structure inside the callback
296 // */
297 //static void dlg_terminated_confirmed(struct cell* t,
298 // int type,
299 // struct tmcb_params* params) {
300 // if (!params || !params->req || !params->param) {
301 // LM_ERR("invalid parameters!\n");
302 // return;
303 // }
304 //
305 // struct dlg_cell* dlg = (struct dlg_cell*) *params->param;
306 //
307 // if (!dlg) {
308 // LM_ERR("failed to get dialog from params!\n");
309 // return;
310 // }
311 // /* dialog termination confirmed (BYE reply) */
312 // run_dlg_callbacks(DLGCB_TERMINATED_CONFIRMED,
313 // dlg,
314 // params->req,
315 // params->rpl,
316 // DLG_DIR_UPSTREAM,
317 // 0);
318 //}
319
dlg_cancel_confirmed(struct cell * t,int type,struct tmcb_params * params)320 static void dlg_cancel_confirmed(struct cell* t,
321 int type,
322 struct tmcb_params* params) {
323 if (!params || !params->req || !params->param) {
324 LM_ERR("invalid parameters!\n");
325 return;
326 }
327
328 struct dlg_cell* dlg = (struct dlg_cell*) *params->param;
329
330 if (!dlg) {
331 LM_ERR("failed to get dialog from params!\n");
332 return;
333 }
334 /* dialog termination confirmed (BYE reply) */
335 run_dlg_callbacks(DLGCB_TERMINATED_CONFIRMED,
336 dlg,
337 params->req,
338 params->rpl,
339 DLG_DIR_UPSTREAM,
340 0);
341 }
342
343 /*!
344 * \brief Execute callback for the BYE request and register callback for the BYE reply
345 * \param req request message
346 * \param dlg corresponding dialog
347 * \param dir message direction
348 */
dlg_terminated(struct sip_msg * req,struct dlg_cell * dlg,unsigned int dir)349 static void dlg_terminated(struct sip_msg* req,
350 struct dlg_cell* dlg,
351 unsigned int dir) {
352 if (!req) {
353 LM_ERR("request is empty!");
354 return;
355 }
356
357 if (!dlg) {
358 LM_ERR("dialog is empty!");
359 return;
360 }
361
362 /* dialog terminated (BYE) */
363 run_dlg_callbacks(DLGCB_TERMINATED, dlg, req, NULL, dir, 0);
364
365 // /* register callback for the coresponding reply */
366 // LM_DBG("Registering tmcb1\n");
367 // if (d_tmb.register_tmcb(req,
368 // 0,
369 // TMCB_RESPONSE_OUT,
370 // dlg_terminated_confirmed,
371 // (void*) dlg,
372 // 0) <= 0) {
373 // LM_ERR("cannot register response callback for BYE request\n");
374 // return;
375 // }
376 }
377
378 /*!
379 * \brief Execute callback for the BYE request and register callback for the BYE reply
380 * \param req request message
381 * \param dlg corresponding dialog
382 * \param dir message direction
383 */
dlg_cancelled(struct sip_msg * req,struct dlg_cell * dlg,unsigned int dir)384 static void dlg_cancelled(struct sip_msg* req,
385 struct dlg_cell* dlg,
386 unsigned int dir) {
387 if (!req) {
388 LM_ERR("request is empty!");
389 return;
390 }
391
392 if (!dlg) {
393 LM_ERR("dialog is empty!");
394 return;
395 }
396
397 /* dialog terminated (BYE) */
398 run_dlg_callbacks(DLGCB_TERMINATED, dlg, req, NULL, dir, 0);
399
400 /* register callback for the coresponding reply */
401 LM_DBG("Registering tmcb for CANCEL confirmed\n");
402 if (d_tmb.register_tmcb(req,
403 0,
404 TMCB_RESPONSE_OUT,
405 dlg_cancel_confirmed,
406 (void*) dlg,
407 0) <= 0) {
408 LM_ERR("cannot register response callback for CANCEL request\n");
409 return;
410 }
411 }
412
413 //static void unlink_dlgouts_from_cb(struct cell* t, int type, struct tmcb_params *param) {
414 // struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
415 //
416 // if (!dlg)
417 // return;
418
419 // if (t && t->fwded_totags && t->fwded_totags->tag.len > 0) {
420 // LM_DBG("unlink_dlgouts_from_cb: transaction [%.*s] can now be removed IFF it has been marked for deletion\n", t->fwded_totags->tag.len, t->fwded_totags->tag.s);
421 // dlg_remove_dlg_out_tag(dlg, &t->fwded_totags->tag);
422 // }
423 //}
424
425 /*static void dlg_oncancel(struct cell* t, int type, struct tmcb_params *param) {
426 struct dlg_cell* dlg;
427 int unref = 0, old_state, new_state;
428
429 LM_DBG("RECEIVED CANCEL ON DIALOG......\n");
430 dlg = (struct dlg_cell *) (*param->param);
431 if (shutdown_done || dlg == 0)
432 return;
433
434 struct sip_msg *req = param->req;
435 old_state = dlg->state;
436 LM_DBG("DLG dialog id is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);
437 next_state_dlg(dlg, DLG_EVENT_REQCANCEL, &old_state, &new_state, &unref, 0);
438
439 if (old_state != DLG_STATE_DELETED && new_state == DLG_STATE_DELETED)
440 dlg_cancelled(req, dlg, DLG_DIR_NONE);
441
442 unref_dlg(dlg, unref);
443 }*/
444
445 /*!
446 * \brief Helper function that run dialog callbacks on forwarded requests
447 * \see dlg_seq_up_onreply
448 * \see dlg_seq_down_onreply
449 * \param t transaction, unused
450 * \param type type of the callback, should be TMCB_RESPONSE_FWDED
451 * \param param saved dialog structure inside the callback
452 * \param direction direction of the request
453 */
dlg_seq_onreply_helper(struct cell * t,int type,struct tmcb_params * param,const int direction)454 static void dlg_seq_onreply_helper(struct cell* t, int type,
455 struct tmcb_params *param, const int direction) {
456 dlg_cell_t *dlg = NULL;
457 dlg_iuid_t *iuid = NULL;
458
459 if (shutdown_done)
460 return;
461 iuid = (dlg_iuid_t*) (*param->param);
462 dlg = dlg_get_by_iuid(iuid);
463 if (dlg == 0)
464 return;
465
466 if (type == TMCB_RESPONSE_FWDED) {
467 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN,
468 dlg,
469 param->req,
470 param->rpl,
471 direction,
472 0);
473 }
474 dlg_release(dlg);
475
476 return;
477 }
478
479 /*!
480 * \brief Run dialog callbacks on forwarded requests in upstream direction
481 * \see dlg_seq_onreply_helper
482 * \param t transaction, unused
483 * \param type type of the callback, should be TMCB_RESPONSE_FWDED
484 * \param param saved dialog structure inside the callback
485 */
dlg_seq_up_onreply(struct cell * t,int type,struct tmcb_params * param)486 static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param) {
487 return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
488 }
489
490 /*!
491 * \brief Run dialog callbacks on forwarded requests in downstream direction
492 * \see dlg_seq_onreply_helper
493 * \param t transaction, unused
494 * \param type type of the callback, should be TMCB_RESPONSE_FWDED
495 * \param param saved dialog structure inside the callback
496 */
dlg_seq_down_onreply(struct cell * t,int type,struct tmcb_params * param)497 static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param) {
498 return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
499 }
500
501 /*!
502 * \brief Return the timeout for a dialog
503 * \param req SIP message
504 * \return value from timeout AVP if present or default timeout
505 */
get_dlg_timeout(struct sip_msg * req)506 inline static int get_dlg_timeout(struct sip_msg *req) {
507 pv_value_t pv_val;
508
509 if (timeout_avp) {
510 if (pv_get_spec_value(req, timeout_avp, &pv_val) == 0 &&
511 pv_val.flags & PV_VAL_INT && pv_val.ri > 0) {
512 return pv_val.ri;
513 }
514 LM_DBG("invalid AVP value, using default timeout\n");
515 }
516 return default_timeout;
517 }
518
519 /*!
520 * \brief Helper function to get the necessary content from SIP message
521 * \param req SIP request
522 * \param callid found callid
523 * \param ftag found from tag
524 * \param ttag found to tag
525 * \param with_ttag flag set if to tag must be found for success
526 * \return 0 on success, -1 on failure
527 */
pre_match_parse(struct sip_msg * req,str * callid,str * ftag,str * ttag,int with_ttag)528 static inline int pre_match_parse(struct sip_msg *req, str *callid,
529 str *ftag, str *ttag, int with_ttag) {
530 if (parse_headers(req, HDR_CALLID_F | HDR_TO_F, 0) < 0 || !req->callid ||
531 !req->to) {
532 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
533 return -1;
534 }
535
536 if (get_to(req)->tag_value.len == 0) {
537 if (with_ttag == 1) {
538 /* out of dialog request with preloaded Route headers; ignore. */
539 return -1;
540 } else {
541 ttag->s = NULL;
542 ttag->len = 0;
543 }
544 } else {
545 *ttag = get_to(req)->tag_value;
546 }
547
548 if (parse_from_header(req) < 0 || get_from(req)->tag_value.len == 0) {
549 LM_ERR("failed to get From header\n");
550 return -1;
551 }
552
553 /* callid */
554 *callid = req->callid->body;
555 trim(callid);
556 /* from tag */
557 *ftag = get_from(req)->tag_value;
558 return 0;
559 }
560
tm_type_to_string(int type)561 static inline char* tm_type_to_string(int type) {
562 switch (type) {
563 case TMCB_REQUEST_IN:
564 return "TMCB_REQUEST_IN";
565 case TMCB_RESPONSE_IN:
566 return "TMCB_RESPONSE_IN";
567 case TMCB_E2EACK_IN:
568 return "TMCB_E2EACK_IN";
569 case TMCB_REQUEST_PENDING:
570 return "TMCB_REQUEST_PENDING";
571 case TMCB_REQUEST_FWDED:
572 return "TMCB_REQUEST_FWDED";
573 case TMCB_RESPONSE_FWDED:
574 return "TMCB_RESPONSE_FWDED";
575 case TMCB_ON_FAILURE_RO:
576 return "TMCB_ON_FAILURE_RO";
577 case TMCB_ON_FAILURE:
578 return "TMCB_ON_FAILURE";
579 case TMCB_REQUEST_OUT:
580 return "TMCB_REQUEST_OUT";
581 case TMCB_RESPONSE_OUT:
582 return "TMCB_RESPONSE_OUT";
583 case TMCB_LOCAL_COMPLETED:
584 return "TMCB_LOCAL_COMPLETED";
585 case TMCB_LOCAL_RESPONSE_OUT:
586 return "TMCB_LOCAL_RESPONSE_OUT";
587 case TMCB_ACK_NEG_IN:
588 return "TMCB_ACK_NEG_IN";
589 case TMCB_REQ_RETR_IN:
590 return "TMCB_REQ_RETR_IN";
591 case TMCB_LOCAL_RESPONSE_IN:
592 return "TMCB_LOCAL_RESPONSE_IN";
593 case TMCB_LOCAL_REQUEST_IN:
594 return "TMCB_LOCAL_REQUEST_IN";
595 case TMCB_DLG:
596 return "TMCB_DLG";
597 case TMCB_DESTROY:
598 return "TMCB_DESTROY";
599 case TMCB_E2ECANCEL_IN:
600 return "TMCB_E2ECANCEL_IN";
601 case TMCB_E2EACK_RETR_IN:
602 return "TMCB_E2EACK_RETR_IN";
603 case TMCB_RESPONSE_READY:
604 return "TMCB_RESPONSE_READY";
605 case TMCB_DONT_ACK:
606 return "TMCB_DONT_ACK";
607 case TMCB_REQUEST_SENT:
608 return "TMCB_REQUEST_SENT";
609 case TMCB_RESPONSE_SENT:
610 return "TMCB_RESPONSE_SENT";
611 case TMCB_ON_BRANCH_FAILURE:
612 return "TMCB_ON_BRANCH_FAILURE";
613 case TMCB_ON_BRANCH_FAILURE_RO:
614 return "TMCB_ON_BRANCH_FAILURE_RO";
615 case TMCB_MAX:
616 return "TMCB_MAX";
617 }
618
619 return "UNKNOWN";
620 }
621
622 /*
623 * \brief Unreference a dialog (small wrapper to take care of shutdown)
624 * \see unref_dlg
625 * \param dialog unreferenced dialog
626 */
627
628 /*static void unreference_dialog(void *dialog) {
629 // if the dialog table is gone, it means the system is shutting down.
630 if (!dialog || !d_table)
631 return;
632 unref_dlg((struct dlg_cell*) dialog, 1);
633 }*/
634
635 /*!
636 * \brief Parse the record-route parameter, to get dialog information back
637 * \param p start of parameter string
638 * \param end end of parameter string
639 * \param h_entry found dialog hash entry
640 * \param h_id found dialog hash id
641 * \return 0 on success, -1 on failure
642 */
parse_dlg_rr_param(char * p,char * end,int * h_entry,int * h_id)643 static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id) {
644 char *s;
645
646 for (s = p; p < end && *p != DLG_SEPARATOR; p++);
647 if (*p != DLG_SEPARATOR) {
648 LM_ERR("malformed rr param '%.*s'\n", (int) (long) (end - s), s);
649 return -1;
650 }
651
652 if (reverse_hex2int(s, p - s, (unsigned int*) h_entry) < 0) {
653 LM_ERR("invalid hash entry '%.*s'\n", (int) (long) (p - s), s);
654 return -1;
655 }
656
657 if (reverse_hex2int(p + 1, end - (p + 1), (unsigned int*) h_id) < 0) {
658 LM_ERR("invalid hash id '%.*s'\n", (int) (long) (end - (p + 1)), p + 1);
659 return -1;
660 }
661
662 return 0;
663 }
664
665 /*!
666 * \brief Register a transaction on a dialog
667 * \param t transaction
668 * \param type type of the entered callback
669 * \param param saved dialog structure in the callback
670 */
671 /*static int store_dlg_in_tm(struct sip_msg* msg,
672 struct cell* t,
673 struct dlg_cell *dlg) {
674 if (!msg || msg == FAKED_REPLY || !t || !dlg) {
675 LM_ERR("invalid parameter msg(%p), t(%p), dlg(%p)\n", msg, t, dlg);
676 return -1;
677 }
678
679 if (get_dialog_from_tm(t)) {
680 LM_NOTICE("dialog %p is already set for this transaction!\n", dlg);
681 return 1;
682 }
683
684 // facilitate referencing of dialog through TMCB_MAX
685 if (d_tmb.register_tmcb(msg,
686 t,
687 TMCB_MAX,
688 dlg_tmcb_dummy,
689 (void*) dlg, unreference_dialog) < 0) {
690 LM_ERR("failed cache in T the shortcut to dlg %p\n", dlg);
691 return -3;
692 }
693
694 // registering succeeded, we must increase the reference counter
695 ref_dlg(dlg, 1);
696
697 return 0;
698 }*/
699
700 /*
701 * \brief Callback to register a transaction on a dialog
702 * \param t transaction, unused
703 * \param type type of the entered callback
704 * \param param saved dialog structure in the callback
705 */
706
707 /*static void store_dlg_in_tm_cb(struct cell* t,
708 int type,
709 struct tmcb_params *param) {
710 struct dlg_cell *dlg = (struct dlg_cell *) (*param->param);
711
712 struct sip_msg* msg = param->rpl;
713 if (msg == NULL || msg == FAKED_REPLY) {
714 msg = param->req;
715 }
716
717 store_dlg_in_tm(msg, t, dlg);
718 }*/
719
720 /*!
721 * \brief Update the saved CSEQ information in dialog from SIP message
722 * \param dlg updated dialog
723 * \param req SIP request
724 * \param dir direction of request, must DLG_DIR_UPSTREAM or DLG_DIR_DOWNSTREAM
725 * \param to_tag dialog to tag
726 * \return 0 on success, -1 on failure
727 */
update_cseqs(struct dlg_cell * dlg,struct sip_msg * req,unsigned int dir,str * to_tag)728 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
729 unsigned int dir, str *to_tag) {
730 if ((!req->cseq && parse_headers(req, HDR_CSEQ_F, 0) < 0) || !req->cseq ||
731 !req->cseq->parsed) {
732 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
733 return -1;
734 }
735
736 if (dir == DLG_DIR_UPSTREAM) {
737 return dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(req))->number), to_tag);
738 } else if (dir == DLG_DIR_DOWNSTREAM) {
739 return dlg_update_cseq(dlg, DLG_CALLER_LEG, &((get_cseq(req))->number), to_tag);
740 } else {
741 LM_CRIT("dir is not set!\n");
742 return -1;
743 }
744 }
745
746 /*!
747 * \brief Function that is registered as TM callback and called on requests
748 * \see dlg_new_dialog
749 * \param t transaction, used to created the dialog
750 * \param type type of the entered callback
751 * \param param saved dialog structure in the callback
752 */
dlg_onreq(struct cell * t,int type,struct tmcb_params * param)753 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param) {
754 sip_msg_t *req = param->req;
755 dlg_cell_t *dlg = NULL;
756
757 if (req->first_line.u.request.method_value == METHOD_BYE) {
758 _dlg_ctx.t = 1;
759 return;
760 }
761
762 if (req->first_line.u.request.method_value != METHOD_INVITE/* && req->first_line.u.request.method_value != METHOD_CANCEL*/) {
763 return;
764 }
765
766 dlg = dlg_get_ctx_dialog();
767
768 if (dlg != NULL) {
769 if (spiral_detected == 1) {
770 LM_DBG("Running DLGB_SPIRALED callback\n");
771 run_dlg_callbacks(DLGCB_SPIRALED, dlg,
772 req, NULL, DLG_DIR_DOWNSTREAM, 0);
773 LM_DBG("This is a spiraled REQUEST\n");
774 } else if (spiral_detected == 0)
775 run_create_callbacks(dlg, req);
776 }
777 if (dlg == NULL) {
778 if ((req->flags & dlg_flag) != dlg_flag)
779 return;
780 LM_DBG("dialog creation on config flag\n");
781 dlg_new_dialog(req, t, 1);
782 dlg = dlg_get_ctx_dialog();
783 }
784 if (dlg != NULL) {
785 if (dlg_set_tm_callbacks(t, req, dlg, spiral_detected) !=0) {
786 LM_ERR("Failed to register TM Callbacks for dialog... this is bad!\n");
787 //the DLG_TM flag will not be set so at least we can clear the dialog later...
788 } else {
789 LM_DBG("dialog [%p] added to tm callbacks\n", dlg);
790 }
791 _dlg_ctx.t = 1;
792 dlg_release(dlg);
793 } else {
794 LM_ERR("Failed to create dialog.... this is bad\n");
795 }
796 }
797
798 /*!
799 * \brief Function that is registered as RR callback for dialog tracking
800 *
801 * Function that is registered as RR callback for dialog tracking. It
802 * sets the appropriate events after the SIP method and run the state
803 * machine to update the dialog state. It updates then the saved
804 * dialogs and also the statistics.
805 * \param req SIP request
806 * \param route_params record-route parameter
807 * \param param unused
808 */
dlg_onroute(struct sip_msg * req,str * route_params,void * param)809 void dlg_onroute(struct sip_msg* req, str *route_params, void *param) {
810 dlg_cell_t *dlg;
811 dlg_iuid_t *iuid;
812 str val, callid, ftag, ttag;
813 int h_entry, h_id, new_state, old_state, unref, event, timeout;
814 unsigned int dir;
815 int ret = 0;
816 int reset = 1;
817
818 dlg = dlg_get_ctx_dialog();
819 if (dlg != NULL) {
820 dlg_release(dlg);
821 return;
822 }
823
824 /* skip initial requests - they may end up here because of the
825 * preloaded route */
826 if ((!req->to && parse_headers(req, HDR_TO_F, 0) < 0) || !req->to) {
827 LM_ERR("bad request or missing TO hdr :-/\n");
828 return;
829 }
830 if (get_to(req)->tag_value.len == 0) {
831 LM_DBG("No to tag header found --- ignoring... MESSAGE [%.*s\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
832 return;
833 }
834
835 dlg = 0;
836 dir = DLG_DIR_NONE;
837
838 if (seq_match_mode != SEQ_MATCH_NO_ID) {
839 if (d_rrb.get_route_param(req, &rr_param, &val) != 0) {
840 LM_DBG("Route param '%.*s' not found\n", rr_param.len, rr_param.s);
841 if (seq_match_mode == SEQ_MATCH_STRICT_ID)
842 return;
843 } else {
844 LM_DBG("route param is '%.*s' (len=%d)\n", val.len, val.s, val.len);
845
846 if (parse_dlg_rr_param(val.s, val.s + val.len, &h_entry, &h_id) < 0)
847 return;
848
849 dlg = lookup_dlg(h_entry, h_id);
850 if (dlg == 0) {
851 LM_WARN("unable to find dialog for %.*s "
852 "with route param '%.*s' [%u:%u]\n",
853 req->first_line.u.request.method.len,
854 req->first_line.u.request.method.s,
855 val.len, val.s, h_entry, h_id);
856 if (seq_match_mode == SEQ_MATCH_STRICT_ID)
857 return;
858 } else {
859 if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0) {
860 // lookup_dlg has incremented the ref count by 1
861 unref_dlg(dlg, 1);
862 return;
863 }
864 if (match_dialog(dlg, &callid, &ftag, &ttag, &dir) == 0) {
865 LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
866 "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
867 req->first_line.u.request.method.len,
868 req->first_line.u.request.method.s,
869 callid.len, callid.s, callid.len,
870 ftag.len, ftag.s, ftag.len,
871 ttag.len, ttag.s, ttag.len, dir);
872 LM_WARN("dialog identification elements are callid='%.*s'/%d, "
873 "caller tag='%.*s'/%d\n",
874 dlg->callid.len, dlg->callid.s, dlg->callid.len,
875 dlg->from_tag.len, dlg->from_tag.s,
876 dlg->from_tag.len);
877 // lookup_dlg has incremented the ref count by 1
878 dlg_release(dlg);
879
880 // Reset variables in order to do a lookup based on SIP-Elements.
881 dlg = 0;
882 dir = DLG_DIR_NONE;
883
884 if (seq_match_mode == SEQ_MATCH_STRICT_ID)
885 return;
886 }
887 }
888 }
889 }
890
891 if (dlg == 0) {
892 if (pre_match_parse(req, &callid, &ftag, &ttag, 1) < 0)
893 return;
894 /* TODO - try to use the RR dir detection to speed up here the
895 * search -bogdan */
896 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
897 if (!dlg) {
898 LM_DBG("Callid '%.*s' not found\n",
899 req->callid->body.len, req->callid->body.s);
900 return;
901 }
902 }
903
904 /* set current dialog - re-use ref increment from dlg_get() above */
905 set_current_dialog(req, dlg);
906 _dlg_ctx.iuid.h_entry = dlg->h_entry;
907 _dlg_ctx.iuid.h_id = dlg->h_id;
908
909 if (req->first_line.u.request.method_value != METHOD_ACK) {
910 iuid = dlg_get_iuid_shm_clone(dlg);
911 if (iuid != NULL) {
912 /* register callback for the replies of this request */
913 if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_IN | TMCB_ON_FAILURE,
914 dlg_onreply, (void*) iuid, dlg_iuid_sfree) < 0) {
915 LM_ERR("failed to register TMCB (3)\n");
916 shm_free(iuid);
917 }
918 iuid = NULL;
919 }
920 }
921 // if (d_tmb.register_tmcb(req, NULL, TMCB_REQUEST_FWDED,
922 // store_dlg_in_tm_cb, (void*) dlg, NULL) < 0) {
923 // LM_ERR("failed to store dialog in transaction during dialog creation for later reference\n");
924 // }
925
926 /* run state machine */
927 switch (req->first_line.u.request.method_value) {
928 case METHOD_PRACK:
929 event = DLG_EVENT_REQPRACK;
930 break;
931 case METHOD_ACK:
932 event = DLG_EVENT_REQACK;
933 break;
934 case METHOD_BYE:
935 event = DLG_EVENT_REQBYE;
936 break;
937 // case METHOD_CANCEL:
938 // event = DLG_EVENT_REQCANCEL;
939 // break;
940 default:
941 event = DLG_EVENT_REQ;
942 }
943
944 next_state_dlg(dlg, event, &old_state, &new_state, &unref, 0);
945 LM_DBG("unref after next state is %i\n", unref);
946 CURR_DLG_ID = req->id;
947 CURR_DLG_LIFETIME = (unsigned int) (time(0)) - dlg->start_ts;
948 CURR_DLG_STATUS = new_state;
949
950 // dlg_run_event_route(dlg, req, old_state, new_state);
951
952 /* delay deletion of dialog until transaction has died off in order
953 * to absorb in-air messages */
954 if ((new_state == DLG_STATE_DELETED) && (old_state != DLG_STATE_DELETED)) {
955 iuid = dlg_get_iuid_shm_clone(dlg);
956 if (iuid != NULL) {
957 if (d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
958 unref_dlg_from_cb, (void*) iuid, dlg_iuid_sfree) < 0) {
959 LM_ERR("failed to register deletion delay function\n");
960 shm_free(iuid);
961 } else {
962 ref_dlg(dlg, 1);
963 }
964 }
965 // unref_dlg(dlg, unref);
966 }
967
968 // if (new_state == DLG_STATE_CONFIRMED && old_state != DLG_STATE_CONFIRMED)
969 // dlg_ka_add(dlg);
970
971 if (event == DLG_EVENT_REQCANCEL && new_state == DLG_STATE_DELETED &&
972 old_state != DLG_STATE_DELETED) {
973 LM_DBG("CANCEL successfully processed and old state was [%d]\n", old_state);
974
975 ret = remove_dialog_timer(&dlg->tl);
976 if (ret < 0) {
977 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
978 "with clid '%.*s' and tags '%.*s'\n",
979 dlg, dlg->h_entry, dlg->h_id,
980 dlg->callid.len, dlg->callid.s,
981 dlg->from_tag.len, dlg->from_tag.s);
982
983 } else if (ret > 0) {
984 LM_WARN("inconsistent dlg timer data on dlg %p [%u:%u] "
985 "with clid '%.*s' and tags '%.*s' \n",
986 dlg, dlg->h_entry, dlg->h_id,
987 dlg->callid.len, dlg->callid.s,
988 dlg->from_tag.len, dlg->from_tag.s);
989
990 } else {
991 unref++;
992 }
993
994 dlg_terminated(req, dlg, dir);
995 unref_dlg(dlg, unref);
996 _dlg_ctx.cpid = my_pid();
997 _dlg_ctx.expect_t = 1;
998 dlg_set_ctx_iuid(dlg);
999
1000 if (old_state == DLG_STATE_EARLY) {
1001 counter_add(dialog_ng_cnts_h.early, -1);
1002 } else if (old_state == DLG_STATE_CONFIRMED ||old_state == DLG_STATE_CONFIRMED_NA) {
1003 counter_add(dialog_ng_cnts_h.active, -1);
1004 }
1005
1006 goto done;
1007 }
1008
1009 /* run actions for the transition */
1010 if (event == DLG_EVENT_REQBYE && new_state == DLG_STATE_DELETED &&
1011 old_state != DLG_STATE_DELETED) {
1012 LM_DBG("BYE successfully processed\n");
1013 /* remove from timer */
1014 ret = remove_dialog_timer(&dlg->tl);
1015 if (ret < 0) {
1016 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
1017 "with clid '%.*s' and tags '%.*s'\n",
1018 dlg, dlg->h_entry, dlg->h_id,
1019 dlg->callid.len, dlg->callid.s,
1020 dlg->from_tag.len, dlg->from_tag.s);
1021
1022 } else if (ret > 0) {
1023 LM_WARN("inconsistent dlg timer data on dlg %p [%u:%u] "
1024 "with clid '%.*s' and tags '%.*s' \n",
1025 dlg, dlg->h_entry, dlg->h_id,
1026 dlg->callid.len, dlg->callid.s,
1027 dlg->from_tag.len, dlg->from_tag.s);
1028
1029 } else {
1030 unref++;
1031 }
1032 /* dialog terminated (BYE) */
1033 dlg_terminated(req, dlg, dir);
1034 unref_dlg(dlg, unref);
1035 _dlg_ctx.cpid = my_pid();
1036 _dlg_ctx.expect_t = 1;
1037 dlg_set_ctx_iuid(dlg);
1038
1039 if (old_state == DLG_STATE_CONFIRMED ||old_state == DLG_STATE_CONFIRMED_NA) {
1040 counter_add(dialog_ng_cnts_h.active, -1);
1041 }
1042
1043 goto done;
1044 }
1045
1046 if (event == DLG_EVENT_REQCANCEL && new_state == DLG_STATE_DELETED &&
1047 old_state != DLG_STATE_DELETED) {
1048 LM_DBG("CANCEL successfully processed\n");
1049 /* remove from timer */
1050 ret = remove_dialog_timer(&dlg->tl);
1051 if (ret < 0) {
1052 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
1053 "with clid '%.*s' and tags '%.*s'\n",
1054 dlg, dlg->h_entry, dlg->h_id,
1055 dlg->callid.len, dlg->callid.s,
1056 dlg->from_tag.len, dlg->from_tag.s);
1057
1058 } else if (ret > 0) {
1059 LM_WARN("inconsistent dlg timer data on dlg %p [%u:%u] "
1060 "with clid '%.*s' and tags '%.*s' \n",
1061 dlg, dlg->h_entry, dlg->h_id,
1062 dlg->callid.len, dlg->callid.s,
1063 dlg->from_tag.len, dlg->from_tag.s);
1064
1065 } else {
1066 unref++;
1067 }
1068 /* dialog terminated (CANCEL) */
1069 dlg_cancelled(req, dlg, dir);
1070 // unref_dlg(dlg, unref);
1071 _dlg_ctx.cpid = my_pid();
1072 _dlg_ctx.expect_t = 1;
1073 dlg_set_ctx_iuid(dlg);
1074 counter_add(dialog_ng_cnts_h.early, -1);
1075 goto done;
1076 }
1077
1078 if ((event == DLG_EVENT_REQ || event == DLG_EVENT_REQACK)
1079 && (new_state == DLG_STATE_CONFIRMED || new_state == DLG_STATE_EARLY)) {
1080
1081 if (event != DLG_EVENT_REQACK) {
1082 if (update_cseqs(dlg, req, dir, &ttag) != 0) {
1083 LM_ERR("cseqs update failed\n");
1084 } else {
1085 dlg->dflags |= DLG_FLAG_CHANGED;
1086 }
1087 }
1088 if (dlg_db_mode == DB_MODE_REALTIME && (dlg->dflags & DLG_FLAG_CHANGED)) {
1089 update_dialog_dbinfo(dlg);
1090 }
1091
1092 if (old_state == DLG_STATE_CONFIRMED_NA) {
1093 LM_DBG("confirming ACK successfully processed\n");
1094
1095 /* confirming ACK request */
1096 run_dlg_callbacks(DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
1097 } else {
1098 LM_DBG("sequential request successfully processed\n");
1099
1100 /* within dialog request */
1101 run_dlg_callbacks(DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);
1102
1103 if ((event != DLG_EVENT_REQACK) &&
1104 (dlg->cbs.types) & DLGCB_RESPONSE_WITHIN) {
1105 iuid = dlg_get_iuid_shm_clone(dlg);
1106 if (iuid != NULL) {
1107 /* register callback for the replies of this request */
1108 if (d_tmb.register_tmcb(req, 0, TMCB_RESPONSE_FWDED,
1109 (dir == DLG_DIR_UPSTREAM) ? dlg_seq_down_onreply :
1110 dlg_seq_up_onreply,
1111 (void*) iuid, dlg_iuid_sfree) < 0) {
1112 LM_ERR("failed to register TMCB (2)\n");
1113 shm_free(iuid);
1114 }
1115 }
1116 }
1117 }
1118
1119 timeout = get_dlg_timeout(req);
1120 if (timeout != default_timeout) {
1121 dlg->lifetime = timeout;
1122 }
1123 // reset = !((dlg->iflags & DLG_IFLAG_TIMER_NORESET) || dlg_timeout_noreset);
1124
1125 if ((new_state != DLG_STATE_EARLY) && (old_state != DLG_STATE_CONFIRMED || reset)) {
1126 if (update_dlg_timer(&dlg->tl, dlg->lifetime) == -1) {
1127 LM_ERR("failed to update dialog lifetime\n");
1128 } else {
1129 dlg->dflags |= DLG_FLAG_CHANGED;
1130 }
1131 }
1132 }
1133
1134 if (new_state == DLG_STATE_CONFIRMED && old_state == DLG_STATE_CONFIRMED_NA) {
1135 dlg->dflags |= DLG_FLAG_CHANGED;
1136 if (dlg_db_mode == DB_MODE_REALTIME)
1137 update_dialog_dbinfo(dlg);
1138 }
1139
1140 done:
1141 dlg_release(dlg);
1142 return;
1143 }
1144
1145 /*!
1146 * \brief Function that is registered as TM callback and called on replies
1147 *
1148 * Function that is registered as TM callback and called on replies. It
1149 * parses the reply and set the appropriate event. This is then used to
1150 * update the dialog state, run eventual dialog callbacks and save or
1151 * update the necessary informations about the dialog.
1152 * \see next_state_dlg
1153 * \param t transaction, unused
1154 * \param type type of the entered callback
1155 * \param param saved dialog structure in the callback
1156 */
dlg_onreply(struct cell * t,int type,struct tmcb_params * param)1157 void dlg_onreply(struct cell* t, int type, struct tmcb_params *param) {
1158 dlg_cell_t *dlg = NULL;
1159 dlg_iuid_t *iuid = NULL;
1160 struct dlg_cell_out *dlg_out = 0;
1161 char *event_s = 0;
1162
1163 int new_state, old_state, unref, event;
1164 str to_tag={0,0}, to_uri={0,0}, branch={0,0};
1165 struct sip_msg *req = param->req;
1166 struct sip_msg *rpl = param->rpl;
1167 struct dlg_entry_out* dlg_entry_out = 0;
1168
1169 char* cb_type_s = tm_type_to_string(type);
1170
1171 if (t && t->fwded_totags)
1172 LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] = [%s]"
1173 " and TO is [%.*s]\n", type, cb_type_s, t->fwded_totags->tag.len,
1174 t->fwded_totags->tag.s);
1175 else
1176 LM_DBG("ONREPLY CALL_BACK from TM received and type is [%i] = [%s]\n",
1177 type, cb_type_s);
1178
1179 if (shutdown_done)
1180 return;
1181
1182 iuid = (dlg_iuid_t*) (*param->param);
1183 dlg = dlg_get_by_iuid(iuid);
1184 if (dlg == 0)
1185 return;
1186
1187 if (t) {
1188 dlg->transaction = t;
1189 }
1190
1191 unref = 0;
1192
1193 LM_DBG("DLG dialogid is entry:id [%i:%i]\n", dlg->h_entry, dlg->h_id);
1194
1195 if (type & TMCB_E2ECANCEL_IN) {
1196 LM_DBG("Received CANCEL...\n");
1197 goto done;
1198 }
1199
1200 if (type & TMCB_REQUEST_OUT) {
1201 LM_DBG("Received Request out for request [%.*s]\n", param->send_buf.len, param->send_buf.s);
1202 if (param->send_buf.s && (param->send_buf.len > 6) && !memcmp(param->send_buf.s, "CANCEL", 6)) {
1203 LM_DBG("Request out sending CANCEL...\n");
1204 type = TMCB_E2ECANCEL_IN;
1205 goto done;
1206 } else {
1207 LM_DBG("Ignoring request out as it's not a CANCEL\n");
1208 goto done;
1209 }
1210 }
1211
1212 if (type & (TMCB_RESPONSE_IN | TMCB_ON_FAILURE)) {
1213 /* Set the dialog context so it is available in onreply_route and failure_route*/
1214 set_current_dialog(req, dlg);
1215 dlg_set_ctx_iuid(dlg);
1216 goto done;
1217 }
1218
1219 if (type == TMCB_RESPONSE_FWDED) {
1220 // The state does not change, but the msg is mutable in this callback
1221 LM_DBG("TMCB_RESPONSE_FWDED from TM received");
1222 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1223 goto done;
1224 }
1225
1226 if (type == TMCB_RESPONSE_READY) {
1227 if (rpl == FAKED_REPLY) {
1228 LM_DBG("Faked reply\n");
1229 //TODO - maybe we should run the state machine especially for things like cancel (ie early dialog.....)
1230 to_tag.s = 0;
1231 to_tag.len = 0;
1232 // goto done;
1233 } else {
1234 // get to tag
1235 LM_DBG("Extracting to-tag from reply");
1236 if (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to)) {
1237 LM_DBG("bad reply or missing TO hdr :-/\n");
1238 to_tag.s = 0;
1239 to_tag.len = 0;
1240 } else {
1241 //populate to uri for this branch.
1242 to_uri = get_to(rpl)->uri;
1243
1244 to_tag = get_to(rpl)->tag_value;
1245 if (to_tag.s == 0 || to_tag.len == 0) {
1246 LM_DBG("missing TAG param in TO hdr :-/\n");
1247 to_tag.s = 0;
1248 to_tag.len = 0;
1249 //Here we assume that the transaction module timer will remove any early dialogs
1250 //return; if we leave this then we have over-reffed dialogs
1251 }
1252 }
1253 }
1254
1255 LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s);
1256 }
1257
1258 if (type == TMCB_DESTROY) {
1259 event = DLG_EVENT_TDEL;
1260 event_s = "DLG_EVENT_TDEL";
1261 // } else if (type == TMCB_E2ECANCEL_IN) {
1262 // event = DLG_EVENT_REQCANCEL;
1263 // event_s = "DLG_EVENT_REQCANCEL";
1264 } else if (param->code < 200) {
1265 event = DLG_EVENT_RPL1xx;
1266 event_s = "DLG_EVENT_RPL1xx";
1267 } else if (param->code < 300) {
1268 event = DLG_EVENT_RPL2xx;
1269 event_s = "DLG_EVENT_RPL2xx";
1270 } else {
1271 event = DLG_EVENT_RPL3xx;
1272 event_s = "DLG_EVENT_RPL3xx";
1273 }
1274
1275 LM_DBG("Calling next_state_dlg and event is %i = %s\n", event, event_s);
1276 next_state_dlg(dlg, event, &old_state, &new_state, &unref, &to_tag);
1277
1278 if (type == TMCB_RESPONSE_READY) {
1279 LM_DBG("Checking if there is an existing dialog_out entry with same to-tag");
1280 if (rpl == FAKED_REPLY) {
1281 LM_DBG("Faked reply\n");
1282
1283 if (new_state == DLG_STATE_DELETED
1284 && (old_state == DLG_STATE_UNCONFIRMED
1285 || old_state == DLG_STATE_EARLY)) {
1286 LM_DBG("dialog %p failed (negative reply)\n", dlg);
1287 /* dialog setup not completed (3456XX) */
1288 run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1289 /* do unref */
1290 if (unref)
1291 unref_dlg(dlg, unref);
1292
1293 if (old_state == DLG_STATE_EARLY)
1294 counter_add(dialog_ng_cnts_h.early, -1);
1295 }
1296 goto done;
1297 }
1298
1299 // get to tag
1300 LM_DBG("Extracting to-tag from reply");
1301 if (rpl == FAKED_REPLY || (!rpl->to && ((parse_headers(rpl, HDR_TO_F, 0) < 0) || !rpl->to))) {
1302 LM_ERR("faked reply or bad reply or missing TO hdr :-/\n");
1303 to_tag.s = 0;
1304 to_tag.len = 0;
1305 } else {
1306 //populate to uri for this branch.
1307 to_uri = get_to(rpl)->uri;
1308
1309 to_tag = get_to(rpl)->tag_value;
1310 if (to_tag.s == 0 || to_tag.len == 0) {
1311 LM_DBG("missing TAG param in TO hdr :-/ - probably a failure response\n");
1312 to_tag.s = 0;
1313 to_tag.len = 0;
1314 //Here we assume that the transaction module timer will remove any early dialogs
1315 if (new_state == DLG_STATE_DELETED
1316 && (old_state == DLG_STATE_UNCONFIRMED
1317 || old_state == DLG_STATE_EARLY)) {
1318 LM_DBG("dialog %p failed (negative reply)\n", dlg);
1319 /* dialog setup not completed (3456XX) */
1320 run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1321 /* do unref */
1322 if (unref)
1323 unref_dlg(dlg, unref);
1324
1325 if (old_state == DLG_STATE_EARLY)
1326 counter_add(dialog_ng_cnts_h.early, -1);
1327 }
1328 goto done;
1329 }
1330 }
1331 LM_DBG("Got to-tag from response: %.*s \n", to_tag.len, to_tag.s);
1332
1333 dlg_entry_out = &dlg->dlg_entry_out;
1334
1335 lock_get(dlg->dlg_out_entries_lock);
1336 dlg_out = dlg_entry_out->first;
1337
1338 LM_DBG("Scanning dlg_entry_out list for dlg_out");
1339 while (dlg_out) {
1340 //Check if there is an already dialog_out entry with same To-tag
1341 if (dlg_out->to_tag.len == to_tag.len &&
1342 memcmp(dlg_out->to_tag.s, to_tag.s, dlg_out->to_tag.len) == 0) {
1343 //Found a dialog_out entry with same to_tag!
1344 LM_DBG("Found dlg_out for to-tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s);
1345 break;
1346 }
1347 dlg_out = dlg_out->next;
1348 }
1349 lock_release(dlg->dlg_out_entries_lock);
1350
1351 if (!dlg_out) {
1352 if (rpl->first_line.u.reply.statuscode < 299) { /*we don't care about failure responses to dialog - not necessary to create dialog out...*/
1353 if (rpl->via1->branch && (rpl->via1->branch->value.s) && (rpl->via1->branch->value.len > 0)) {
1354 branch = rpl->via1->branch->value;
1355 }
1356
1357 LM_DBG("No dlg_out entry found - creating a new dialog_out entry on dialog [%p]\n", dlg);
1358 dlg_out = build_new_dlg_out(dlg, &to_uri, &to_tag, &branch);
1359
1360 link_dlg_out(dlg, dlg_out, 0);
1361
1362 /* save callee's cseq, caller cseq, callee contact and callee record route*/
1363 if (populate_leg_info(dlg, rpl, t, DLG_CALLEE_LEG, &to_tag) != 0) {
1364 LM_ERR("could not add further info to the dlg out\n");
1365 }
1366
1367 if (!dlg_out) {
1368 LM_ERR("failed to create new dialog out structure\n");
1369 goto done;
1370 //TODO do something on this error!
1371
1372 }
1373 }
1374 } else {
1375 //This dlg_out already exists, update cseq and contact if present
1376
1377 LM_DBG("dlg_out entry found - updating cseq's for dialog out [%p] for to-tag [%.*s] \n", dlg_out, dlg_out->to_tag.len, dlg_out->to_tag.s);
1378
1379 if ((!rpl->cseq && parse_headers(rpl, HDR_CSEQ_F, 0) < 0) || !rpl->cseq ||
1380 !rpl->cseq->parsed) {
1381 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
1382 }
1383 dlg_update_cseq(dlg, DLG_CALLEE_LEG, &((get_cseq(rpl))->number), &(dlg_out->to_tag));
1384
1385
1386 /* extract the contact address to update if present*/
1387 if (!rpl->contact && (parse_headers(rpl, HDR_CONTACT_F, 0) < 0 || !rpl->contact)) {
1388 LM_DBG("Can not update callee contact: bad sip message or missing Contact hdr\n");
1389 } else if (parse_contact(rpl->contact) < 0 ||
1390 ((contact_body_t *) rpl->contact->parsed)->contacts == NULL ||
1391 ((contact_body_t *) rpl->contact->parsed)->contacts->next != NULL) {
1392 LM_ERR("Can not update callee contact: bad Contact HDR\n");
1393 } else {
1394 str contact;
1395 contact = ((contact_body_t *) rpl->contact->parsed)->contacts->uri;
1396 dlg_update_contact(dlg, DLG_CALLEE_LEG, &contact, &(dlg_out->to_tag));
1397 }
1398 }
1399 }
1400 if (new_state == DLG_STATE_EARLY) {
1401 if (dlg_db_mode == DB_MODE_REALTIME)
1402 update_dialog_dbinfo(dlg);
1403 run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1404 if (old_state != DLG_STATE_EARLY)
1405 counter_inc(dialog_ng_cnts_h.early);
1406 goto done;
1407 }
1408
1409 LM_DBG("new state is %i and old state is %i\n", new_state, old_state);
1410
1411 if (new_state == DLG_STATE_CONFIRMED_NA &&
1412 old_state != DLG_STATE_CONFIRMED_NA && old_state != DLG_STATE_CONFIRMED) {
1413 // if ((new_state == DLG_STATE_CONFIRMED) && (event == DLG_EVENT_RPL2xx)) {
1414 LM_DBG("dialog %p confirmed (No Ack) \n", dlg);
1415
1416 /* set start time */
1417 dlg->start_ts = (unsigned int) (time(0));
1418
1419 /* save the settings to the database,
1420 * if realtime saving mode configured- save dialog now
1421 * else: the next time the timer will fire the update*/
1422 if ((dlg->dflags & DLG_FLAG_INSERTED) == 0) {
1423 dlg->dflags |= DLG_FLAG_NEW;
1424 } else {
1425 dlg->dflags |= DLG_FLAG_CHANGED;
1426 }
1427 if (dlg_db_mode == DB_MODE_REALTIME)
1428 update_dialog_dbinfo(dlg);
1429
1430 if (0 != insert_dlg_timer(&dlg->tl, dlg->lifetime)) {
1431 LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
1432 "with clid '%.*s' and tags '%.*s' \n",
1433 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
1434 dlg->callid.len, dlg->callid.s,
1435 dlg->from_tag.len, dlg->from_tag.s);
1436 } else {
1437 ref_dlg(dlg, 1);
1438 }
1439
1440 /* dialog confirmed (ACK pending) */
1441 run_dlg_callbacks(DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1442
1443 if (old_state == DLG_STATE_EARLY)
1444 counter_add(dialog_ng_cnts_h.early, -1);
1445
1446 if (unref) unref_dlg(dlg, unref);
1447
1448 counter_inc(dialog_ng_cnts_h.active);
1449
1450 goto done;
1451 }
1452
1453 if (new_state == DLG_STATE_CONCURRENTLY_CONFIRMED && (old_state == DLG_STATE_CONFIRMED || old_state == DLG_STATE_CONCURRENTLY_CONFIRMED)) {
1454 //This is a concurrently confirmed call
1455 LM_DBG("This is a concurrently confirmed call.");
1456 //Create a new Dialog ID token “X”
1457 //Not sure how to do this so just going to use existing Did and add an X character to it
1458 str new_did;
1459 create_concurrent_did(dlg, &new_did);
1460
1461 //assign new did to the created or updated dialog_out entry.
1462 update_dlg_out_did(dlg_out, &new_did);
1463
1464 //Then, duplicate the dialog_in entry and set its Dialog ID value to new_did
1465 //for now rather just create new dlg structure with the correct params - this should be fixed if future use requires
1466
1467 struct dlg_cell *new_dlg = 0;
1468 new_dlg = build_new_dlg(&(dlg->callid) /*callid*/,
1469 &(dlg->from_uri) /*from uri*/,
1470 &(dlg->from_tag)/*from_tag*/,
1471 &(dlg->req_uri) /*r-uri*/);
1472
1473 //assign new did to dlg_in
1474 update_dlg_did(new_dlg, &new_did);
1475
1476 if (new_dlg == 0) {
1477 LM_ERR("failed to create new dialog\n");
1478 goto done;
1479 }
1480
1481 //link the new_dlg with dlg_out object
1482 link_dlg_out(new_dlg, dlg_out, 0);
1483
1484 }
1485
1486 if (new_state == DLG_STATE_DELETED
1487 && (old_state == DLG_STATE_UNCONFIRMED
1488 || old_state == DLG_STATE_EARLY)) {
1489 LM_DBG("dialog %p failed (negative reply)\n", dlg);
1490 /* dialog setup not completed (3456XX) */
1491 run_dlg_callbacks(DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
1492 /* do unref */
1493 if (unref)
1494 unref_dlg(dlg, unref);
1495
1496 if (old_state == DLG_STATE_EARLY)
1497 counter_add(dialog_ng_cnts_h.early, -1);
1498 goto done;
1499 }
1500
1501 if (unref) unref_dlg(dlg, unref);
1502
1503 done:
1504 /* unref due to dlg_get_by_iuid() */
1505 dlg_release(dlg);
1506 return;
1507 }
1508
1509 /*!
1510 * \brief Unreference a new dialog, helper function for dlg_onreq
1511 * \see dlg_onreq
1512 * \param dialog unreferenced dialog
1513 */
1514 /*static void unref_new_dialog(void *dialog) {
1515 struct tmcb_params p;
1516
1517 memset(&p, 0, sizeof (struct tmcb_params));
1518 p.param = (void*) &dialog;
1519 dlg_onreply(0, TMCB_DESTROY, &p);
1520 }*/
1521
1522 /*!
1523 * \brief Dummy callback just to keep the compiler happy
1524 * \param t unused
1525 * \param type unused
1526 * \param param unused
1527 */
dlg_tmcb_dummy(struct cell * t,int type,struct tmcb_params * param)1528 void dlg_tmcb_dummy(struct cell* t, int type, struct tmcb_params *param) {
1529 return;
1530 }
1531
1532 /*!
1533 * \brief Create a new dialog from a sip message
1534 *
1535 * Create a new dialog from a SIP message, register a callback
1536 * to keep track of the dialog with help of the tm module.
1537 * This function is either called from the request callback, or
1538 * from the dlg_manage function in the configuration script.
1539 * \see dlg_onreq
1540 * \see w_dlg_manage
1541 * \param req SIP message
1542 * \param t transaction
1543 * \param run_initial_cbs if set zero, initial callbacks are not executed
1544 * \return 0 on success, -1 on failure
1545 */
dlg_new_dialog(struct sip_msg * req,struct cell * t,const int run_initial_cbs)1546 int dlg_new_dialog(struct sip_msg *req, struct cell *t, const int run_initial_cbs) {
1547 struct dlg_cell *dlg;
1548 str s;
1549 str callid;
1550 str ftag;
1551 str ttag;
1552 str req_uri;
1553 unsigned int dir;
1554 int mlock;
1555
1556 if (req->first_line.u.request.method_value != METHOD_INVITE)
1557 return -1;
1558
1559 LM_DBG("starting dlg_new_dialog and method is [%.*s]\n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
1560
1561 if (pre_match_parse(req, &callid, &ftag, &ttag, 0) < 0) {
1562 LM_WARN("pre-matching failed\n");
1563 return -1;
1564 }
1565
1566 if (ttag.s != 0 && ttag.len != 0)
1567 return -1;
1568
1569 if (pv_printf_s(req, ruri_param_model, &req_uri) < 0) {
1570 LM_ERR("error - cannot print the r-uri format\n");
1571 return -1;
1572 }
1573 trim(&req_uri);
1574
1575 mlock = 1;
1576 dlg = search_dlg(&callid, &ftag, &ttag, &dir);
1577 if (detect_spirals) {
1578 if (spiral_detected == 1) {
1579 LM_DBG("spiral detected - returning 0\n");
1580 return 0;
1581 }
1582 dir = DLG_DIR_NONE;
1583 if (dlg) {
1584 mlock = 0;
1585 if (dlg->state != DLG_STATE_DELETED) {
1586 LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
1587 callid.len, callid.s);
1588 spiral_detected = 1;
1589
1590 if (run_initial_cbs)
1591 run_dlg_callbacks(DLGCB_SPIRALED, dlg, req, NULL, DLG_DIR_DOWNSTREAM, 0);
1592
1593 //Add did to rr header for all spiralled requested INVITEs
1594 if (req->first_line.u.request.method_value == METHOD_INVITE) {
1595 if (add_dlg_rr_param(req, dlg->h_entry, dlg->h_id) < 0) {
1596 LM_ERR("failed to add RR param\n");
1597 }
1598 }
1599 // dlg_release(dlg); //this is a fix so that we register for terminating callbacks too (caters for spiralled invites on same P/S-CSCF)
1600 _dlg_ctx.cpid = my_pid();
1601 _dlg_ctx.iuid.h_entry = dlg->h_entry;
1602 _dlg_ctx.iuid.h_id = dlg->h_id;
1603 set_current_dialog(req, dlg);
1604 dlg_release(dlg);
1605 return 0;
1606 } else {
1607 LM_DBG("spiral deteced and current state is [%d]\n", dlg->start_ts);
1608 }
1609 // get_dlg has incremented the ref count by 1
1610 dlg_release(dlg);
1611 }
1612 } else {
1613 // get_dlg has incremented the ref count by 1
1614 if (dlg)
1615 dlg_release(dlg);
1616 }
1617 spiral_detected = 0;
1618
1619
1620 LM_DBG("Building new Dialog for call-id %.*s\n", callid.len, callid.s);
1621 LM_DBG("SIP Method: %.*s \n", req->first_line.u.request.method.len, req->first_line.u.request.method.s);
1622 dlg = build_new_dlg(&callid /*callid*/,
1623 &(get_from(req)->uri) /*from uri*/,
1624 &ftag/*from_tag*/,
1625 &req_uri /*r-uri*/);
1626
1627 if (dlg == 0) {
1628 if (likely(mlock == 1)) dlg_hash_release(&callid);
1629 LM_ERR("failed to create new dialog\n");
1630 return -1;
1631 }
1632
1633 /* save caller's tag, cseq, contact and record route*/
1634 if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
1635 &(get_from(req)->tag_value)) != 0) {
1636 LM_ERR("could not add further info to the dialog\n");
1637 lock_destroy(dlg->dlg_out_entries_lock);
1638 lock_dealloc(dlg->dlg_out_entries_lock);
1639 shm_free(dlg);
1640 return -1;
1641 }
1642
1643 /* Populate initial varlist: */
1644 dlg->vars = get_local_varlist_pointer(req, 1);
1645
1646 /* if search_dlg() returned NULL, slot was kept locked */
1647 link_dlg(dlg, 0, mlock);
1648 if (likely(mlock == 1)) dlg_hash_release(&callid);
1649
1650 s.s = _dlg_ctx.to_route_name;
1651 s.len = strlen(s.s);
1652 dlg_set_toroute(dlg, &s);
1653 dlg->sflags |= _dlg_ctx.flags;
1654 // dlg->iflags |= _dlg_ctx.iflags;
1655
1656 // if (dlg_send_bye != 0 || _dlg_ctx.to_bye != 0)
1657 // dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;
1658
1659 if (run_initial_cbs) run_create_callbacks(dlg, req);
1660
1661 dlg->lifetime = get_dlg_timeout(req);
1662
1663 /* first INVITE seen (dialog created, unconfirmed) */
1664 if (seq_match_mode != SEQ_MATCH_NO_ID &&
1665 add_dlg_rr_param(req, dlg->h_entry, dlg->h_id) < 0) {
1666 LM_ERR("failed to add RR param\n");
1667 goto error;
1668 }
1669
1670 counter_inc(dialog_ng_cnts_h.processed);
1671
1672 _dlg_ctx.cpid = my_pid();
1673 _dlg_ctx.iuid.h_entry = dlg->h_entry;
1674 _dlg_ctx.iuid.h_id = dlg->h_id;
1675 set_current_dialog(req, dlg);
1676
1677 LM_DBG("New dialog created\n");
1678
1679 return 0;
1680
1681 error:
1682 if (!spiral_detected)
1683 unref_dlg(dlg, 1); // undo ref regarding linking
1684 return -1;
1685
1686 }
1687
1688 /*!
1689 * \brief add dlg structure to tm callbacks
1690 * \param t current transaction
1691 * \param req current sip request
1692 * \param dlg current dialog
1693 * \param smode if the sip request was spiraled
1694 * \return 0 on success, -1 on failure
1695 */
dlg_set_tm_callbacks(tm_cell_t * t,sip_msg_t * req,dlg_cell_t * dlg,int smode)1696 int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg,
1697 int smode) {
1698 dlg_iuid_t *iuid = NULL;
1699 if (t == NULL)
1700 return -1;
1701
1702 if (smode == 0) {
1703 // if (smode == 1) {
1704 // LM_DBG("Setting up TM callbacks for spiralled request on T (%p)\n", t);
1705 // }
1706 iuid = dlg_get_iuid_shm_clone(dlg);
1707 if (iuid == NULL) {
1708 LM_ERR("failed to create dialog unique id clone\n");
1709 goto error;
1710 }
1711 if (d_tmb.register_tmcb(req, t,
1712 TMCB_RESPONSE_IN | TMCB_RESPONSE_READY | TMCB_RESPONSE_FWDED | TMCB_ON_FAILURE | TMCB_E2ECANCEL_IN | TMCB_REQUEST_OUT,
1713 dlg_onreply, (void*) iuid, dlg_iuid_sfree) < 0) {
1714 LM_ERR("failed to register TMCB\n");
1715 goto error;
1716 }
1717 } else {
1718 LM_DBG("Not registering for TM callbacks because this is a spiraled request and we should have already registered callbacks on this transaction....\n");
1719 }
1720
1721 dlg->dflags |= DLG_FLAG_TM;
1722
1723 return 0;
1724 error:
1725 dlg_iuid_sfree(iuid);
1726 return -1;
1727 }
1728
1729 static str reason_hdr_s = {"Reason: dialog_timeout\r\n", 24};
1730
1731 /*!
1732 * \brief Timer function that removes expired dialogs, run timeout route
1733 * \param tl dialog timer list
1734 */
dlg_ontimeout(struct dlg_tl * tl)1735 void dlg_ontimeout(struct dlg_tl *tl) {
1736 dlg_cell_t *dlg;
1737 int new_state, old_state, unref;
1738 sip_msg_t *fmsg;
1739
1740
1741 /* get the dialog tl payload */
1742 dlg = ((struct dlg_cell*) ((char *) (tl) -
1743 (unsigned long) (&((struct dlg_cell*) 0)->tl)));
1744
1745 /* mark dialog as expired */
1746 dlg->dflags |= DLG_FLAG_EXPIRED;
1747
1748 if (dlg->state == DLG_STATE_CONFIRMED_NA
1749 || dlg->state == DLG_STATE_CONFIRMED) {
1750 if (dlg->toroute > 0 && dlg->toroute < main_rt.entries
1751 && main_rt.rlist[dlg->toroute] != NULL) {
1752 fmsg = faked_msg_next();
1753 if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE) > 0) {
1754 ref_dlg(dlg, 1);
1755 dlg_set_ctx_iuid(dlg);
1756 LM_DBG("executing route %d on timeout\n", dlg->toroute);
1757 set_route_type(REQUEST_ROUTE);
1758 run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0);
1759 dlg_reset_ctx_iuid();
1760 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
1761 unref_dlg(dlg, 1);
1762 }
1763 }
1764
1765 // if (dlg->iflags & DLG_IFLAG_TIMEOUTBYE) { //TODO return therse flags
1766 if (dlg->state == DLG_STATE_CONFIRMED) {
1767 if (dlg_bye_all(dlg, &reason_hdr_s) < 0 ) /* function only supports DLG_STATE_CONFIRMED*/
1768 LM_DBG("Failed to do dlg_bye_all.!!");
1769 // unref_dlg(dlg, 1);
1770 }
1771 // else if (dlg->state == DLG_STATE_CONFIRMED_NA)
1772 // unref_dlg(dlg, 1);
1773 // counter_inc(dialog_ng_cnts_h.expired);
1774 // return;
1775 }
1776
1777 next_state_dlg(dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref, 0);
1778 // dlg_run_event_route(dlg, NULL, old_state, new_state); //TODO replace
1779
1780 if (new_state == DLG_STATE_DELETED && old_state != DLG_STATE_DELETED) {
1781 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s'\n",
1782 dlg->callid.len, dlg->callid.s,
1783 dlg->from_tag.len, dlg->from_tag.s);
1784
1785 /* dialog timeout */
1786 run_dlg_callbacks(DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
1787
1788 unref_dlg(dlg, unref + 1);
1789 counter_add(dialog_ng_cnts_h.active, -1);
1790 counter_inc(dialog_ng_cnts_h.expired);
1791 } else {
1792 unref_dlg(dlg, 1);
1793 }
1794
1795 return;
1796 }
1797
1798 /*!
1799 * \brief Function that returns the dialog lifetime as pseudo-variable
1800 * \param msg SIP message
1801 * \param param pseudo-variable parameter
1802 * \param res pseudo-variable result
1803 * \return 0 on success, -1 on failure
1804 */
pv_get_dlg_lifetime(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)1805 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
1806 int l = 0;
1807 char *ch = NULL;
1808
1809 if (msg == NULL || res == NULL)
1810 return -1;
1811
1812 if (CURR_DLG_ID != msg->id)
1813 return pv_get_null(msg, param, res);
1814
1815 res->ri = CURR_DLG_LIFETIME;
1816 ch = int2str((unsigned long) res->ri, &l);
1817
1818 res->rs.s = ch;
1819 res->rs.len = l;
1820
1821 res->flags = PV_VAL_STR | PV_VAL_INT | PV_TYPE_INT;
1822
1823 return 0;
1824 }
1825
1826 /*!
1827 * \brief Function that returns the dialog state as pseudo-variable
1828 * \param msg SIP message
1829 * \param param pseudo-variable parameter
1830 * \param res pseudo-variable result
1831 * \return 0 on success, -1 on failure
1832 */
pv_get_dlg_status(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)1833 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param, pv_value_t *res) {
1834 int l = 0;
1835 char *ch = NULL;
1836
1837 if (msg == NULL || res == NULL)
1838 return -1;
1839
1840 if (CURR_DLG_ID != msg->id)
1841 return pv_get_null(msg, param, res);
1842
1843 res->ri = CURR_DLG_STATUS;
1844 ch = int2str((unsigned long) res->ri, &l);
1845
1846 res->rs.s = ch;
1847 res->rs.len = l;
1848
1849 res->flags = PV_VAL_STR | PV_VAL_INT | PV_TYPE_INT;
1850
1851 return 0;
1852 }
1853
1854 /*!
1855 * \brief Helper function that prints all the properties of a dialog including all the dlg_out's
1856 * \param dlg dialog cell
1857 * \return void
1858 */
1859
internal_print_all_dlg(struct dlg_cell * dlg)1860 void internal_print_all_dlg(struct dlg_cell *dlg) {
1861
1862 LM_DBG("Trying to get lock for printing\n");
1863 lock_get(dlg->dlg_out_entries_lock);
1864
1865 struct dlg_cell_out *dlg_out;
1866 struct dlg_entry_out *d_entry_out = &(dlg->dlg_entry_out);
1867
1868 LM_DBG("----------------------------");
1869 LM_DBG("Dialog h_entry:h_id = [%u : %u]\n", dlg->h_entry, dlg->h_id);
1870 LM_DBG("Dialog age: %ld\n", act_time - dlg->init_ts);
1871 LM_DBG("Dialog call-id: %.*s\n", dlg->callid.len, dlg->callid.s);
1872 LM_DBG("Dialog state: %d\n", dlg->state);
1873 LM_DBG("Dialog ref counter: %d\n", dlg->ref);
1874 LM_DBG("Dialog did: %.*s\n", dlg->did.len, dlg->did.s);
1875 LM_DBG("Dialog from_tag: %.*s\n", dlg->from_tag.len, dlg->from_tag.s);
1876 LM_DBG("Dialog from_uri: %.*s\n", dlg->from_uri.len, dlg->from_uri.s);
1877 LM_DBG("Dialog caller contact: %.*s\n", dlg->caller_contact.len, dlg->caller_contact.s);
1878 LM_DBG("Dialog first request cseq: %.*s\n", dlg->first_req_cseq.len, dlg->first_req_cseq.s);
1879 LM_DBG("Dialog caller route set: %.*s\n", dlg->caller_route_set.len, dlg->caller_route_set.s);
1880 LM_DBG("Dialog lifetime: %d\n", dlg->lifetime);
1881 LM_DBG("Dialog bind_address: %.*s\n", dlg->caller_bind_addr ? dlg->caller_bind_addr->sock_str.len : 0, dlg->caller_bind_addr ? dlg->caller_bind_addr->sock_str.s : 0);
1882 LM_DBG("Dialog-creating transaction pointer [%p]\n", dlg->transaction);
1883
1884 dlg_out = d_entry_out->first;
1885
1886 while (dlg_out) {
1887
1888 LM_DBG("----------");
1889 LM_DBG("Dialog out h_entry:h_id = [%u : %u]\n", dlg_out->h_entry, dlg_out->h_id);
1890 LM_DBG("Dialog out did: %.*s\n", dlg_out->did.len, dlg_out->did.s);
1891 LM_DBG("Dialog out to_tag: %.*s\n", dlg_out->to_tag.len, dlg_out->to_tag.s);
1892 LM_DBG("Dialog out caller cseq: %.*s\n", dlg_out->caller_cseq.len, dlg_out->caller_cseq.s);
1893 LM_DBG("Dialog out callee cseq: %.*s\n", dlg_out->callee_cseq.len, dlg_out->callee_cseq.s);
1894 LM_DBG("Dialog out callee contact: %.*s\n", dlg_out->callee_contact.len, dlg_out->callee_contact.s);
1895 LM_DBG("Dialog out callee route set: %.*s\n", dlg_out->callee_route_set.len, dlg_out->callee_route_set.s);
1896 LM_DBG("Dialog out branch: %.*s\n", dlg_out->branch.len, dlg_out->branch.s);
1897 LM_DBG("Dialog out state (deleted): %i\n", dlg_out->deleted);
1898
1899 LM_DBG("----------");
1900 dlg_out = dlg_out->next;
1901 }
1902
1903 LM_DBG("Releasing lock for dlgout\n");
1904 lock_release(dlg->dlg_out_entries_lock);
1905
1906 LM_DBG("----------------------------");
1907
1908 }
1909
1910 /*!
1911 * \brief Helper function that prints information for all dialogs
1912 * \return void
1913 */
1914
print_all_dlgs()1915 void print_all_dlgs() {
1916 //print all dialog information - this is just for testing and is set to happen every 10 seconds
1917
1918 struct dlg_cell *dlg;
1919 unsigned int i;
1920
1921 act_time = time(0);
1922
1923 LM_DBG("********************");
1924 LM_DBG("printing %i dialogs\n", d_table->size);
1925
1926 for (i = 0; i < d_table->size; i++) {
1927 dlg_lock(d_table, &(d_table->entries[i]));
1928
1929 for (dlg = d_table->entries[i].first; dlg; dlg = dlg->next) {
1930 internal_print_all_dlg(dlg);
1931 }
1932 dlg_unlock(d_table, &(d_table->entries[i]));
1933 }
1934 LM_DBG("********************");
1935
1936 }
1937
1938 /*!
1939 * \brief Get the current dialog based on the current SIP message
1940 * \param msg SIP message
1941 * \return current dialog, null if none.
1942 */
1943
dlg_get_msg_dialog(sip_msg_t * msg)1944 struct dlg_cell *dlg_get_msg_dialog(sip_msg_t *msg) {
1945 struct dlg_cell *dlg = NULL;
1946 str callid;
1947 str ftag;
1948 str ttag;
1949 unsigned int dir;
1950
1951 /* Retrieve the current dialog */
1952 dlg = dlg_get_ctx_dialog();
1953 if (dlg != NULL)
1954 return dlg;
1955
1956 if (pre_match_parse(msg, &callid, &ftag, &ttag, 0) < 0)
1957 return NULL;
1958 dir = DLG_DIR_NONE;
1959 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
1960 if (dlg == NULL) {
1961 LM_DBG("dlg with callid '%.*s' not found\n",
1962 msg->callid->body.len, msg->callid->body.s);
1963 return NULL;
1964 }
1965 return dlg;
1966 }
1967
1968