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