modules_k/dialog: Enhance unref_dlg_from_cb() robustness.
[sip-router] / modules_k / dialog / dlg_handlers.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2006 Voice System SRL
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version
12  *
13  * Kamailio is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * History:
23  * --------
24  * 2006-04-14  initial version (bogdan)
25  * 2006-11-28  Added support for tracking the number of early dialogs, and the
26  *             number of failed dialogs. This involved updates to dlg_onreply()
27  *             (Jeffrey Magder - SOMA Networks)
28  * 2007-03-06  syncronized state machine added for dialog state. New tranzition
29  *             design based on events; removed num_1xx and num_2xx (bogdan)
30  * 2007-04-30  added dialog matching without DID (dialog ID), but based only
31  *             on RFC3261 elements - based on an original patch submitted
32  *             by Michel Bensoussan <michel@extricom.com> (bogdan)
33  * 2007-05-17  new feature: saving dialog info into a database if
34  *             realtime update is set(ancuta)
35  * 2007-07-06  support for saving additional dialog info : cseq, contact,
36  *             route_set and socket_info for both caller and callee (ancuta)
37  * 2007-07-10  Optimized dlg_match_mode 2 (DID_NONE), it now employs a proper
38  *             hash table lookup and isn't dependant on the is_direction
39  *             function (which requires an RR param like dlg_match_mode 0
40  *             anyways.. ;) ; based on a patch from
41  *             Tavis Paquette <tavis@galaxytelecom.net>
42  *             and Peter Baer <pbaer@galaxytelecom.net>  (bogdan)
43  * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
44  */
45
46
47 /*!
48  * \file
49  * \brief Functions related to dialog handling
50  * \ingroup dialog
51  * Module: \ref dialog
52  */
53
54 #include <string.h>
55 #include <time.h>
56
57 #include "../../trim.h"
58 #include "../../pvar.h"
59 #include "../../timer.h"
60 #include "../../lib/kcore/statistics.h"
61 #include "../../action.h"
62 #include "../../script_cb.h"
63 #include "../../lib/kcore/faked_msg.h"
64 #include "../../lib/kcore/parser_helpers.h"
65 #include "../../parser/parse_from.h"
66 #include "../../parser/parse_cseq.h"
67 #include "../../parser/contact/parse_contact.h"
68 #include "../../parser/parse_from.h"
69 #include "../../parser/parse_rr.h"
70 #include "../../modules/tm/tm_load.h"
71 #include "../rr/api.h"
72 #include "dlg_hash.h"
73 #include "dlg_timer.h"
74 #include "dlg_cb.h"
75 #include "dlg_handlers.h"
76 #include "dlg_req_within.h"
77 #include "dlg_db_handler.h"
78 #include "dlg_profile.h"
79 #include "dlg_var.h"
80
81 static str       rr_param;              /*!< record-route parameter for matching */
82 static int       dlg_flag;              /*!< flag for dialog tracking */
83 static pv_spec_t *timeout_avp;          /*!< AVP for timeout setting */
84 static int       default_timeout;       /*!< default dialog timeout */
85 static int       seq_match_mode;        /*!< dlg_match mode */ 
86 static int       shutdown_done = 0;     /*!< 1 when destroy_dlg_handlers was called */
87 extern int       detect_spirals;
88
89 extern struct rr_binds d_rrb;           /*!< binding to record-routing module */
90
91 /* statistic variables */
92 extern stat_var *early_dlgs;            /*!< number of early dialogs */
93 extern stat_var *processed_dlgs;        /*!< number of processed dialogs */
94 extern stat_var *expired_dlgs;          /*!< number of expired dialogs */
95 extern stat_var *failed_dlgs;           /*!< number of failed dialogs */
96
97 extern pv_elem_t *ruri_param_model;     /*!< pv-string to get r-uri */
98
99 static unsigned int CURR_DLG_LIFETIME = 0;      /*!< current dialog lifetime */
100 static unsigned int CURR_DLG_STATUS = 0;        /*!< current dialog state */
101 static unsigned int CURR_DLG_ID  = 0xffffffff;  /*!< current dialog id */
102
103
104 /*! size of the dialog record-route parameter */
105 #define RR_DLG_PARAM_SIZE  (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
106 /*! separator inside the record-route paramter */
107 #define DLG_SEPARATOR      '.'
108
109
110 /*!
111  * \brief Initialize the dialog handlers
112  * \param rr_param_p added record-route parameter
113  * \param dlg_flag_p dialog flag
114  * \param timeout_avp_p AVP for timeout setting
115  * \param default_timeout_p default timeout
116  * \param seq_match_mode_p matching mode
117  */
118 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
119                 pv_spec_t *timeout_avp_p ,int default_timeout_p,
120                 int seq_match_mode_p)
121 {
122         rr_param.s = rr_param_p;
123         rr_param.len = strlen(rr_param.s);
124
125         dlg_flag = 1<<dlg_flag_p;
126
127         timeout_avp = timeout_avp_p;
128         default_timeout = default_timeout_p;
129         seq_match_mode = seq_match_mode_p;
130 }
131
132
133 /*!
134  * \brief Shutdown operation of the module
135  */
136 void destroy_dlg_handlers(void)
137 {
138         shutdown_done = 1;
139 }
140
141
142 /*!
143  * \brief Add record-route parameter for dialog tracking
144  * \param req SIP request
145  * \param entry dialog hash entry
146  * \param id dialog hash id
147  * \return 0 on success, -1 on failure
148  */
149 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
150                 unsigned int id)
151 {
152         static char buf[RR_DLG_PARAM_SIZE];
153         str s;
154         int n;
155         char *p;
156
157         s.s = p = buf;
158
159         *(p++) = ';';
160         memcpy(p, rr_param.s, rr_param.len);
161         p += rr_param.len;
162         *(p++) = '=';
163
164         n = RR_DLG_PARAM_SIZE - (p-buf);
165         if (int2reverse_hex( &p, &n, entry)==-1)
166                 return -1;
167
168         *(p++) = DLG_SEPARATOR;
169
170         n = RR_DLG_PARAM_SIZE - (p-buf);
171         if (int2reverse_hex( &p, &n, id)==-1)
172                 return -1;
173
174         s.len = p-buf;
175
176         if (d_rrb.add_rr_param( req, &s)<0) {
177                 LM_ERR("failed to add rr param\n");
178                 return -1;
179         }
180
181         return 0;
182 }
183
184
185 /*!
186  * \brief Parse SIP message and populate leg informations
187  *
188  * Parse SIP message and populate leg informations. 
189  * \param dlg the dialog to add cseq, contact & record_route
190  * \param msg sip message
191  * \param flag  0-for a request(INVITE), 1- for a reply(200 ok)
192  * \return 0 on success, -1 on failure
193  * \note for a request: get record route in normal order, for a reply get
194  * in reverse order, skipping the ones from the request and the proxies' own
195  */
196 int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
197         struct cell* t, unsigned int leg, str *tag)
198 {
199         unsigned int skip_recs;
200         str cseq;
201         str contact;
202         str rr_set;
203
204         dlg->bind_addr[leg] = msg->rcv.bind_address;
205
206         /* extract the cseq number as string */
207         if (leg==DLG_CALLER_LEG) {
208                 if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
209                         || !msg->cseq->parsed){
210                         LM_ERR("bad sip message or missing CSeq hdr :-/\n");
211                         goto error0;
212                 }
213                 cseq = (get_cseq(msg))->number;
214         } else {
215                 /* use the same as in request */
216                 cseq = dlg->cseq[DLG_CALLER_LEG];
217         }
218
219         /* extract the contact address */
220         if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
221                 LM_ERR("bad sip message or missing Contact hdr\n");
222                 goto error0;
223         }
224         if ( parse_contact(msg->contact)<0 ||
225         ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
226         ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
227                 LM_ERR("bad Contact HDR\n");
228                 goto error0;
229         }
230         contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;
231
232         /* extract the RR parts */
233         if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0)  ){
234                 LM_ERR("failed to parse record route header\n");
235                 goto error0;
236         }
237
238         if (leg==DLG_CALLER_LEG) {
239                 skip_recs = 0;
240         } else {
241                 /* was the 200 OK received or local generated */
242                 skip_recs = dlg->from_rr_nb +
243                         ((t->relayed_reply_branch>=0)?
244                                 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
245                                  ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
246                                 :0);
247         }
248
249         if(msg->record_route){
250                 if( print_rr_body(msg->record_route, &rr_set, leg,
251                                                         &skip_recs) != 0 ){
252                         LM_ERR("failed to print route records \n");
253                         goto error0;
254                 }
255         } else {
256                 rr_set.s = 0;
257                 rr_set.len = 0;
258         }
259
260         if(leg==DLG_CALLER_LEG)
261                 dlg->from_rr_nb = skip_recs;
262
263         LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
264                 rr_set.len, rr_set.s, contact.len, contact.s,
265                 cseq.len, cseq.s,
266                 msg->rcv.bind_address->sock_str.len,
267                 msg->rcv.bind_address->sock_str.s);
268
269         if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
270                 LM_ERR("dlg_set_leg_info failed\n");
271                 if (rr_set.s) pkg_free(rr_set.s);
272                 goto error0;
273         }
274
275         if (rr_set.s) pkg_free(rr_set.s);
276
277         return 0;
278 error0:
279         return -1;
280 }
281
282
283 /*!
284  * \brief Function that is registered as TM callback and called on replies
285  *
286  * Function that is registered as TM callback and called on replies. It
287  * parses the reply and set the appropriate event. This is then used to
288  * update the dialog state, run eventual dialog callbacks and save or
289  * update the necessary informations about the dialog.
290  * \see next_state_dlg
291  * \param t transaction, unused
292  * \param type type of the entered callback
293  * \param param saved dialog structure in the callback
294  */
295 static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
296 {
297         struct sip_msg *rpl;
298         struct dlg_cell *dlg;
299         int new_state, old_state, unref, event;
300         str tag;
301
302         dlg = (struct dlg_cell *)(*param->param);
303         if (shutdown_done || dlg==0)
304                 return;
305
306         rpl = param->rpl;
307
308         if (type==TMCB_RESPONSE_FWDED) {
309                 /* The state does not change, but the msg is mutable in this callback*/
310                 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
311                 return;
312         }
313
314         if (type==TMCB_DESTROY)
315                 event = DLG_EVENT_TDEL;
316         else if (param->code<200)
317                 event = DLG_EVENT_RPL1xx;
318         else if (param->code<300)
319                 event = DLG_EVENT_RPL2xx;
320         else
321                 event = DLG_EVENT_RPL3xx;
322
323         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
324
325         if (new_state==DLG_STATE_EARLY) {
326                 run_dlg_callbacks(DLGCB_EARLY, dlg, rpl, DLG_DIR_UPSTREAM, 0);
327                 if (old_state!=DLG_STATE_EARLY)
328                         if_update_stat(dlg_enable_stats, early_dlgs, 1);
329                 return;
330         }
331
332         if (new_state==DLG_STATE_CONFIRMED_NA &&
333         old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
334                 LM_DBG("dialog %p confirmed\n",dlg);
335
336                  if (rpl != FAKED_REPLY) {
337                         /* get to tag*/
338                         if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
339                                                 || !rpl->to) ) {
340                                 LM_ERR("bad reply or missing TO hdr :-/\n");
341                                 tag.s = 0;
342                                 tag.len = 0;
343                         } else {
344                                 tag = get_to(rpl)->tag_value;
345                                 if (tag.s==0 || tag.len==0) {
346                                         LM_ERR("missing TAG param in TO hdr :-/\n");
347                                         tag.s = 0;
348                                         tag.len = 0;
349                                 }
350                         }
351
352                         /* save callee's tag, cseq, contact and record route*/
353                         if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
354                                 LM_ERR("could not add further info to the dialog\n");
355                         }
356                  } else {
357                          LM_ERR("Faked reply!\n");
358                  }
359
360                 /* set start time */
361                 dlg->start_ts = (unsigned int)(time(0));
362
363                 /* save the settings to the database,
364                  * if realtime saving mode configured- save dialog now
365                  * else: the next time the timer will fire the update*/
366                 dlg->dflags |= DLG_FLAG_NEW;
367                 if ( dlg_db_mode==DB_MODE_REALTIME )
368                         update_dialog_dbinfo(dlg);
369
370                 if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
371                         LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
372                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
373                                 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
374                                 dlg->callid.len, dlg->callid.s,
375                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
376                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
377                 } else {
378                         ref_dlg(dlg,1);
379                 }
380
381                 /* dialog confirmed */
382                 run_dlg_callbacks( DLGCB_CONFIRMED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
383
384                 if (old_state==DLG_STATE_EARLY)
385                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
386
387                 if (unref) unref_dlg(dlg,unref);
388                 if_update_stat(dlg_enable_stats, active_dlgs, 1);
389                 return;
390         }
391
392         if ( old_state!=DLG_STATE_DELETED && new_state==DLG_STATE_DELETED ) {
393                 LM_DBG("dialog %p failed (negative reply)\n", dlg);
394                 /* dialog setup not completed (3456XX) */
395                 run_dlg_callbacks( DLGCB_FAILED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
396                 /* do unref */
397                 if (unref)
398                         unref_dlg(dlg,unref);
399                 if (old_state==DLG_STATE_EARLY)
400                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
401
402                 if_update_stat(dlg_enable_stats, failed_dlgs, 1);
403
404                 return;
405         }
406
407         if (unref) unref_dlg(dlg,unref);
408
409         return;
410 }
411
412
413 /*!
414  * \brief Helper function that run dialog callbacks on forwarded requests
415  * \see dlg_seq_up_onreply
416  * \see dlg_seq_down_onreply
417  * \param t transaction, unused
418  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
419  * \param param saved dialog structure inside the callback
420  * \param direction direction of the request
421  */
422 static void dlg_seq_onreply_helper(struct cell* t, int type,
423                 struct tmcb_params *param, const int direction)
424 {
425         struct dlg_cell *dlg;
426
427         dlg = (struct dlg_cell *)(*param->param);
428         if (shutdown_done || dlg==0)
429                 return;
430
431         if (type==TMCB_RESPONSE_FWDED) {
432                 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN, dlg, param->rpl,
433                         direction, 0);
434                 return;
435         }
436
437         return;
438 }
439
440
441 /*!
442  * \brief Run dialog callbacks on forwarded requests in upstream direction
443  * \see dlg_seq_onreply_helper
444  * \param t transaction, unused
445  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
446  * \param param saved dialog structure inside the callback
447  */
448 static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param)
449 {
450         return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
451 }
452
453
454 /*!
455  * \brief Run dialog callbacks on forwarded requests in downstream direction
456  * \see dlg_seq_onreply_helper
457  * \param t transaction, unused
458  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
459  * \param param saved dialog structure inside the callback
460  */
461 static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param)
462 {
463         return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
464 }
465
466
467 /*!
468  * \brief Return the timeout for a dialog
469  * \param req SIP message
470  * \return value from timeout AVP if present or default timeout
471  */
472 inline static int get_dlg_timeout(struct sip_msg *req)
473 {
474         pv_value_t pv_val;
475
476         if( timeout_avp ) {
477                 if ( pv_get_spec_value( req, timeout_avp, &pv_val)==0 &&
478                                 pv_val.flags&PV_VAL_INT && pv_val.ri>0 ) {
479                         return pv_val.ri;
480                 }
481                 LM_DBG("invalid AVP value, using default timeout\n");
482         }
483         return default_timeout;
484 }
485
486
487 /*!
488  * \brief Helper function to get the necessary content from SIP message
489  * \param req SIP request
490  * \param callid found callid
491  * \param ftag found from tag
492  * \param ttag found to tag
493  * \param with_ttag flag set if to tag must be found for success
494  * \return 0 on success, -1 on failure
495  */
496 static inline int pre_match_parse( struct sip_msg *req, str *callid,
497                 str *ftag, str *ttag, int with_ttag)
498 {
499         if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
500                         !req->to ) {
501                 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
502                 return -1;
503         }
504
505         if (get_to(req)->tag_value.len==0) {
506                 if (with_ttag == 1) {
507                         /* out of dialog request with preloaded Route headers; ignore. */
508                         return -1;
509                 } else {
510                         ttag->s = NULL;
511                         ttag->len = 0;
512                 }
513         } else {
514                 *ttag = get_to(req)->tag_value;
515         }
516
517         if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
518                 LM_ERR("failed to get From header\n");
519                 return -1;
520         }
521
522         /* callid */
523         *callid = req->callid->body;
524         trim(callid);
525         /* from tag */
526         *ftag = get_from(req)->tag_value;
527         return 0;
528 }
529
530
531 /*!
532  * \brief Function that is registered as TM callback and called on requests
533  * \see dlg_new_dialog
534  * \param t transaction, used to created the dialog
535  * \param type type of the entered callback
536  * \param param saved dialog structure in the callback
537  */
538 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
539 {
540         struct dlg_cell *dlg;
541         str callid;
542         str ftag;
543         str ttag;
544         unsigned int dir;
545         unsigned int del;
546         struct sip_msg *req = param->req;
547
548         if((req->flags&dlg_flag)!=dlg_flag)
549                 return;
550         if (current_dlg_pointer!=NULL)
551                 return;
552         if (!detect_spirals)
553                 goto create;
554
555         /* skip initial requests - they may end up here because of the
556          * preloaded route */
557         if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
558                 LM_ERR("bad request or missing TO hdr :-/\n");
559                 return;
560         }
561
562         dlg = 0;
563         dir = DLG_DIR_NONE;
564
565         if (pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
566                 LM_WARN("pre-matching failed\n");
567                 return;
568         }
569         dlg = get_dlg(&callid, &ftag, &ttag, &dir, &del);
570         if (del == 1) {
571                 LM_DBG("dialog marked for deletion, ignoring\n");
572                 return;
573         }
574         if (!dlg){
575                 LM_DBG("Callid '%.*s' not found, must be a new dialog\n",
576                                 req->callid->body.len, req->callid->body.s);
577                 goto create;
578         }
579
580         run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, DLG_DIR_DOWNSTREAM, 0);
581
582         unref_dlg(dlg, 1);
583         return;
584
585 create:
586         dlg_new_dialog(req, t);
587 }
588
589
590 /*!
591  * \brief Unreference a new dialog, helper function for dlg_onreq
592  * \see dlg_onreq
593  * \param dialog unreferenced dialog
594  */
595 static void unref_new_dialog(void *dialog)
596 {
597         struct tmcb_params p;
598
599         memset(&p, 0, sizeof(struct tmcb_params));
600         p.param = (void*)&dialog;
601         dlg_onreply(0, TMCB_DESTROY, &p);
602 }
603
604
605 /*!
606  * \brief Dummy callback just to keep the compiler happy
607  * \param t unused
608  * \param type unused
609  * \param param unused
610  */
611 void dlg_tmcb_dummy(struct cell* t, int type, struct tmcb_params *param)
612 {
613         return;
614 }
615
616
617 /*!
618  * \brief Create a new dialog from a sip message
619  *
620  * Create a new dialog from a SIP message, register a callback
621  * to keep track of the dialog with help of the tm module.
622  * This function is either called from the request callback, or
623  * from the dlg_manage function in the configuration script.
624  * \see dlg_onreq
625  * \see w_dlg_manage
626  * \param msg SIP message
627  * \param t transaction
628  * \return 0 on success, -1 on failure
629  */ 
630 int dlg_new_dialog(struct sip_msg *msg, struct cell *t)
631 {
632         struct dlg_cell *dlg;
633         str s;
634         str req_uri;
635
636         if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
637         {
638                 LM_ERR("bad request or missing TO hdr\n");
639                 return -1;
640         }
641         s = get_to(msg)->tag_value;
642         if(s.s!=0 && s.len!=0)
643                 return -1;
644
645         if(msg->first_line.u.request.method_value==METHOD_CANCEL)
646                 return -1;
647
648         if(parse_from_header(msg))
649         {
650                 LM_ERR("bad request or missing FROM hdr\n");
651                 return -1;
652         }
653         if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
654                         || msg->callid==NULL){
655                 LM_ERR("bad request or missing CALLID hdr\n");
656                 return -1;
657         }
658         s = msg->callid->body;
659         trim(&s);
660
661         if (pv_printf_s(msg, ruri_param_model, &req_uri)<0) {
662                 LM_ERR("error - cannot print the r-uri format\n");
663                 return -1;
664         }
665         trim(&req_uri);
666
667         /* some sanity checks */
668         if (s.len==0 || get_from(msg)->tag_value.len==0) {
669                 LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
670                         s.len, get_from(msg)->tag_value.len);
671                 return -1;
672         }
673
674         dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/,
675                 &(get_to(msg)->uri) /*to uri*/,
676                 &(get_from(msg)->tag_value)/*from_tag*/, &req_uri /*r-uri*/ );
677         if (dlg==0) {
678                 LM_ERR("failed to create new dialog\n");
679                 return -1;
680         }
681
682         /* save caller's tag, cseq, contact and record route*/
683         if (populate_leg_info(dlg, msg, t, DLG_CALLER_LEG,
684                         &(get_from(msg)->tag_value)) !=0)
685         {
686                 LM_ERR("could not add further info to the dialog\n");
687                 shm_free(dlg);
688                 return -1;
689         }
690
691         set_current_dialog(msg, dlg);
692         _dlg_ctx.dlg = dlg;
693
694         link_dlg(dlg, 2/* extra ref for the callback and current dlg hook */);
695
696         /* first INVITE seen (dialog created, unconfirmed) */
697         if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
698                         add_dlg_rr_param( msg, dlg->h_entry, dlg->h_id)<0 ) {
699                 LM_ERR("failed to add RR param\n");
700                 goto error;
701         }
702
703         if ( d_tmb.register_tmcb( msg, t,
704                                 TMCB_RESPONSE_READY|TMCB_RESPONSE_FWDED,
705                                 dlg_onreply, (void*)dlg, unref_new_dialog)<0 ) {
706                 LM_ERR("failed to register TMCB\n");
707                 goto error;
708         }
709
710         dlg->lifetime = get_dlg_timeout(msg);
711         s.s   = _dlg_ctx.to_route_name;
712         s.len = strlen(s.s);
713         dlg_set_toroute(dlg, &s);
714         dlg->sflags |= _dlg_ctx.flags;
715
716         if (_dlg_ctx.to_bye!=0)
717                 dlg->dflags |= DLG_FLAG_TOBYE;
718
719         if (t) {
720                 if ( d_tmb.register_tmcb( msg, t, TMCB_MAX,
721                                         dlg_tmcb_dummy, (void*)dlg, 0)<0 ) {
722                         LM_ERR("failed cache in T the shortcut to dlg\n");
723                         goto error;
724                 }
725         }
726 #if 0
727                 t->dialog_ctx = (void*) dlg;
728 #endif
729
730         run_create_callbacks( dlg, msg);
731
732         if_update_stat( dlg_enable_stats, processed_dlgs, 1);
733
734         return 0;
735 error:
736         unref_dlg(dlg,1);
737         profile_cleanup(msg, 0, NULL);
738         return -1;
739 }
740
741
742 /*!
743  * \brief Parse the record-route parameter, to get dialog information back
744  * \param p start of parameter string
745  * \param end end of parameter string
746  * \param h_entry found dialog hash entry
747  * \param h_id found dialog hash id
748  * \return 0 on success, -1 on failure
749  */
750 static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id)
751 {
752         char *s;
753
754         for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
755         if (*p!=DLG_SEPARATOR) {
756                 LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s);
757                 return -1;
758         }
759
760         if ( reverse_hex2int( s, p-s, (unsigned int*)h_entry)<0 ) {
761                 LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s);
762                 return -1;
763         }
764
765         if ( reverse_hex2int( p+1, end-(p+1), (unsigned int*)h_id)<0 ) {
766                 LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 );
767                 return -1;
768         }
769
770         return 0;
771 }
772
773
774 /*!
775  * \brief Update the saved CSEQ information in dialog from SIP message
776  * \param dlg updated dialog
777  * \param req SIP request
778  * \param dir direction of request, must DLG_DIR_UPSTREAM or DLG_DIR_DOWNSTREAM
779  * \return 0 on success, -1 on failure
780  */
781 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
782                 unsigned int dir)
783 {
784         if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
785         !req->cseq->parsed) {
786                 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
787                 return -1;
788         }
789
790         if ( dir==DLG_DIR_UPSTREAM) {
791                 return dlg_update_cseq(dlg, DLG_CALLEE_LEG,&((get_cseq(req))->number));
792         } else if ( dir==DLG_DIR_DOWNSTREAM) {
793                 return dlg_update_cseq(dlg, DLG_CALLER_LEG,&((get_cseq(req))->number));
794         } else {
795                 LM_CRIT("dir is not set!\n");
796                 return -1;
797         }
798 }
799
800
801 /*!
802  * \brief Unreference a dialog, small wrapper to care for shutdown
803  * \see unref_dlg 
804  * \param dialog unreferenced dialog
805  */
806 static void unreference_dialog(void *dialog)
807 {
808         // if the dialog table is gone, it means the system is shutting down.
809         if (!d_table)
810                 return;
811         unref_dlg((struct dlg_cell*)dialog, 1);
812 }
813
814
815 /*!
816  * \brief Unreference a dialog from tm callback (another wrapper)
817  * \param t transaction, unused
818  * \param type type of the entered callback
819  * \param param saved dialog structure in the callback
820  */
821 static void unref_dlg_from_cb(struct cell* t, int type, struct tmcb_params *param)
822 {
823         struct dlg_cell *dlg = (struct dlg_cell *)(*param->param);
824
825         if (!dlg)
826                 return;
827
828         /* destroy dialog */
829         unreference_dialog(dlg);
830 }
831
832
833 /*!
834  * \brief Function that is registered as RR callback for dialog tracking
835  * 
836  * Function that is registered as RR callback for dialog tracking. It
837  * sets the appropriate events after the SIP method and run the state
838  * machine to update the dialog state. It updates then the saved
839  * dialogs and also the statistics.
840  * \param req SIP request
841  * \param route_params record-route parameter
842  * \param param unused
843  */
844 void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
845 {
846         struct dlg_cell *dlg;
847         str val, callid, ftag, ttag;
848         int h_entry, h_id, new_state, old_state, unref, event, timeout;
849         unsigned int dir;
850         unsigned int del;
851         int ret = 0;
852
853         if (current_dlg_pointer!=NULL)
854                 return;
855
856         /* skip initial requests - they may end up here because of the
857          * preloaded route */
858         if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
859                 LM_ERR("bad request or missing TO hdr :-/\n");
860                 return;
861         }
862         if ( get_to(req)->tag_value.len==0 )
863                 return;
864
865         dlg = 0;
866         dir = DLG_DIR_NONE;
867
868         if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
869                 if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
870                         LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
871                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
872                                 return;
873                 } else {
874                         LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);
875
876                         if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
877                                 return;
878
879                         dlg = lookup_dlg( h_entry, h_id, &del);
880                         if (del == 1) {
881                                 LM_DBG("dialog marked for deletion, ignoring\n");
882                                 return;
883                         }
884                         if (dlg==0) {
885                                 LM_WARN("unable to find dialog for %.*s "
886                                         "with route param '%.*s' [%u:%u]\n",
887                                         req->first_line.u.request.method.len,
888                                         req->first_line.u.request.method.s,
889                                         val.len,val.s, h_entry, h_id);
890                                 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
891                                         return;
892                         } else {
893                                 // lookup_dlg has incremented the ref count by 1
894                                 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
895                                         unref_dlg(dlg, 1);
896                                         return;
897                                 }
898                                 if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
899                                         LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
900                                                         "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
901                                                         req->first_line.u.request.method.len,
902                                                         req->first_line.u.request.method.s,
903                                                         callid.len, callid.s, callid.len,
904                                                         ftag.len, ftag.s, ftag.len,
905                                                         ttag.len, ttag.s, ttag.len, dir);
906                                         LM_WARN("dialog identification elements are callid='%.*s'/%d, "
907                                                         "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
908                                                         dlg->callid.len, dlg->callid.s, dlg->callid.len,
909                                                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
910                                                         dlg->tag[DLG_CALLER_LEG].len,
911                                                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
912                                                         dlg->tag[DLG_CALLEE_LEG].len);
913                                         unref_dlg(dlg, 1);
914
915                                         // Reset variables in order to do a lookup based on SIP-Elements.
916                                         dlg = 0;
917                                         dir = DLG_DIR_NONE;
918
919                                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
920                                                 return;
921                                 }
922                         }
923                 }
924         }
925
926         if (dlg==0) {
927                 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
928                         return;
929                 /* TODO - try to use the RR dir detection to speed up here the
930                  * search -bogdan */
931                 dlg = get_dlg(&callid, &ftag, &ttag, &dir, &del);
932                 if (del == 1) {
933                         LM_DBG("dialog marked for deletion, ignoring\n");
934                         return;
935                 }
936                 if (!dlg){
937                         LM_DBG("Callid '%.*s' not found\n",
938                                 req->callid->body.len, req->callid->body.s);
939                         return;
940                 }
941         }
942
943         /* run state machine */
944         switch ( req->first_line.u.request.method_value ) {
945                 case METHOD_PRACK:
946                         event = DLG_EVENT_REQPRACK; break;
947                 case METHOD_ACK:
948                         event = DLG_EVENT_REQACK; break;
949                 case METHOD_BYE:
950                         event = DLG_EVENT_REQBYE; break;
951                 default:
952                         event = DLG_EVENT_REQ;
953         }
954
955         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
956
957         CURR_DLG_ID = req->id;
958         CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
959         CURR_DLG_STATUS = new_state;
960
961         /* set current dialog - it will keep a ref! */
962         set_current_dialog( req, dlg);
963         _dlg_ctx.dlg = dlg;
964
965         /* delay deletion of dialog until transaction has died off in order
966          * to absorb in-air messages */
967         if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
968                 if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
969                                         unref_dlg_from_cb, (void*)dlg, NULL)<0 ) {
970                         LM_ERR("failed to register deletion delay function\n");
971                 } else {
972                         ref_dlg(dlg, 1);
973                 }
974         }
975
976         /* run actions for the transition */
977         if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
978         old_state!=DLG_STATE_DELETED) {
979                 LM_DBG("BYE successfully processed\n");
980                 /* remove from timer */
981                 ret = remove_dialog_timer(&dlg->tl);
982                 if (ret < 0) {
983                         LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
984                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
985                                 dlg, dlg->h_entry, dlg->h_id,
986                                 dlg->callid.len, dlg->callid.s,
987                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
988                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
989                 } else if (ret > 0) {
990                         LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
991                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
992                                 dlg, dlg->h_entry, dlg->h_id,
993                                 dlg->callid.len, dlg->callid.s,
994                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
995                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
996                 } else {
997                         unref++;
998                 }
999                 /* dialog terminated (BYE) */
1000                 run_dlg_callbacks( DLGCB_TERMINATED, dlg, req, dir, 0);
1001
1002                 /* delete the dialog from DB */
1003                 if (dlg_db_mode)
1004                         remove_dialog_from_db(dlg);
1005
1006                 unref_dlg(dlg, unref);
1007
1008                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
1009                 return;
1010         }
1011
1012         if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
1013         && new_state==DLG_STATE_CONFIRMED) {
1014                 LM_DBG("sequential request successfully processed\n");
1015                 timeout = get_dlg_timeout(req);
1016                 if (timeout!=default_timeout) {
1017                         dlg->lifetime = timeout;
1018                 }
1019                 if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
1020                         LM_ERR("failed to update dialog lifetime\n");
1021                 }
1022                 if (update_cseqs(dlg, req, dir)!=0) {
1023                         LM_ERR("cseqs update failed\n");
1024                 } else {
1025                         dlg->dflags |= DLG_FLAG_CHANGED;
1026                         if ( dlg_db_mode==DB_MODE_REALTIME )
1027                                 update_dialog_dbinfo(dlg);
1028                 }
1029
1030                 /* within dialog request */
1031                 run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, dir, 0);
1032
1033                 if ( (event!=DLG_EVENT_REQACK) &&
1034                 (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
1035                         /* ref the dialog as registered into the transaction callback.
1036                          * unref will be done when the callback will be destroyed */
1037                         ref_dlg( dlg , 1);
1038                         /* register callback for the replies of this request */
1039                         if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
1040                         (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:dlg_seq_up_onreply,
1041                         (void*)dlg, unreference_dialog)<0 ) {
1042                                 LM_ERR("failed to register TMCB (2)\n");
1043                                         unref_dlg( dlg , 1);
1044                         }
1045                 }
1046         }
1047
1048         if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
1049                 dlg->dflags |= DLG_FLAG_CHANGED;
1050                 if(dlg_db_mode == DB_MODE_REALTIME)
1051                         update_dialog_dbinfo(dlg);
1052         }
1053
1054         return;
1055 }
1056
1057
1058 /*!
1059  * \brief Timer function that removes expired dialogs, run timeout route
1060  * \param tl dialog timer list
1061  */
1062 void dlg_ontimeout( struct dlg_tl *tl)
1063 {
1064         struct dlg_cell *dlg;
1065         int new_state, old_state, unref;
1066         struct sip_msg *fmsg;
1067
1068         /* get the dialog tl payload */
1069         dlg = ((struct dlg_cell*)((char *)(tl) -
1070                 (unsigned long)(&((struct dlg_cell*)0)->tl)));
1071
1072         if(dlg->toroute>0 && dlg->toroute<main_rt.entries
1073                         && main_rt.rlist[dlg->toroute]!=NULL)
1074         {
1075                 fmsg = faked_msg_next();
1076                 if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
1077                 {
1078                         dlg_set_ctx_dialog(dlg);
1079                         LM_DBG("executing route %d on timeout\n", dlg->toroute);
1080                         set_route_type(REQUEST_ROUTE);
1081                         run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0);
1082                         dlg_set_ctx_dialog(0);
1083                         exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
1084                 }
1085         }
1086
1087         if ((dlg->dflags&DLG_FLAG_TOBYE)
1088                         && (dlg->state==DLG_STATE_CONFIRMED_NA
1089                                 || dlg->state==DLG_STATE_CONFIRMED))
1090         {
1091                 dlg_bye_all(dlg, NULL);
1092                 unref_dlg(dlg, 1);
1093                 if_update_stat(dlg_enable_stats, expired_dlgs, 1);
1094                 return;
1095         }
1096
1097         next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
1098
1099         if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
1100                 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
1101                         dlg->callid.len, dlg->callid.s,
1102                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
1103                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
1104
1105                 /* dialog timeout */
1106                 run_dlg_callbacks( DLGCB_EXPIRED, dlg, 0, DLG_DIR_NONE, 0);
1107
1108                 /* delete the dialog from DB */
1109                 if (dlg_db_mode)
1110                         remove_dialog_from_db(dlg);
1111
1112                 unref_dlg(dlg, unref+1);
1113
1114                 if_update_stat( dlg_enable_stats, expired_dlgs, 1);
1115                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
1116         } else {
1117                 unref_dlg(dlg, 1);
1118         }
1119
1120         return;
1121 }
1122
1123
1124 /*!
1125  * \brief Function that returns the dialog lifetime as pseudo-variable
1126  * \param msg SIP message
1127  * \param param pseudo-variable parameter
1128  * \param res pseudo-variable result
1129  * \return 0 on success, -1 on failure
1130  */
1131 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1132 {
1133         int l = 0;
1134         char *ch = NULL;
1135
1136         if(msg==NULL || res==NULL)
1137                 return -1;
1138
1139         if (CURR_DLG_ID!=msg->id)
1140                 return pv_get_null( msg, param, res);
1141
1142         res->ri = CURR_DLG_LIFETIME;
1143         ch = int2str( (unsigned long)res->ri, &l);
1144
1145         res->rs.s = ch;
1146         res->rs.len = l;
1147
1148         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
1149
1150         return 0;
1151 }
1152
1153
1154 /*!
1155  * \brief Function that returns the dialog state as pseudo-variable
1156  * \param msg SIP message
1157  * \param param pseudo-variable parameter
1158  * \param res pseudo-variable result
1159  * \return 0 on success, -1 on failure
1160  */
1161 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1162 {
1163         int l = 0;
1164         char *ch = NULL;
1165
1166         if(msg==NULL || res==NULL)
1167                 return -1;
1168
1169         if (CURR_DLG_ID!=msg->id)
1170                 return pv_get_null( msg, param, res);
1171
1172         res->ri = CURR_DLG_STATUS;
1173         ch = int2str( (unsigned long)res->ri, &l);
1174
1175         res->rs.s = ch;
1176         res->rs.len = l;
1177
1178         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
1179
1180         return 0;
1181 }