script parsing: fix bug in expression error checking
[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 #include <string.h>
48 #include <time.h>
49
50 #include "../../trim.h"
51 #include "../../pvar.h"
52 #include "../../timer.h"
53 #include "../../lib/kcore/statistics.h"
54 #include "../../action.h"
55 #include "../../script_cb.h"
56 #include "../../lib/kcore/faked_msg.h"
57 #include "../../lib/kcore/parser_helpers.h"
58 #include "../../parser/parse_from.h"
59 #include "../../parser/parse_cseq.h"
60 #include "../../parser/contact/parse_contact.h"
61 #include "../../parser/parse_from.h"
62 #include "../../parser/parse_rr.h"
63 #include "../../modules/tm/tm_load.h"
64 #include "../rr/api.h"
65 #include "dlg_hash.h"
66 #include "dlg_timer.h"
67 #include "dlg_cb.h"
68 #include "dlg_handlers.h"
69 #include "dlg_req_within.h"
70 #include "dlg_db_handler.h"
71 #include "dlg_profile.h"
72 #include "dlg_var.h"
73
74 static str       rr_param;
75 static int       dlg_flag;
76 static pv_spec_t *timeout_avp;
77 static int       default_timeout;
78 static int       seq_match_mode;
79 static int       shutdown_done = 0;
80
81 extern struct rr_binds d_rrb;
82
83 /* statistic variables */
84 extern stat_var *early_dlgs;
85 extern stat_var *processed_dlgs;
86 extern stat_var *expired_dlgs;
87 extern stat_var *failed_dlgs;
88
89
90 static unsigned int CURR_DLG_LIFETIME = 0;
91 static unsigned int CURR_DLG_STATUS = 0;
92 static unsigned int CURR_DLG_ID  = 0xffffffff;
93
94 #define RR_DLG_PARAM_SIZE  (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
95 #define DLG_SEPARATOR      '.'
96
97
98 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
99                 pv_spec_t *timeout_avp_p ,int default_timeout_p,
100                 int seq_match_mode_p)
101 {
102         rr_param.s = rr_param_p;
103         rr_param.len = strlen(rr_param.s);
104
105         dlg_flag = 1<<dlg_flag_p;
106
107         timeout_avp = timeout_avp_p;
108         default_timeout = default_timeout_p;
109         seq_match_mode = seq_match_mode_p;
110 }
111
112
113 void destroy_dlg_handlers(void)
114 {
115         shutdown_done = 1;
116 }
117
118
119 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
120                                                                                                         unsigned int id)
121 {
122         static char buf[RR_DLG_PARAM_SIZE];
123         str s;
124         int n;
125         char *p;
126
127         s.s = p = buf;
128
129         *(p++) = ';';
130         memcpy(p, rr_param.s, rr_param.len);
131         p += rr_param.len;
132         *(p++) = '=';
133
134         n = RR_DLG_PARAM_SIZE - (p-buf);
135         if (int2reverse_hex( &p, &n, entry)==-1)
136                 return -1;
137
138         *(p++) = DLG_SEPARATOR;
139
140         n = RR_DLG_PARAM_SIZE - (p-buf);
141         if (int2reverse_hex( &p, &n, id)==-1)
142                 return -1;
143
144         s.len = p-buf;
145
146         if (d_rrb.add_rr_param( req, &s)<0) {
147                 LM_ERR("failed to add rr param\n");
148                 return -1;
149         }
150
151         return 0;
152 }
153
154
155 /*usage: dlg: the dialog to add cseq, contact & record_route
156  *               msg: sip message
157  *               flag: 0-for a request(INVITE),
158  *                              1- for a reply(200 ok)
159  *
160  *      for a request: get record route in normal order
161  *      for a reply  : get in reverse order, skipping the ones from the request and
162  *                                 the proxies' own
163  */
164 int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
165         struct cell* t, unsigned int leg, str *tag)
166 {
167         unsigned int skip_recs;
168         str cseq;
169         str contact;
170         str rr_set;
171
172         /* extract the cseq number as string */
173         if (leg==DLG_CALLER_LEG) {
174                 if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
175                         || !msg->cseq->parsed){
176                         LM_ERR("bad sip message or missing CSeq hdr :-/\n");
177                         goto error0;
178                 }
179                 cseq = (get_cseq(msg))->number;
180         } else {
181                 /* use the same as in request */
182                 cseq = dlg->cseq[DLG_CALLER_LEG];
183         }
184
185         /* extract the contact address */
186         if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
187                 LM_ERR("bad sip message or missing Contact hdr\n");
188                 goto error0;
189         }
190         if ( parse_contact(msg->contact)<0 ||
191         ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
192         ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
193                 LM_ERR("bad Contact HDR\n");
194                 goto error0;
195         }
196         contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;
197
198         /* extract the RR parts */
199         if(!msg->record_route && (parse_headers(msg,HDR_RECORDROUTE_F,0)<0)  ){
200                 LM_ERR("failed to parse record route header\n");
201                 goto error0;
202         }
203
204         if (leg==DLG_CALLER_LEG) {
205                 skip_recs = 0;
206         } else {
207                 /* was the 200 OK received or local generated */
208                 skip_recs = dlg->from_rr_nb +
209                         ((t->relayed_reply_branch>=0)?
210                                 ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_R2)?2:
211                                  ((t->uac[t->relayed_reply_branch].flags&TM_UAC_FLAG_RR)?1:0))
212                                 :0);
213         }
214
215         if(msg->record_route){
216                 if( print_rr_body(msg->record_route, &rr_set, leg,
217                                                         &skip_recs) != 0 ){
218                         LM_ERR("failed to print route records \n");
219                         goto error0;
220                 }
221         } else {
222                 rr_set.s = 0;
223                 rr_set.len = 0;
224         }
225
226         if(leg==DLG_CALLER_LEG)
227                 dlg->from_rr_nb = skip_recs;
228
229         LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
230                 rr_set.len, rr_set.s, contact.len, contact.s,
231                 cseq.len, cseq.s,
232                 msg->rcv.bind_address->sock_str.len,
233                 msg->rcv.bind_address->sock_str.s);
234
235         if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
236                 LM_ERR("dlg_set_leg_info failed\n");
237                 if (rr_set.s) pkg_free(rr_set.s);
238                 goto error0;
239         }
240
241         dlg->bind_addr[leg] = msg->rcv.bind_address;
242         if (rr_set.s) pkg_free(rr_set.s);
243
244         return 0;
245 error0:
246         return -1;
247 }
248
249
250 static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
251 {
252         struct sip_msg *rpl;
253         struct dlg_cell *dlg;
254         int new_state;
255         int old_state;
256         int unref;
257         int event;
258         str tag;
259
260         dlg = (struct dlg_cell *)(*param->param);
261         if (shutdown_done || dlg==0)
262                 return;
263
264         rpl = param->rpl;
265
266         if (type==TMCB_RESPONSE_FWDED) {
267                 /* The state does not change, but the msg is mutable in this callback*/
268                 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
269                 return;
270         }
271
272         if (type==TMCB_DESTROY)
273                 event = DLG_EVENT_TDEL;
274         else if (param->code<200)
275                 event = DLG_EVENT_RPL1xx;
276         else if (param->code<300)
277                 event = DLG_EVENT_RPL2xx;
278         else
279                 event = DLG_EVENT_RPL3xx;
280
281         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
282
283         if (new_state==DLG_STATE_EARLY) {
284                 run_dlg_callbacks(DLGCB_EARLY, dlg, rpl, DLG_DIR_UPSTREAM, 0);
285                 if (old_state!=DLG_STATE_EARLY)
286                         if_update_stat(dlg_enable_stats, early_dlgs, 1);
287                 return;
288         }
289
290         if (new_state==DLG_STATE_CONFIRMED_NA &&
291         old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
292                 LM_DBG("dialog %p confirmed\n",dlg);
293
294                 /* get to tag*/
295                 if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0) || !rpl->to) ) {
296                         LM_ERR("bad reply or missing TO hdr :-/\n");
297                         tag.s = 0;
298                         tag.len = 0;
299                 } else {
300                         tag = get_to(rpl)->tag_value;
301                         if (tag.s==0 || tag.len==0) {
302                                 LM_ERR("missing TAG param in TO hdr :-/\n");
303                                 tag.s = 0;
304                                 tag.len = 0;
305                         }
306                 }
307
308                 /* save callee's tag, cseq, contact and record route*/
309                 if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
310                         LM_ERR("could not add further info to the dialog\n");
311                 }
312
313                 /* set start time */
314                 dlg->start_ts = (unsigned int)(time(0));
315
316                 /* save the settings to the database,
317                  * if realtime saving mode configured- save dialog now
318                  * else: the next time the timer will fire the update*/
319                 dlg->dflags |= DLG_FLAG_NEW;
320                 if ( dlg_db_mode==DB_MODE_REALTIME )
321                         update_dialog_dbinfo(dlg);
322
323                 if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
324                         LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
325                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
326                                 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
327                                 dlg->callid.len, dlg->callid.s,
328                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
329                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
330                 } else {
331                         ref_dlg(dlg,1);
332                 }
333
334                 /* dialog confirmed */
335                 run_dlg_callbacks( DLGCB_CONFIRMED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
336
337                 if (old_state==DLG_STATE_EARLY)
338                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
339
340                 if (unref) unref_dlg(dlg,unref);
341                 if_update_stat(dlg_enable_stats, active_dlgs, 1);
342                 return;
343         }
344
345         if ( old_state!=DLG_STATE_DELETED && new_state==DLG_STATE_DELETED ) {
346                 LM_DBG("dialog %p failed (negative reply)\n", dlg);
347                 /* dialog setup not completed (3456XX) */
348                 run_dlg_callbacks( DLGCB_FAILED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
349                 /* do unref */
350                 if (unref)
351                         unref_dlg(dlg,unref);
352                 if (old_state==DLG_STATE_EARLY)
353                         if_update_stat(dlg_enable_stats, early_dlgs, -1);
354                 return;
355         }
356
357         if (unref) unref_dlg(dlg,unref);
358
359         return;
360 }
361
362
363 static void dlg_seq_up_onreply(struct cell* t, int type,
364                                                                                                         struct tmcb_params *param)
365 {
366         struct dlg_cell *dlg;
367
368         dlg = (struct dlg_cell *)(*param->param);
369         if (shutdown_done || dlg==0)
370                 return;
371
372         if (type==TMCB_RESPONSE_FWDED) {
373                 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN, dlg, param->rpl,
374                         DLG_DIR_UPSTREAM, 0);
375                 return;
376         }
377
378         return;
379 }
380
381
382
383 static void dlg_seq_down_onreply(struct cell* t, int type,
384                                                                                                         struct tmcb_params *param)
385 {
386         struct dlg_cell *dlg;
387
388         dlg = (struct dlg_cell *)(*param->param);
389         if (shutdown_done || dlg==0)
390                 return;
391
392         if (type==TMCB_RESPONSE_FWDED) {
393                 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN, dlg, param->rpl,
394                         DLG_DIR_DOWNSTREAM, 0);
395                 return;
396         }
397
398         return;
399 }
400
401
402 inline static int get_dlg_timeout(struct sip_msg *req)
403 {
404         pv_value_t pv_val;
405
406         if( timeout_avp && pv_get_spec_value( req, timeout_avp, &pv_val)==0
407         && pv_val.flags&PV_VAL_INT && pv_val.ri>0 ) {
408                 return pv_val.ri;
409         }
410         LM_DBG("invalid AVP value, use default timeout");
411         return default_timeout;
412 }
413
414
415
416 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
417 {
418         struct sip_msg *msg;
419         msg = param->req;
420         if((msg->flags&dlg_flag)!=dlg_flag)
421                 return;
422         if (current_dlg_pointer!=NULL)
423                 return;
424         dlg_new_dialog(msg, t);
425 }
426
427 void unref_new_dialog(void *dialog)
428 {
429         struct tmcb_params p;
430
431         p.param = (void*)&dialog;
432         dlg_onreply(0, TMCB_DESTROY, &p);
433 }
434
435
436 void dlg_tmcb_dummy(struct cell* t, int type, struct tmcb_params *param)
437 {
438         return;
439 }
440
441 int dlg_new_dialog(struct sip_msg *msg, struct cell *t)
442 {
443         struct dlg_cell *dlg;
444         str s;
445
446         if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
447         {
448                 LM_ERR("bad request or missing TO hdr\n");
449                 return -1;
450         }
451         s = get_to(msg)->tag_value;
452         if(s.s!=0 && s.len!=0)
453                 return -1;
454
455         if(msg->first_line.u.request.method_value==METHOD_CANCEL)
456                 return -1;
457
458         if(parse_from_header(msg))
459         {
460                 LM_ERR("bad request or missing FROM hdr\n");
461                 return -1;
462         }
463         if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
464                         || msg->callid==NULL){
465                 LM_ERR("bad request or missing CALLID hdr\n");
466                 return -1;
467         }
468         s = msg->callid->body;
469         trim(&s);
470
471         /* some sanity checks */
472         if (s.len==0 || get_from(msg)->tag_value.len==0) {
473                 LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
474                         s.len, get_from(msg)->tag_value.len);
475                 return -1;
476         }
477
478         dlg = build_new_dlg(&s /*callid*/, &(get_from(msg)->uri) /*from uri*/,
479                 &(get_to(msg)->uri) /*to uri*/,
480                 &(get_from(msg)->tag_value)/*from_tag*/ );
481         if (dlg==0) {
482                 LM_ERR("failed to create new dialog\n");
483                 return -1;
484         }
485
486         /* save caller's tag, cseq, contact and record route*/
487         if (populate_leg_info(dlg, msg, t, DLG_CALLER_LEG,
488                         &(get_from(msg)->tag_value)) !=0)
489         {
490                 LM_ERR("could not add further info to the dialog\n");
491                 shm_free(dlg);
492                 return -1;
493         }
494
495         set_current_dialog(msg, dlg);
496         _dlg_ctx.dlg = dlg;
497
498         link_dlg(dlg, 2/* extra ref for the callback and current dlg hook */);
499
500         /* first INVITE seen (dialog created, unconfirmed) */
501         if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
502                         add_dlg_rr_param( msg, dlg->h_entry, dlg->h_id)<0 ) {
503                 LM_ERR("failed to add RR param\n");
504                 goto error;
505         }
506
507         if ( d_tmb.register_tmcb( msg, t,
508                                 TMCB_RESPONSE_READY|TMCB_RESPONSE_FWDED,
509                                 dlg_onreply, (void*)dlg, unref_new_dialog)<0 ) {
510                 LM_ERR("failed to register TMCB\n");
511                 goto error;
512         }
513
514         dlg->lifetime = get_dlg_timeout(msg);
515         dlg->toroute = _dlg_ctx.to_route;
516         dlg->sflags |= _dlg_ctx.flags;
517
518         if (_dlg_ctx.to_bye!=0)
519                 dlg->dflags |= DLG_FLAG_TOBYE;
520
521         if (t) {
522                 if ( d_tmb.register_tmcb( msg, t, TMCB_MAX,
523                                         dlg_tmcb_dummy, (void*)dlg, 0)<0 ) {
524                         LM_ERR("failed cache in T the shortcut to dlg\n");
525                         goto error;
526                 }
527         }
528 #if 0
529                 t->dialog_ctx = (void*) dlg;
530 #endif
531
532         run_create_callbacks( dlg, msg);
533
534         if_update_stat( dlg_enable_stats, processed_dlgs, 1);
535
536         return 0;
537 error:
538         unref_dlg(dlg,1);
539         profile_cleanup(msg, NULL);
540         update_stat(failed_dlgs, 1);
541         return -1;
542 }
543
544
545 static inline int parse_dlg_rr_param(char *p, char *end,
546                                                                                                         int *h_entry, int *h_id)
547 {
548         char *s;
549
550         for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
551         if (*p!=DLG_SEPARATOR) {
552                 LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s);
553                 return -1;
554         }
555
556         if ( reverse_hex2int( s, p-s, (unsigned int*)h_entry)<0 ) {
557                 LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s);
558                 return -1;
559         }
560
561         if ( reverse_hex2int( p+1, end-(p+1), (unsigned int*)h_id)<0 ) {
562                 LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 );
563                 return -1;
564         }
565
566         return 0;
567 }
568
569
570 static inline int pre_match_parse( struct sip_msg *req, str *callid,
571                                                                                                                 str *ftag, str *ttag)
572 {
573         if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
574         !req->to ) {
575                 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
576                 return -1;
577         }
578
579         if (get_to(req)->tag_value.len==0) {
580                 /* out of dialog request with preloaded Route headers; ignore. */
581                 return -1;
582         }
583
584         if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
585                 LM_ERR("failed to get From header\n");
586                 return -1;
587         }
588
589         /* callid */
590         *callid = req->callid->body;
591         trim(callid);
592         /* to tag */
593         *ttag = get_to(req)->tag_value;
594         /* from tag */
595         *ftag = get_from(req)->tag_value;
596         return 0;
597 }
598
599
600 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
601                                                                                                                         unsigned int dir)
602 {
603         if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
604         !req->cseq->parsed) {
605                 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
606                 return -1;
607         }
608
609         if ( dir==DLG_DIR_UPSTREAM) {
610                 return dlg_update_cseq(dlg, DLG_CALLEE_LEG,&((get_cseq(req))->number));
611         } else if ( dir==DLG_DIR_DOWNSTREAM) {
612                 return dlg_update_cseq(dlg, DLG_CALLER_LEG,&((get_cseq(req))->number));
613         } else {
614                 LM_CRIT("dir is not set!\n");
615                 return -1;
616         }
617 }
618
619
620 static void
621 unreference_dialog(void *dialog)
622 {
623         // if the dialog table is gone, it means the system is shutting down.
624         if (!d_table)
625                 return;
626         unref_dlg((struct dlg_cell*)dialog, 1);
627 }
628
629
630 void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
631 {
632         struct dlg_cell *dlg;
633         str val;
634         str callid;
635         str ftag;
636         str ttag;
637         int h_entry;
638         int h_id;
639         int new_state;
640         int old_state;
641         int unref;
642         int event;
643         int timeout;
644         unsigned int dir;
645         int ret = 0;
646
647         if (current_dlg_pointer!=NULL)
648                 return;
649
650         /* skip initial requests - they may end up here because of the
651          * preloaded route */
652         if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
653                 LM_ERR("bad request or missing TO hdr :-/\n");
654                 return;
655         }
656         if ( get_to(req)->tag_value.len==0 )
657                 return;
658
659         dlg = 0;
660         dir = DLG_DIR_NONE;
661
662         if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
663                 if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
664                         LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
665                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
666                                 return;
667                 } else {
668                         LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);
669
670                         if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
671                                 return;
672
673                         dlg = lookup_dlg( h_entry, h_id);
674                         if (dlg==0) {
675                                 LM_WARN("unable to find dialog for %.*s "
676                                         "with route param '%.*s' [%u:%u]\n",
677                                         req->first_line.u.request.method.len,
678                                         req->first_line.u.request.method.s,
679                                         val.len,val.s, h_entry, h_id);
680                                 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
681                                         return;
682                         } else {
683                                 // lookup_dlg has incremented the ref count by 1
684                                 if (pre_match_parse( req, &callid, &ftag, &ttag)<0) {
685                                         unref_dlg(dlg, 1);
686                                         return;
687                                 }
688                                 if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
689                                         LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
690                                                         "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
691                                                         req->first_line.u.request.method.len,
692                                                         req->first_line.u.request.method.s,
693                                                         callid.len, callid.s, callid.len,
694                                                         ftag.len, ftag.s, ftag.len,
695                                                         ttag.len, ttag.s, ttag.len, dir);
696                                         LM_WARN("dialog identification elements are callid='%.*s'/%d, "
697                                                         "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
698                                                         dlg->callid.len, dlg->callid.s, dlg->callid.len,
699                                                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
700                                                         dlg->tag[DLG_CALLER_LEG].len,
701                                                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
702                                                         dlg->tag[DLG_CALLEE_LEG].len);
703                                         unref_dlg(dlg, 1);
704
705                                         // Reset variables in order to do a lookup based on SIP-Elements.
706                                         dlg = 0;
707                                         dir = DLG_DIR_NONE;
708
709                                         if (seq_match_mode==SEQ_MATCH_STRICT_ID )
710                                                 return;
711                                 }
712                         }
713                 }
714         }
715
716         if (dlg==0) {
717                 if (pre_match_parse( req, &callid, &ftag, &ttag)<0)
718                         return;
719                 /* TODO - try to use the RR dir detection to speed up here the
720                  * search -bogdan */
721                 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
722                 if (!dlg){
723                         LM_DBG("Callid '%.*s' not found\n",
724                                 req->callid->body.len, req->callid->body.s);
725                         return;
726                 }
727         }
728
729         /* run state machine */
730         switch ( req->first_line.u.request.method_value ) {
731                 case METHOD_PRACK:
732                         event = DLG_EVENT_REQPRACK; break;
733                 case METHOD_ACK:
734                         event = DLG_EVENT_REQACK; break;
735                 case METHOD_BYE:
736                         event = DLG_EVENT_REQBYE; break;
737                 default:
738                         event = DLG_EVENT_REQ;
739         }
740
741         next_state_dlg( dlg, event, &old_state, &new_state, &unref);
742
743         CURR_DLG_ID = req->id;
744         CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
745         CURR_DLG_STATUS = new_state;
746
747         /* set current dialog - it will keep a ref! */
748         set_current_dialog( req, dlg);
749         _dlg_ctx.dlg = dlg;
750
751         /* run actions for the transition */
752         if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
753         old_state!=DLG_STATE_DELETED) {
754                 LM_DBG("BYE successfully processed\n");
755                 /* remove from timer */
756                 ret = remove_dialog_timer(&dlg->tl);
757                 if (ret < 0) {
758                         LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
759                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
760                                 dlg, dlg->h_entry, dlg->h_id,
761                                 dlg->callid.len, dlg->callid.s,
762                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
763                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
764                 } else if (ret > 0) {
765                         LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
766                                 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
767                                 dlg, dlg->h_entry, dlg->h_id,
768                                 dlg->callid.len, dlg->callid.s,
769                                 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
770                                 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
771                 } else {
772                         unref++;
773                 }
774                 /* dialog terminated (BYE) */
775                 run_dlg_callbacks( DLGCB_TERMINATED, dlg, req, dir, 0);
776
777                 /* delete the dialog from DB */
778                 if (dlg_db_mode)
779                         remove_dialog_from_db(dlg);
780
781                 /* destroy dialog */
782                 unref_dlg(dlg, unref);
783
784                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
785                 return;
786         }
787
788         if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
789         && new_state==DLG_STATE_CONFIRMED) {
790                 LM_DBG("sequential request successfully processed\n");
791                 timeout = get_dlg_timeout(req);
792                 /* update timer during sequential request? */
793                 if (timeout!=default_timeout) {
794                         dlg->lifetime = timeout;
795                         if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1)
796                                 LM_ERR("failed to update dialog lifetime\n");
797                 }
798                 if (update_cseqs(dlg, req, dir)!=0) {
799                         LM_ERR("cseqs update failed\n");
800                 } else {
801                         dlg->dflags |= DLG_FLAG_CHANGED;
802                         if ( dlg_db_mode==DB_MODE_REALTIME )
803                                 update_dialog_dbinfo(dlg);
804                 }
805
806                 /* within dialog request */
807                 run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, dir, 0);
808
809                 if ( (event!=DLG_EVENT_REQACK) &&
810                 (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
811                         /* ref the dialog as registered into the transaction callback.
812                          * unref will be done when the callback will be destroyed */
813                         ref_dlg( dlg , 1);
814                         /* register callback for the replies of this request */
815                         if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
816                         (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:dlg_seq_up_onreply,
817                         (void*)dlg, unreference_dialog)<0 ) {
818                                 LM_ERR("failed to register TMCB (2)\n");
819                                         unref_dlg( dlg , 1);
820                         }
821                 }
822         }
823
824         if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
825                 dlg->dflags |= DLG_FLAG_CHANGED;
826                 if(dlg_db_mode == DB_MODE_REALTIME)
827                         update_dialog_dbinfo(dlg);
828         }
829
830         return;
831 }
832
833
834
835 #define get_dlg_tl_payload(_tl_)  ((struct dlg_cell*)((char *)(_tl_)- \
836                 (unsigned long)(&((struct dlg_cell*)0)->tl)))
837
838 void dlg_ontimeout( struct dlg_tl *tl)
839 {
840         struct dlg_cell *dlg;
841         int new_state;
842         int old_state;
843         int unref;
844         struct sip_msg *fmsg;
845
846         dlg = get_dlg_tl_payload(tl);
847
848         if(dlg->toroute>0 && dlg->toroute<RT_NO)
849         {
850                 dlg_set_ctx_dialog(dlg);
851                 fmsg = faked_msg_next();
852                 if (exec_pre_req_cb(fmsg)>0)
853                 {
854                         LM_DBG("executing route %d on timeout\n", dlg->toroute);
855                         set_route_type(REQUEST_ROUTE);
856                         run_top_route(main_rt.rlist[dlg->toroute], fmsg);
857                         exec_post_req_cb(fmsg);
858                 }
859         }
860
861         if ((dlg->dflags&DLG_FLAG_TOBYE)
862                         && (dlg->state==DLG_STATE_CONFIRMED_NA
863                                 || dlg->state==DLG_STATE_CONFIRMED))
864         {
865                 dlg_bye_all(dlg, NULL);
866                 unref_dlg(dlg, 1);
867                 if_update_stat(dlg_enable_stats, expired_dlgs, 1);
868                 return;
869         }
870
871         next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
872
873         if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
874                 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
875                         dlg->callid.len, dlg->callid.s,
876                         dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
877                         dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
878
879                 /* dialog timeout */
880                 run_dlg_callbacks( DLGCB_EXPIRED, dlg, 0, DLG_DIR_NONE, 0);
881
882                 /* delete the dialog from DB */
883                 if (dlg_db_mode)
884                         remove_dialog_from_db(dlg);
885
886                 unref_dlg(dlg, unref+1);
887
888                 if_update_stat( dlg_enable_stats, expired_dlgs, 1);
889                 if_update_stat( dlg_enable_stats, active_dlgs, -1);
890         } else {
891                 unref_dlg(dlg, 1);
892         }
893
894         return;
895 }
896
897
898 /* item/pseudo-variables functions */
899 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param,
900                 pv_value_t *res)
901 {
902         int l = 0;
903         char *ch = NULL;
904
905         if(msg==NULL || res==NULL)
906                 return -1;
907
908         if (CURR_DLG_ID!=msg->id)
909                 return pv_get_null( msg, param, res);
910
911         res->ri = CURR_DLG_LIFETIME;
912         ch = int2str( (unsigned long)res->ri, &l);
913
914         res->rs.s = ch;
915         res->rs.len = l;
916
917         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
918
919         return 0;
920 }
921
922
923 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param,
924                 pv_value_t *res)
925 {
926         int l = 0;
927         char *ch = NULL;
928
929         if(msg==NULL || res==NULL)
930                 return -1;
931
932         if (CURR_DLG_ID!=msg->id)
933                 return pv_get_null( msg, param, res);
934
935         res->ri = CURR_DLG_STATUS;
936         ch = int2str( (unsigned long)res->ri, &l);
937
938         res->rs.s = ch;
939         res->rs.len = l;
940
941         res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
942
943         return 0;
944 }
945