dialog: increment cseq in early stage for PRACK and UPDATE
[sip-router] / modules / dialog / dlg_handlers.c
1 /*
2  * Copyright (C) 2006 Voice System SRL
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * History:
21  * --------
22  * 2006-04-14  initial version (bogdan)
23  * 2006-11-28  Added support for tracking the number of early dialogs, and the
24  *             number of failed dialogs. This involved updates to dlg_onreply()
25  *             (Jeffrey Magder - SOMA Networks)
26  * 2007-03-06  syncronized state machine added for dialog state. New tranzition
27  *             design based on events; removed num_1xx and num_2xx (bogdan)
28  * 2007-04-30  added dialog matching without DID (dialog ID), but based only
29  *             on RFC3261 elements - based on an original patch submitted
30  *             by Michel Bensoussan <michel@extricom.com> (bogdan)
31  * 2007-05-17  new feature: saving dialog info into a database if
32  *             realtime update is set(ancuta)
33  * 2007-07-06  support for saving additional dialog info : cseq, contact,
34  *             route_set and socket_info for both caller and callee (ancuta)
35  * 2007-07-10  Optimized dlg_match_mode 2 (DID_NONE), it now employs a proper
36  *             hash table lookup and isn't dependant on the is_direction
37  *             function (which requires an RR param like dlg_match_mode 0
38  *             anyways.. ;) ; based on a patch from
39  *             Tavis Paquette <tavis@galaxytelecom.net>
40  *             and Peter Baer <pbaer@galaxytelecom.net>  (bogdan)
41  * 2008-04-04  added direction reporting in dlg callbacks (bogdan)
42  */
43
44
45 /*!
46  * \file
47  * \brief Functions related to dialog handling
48  * \ingroup dialog
49  * Module: \ref dialog
50  */
51
52 #include <string.h>
53 #include <time.h>
54
55 #include "../../trim.h"
56 #include "../../pvar.h"
57 #include "../../timer.h"
58 #include "../../lib/kcore/statistics.h"
59 #include "../../action.h"
60 #include "../../script_cb.h"
61 #include "../../lib/kcore/faked_msg.h"
62 #include "../../parser/parse_from.h"
63 #include "../../parser/parse_cseq.h"
64 #include "../../parser/contact/parse_contact.h"
65 #include "../../parser/parse_from.h"
66 #include "../../parser/parse_rr.h"
67 #include "../../modules/tm/tm_load.h"
68 #include "../rr/api.h"
69 #include "dlg_hash.h"
70 #include "dlg_timer.h"
71 #include "dlg_cb.h"
72 #include "dlg_handlers.h"
73 #include "dlg_req_within.h"
74 #include "dlg_db_handler.h"
75 #include "dlg_profile.h"
76 #include "dlg_var.h"
77
78 static str       rr_param;              /*!< record-route parameter for matching */
79 static int       dlg_flag;              /*!< flag for dialog tracking */
80 static pv_spec_t *timeout_avp;          /*!< AVP for timeout setting */
81 static int       default_timeout;       /*!< default dialog timeout */
82 static int       seq_match_mode;        /*!< dlg_match mode */ 
83 static int       shutdown_done = 0;     /*!< 1 when destroy_dlg_handlers was called */
84 extern int       detect_spirals;
85 extern int       initial_cbs_inscript;
86 extern int       dlg_send_bye;
87 extern int       dlg_event_rt[DLG_EVENTRT_MAX];
88 extern int       dlg_wait_ack;
89 int              spiral_detected = -1;
90
91 extern struct rr_binds d_rrb;           /*!< binding to record-routing module */
92
93 /* statistic variables */
94 extern stat_var *early_dlgs;            /*!< number of early dialogs */
95 extern stat_var *processed_dlgs;        /*!< number of processed dialogs */
96 extern stat_var *expired_dlgs;          /*!< number of expired dialogs */
97 extern stat_var *failed_dlgs;           /*!< number of failed dialogs */
98
99 extern pv_elem_t *ruri_param_model;     /*!< pv-string to get r-uri */
100
101 static unsigned int CURR_DLG_LIFETIME = 0;      /*!< current dialog lifetime */
102 static unsigned int CURR_DLG_STATUS = 0;        /*!< current dialog state */
103 static unsigned int CURR_DLG_ID  = 0xffffffff;  /*!< current dialog id */
104
105
106 /*! size of the dialog record-route parameter */
107 #define RR_DLG_PARAM_SIZE  (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
108 /*! separator inside the record-route paramter */
109 #define DLG_SEPARATOR      '.'
110
111 int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg,
112                 int mode);
113 int dlg_set_tm_waitack(tm_cell_t *t, dlg_cell_t *dlg);
114
115 /*!
116  * \brief Initialize the dialog handlers
117  * \param rr_param_p added record-route parameter
118  * \param dlg_flag_p dialog flag
119  * \param timeout_avp_p AVP for timeout setting
120  * \param default_timeout_p default timeout
121  * \param seq_match_mode_p matching mode
122  */
123 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
124                 pv_spec_t *timeout_avp_p ,int default_timeout_p,
125                 int seq_match_mode_p)
126 {
127         rr_param.s = rr_param_p;
128         rr_param.len = strlen(rr_param.s);
129
130         dlg_flag = 1<<dlg_flag_p;
131
132         timeout_avp = timeout_avp_p;
133         default_timeout = default_timeout_p;
134         seq_match_mode = seq_match_mode_p;
135 }
136
137
138 /*!
139  * \brief Shutdown operation of the module
140  */
141 void destroy_dlg_handlers(void)
142 {
143         shutdown_done = 1;
144 }
145
146
147 /*!
148  * \brief Add record-route parameter for dialog tracking
149  * \param req SIP request
150  * \param entry dialog hash entry
151  * \param id dialog hash id
152  * \return 0 on success, -1 on failure
153  */
154 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
155                 unsigned int id)
156 {
157         static char buf[RR_DLG_PARAM_SIZE];
158         str s;
159         int n;
160         char *p;
161
162         s.s = p = buf;
163
164         *(p++) = ';';
165         memcpy(p, rr_param.s, rr_param.len);
166         p += rr_param.len;
167         *(p++) = '=';
168
169         n = RR_DLG_PARAM_SIZE - (p-buf);
170         if (int2reverse_hex( &p, &n, entry)==-1)
171                 return -1;
172
173         *(p++) = DLG_SEPARATOR;
174
175         n = RR_DLG_PARAM_SIZE - (p-buf);
176         if (int2reverse_hex( &p, &n, id)==-1)
177                 return -1;
178
179         s.len = p-buf;
180
181         if (d_rrb.add_rr_param( req, &s)<0) {
182                 LM_ERR("failed to add rr param\n");
183                 return -1;
184         }
185
186         return 0;
187 }
188
189
190 /*!
191  * \brief Parse SIP message and populate leg informations
192  *
193  * Parse SIP message and populate leg informations. 
194  * \param dlg the dialog to add cseq, contact & record_route
195  * \param msg sip message
196  * \param t transaction
197  * \param leg type of the call leg
198  * \param tag SIP To tag
199  * \return 0 on success, -1 on failure
200  * \note for a request: get record route in normal order, for a reply get
201  * in reverse order, skipping the ones from the request and the proxies' own
202  */
203 int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
204         struct cell* t, unsigned int leg, str *tag)
205 {
206         unsigned int skip_recs;
207         str cseq;
208         str contact;
209         str rr_set;
210
211         dlg->bind_addr[leg] = msg->rcv.bind_address;
212
213         /* extract the cseq number as string */
214         if (leg==DLG_CALLER_LEG) {
215                 if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
216                         || !msg->cseq->parsed){
217                         LM_ERR("bad sip message or missing CSeq hdr :-/\n");
218                         goto error0;
219                 }
220                 cseq = (get_cseq(msg))->number;
221         } else {
222                 /* use the same as in request */
223                 cseq = dlg->cseq[DLG_CALLEE_LEG];
224         }
225
226         /* extract the contact address */
227         if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
228                 LM_ERR("bad sip message or missing Contact hdr\n");
229                 goto error0;
230         }
231         if ( parse_contact(msg->contact)<0 ||
232         ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
233         ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
234                 LM_ERR("bad Contact HDR\n");
235                 goto error0;
236         }
237         contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;
238
239         /* extract the RR parts */
240         if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0)  ){
241                 LM_ERR("failed to parse record route header\n");
242                 goto error0;
243         }
244
245         if (leg==DLG_CALLER_LEG) {
246                 skip_recs = 0;
247         } else {
248                 /* was the 200 OK received or local generated */
249                 skip_recs = dlg->from_rr_nb +
250                         ((t->relayed_reply_branch>=0)?
251                                 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
252                                  ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
253                                 :0);
254         }
255
256         if(msg->record_route){
257                 if( print_rr_body(msg->record_route, &rr_set, leg,
258                                                         &skip_recs) != 0 ){
259                         LM_ERR("failed to print route records \n");
260                         goto error0;
261                 }
262         } else {
263                 rr_set.s = 0;
264                 rr_set.len = 0;
265         }
266
267         if(leg==DLG_CALLER_LEG)
268                 dlg->from_rr_nb = skip_recs;
269
270         LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
271                 rr_set.len, rr_set.s, contact.len, contact.s,
272                 cseq.len, cseq.s,
273                 msg->rcv.bind_address->sock_str.len,
274                 msg->rcv.bind_address->sock_str.s);
275
276         if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
277                 LM_ERR("dlg_set_leg_info failed\n");
278                 if (rr_set.s) pkg_free(rr_set.s);
279                 goto error0;
280         }
281
282         if (rr_set.s) pkg_free(rr_set.s);
283
284         return 0;
285 error0:
286         return -1;
287 }
288
289 /*!
290  * \brief Clone dialog internal unique id to shared memory
291  */
292 dlg_iuid_t *dlg_get_iuid_shm_clone(dlg_cell_t *dlg)
293 {
294         dlg_iuid_t *iuid = NULL;
295
296         if(dlg==NULL)
297                 return NULL;
298
299         iuid = (dlg_iuid_t*)shm_malloc(sizeof(dlg_iuid_t));
300         if(iuid==NULL)
301         {
302                 LM_ERR("failed to clone dialog iuid\n");
303                 return NULL;
304         }
305
306         memset(iuid, 0, sizeof(dlg_iuid_t));
307         iuid->h_entry = dlg->h_entry;
308         iuid->h_id = dlg->h_id;
309
310         return iuid;
311 }
312
313
314 /*!
315  * \brief Free dialog internal unique id stored in shared memory
316  */
317 void dlg_iuid_sfree(void *iuid)
318 {
319     if(iuid) {
320                 LM_DBG("freeing dlg iuid [%u:%u] (%p)\n",
321                                 ((dlg_iuid_t*)iuid)->h_entry,
322                                 ((dlg_iuid_t*)iuid)->h_id, iuid);
323                 shm_free(iuid);
324         }
325 }
326
327
328 /*!
329  * \brief Function that executes BYE reply callbacks
330  * \param t transaction, unused
331  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
332  * \param params saved dialog structure inside the callback
333  */
334 static void dlg_terminated_confirmed(tm_cell_t *t, int type,
335                                      struct tmcb_params* params)
336 {
337     dlg_cell_t *dlg = NULL;
338         dlg_iuid_t *iuid = NULL;
339
340     if(!params || !params->req || !params->param)
341     {
342         LM_ERR("invalid parameters!\n");
343         return;
344     }
345
346         iuid = (dlg_iuid_t*)*params->param;
347         if(iuid==NULL)
348                 return;
349
350     dlg = dlg_get_by_iuid(iuid);
351
352     if(dlg==NULL)
353     {
354         LM_ERR("failed to get dialog from params!\n");
355         return;
356     }
357     /* dialog termination confirmed (BYE reply) */
358     run_dlg_callbacks(DLGCB_TERMINATED_CONFIRMED,
359                       dlg,
360                       params->req,
361                       params->rpl,
362                       DLG_DIR_UPSTREAM,
363                       0);
364         dlg_release(dlg);
365 }
366
367 /*!
368  * \brief Execute callback for the BYE request and register callback for the BYE reply
369  * \param req request message
370  * \param dlg corresponding dialog
371  * \param dir message direction
372  */
373 static void dlg_terminated(sip_msg_t *req, dlg_cell_t *dlg, unsigned int dir)
374 {
375         dlg_iuid_t *iuid = NULL;
376
377     if(!req) {
378         LM_ERR("request is empty!");
379         return;
380     }
381
382     if(!dlg) {
383         LM_ERR("dialog is empty!");
384         return;
385     }
386
387     /* dialog terminated (BYE) */
388     run_dlg_callbacks(DLGCB_TERMINATED, dlg, req, NULL, dir, 0);
389
390         iuid = dlg_get_iuid_shm_clone(dlg);
391         if(iuid==NULL)
392                 return;
393
394     /* register callback for the coresponding reply */
395     if (d_tmb.register_tmcb(req,
396                             0,
397                             TMCB_RESPONSE_OUT,
398                             dlg_terminated_confirmed,
399                             (void*)iuid,
400                             dlg_iuid_sfree) <= 0 ) {
401         LM_ERR("cannot register response callback for BYE request\n");
402         return;
403     }
404 }
405
406 /*!
407  * \brief Function that is registered as TM callback and called on T destroy
408  *
409  * - happens when wait_ack==1
410  *
411  */
412 static void dlg_ontdestroy(struct cell* t, int type, struct tmcb_params *param)
413 {
414         dlg_cell_t *dlg = NULL;
415         dlg_iuid_t *iuid = NULL;
416
417         iuid = (dlg_iuid_t*)(*param->param);
418         dlg = dlg_get_by_iuid(iuid);
419         if(dlg==0)
420                 return;
421         /* 1 for callback and 1 for dlg lookup */
422         dlg_unref(dlg, 2);
423 }
424
425 /*!
426  * \brief Function that is registered as TM callback and called on replies
427  *
428  * Function that is registered as TM callback and called on replies. It
429  * parses the reply and set the appropriate event. This is then used to
430  * update the dialog state, run eventual dialog callbacks and save or
431  * update the necessary informations about the dialog.
432  * \see next_state_dlg
433  * \param t transaction, unused
434  * \param type type of the entered callback
435  * \param param saved dialog structure in the callback
436  */
437 static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
438 {
439     dlg_cell_t *dlg = NULL;
440         dlg_iuid_t *iuid = NULL;
441     int new_state, old_state, unref, event;
442     str tag;
443     sip_msg_t *req = param->req;
444         sip_msg_t *rpl = param->rpl;
445
446         if (shutdown_done)
447                 return;
448         iuid = (dlg_iuid_t*)(*param->param);
449         dlg = dlg_get_by_iuid(iuid);
450         if(dlg==0)
451                 return;
452
453         unref = 0;
454         if (type==TMCB_RESPONSE_FWDED) {
455                 /* The state does not change, but the msg is mutable in this callback*/
456                 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
457                 goto done;
458         }
459
460         if (type==TMCB_DESTROY)
461                 event = DLG_EVENT_TDEL;
462         else if (param->code<200)
463                 event = DLG_EVENT_RPL1xx;
464         else if (param->code<300)
465                 event = DLG_EVENT_RPL2xx;
466         else
467                 event = DLG_EVENT_RPL3xx;
468
469         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
470         dlg_run_event_route(dlg, (rpl==FAKED_REPLY)?NULL:rpl, old_state, new_state);
471
472         if (new_state==DLG_STATE_EARLY) {
473                 run_dlg_callbacks(DLGCB_EARLY, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
474                 if (old_state!=DLG_STATE_EARLY)
475                         if_update_stat(dlg_enable_stats, early_dlgs, 1);
476                 goto done;
477         }
478
479         if (new_state==DLG_STATE_CONFIRMED_NA &&
480         old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
481                 LM_DBG("dialog %p confirmed (ACK pending)\n",dlg);
482
483                  if (rpl != FAKED_REPLY) {
484                         /* get to tag*/
485                         if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0)
486                                                 || !rpl->to) ) {
487                                 LM_ERR("bad reply or missing TO hdr :-/\n");
488                                 tag.s = 0;
489                                 tag.len = 0;
490                         } else {
491                                 tag = get_to(rpl)->tag_value;
492                                 if (tag.s==0 || tag.len==0) {
493                                         LM_ERR("missing TAG param in TO hdr :-/\n");
494                                         tag.s = 0;
495                                         tag.len = 0;
496                                 }
497                         }
498
499                         /* save callee's tag, cseq, contact and record route*/
500                         if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
501                                 LM_ERR("could not add further info to the dialog\n");
502                         }
503                  } else {
504                          LM_ERR("Faked reply!\n");
505                  }
506
507                 /* set start time */
508                 dlg->start_ts = (unsigned int)(time(0));
509
510                 /* save the settings to the database,
511                  * if realtime saving mode configured- save dialog now
512                  * else: the next time the timer will fire the update*/
513                 dlg->dflags |= DLG_FLAG_NEW;
514                 if ( dlg_db_mode==DB_MODE_REALTIME )
515                         update_dialog_dbinfo(dlg);
516
517                 if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
518                         LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
519                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
520                                 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
521                                 dlg->callid.len, dlg->callid.s,
522                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
523                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
524                 } else {
525                         /* dialog pointer inserted in timer list */
526                         dlg_ref(dlg, 1);
527                 }
528
529                 /* dialog confirmed (ACK pending) */
530                 run_dlg_callbacks( DLGCB_CONFIRMED_NA, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
531
532                 if (old_state==DLG_STATE_EARLY)
533                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
534
535                 if (unref) dlg_unref(dlg, unref);
536                 if_update_stat(dlg_enable_stats, active_dlgs, 1);
537                 goto done;
538         }
539
540         if ( new_state==DLG_STATE_DELETED
541                                 && (old_state==DLG_STATE_UNCONFIRMED
542                                         || old_state==DLG_STATE_EARLY) ) {
543                 LM_DBG("dialog %p failed (negative reply)\n", dlg);
544                 /* dialog setup not completed (3456XX) */
545                 run_dlg_callbacks( DLGCB_FAILED, dlg, req, rpl, DLG_DIR_UPSTREAM, 0);
546                 /* do unref */
547                 if (unref)
548                         dlg_unref(dlg, unref);
549                 if (old_state==DLG_STATE_EARLY)
550                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
551
552                 if_update_stat(dlg_enable_stats, failed_dlgs, 1);
553
554                 if(dlg_wait_ack==1)
555                         dlg_set_tm_waitack(t, dlg);
556                 goto done;
557         }
558
559         if (unref) dlg_unref(dlg, unref);
560
561 done:
562         /* unref due to dlg_get_by_iuid() */
563         dlg_release(dlg);
564         return;
565 }
566
567
568 /*!
569  * \brief Helper function that run dialog callbacks on forwarded requests
570  * \see dlg_seq_up_onreply
571  * \see dlg_seq_down_onreply
572  * \param t transaction, unused
573  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
574  * \param param saved dialog structure inside the callback
575  * \param direction direction of the request
576  */
577 static void dlg_seq_onreply_helper(struct cell* t, int type,
578                 struct tmcb_params *param, const int direction)
579 {
580         dlg_cell_t *dlg = NULL;
581         dlg_iuid_t *iuid = NULL;
582
583         if (shutdown_done)
584                 return;
585         iuid = (dlg_iuid_t*)(*param->param);
586         dlg = dlg_get_by_iuid(iuid);
587         if (dlg==0)
588                 return;
589
590         if (type==TMCB_RESPONSE_FWDED)
591         {
592                 run_dlg_callbacks( DLGCB_RESPONSE_WITHIN,
593                                    dlg,
594                                    param->req,
595                                    param->rpl,
596                                    direction,
597                                    0);
598         }
599         dlg_release(dlg);
600
601         return;
602 }
603
604
605 /*!
606  * \brief Run dialog callbacks on forwarded requests in upstream direction
607  * \see dlg_seq_onreply_helper
608  * \param t transaction, unused
609  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
610  * \param param saved dialog structure inside the callback
611  */
612 static void dlg_seq_up_onreply(struct cell* t, int type, struct tmcb_params *param)
613 {
614         return dlg_seq_onreply_helper(t, type, param, DLG_DIR_UPSTREAM);
615 }
616
617
618 /*!
619  * \brief Run dialog callbacks on forwarded requests in downstream direction
620  * \see dlg_seq_onreply_helper
621  * \param t transaction, unused
622  * \param type type of the callback, should be TMCB_RESPONSE_FWDED
623  * \param param saved dialog structure inside the callback
624  */
625 static void dlg_seq_down_onreply(struct cell* t, int type, struct tmcb_params *param)
626 {
627         return dlg_seq_onreply_helper(t, type, param, DLG_DIR_DOWNSTREAM);
628 }
629
630
631 /*!
632  * \brief Return the timeout for a dialog
633  * \param req SIP message
634  * \return value from timeout AVP if present or default timeout
635  */
636 inline static int get_dlg_timeout(struct sip_msg *req)
637 {
638         pv_value_t pv_val;
639
640         if( timeout_avp ) {
641                 if ( pv_get_spec_value( req, timeout_avp, &pv_val)==0 &&
642                                 pv_val.flags&PV_VAL_INT && pv_val.ri>0 ) {
643                         return pv_val.ri;
644                 }
645                 LM_DBG("invalid AVP value, using default timeout\n");
646         }
647         return default_timeout;
648 }
649
650
651 /*!
652  * \brief Helper function to get the necessary content from SIP message
653  * \param req SIP request
654  * \param callid found callid
655  * \param ftag found from tag
656  * \param ttag found to tag
657  * \param with_ttag flag set if to tag must be found for success
658  * \return 0 on success, -1 on failure
659  */
660 static inline int pre_match_parse( struct sip_msg *req, str *callid,
661                 str *ftag, str *ttag, int with_ttag)
662 {
663         if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
664                         !req->to ) {
665                 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
666                 return -1;
667         }
668
669         if (get_to(req)->tag_value.len==0) {
670                 if (with_ttag == 1) {
671                         /* out of dialog request with preloaded Route headers; ignore. */
672                         return -1;
673                 } else {
674                         ttag->s = NULL;
675                         ttag->len = 0;
676                 }
677         } else {
678                 *ttag = get_to(req)->tag_value;
679         }
680
681         if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
682                 LM_ERR("failed to get From header\n");
683                 return -1;
684         }
685
686         /* callid */
687         *callid = req->callid->body;
688         trim(callid);
689         /* from tag */
690         *ftag = get_from(req)->tag_value;
691         return 0;
692 }
693
694
695 /*!
696  * \brief Function that is registered as TM callback and called on requests
697  * \see dlg_new_dialog
698  * \param t transaction, used to created the dialog
699  * \param type type of the entered callback
700  * \param param saved dialog structure in the callback
701  */
702 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
703 {
704         sip_msg_t *req = param->req;
705         dlg_cell_t *dlg = NULL;
706
707         if(req->first_line.u.request.method_value != METHOD_INVITE)
708                 return;
709
710         dlg = dlg_get_ctx_dialog();
711
712         if (dlg!=NULL) {
713                 if (!initial_cbs_inscript) {
714                         if (spiral_detected == 1)
715                                 run_dlg_callbacks( DLGCB_SPIRALED, dlg,
716                                                 req, NULL, DLG_DIR_DOWNSTREAM, 0);
717                         else if (spiral_detected == 0)
718                                 run_create_callbacks(dlg, req);
719                 }
720         }
721         if (dlg==NULL) {
722                 if((req->flags&dlg_flag)!=dlg_flag)
723                         return;
724                 dlg_new_dialog(req, t, 1);
725                 dlg = dlg_get_ctx_dialog();
726         }
727         if (dlg!=NULL) {
728                 dlg_set_tm_callbacks(t, req, dlg, spiral_detected);
729                 dlg_release(dlg);
730         }
731 }
732
733
734 /*!
735  * \brief Unreference a new dialog, helper function for dlg_onreq
736  * \see dlg_onreq
737  * \param dialog unreferenced dialog
738  */
739 #if 0
740 static void unref_new_dialog(void *iuid)
741 {
742         struct tmcb_params p;
743
744         memset(&p, 0, sizeof(struct tmcb_params));
745         p.param = (void*)&iuid;
746         dlg_onreply(0, TMCB_DESTROY, &p);
747 }
748 #endif
749
750
751 /*!
752  * \brief Create a new dialog from a sip message
753  *
754  * Create a new dialog from a SIP message, register a callback
755  * to keep track of the dialog with help of the tm module.
756  * This function is either called from the request callback, or
757  * from the dlg_manage function in the configuration script.
758  * \see dlg_onreq
759  * \see w_dlg_manage
760  * \param req SIP message
761  * \param t transaction
762  * \param run_initial_cbs if set zero, initial callbacks are not executed
763  * \return 0 on success, -1 on failure
764  */ 
765 int dlg_new_dialog(sip_msg_t *req, struct cell *t, const int run_initial_cbs)
766 {
767         dlg_cell_t *dlg;
768         str s;
769         str callid;
770     str ftag;
771     str ttag;
772     str req_uri;
773     unsigned int dir;
774
775         dlg = dlg_get_ctx_dialog();
776     if(dlg != NULL) {
777                 dlg_release(dlg);
778         return -1;
779         }
780
781         if(req->first_line.u.request.method_value != METHOD_INVITE)
782                 return -1;
783
784     if(pre_match_parse( req, &callid, &ftag, &ttag, 0)<0) {
785         LM_WARN("pre-matching failed\n");
786         return -1;
787     }
788
789     if(ttag.s!=0 && ttag.len!=0)
790         return -1;
791
792     if(pv_printf_s(req, ruri_param_model, &req_uri)<0) {
793         LM_ERR("error - cannot print the r-uri format\n");
794         return -1;
795     }
796     trim(&req_uri);
797
798     if (detect_spirals)
799     {
800         if (spiral_detected == 1)
801             return 0;
802
803         dir = DLG_DIR_NONE;
804
805         dlg = get_dlg(&callid, &ftag, &ttag, &dir);
806         if (dlg)
807         {
808                         if ( dlg->state != DLG_STATE_DELETED )
809                         {
810                                 LM_DBG("Callid '%.*s' found, must be a spiraled request\n",
811                                         callid.len, callid.s);
812                                 spiral_detected = 1;
813
814                                 if (run_initial_cbs)
815                                         run_dlg_callbacks( DLGCB_SPIRALED, dlg, req, NULL,
816                                                         DLG_DIR_DOWNSTREAM, 0);
817                                 /* get_dlg() has incremented the ref count by 1
818                                  * - it's ok, dlg will be unref at the end of function */
819                                 goto finish;
820                         }
821                         dlg_release(dlg);
822         }
823     }
824     spiral_detected = 0;
825
826     dlg = build_new_dlg (&callid /*callid*/,
827                          &(get_from(req)->uri) /*from uri*/,
828                          &(get_to(req)->uri) /*to uri*/,
829                          &ftag/*from_tag*/,
830                          &req_uri /*r-uri*/ );
831
832         if (dlg==0)
833         {
834                 LM_ERR("failed to create new dialog\n");
835                 return -1;
836         }
837
838         /* save caller's tag, cseq, contact and record route*/
839         if (populate_leg_info(dlg, req, t, DLG_CALLER_LEG,
840                         &(get_from(req)->tag_value)) !=0)
841         {
842                 LM_ERR("could not add further info to the dialog\n");
843                 shm_free(dlg);
844                 return -1;
845         }
846
847         /* Populate initial varlist: */
848         dlg->vars = get_local_varlist_pointer(req, 1);
849
850         link_dlg(dlg, 0);
851
852         dlg->lifetime = get_dlg_timeout(req);
853         s.s   = _dlg_ctx.to_route_name;
854         s.len = strlen(s.s);
855         dlg_set_toroute(dlg, &s);
856         dlg->sflags |= _dlg_ctx.flags;
857         dlg->iflags |= _dlg_ctx.iflags;
858
859         if (dlg_send_bye!=0 || _dlg_ctx.to_bye!=0)
860                 dlg->iflags |= DLG_IFLAG_TIMEOUTBYE;
861
862     if (run_initial_cbs)  run_create_callbacks( dlg, req);
863
864         /* first INVITE seen (dialog created, unconfirmed) */
865         if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
866                         add_dlg_rr_param( req, dlg->h_entry, dlg->h_id)<0 ) {
867                 LM_ERR("failed to add RR param\n");
868                 goto error;
869         }
870
871         /* new dlg - reference it once more for current dialog iuid shortcut */
872     dlg_ref(dlg, 1);
873
874     if_update_stat( dlg_enable_stats, processed_dlgs, 1);
875
876 finish:
877     _dlg_ctx.iuid.h_entry = dlg->h_entry;
878     _dlg_ctx.iuid.h_id = dlg->h_id;
879     set_current_dialog(req, dlg);
880         dlg_release(dlg);
881
882         return 0;
883
884 error:
885         if (!spiral_detected)
886                 dlg_unref(dlg, 1);               // undo ref regarding linking
887         return -1;
888 }
889
890
891 /*!
892  * \brief add dlg structure to tm callbacks
893  * \param t current transaction
894  * \param req current sip request
895  * \param dlg current dialog
896  * \param smode if the sip request was spiraled
897  * \return 0 on success, -1 on failure
898  */
899 int dlg_set_tm_callbacks(tm_cell_t *t, sip_msg_t *req, dlg_cell_t *dlg,
900                 int smode)
901 {
902         dlg_iuid_t *iuid = NULL;
903         if(t==NULL)
904                 return -1;
905
906         if(smode==0) {
907                 iuid = dlg_get_iuid_shm_clone(dlg);
908                 if(iuid==NULL)
909                 {
910                         LM_ERR("failed to create dialog unique id clone\n");
911                         goto error;
912                 }
913                 if ( d_tmb.register_tmcb( req, t,
914                                 TMCB_RESPONSE_READY|TMCB_RESPONSE_FWDED,
915                                 dlg_onreply, (void*)iuid, dlg_iuid_sfree)<0 ) {
916                         LM_ERR("failed to register TMCB\n");
917                         goto error;
918                 }
919         }
920
921         dlg->dflags |= DLG_FLAG_TM;
922
923         return 0;
924 error:
925         dlg_iuid_sfree(iuid);
926         return -1;
927 }
928
929 /*!
930  * \brief add dlg structure to tm callbacks to wait for negative ACK
931  * \param t current transaction
932  * \param dlg current dialog
933  * \return 0 on success, -1 on failure
934  */
935 int dlg_set_tm_waitack(tm_cell_t *t, dlg_cell_t *dlg)
936 {
937         dlg_iuid_t *iuid = NULL;
938         if(t==NULL)
939                 return -1;
940
941         LM_DBG("registering TMCB to wait for negative ACK\n");
942         iuid = dlg_get_iuid_shm_clone(dlg);
943         if(iuid==NULL)
944         {
945                 LM_ERR("failed to create dialog unique id clone\n");
946                 goto error;
947         }
948         dlg_ref(dlg, 1);
949         if ( d_tmb.register_tmcb( NULL, t,
950                         TMCB_DESTROY,
951                         dlg_ontdestroy, (void*)iuid, dlg_iuid_sfree)<0 ) {
952                 LM_ERR("failed to register TMCB to wait for negative ACK\n");
953                 dlg_unref(dlg, 1);
954                 goto error;
955         }
956
957         return 0;
958 error:
959         dlg_iuid_sfree(iuid);
960         return -1;
961 }
962
963 /*!
964  * \brief Parse the record-route parameter, to get dialog information back
965  * \param p start of parameter string
966  * \param end end of parameter string
967  * \param h_entry found dialog hash entry
968  * \param h_id found dialog hash id
969  * \return 0 on success, -1 on failure
970  */
971 static inline int parse_dlg_rr_param(char *p, char *end, int *h_entry, int *h_id)
972 {
973         char *s;
974
975         for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
976         if (*p!=DLG_SEPARATOR) {
977                 LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s);
978                 return -1;
979         }
980
981         if ( reverse_hex2int( s, p-s, (unsigned int*)h_entry)<0 ) {
982                 LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s);
983                 return -1;
984         }
985
986         if ( reverse_hex2int( p+1, end-(p+1), (unsigned int*)h_id)<0 ) {
987                 LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 );
988                 return -1;
989         }
990
991         return 0;
992 }
993
994
995 /*!
996  * \brief Update the saved CSEQ information in dialog from SIP message
997  * \param dlg updated dialog
998  * \param req SIP request
999  * \param dir direction of request, must DLG_DIR_UPSTREAM or DLG_DIR_DOWNSTREAM
1000  * \return 0 on success, -1 on failure
1001  */
1002 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
1003                 unsigned int dir)
1004 {
1005         if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
1006         !req->cseq->parsed) {
1007                 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
1008                 return -1;
1009         }
1010
1011         if ( dir==DLG_DIR_UPSTREAM) {
1012                 return dlg_update_cseq(dlg, DLG_CALLEE_LEG,&((get_cseq(req))->number));
1013         } else if ( dir==DLG_DIR_DOWNSTREAM) {
1014                 return dlg_update_cseq(dlg, DLG_CALLER_LEG,&((get_cseq(req))->number));
1015         } else {
1016                 LM_CRIT("dir is not set!\n");
1017                 return -1;
1018         }
1019 }
1020
1021 /*!
1022  * \brief Unreference a dialog from tm callback (another wrapper)
1023  * \param t transaction, unused
1024  * \param type type of the entered callback
1025  * \param param saved dialog structure in the callback
1026  */
1027 static void unref_dlg_from_cb(struct cell* t, int type, struct tmcb_params *param)
1028 {
1029         dlg_cell_t *dlg = NULL;
1030         dlg_iuid_t *iuid = NULL;
1031
1032         iuid = (dlg_iuid_t*)(*param->param);
1033         if (iuid==NULL)
1034                 return;
1035
1036         dlg = dlg_get_by_iuid(iuid);
1037         if(dlg==NULL)
1038                 return;
1039         /* unref by 2: 1 set when adding in tm cb, 1 sent by dlg_get_by_iuid() */
1040         dlg_unref(dlg, 2);
1041 }
1042
1043
1044 dlg_cell_t *dlg_get_msg_dialog(sip_msg_t *msg)
1045 {
1046         dlg_cell_t *dlg = NULL;
1047         str callid;
1048         str ftag;
1049         str ttag;
1050         unsigned int dir;
1051
1052         /* Retrieve the current dialog */
1053         dlg = dlg_get_ctx_dialog();
1054         if(dlg!=NULL)
1055                 return dlg;
1056         
1057         if (pre_match_parse(msg, &callid, &ftag, &ttag, 0)<0)
1058                 return NULL;
1059         dir = DLG_DIR_NONE;
1060         dlg = get_dlg(&callid, &ftag, &ttag, &dir);
1061         if (dlg==NULL){
1062                 LM_DBG("dlg with callid '%.*s' not found\n",
1063                                 msg->callid->body.len, msg->callid->body.s);
1064                 return NULL;
1065         }
1066         return dlg;
1067 }
1068
1069 /*!
1070  * \brief Function that is registered as RR callback for dialog tracking
1071  * 
1072  * Function that is registered as RR callback for dialog tracking. It
1073  * sets the appropriate events after the SIP method and run the state
1074  * machine to update the dialog state. It updates then the saved
1075  * dialogs and also the statistics.
1076  * \param req SIP request
1077  * \param route_params record-route parameter
1078  * \param param unused
1079  */
1080 void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
1081 {
1082         dlg_cell_t *dlg;
1083         dlg_iuid_t *iuid;
1084         str val, callid, ftag, ttag;
1085         int h_entry, h_id, new_state, old_state, unref, event, timeout;
1086         unsigned int dir;
1087         int ret = 0;
1088
1089         dlg = dlg_get_ctx_dialog();
1090         if (dlg!=NULL) {
1091                 dlg_release(dlg);
1092                 return;
1093         }
1094
1095         /* skip initial requests - they may end up here because of the
1096          * preloaded route */
1097         if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
1098                 LM_ERR("bad request or missing TO hdr :-/\n");
1099                 return;
1100         }
1101         if ( get_to(req)->tag_value.len==0 )
1102                 return;
1103
1104         dlg = 0;
1105         dir = DLG_DIR_NONE;
1106
1107         if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
1108                 if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
1109                         LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
1110                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
1111                                 return;
1112                 } else {
1113                         LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);
1114
1115                         if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
1116                                 return;
1117
1118                         dlg = dlg_lookup(h_entry, h_id);
1119                         if (dlg==0) {
1120                                 LM_WARN("unable to find dialog for %.*s "
1121                                         "with route param '%.*s' [%u:%u]\n",
1122                                         req->first_line.u.request.method.len,
1123                                         req->first_line.u.request.method.s,
1124                                         val.len,val.s, h_entry, h_id);
1125                                 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
1126                                         return;
1127                         } else {
1128                                 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0) {
1129                                         // lookup_dlg has incremented the ref count by 1
1130                                         dlg_release(dlg);
1131                                         return;
1132                                 }
1133                                 if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
1134                                         LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
1135                                                         "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
1136                                                         req->first_line.u.request.method.len,
1137                                                         req->first_line.u.request.method.s,
1138                                                         callid.len, callid.s, callid.len,
1139                                                         ftag.len, ftag.s, ftag.len,
1140                                                         ttag.len, ttag.s, ttag.len, dir);
1141                                         LM_WARN("dialog identification elements are callid='%.*s'/%d, "
1142                                                         "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
1143                                                         dlg->callid.len, dlg->callid.s, dlg->callid.len,
1144                                                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
1145                                                         dlg->tag[DLG_CALLER_LEG].len,
1146                                                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
1147                                                         dlg->tag[DLG_CALLEE_LEG].len);
1148                                         // lookup_dlg has incremented the ref count by 1
1149                                         dlg_release(dlg);
1150
1151                                         // Reset variables in order to do a lookup based on SIP-Elements.
1152                                         dlg = 0;
1153                                         dir = DLG_DIR_NONE;
1154
1155                                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
1156                                                 return;
1157                                 }
1158                         }
1159                 }
1160         }
1161
1162         if (dlg==0) {
1163                 if (pre_match_parse( req, &callid, &ftag, &ttag, 1)<0)
1164                         return;
1165                 /* TODO - try to use the RR dir detection to speed up here the
1166                  * search -bogdan */
1167                 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
1168                 if (dlg==0){
1169                         LM_DBG("Callid '%.*s' not found\n",
1170                                 req->callid->body.len, req->callid->body.s);
1171                         return;
1172                 }
1173         }
1174
1175     /* set current dialog - re-use ref increment from dlg_get() above */
1176     set_current_dialog( req, dlg);
1177     _dlg_ctx.iuid.h_entry = dlg->h_entry;
1178     _dlg_ctx.iuid.h_id = dlg->h_id;
1179
1180         /* run state machine */
1181         switch ( req->first_line.u.request.method_value ) {
1182                 case METHOD_PRACK:
1183                         event = DLG_EVENT_REQPRACK; break;
1184                 case METHOD_ACK:
1185                         event = DLG_EVENT_REQACK; break;
1186                 case METHOD_BYE:
1187                         event = DLG_EVENT_REQBYE; break;
1188                 default:
1189                         event = DLG_EVENT_REQ;
1190         }
1191
1192         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
1193
1194         CURR_DLG_ID = req->id;
1195         CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
1196         CURR_DLG_STATUS = new_state;
1197
1198         dlg_run_event_route(dlg, req, old_state, new_state);
1199
1200         /* delay deletion of dialog until transaction has died off in order
1201          * to absorb in-air messages */
1202         if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
1203                 iuid = dlg_get_iuid_shm_clone(dlg);
1204                 if(iuid!=NULL) {
1205                         if ( d_tmb.register_tmcb(req, NULL, TMCB_DESTROY,
1206                                         unref_dlg_from_cb, (void*)iuid, dlg_iuid_sfree)<0 ) {
1207                                 LM_ERR("failed to register deletion delay function\n");
1208                                 shm_free(iuid);
1209                         } else {
1210                                 dlg_ref(dlg, 1);
1211                         }
1212                 }
1213         }
1214
1215         if (new_state==DLG_STATE_CONFIRMED && old_state!=DLG_STATE_CONFIRMED)
1216                 dlg_ka_add(dlg);
1217
1218         /* run actions for the transition */
1219         if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
1220         old_state!=DLG_STATE_DELETED) {
1221                 LM_DBG("BYE successfully processed\n");
1222                 /* remove from timer */
1223                 ret = remove_dialog_timer(&dlg->tl);
1224                 if (ret < 0) {
1225                         LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
1226                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
1227                                 dlg, dlg->h_entry, dlg->h_id,
1228                                 dlg->callid.len, dlg->callid.s,
1229                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
1230                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
1231                 } else if (ret > 0) {
1232                         LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
1233                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
1234                                 dlg, dlg->h_entry, dlg->h_id,
1235                                 dlg->callid.len, dlg->callid.s,
1236                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
1237                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
1238                 } else {
1239                         /* one extra unref due to removal from timer list */
1240                         unref++;
1241                 }
1242                 /* dialog terminated (BYE) */
1243         dlg_terminated( req, dlg, dir);
1244
1245                 dlg_unref(dlg, unref);
1246
1247                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
1248                 goto done;
1249         }
1250
1251         if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
1252         && (new_state==DLG_STATE_CONFIRMED || new_state==DLG_STATE_EARLY)) {
1253
1254                 timeout = get_dlg_timeout(req);
1255                 if (timeout!=default_timeout) {
1256                         dlg->lifetime = timeout;
1257                 }
1258                 if (new_state!=DLG_STATE_EARLY) {
1259                         if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1) {
1260                                 LM_ERR("failed to update dialog lifetime\n");
1261                         } else {
1262                                 dlg->dflags |= DLG_FLAG_CHANGED;
1263                         }
1264                 }
1265                 if(event != DLG_EVENT_REQACK) {
1266                         if(update_cseqs(dlg, req, dir)!=0) {
1267                                 LM_ERR("cseqs update failed\n");
1268                         } else {
1269                                 dlg->dflags |= DLG_FLAG_CHANGED;
1270                         }
1271                 }
1272                 if(dlg_db_mode==DB_MODE_REALTIME && (dlg->dflags&DLG_FLAG_CHANGED)) {
1273                         update_dialog_dbinfo(dlg);
1274                 }
1275
1276                 if (old_state==DLG_STATE_CONFIRMED_NA) {
1277                         LM_DBG("confirming ACK successfully processed\n");
1278
1279                         /* confirming ACK request */
1280                         run_dlg_callbacks( DLGCB_CONFIRMED, dlg, req, NULL, dir, 0);
1281                 } else {
1282                         LM_DBG("sequential request successfully processed\n");
1283
1284                         /* within dialog request */
1285                         run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, NULL, dir, 0);
1286
1287                         if ( (event!=DLG_EVENT_REQACK) &&
1288                                         (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
1289                                 iuid = dlg_get_iuid_shm_clone(dlg);
1290                                 if(iuid!=NULL)
1291                                 {
1292                                         /* register callback for the replies of this request */
1293                                         if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
1294                                                         (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:
1295                                                                                                                 dlg_seq_up_onreply,
1296                                                         (void*)iuid, dlg_iuid_sfree)<0 ) {
1297                                                 LM_ERR("failed to register TMCB (2)\n");
1298                                                 shm_free(iuid);
1299                                         }
1300                                 }
1301                         }
1302                 }
1303         }
1304
1305         if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
1306                 dlg->dflags |= DLG_FLAG_CHANGED;
1307                 if(dlg_db_mode == DB_MODE_REALTIME)
1308                         update_dialog_dbinfo(dlg);
1309         }
1310
1311 done:
1312         dlg_release(dlg);
1313         return;
1314 }
1315
1316
1317 /*!
1318  * \brief Timer function that removes expired dialogs, run timeout route
1319  * \param tl dialog timer list
1320  */
1321 void dlg_ontimeout(struct dlg_tl *tl)
1322 {
1323         dlg_cell_t *dlg;
1324         int new_state, old_state, unref;
1325         sip_msg_t *fmsg;
1326
1327         /* get the dialog tl payload */
1328         dlg = ((struct dlg_cell*)((char *)(tl) -
1329                         (unsigned long)(&((struct dlg_cell*)0)->tl)));
1330
1331         if(dlg->state==DLG_STATE_CONFIRMED_NA
1332                                 || dlg->state==DLG_STATE_CONFIRMED)
1333         {
1334                 if(dlg->toroute>0 && dlg->toroute<main_rt.entries
1335                         && main_rt.rlist[dlg->toroute]!=NULL)
1336                 {
1337                         fmsg = faked_msg_next();
1338                         if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
1339                         {
1340                                 dlg_ref(dlg, 1);
1341                                 dlg_set_ctx_iuid(dlg);
1342                                 LM_DBG("executing route %d on timeout\n", dlg->toroute);
1343                                 set_route_type(REQUEST_ROUTE);
1344                                 run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0);
1345                                 dlg_reset_ctx_iuid();
1346                                 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
1347                                 dlg_unref(dlg, 1);
1348                         }
1349                 }
1350
1351                 if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE)
1352                 {
1353                         dlg_bye_all(dlg, NULL);
1354                         /* run event route for end of dlg */
1355                         dlg_run_event_route(dlg, NULL, dlg->state, DLG_STATE_DELETED);
1356                         dlg_unref(dlg, 1);
1357                         if_update_stat(dlg_enable_stats, expired_dlgs, 1);
1358                         return;
1359                 }
1360         }
1361
1362         next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
1363         dlg_run_event_route(dlg, NULL, old_state, new_state);
1364
1365         if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
1366                 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
1367                         dlg->callid.len, dlg->callid.s,
1368                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
1369                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
1370
1371                 /* dialog timeout */
1372                 run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0);
1373
1374                 dlg_unref(dlg, unref+1);
1375
1376                 if_update_stat( dlg_enable_stats, expired_dlgs, 1);
1377                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
1378         } else {
1379                 dlg_unref(dlg, 1);
1380         }
1381
1382         return;
1383 }
1384
1385
1386 /*!
1387  * \brief Function that returns the dialog lifetime as pseudo-variable
1388  * \param msg SIP message
1389  * \param param pseudo-variable parameter
1390  * \param res pseudo-variable result
1391  * \return 0 on success, -1 on failure
1392  */
1393 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1394 {
1395         int l = 0;
1396         char *ch = NULL;
1397
1398         if(msg==NULL || res==NULL)
1399                 return -1;
1400
1401         if (CURR_DLG_ID!=msg->id)
1402                 return pv_get_null( msg, param, res);
1403
1404         res->ri = CURR_DLG_LIFETIME;
1405         ch = int2str( (unsigned long)res->ri, &l);
1406
1407         res->rs.s = ch;
1408         res->rs.len = l;
1409
1410         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
1411
1412         return 0;
1413 }
1414
1415
1416 /*!
1417  * \brief Function that returns the dialog state as pseudo-variable
1418  * \param msg SIP message
1419  * \param param pseudo-variable parameter
1420  * \param res pseudo-variable result
1421  * \return 0 on success, -1 on failure
1422  */
1423 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
1424 {
1425         int l = 0;
1426         char *ch = NULL;
1427
1428         if(msg==NULL || res==NULL)
1429                 return -1;
1430
1431         if (CURR_DLG_ID!=msg->id)
1432                 return pv_get_null( msg, param, res);
1433
1434         res->ri = CURR_DLG_STATUS;
1435         ch = int2str( (unsigned long)res->ri, &l);
1436
1437         res->rs.s = ch;
1438         res->rs.len = l;
1439
1440         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
1441
1442         return 0;
1443 }
1444
1445 /*!
1446  * \brief Execute event routes based on new state
1447  *
1448  */
1449 void dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate)
1450 {
1451         sip_msg_t *fmsg;
1452         int rt;
1453
1454         if(dlg==NULL)
1455                 return;
1456         if(ostate==nstate)
1457                 return;
1458
1459         rt = -1;
1460         if(nstate==DLG_STATE_CONFIRMED_NA) {
1461                 rt = dlg_event_rt[DLG_EVENTRT_START];
1462         } else if(nstate==DLG_STATE_DELETED) {
1463                 if(ostate==DLG_STATE_CONFIRMED || ostate==DLG_STATE_CONFIRMED_NA)
1464                         rt = dlg_event_rt[DLG_EVENTRT_END];
1465                 else if(ostate==DLG_STATE_UNCONFIRMED || ostate==DLG_STATE_EARLY)
1466                         rt = dlg_event_rt[DLG_EVENTRT_FAILED];
1467         }
1468
1469         if(rt==-1 || event_rt.rlist[rt]==NULL)
1470                 return;
1471
1472         if(msg==NULL)
1473                 fmsg = faked_msg_next();
1474         else
1475                 fmsg = msg;
1476
1477         if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0)
1478         {
1479                 dlg_ref(dlg, 1);
1480                 dlg_set_ctx_iuid(dlg);
1481                 LM_DBG("executing event_route %d on state %d\n", rt, nstate);
1482                 set_route_type(REQUEST_ROUTE);
1483                 run_top_route(event_rt.rlist[rt], fmsg, 0);
1484                 dlg_reset_ctx_iuid();
1485                 exec_post_script_cb(fmsg, REQUEST_CB_TYPE);
1486                 dlg_unref(dlg, 1);
1487         }
1488 }
1489
1490 int dlg_manage(sip_msg_t *msg)
1491 {
1492         str tag;
1493         int backup_mode;
1494         dlg_cell_t *dlg = NULL;
1495         tm_cell_t *t = NULL;
1496
1497         if( (msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL )
1498         {
1499                 LM_ERR("bad TO header\n");
1500                 return -1;
1501         }
1502         tag = get_to(msg)->tag_value;
1503         if(tag.s!=0 && tag.len!=0)
1504         {
1505                 backup_mode = seq_match_mode;
1506                 seq_match_mode = SEQ_MATCH_NO_ID;
1507                 dlg_onroute(msg, NULL, NULL);
1508                 seq_match_mode = backup_mode;
1509         } else {
1510                 t = d_tmb.t_gett();
1511                 if(t==T_UNDEFINED)
1512                         t = NULL;
1513                 if(dlg_new_dialog(msg, t, initial_cbs_inscript)!=0)
1514                         return -1;
1515                 dlg = dlg_get_ctx_dialog();
1516                 if(dlg==NULL)
1517                         return -1;
1518                 if(t!=NULL)
1519                         dlg_set_tm_callbacks(t, msg, dlg, spiral_detected);
1520                 dlg_release(dlg);
1521         }
1522         return 1;
1523 }