00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include <string.h>
00048 #include <time.h>
00049
00050 #include "../../trim.h"
00051 #include "../../pvar.h"
00052 #include "../../timer.h"
00053 #include "../../statistics.h"
00054 #include "../../action.h"
00055 #include "../../script_cb.h"
00056 #include "../../faked_msg.h"
00057 #include "../../parser/parse_from.h"
00058 #include "../../parser/parse_cseq.h"
00059 #include "../../parser/contact/parse_contact.h"
00060 #include "../../parser/parse_from.h"
00061 #include "../../parser/parse_rr.h"
00062 #include "../tm/tm_load.h"
00063 #include "../rr/api.h"
00064 #include "dlg_hash.h"
00065 #include "dlg_timer.h"
00066 #include "dlg_cb.h"
00067 #include "dlg_handlers.h"
00068 #include "dlg_req_within.h"
00069 #include "dlg_db_handler.h"
00070 #include "dlg_profile.h"
00071 #include "dlg_var.h"
00072
00073 static str rr_param;
00074 static int dlg_flag;
00075 static pv_spec_t *timeout_avp;
00076 static int default_timeout;
00077 static int seq_match_mode;
00078 static int shutdown_done = 0;
00079
00080 extern struct rr_binds d_rrb;
00081
00082
00083 extern stat_var *early_dlgs;
00084 extern stat_var *processed_dlgs;
00085 extern stat_var *expired_dlgs;
00086 extern stat_var *failed_dlgs;
00087
00088
00089 static unsigned int CURR_DLG_LIFETIME = 0;
00090 static unsigned int CURR_DLG_STATUS = 0;
00091 static unsigned int CURR_DLG_ID = 0xffffffff;
00092
00093 #define RR_DLG_PARAM_SIZE (2*2*sizeof(int)+3+MAX_DLG_RR_PARAM_NAME)
00094 #define DLG_SEPARATOR '.'
00095
00096
00097 void init_dlg_handlers(char *rr_param_p, int dlg_flag_p,
00098 pv_spec_t *timeout_avp_p ,int default_timeout_p,
00099 int seq_match_mode_p)
00100 {
00101 rr_param.s = rr_param_p;
00102 rr_param.len = strlen(rr_param.s);
00103
00104 dlg_flag = 1<<dlg_flag_p;
00105
00106 timeout_avp = timeout_avp_p;
00107 default_timeout = default_timeout_p;
00108 seq_match_mode = seq_match_mode_p;
00109 }
00110
00111
00112 void destroy_dlg_handlers(void)
00113 {
00114 shutdown_done = 1;
00115 }
00116
00117
00118 static inline int add_dlg_rr_param(struct sip_msg *req, unsigned int entry,
00119 unsigned int id)
00120 {
00121 static char buf[RR_DLG_PARAM_SIZE];
00122 str s;
00123 int n;
00124 char *p;
00125
00126 s.s = p = buf;
00127
00128 *(p++) = ';';
00129 memcpy(p, rr_param.s, rr_param.len);
00130 p += rr_param.len;
00131 *(p++) = '=';
00132
00133 n = RR_DLG_PARAM_SIZE - (p-buf);
00134 if (int2reverse_hex( &p, &n, entry)==-1)
00135 return -1;
00136
00137 *(p++) = DLG_SEPARATOR;
00138
00139 n = RR_DLG_PARAM_SIZE - (p-buf);
00140 if (int2reverse_hex( &p, &n, id)==-1)
00141 return -1;
00142
00143 s.len = p-buf;
00144
00145 if (d_rrb.add_rr_param( req, &s)<0) {
00146 LM_ERR("failed to add rr param\n");
00147 return -1;
00148 }
00149
00150 return 0;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 int populate_leg_info( struct dlg_cell *dlg, struct sip_msg *msg,
00164 struct cell* t, unsigned int leg, str *tag)
00165 {
00166 unsigned int skip_recs;
00167 str cseq;
00168 str contact;
00169 str rr_set;
00170
00171 dlg->bind_addr[leg] = msg->rcv.bind_address;
00172
00173
00174 if (leg==DLG_CALLER_LEG) {
00175 if((!msg->cseq && (parse_headers(msg,HDR_CSEQ_F,0)<0 || !msg->cseq))
00176 || !msg->cseq->parsed){
00177 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
00178 goto error0;
00179 }
00180 cseq = (get_cseq(msg))->number;
00181 } else {
00182
00183 cseq = dlg->cseq[DLG_CALLER_LEG];
00184 }
00185
00186
00187 if (!msg->contact&&(parse_headers(msg,HDR_CONTACT_F,0)<0||!msg->contact)){
00188 LM_ERR("bad sip message or missing Contact hdr\n");
00189 goto error0;
00190 }
00191 if ( parse_contact(msg->contact)<0 ||
00192 ((contact_body_t *)msg->contact->parsed)->contacts==NULL ||
00193 ((contact_body_t *)msg->contact->parsed)->contacts->next!=NULL ) {
00194 LM_ERR("bad Contact HDR\n");
00195 goto error0;
00196 }
00197 contact = ((contact_body_t *)msg->contact->parsed)->contacts->uri;
00198
00199
00200 if(!msg->record_route && (parse_headers(msg,HDR_EOH_F,0)<0) ){
00201 LM_ERR("failed to parse record route header\n");
00202 goto error0;
00203 }
00204
00205 if (leg==DLG_CALLER_LEG) {
00206 skip_recs = 0;
00207 } else {
00208
00209 skip_recs = dlg->from_rr_nb +
00210 ((t->relayed_reply_branch>=0)?
00211 (t->uac[t->relayed_reply_branch].added_rr):0);
00212 }
00213
00214 if(msg->record_route){
00215 if( print_rr_body(msg->record_route, &rr_set, leg,
00216 &skip_recs) != 0 ){
00217 LM_ERR("failed to print route records \n");
00218 goto error0;
00219 }
00220 } else {
00221 rr_set.s = 0;
00222 rr_set.len = 0;
00223 }
00224
00225 if(leg==DLG_CALLER_LEG)
00226 dlg->from_rr_nb = skip_recs;
00227
00228 LM_DBG("route_set %.*s, contact %.*s, cseq %.*s and bind_addr %.*s\n",
00229 rr_set.len, rr_set.s, contact.len, contact.s,
00230 cseq.len, cseq.s,
00231 msg->rcv.bind_address->sock_str.len,
00232 msg->rcv.bind_address->sock_str.s);
00233
00234 if (dlg_set_leg_info( dlg, tag, &rr_set, &contact, &cseq, leg)!=0) {
00235 LM_ERR("dlg_set_leg_info failed\n");
00236 if (rr_set.s) pkg_free(rr_set.s);
00237 goto error0;
00238 }
00239
00240 if (rr_set.s) pkg_free(rr_set.s);
00241
00242 return 0;
00243 error0:
00244 return -1;
00245 }
00246
00247
00248 static void dlg_onreply(struct cell* t, int type, struct tmcb_params *param)
00249 {
00250 struct sip_msg *rpl;
00251 struct dlg_cell *dlg;
00252 int new_state;
00253 int old_state;
00254 int unref;
00255 int event;
00256 str tag;
00257
00258 dlg = (struct dlg_cell *)(*param->param);
00259 if (shutdown_done || dlg==0)
00260 return;
00261
00262 rpl = param->rpl;
00263
00264 if (type==TMCB_RESPONSE_FWDED) {
00265
00266 run_dlg_callbacks(DLGCB_RESPONSE_FWDED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
00267 return;
00268 }
00269
00270 if (type==TMCB_TRANS_DELETED)
00271 event = DLG_EVENT_TDEL;
00272 else if (param->code<200)
00273 event = DLG_EVENT_RPL1xx;
00274 else if (param->code<300)
00275 event = DLG_EVENT_RPL2xx;
00276 else
00277 event = DLG_EVENT_RPL3xx;
00278
00279 next_state_dlg( dlg, event, &old_state, &new_state, &unref);
00280
00281 if (new_state==DLG_STATE_EARLY) {
00282 run_dlg_callbacks(DLGCB_EARLY, dlg, rpl, DLG_DIR_UPSTREAM, 0);
00283 if (old_state!=DLG_STATE_EARLY)
00284 if_update_stat(dlg_enable_stats, early_dlgs, 1);
00285 return;
00286 }
00287
00288 if (new_state==DLG_STATE_CONFIRMED_NA &&
00289 old_state!=DLG_STATE_CONFIRMED_NA && old_state!=DLG_STATE_CONFIRMED ) {
00290 LM_DBG("dialog %p confirmed\n",dlg);
00291
00292
00293 if ( !rpl->to && ((parse_headers(rpl, HDR_TO_F,0)<0) || !rpl->to) ) {
00294 LM_ERR("bad reply or missing TO hdr :-/\n");
00295 tag.s = 0;
00296 tag.len = 0;
00297 } else {
00298 tag = get_to(rpl)->tag_value;
00299 if (tag.s==0 || tag.len==0) {
00300 LM_ERR("missing TAG param in TO hdr :-/\n");
00301 tag.s = 0;
00302 tag.len = 0;
00303 }
00304 }
00305
00306
00307 if (populate_leg_info( dlg, rpl, t, DLG_CALLEE_LEG, &tag) !=0) {
00308 LM_ERR("could not add further info to the dialog\n");
00309 }
00310
00311
00312 dlg->start_ts = (unsigned int)(time(0));
00313
00314
00315
00316
00317 dlg->dflags |= DLG_FLAG_NEW;
00318 if ( dlg_db_mode==DB_MODE_REALTIME )
00319 update_dialog_dbinfo(dlg);
00320
00321 if (0 != insert_dlg_timer( &dlg->tl, dlg->lifetime )) {
00322 LM_CRIT("Unable to insert dlg %p [%u:%u] on event %d [%d->%d] "
00323 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00324 dlg, dlg->h_entry, dlg->h_id, event, old_state, new_state,
00325 dlg->callid.len, dlg->callid.s,
00326 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00327 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00328 } else {
00329 ref_dlg(dlg,1);
00330 }
00331
00332
00333 run_dlg_callbacks( DLGCB_CONFIRMED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
00334
00335 if (old_state==DLG_STATE_EARLY)
00336 if_update_stat(dlg_enable_stats, early_dlgs, -1);
00337
00338 if (unref) unref_dlg(dlg,unref);
00339 if_update_stat(dlg_enable_stats, active_dlgs, 1);
00340 return;
00341 }
00342
00343 if ( old_state!=DLG_STATE_DELETED && new_state==DLG_STATE_DELETED ) {
00344 LM_DBG("dialog %p failed (negative reply)\n", dlg);
00345
00346 run_dlg_callbacks( DLGCB_FAILED, dlg, rpl, DLG_DIR_UPSTREAM, 0);
00347
00348 if (unref)
00349 unref_dlg(dlg,unref);
00350 if (old_state==DLG_STATE_EARLY)
00351 if_update_stat(dlg_enable_stats, early_dlgs, -1);
00352 return;
00353 }
00354
00355 if (unref) unref_dlg(dlg,unref);
00356
00357 return;
00358 }
00359
00360
00361 static void dlg_seq_up_onreply(struct cell* t, int type,
00362 struct tmcb_params *param)
00363 {
00364 struct dlg_cell *dlg;
00365
00366 dlg = (struct dlg_cell *)(*param->param);
00367 if (shutdown_done || dlg==0)
00368 return;
00369
00370 if (type==TMCB_RESPONSE_FWDED) {
00371 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN, dlg, param->rpl,
00372 DLG_DIR_UPSTREAM, 0);
00373 return;
00374 }
00375
00376 return;
00377 }
00378
00379
00380
00381 static void dlg_seq_down_onreply(struct cell* t, int type,
00382 struct tmcb_params *param)
00383 {
00384 struct dlg_cell *dlg;
00385
00386 dlg = (struct dlg_cell *)(*param->param);
00387 if (shutdown_done || dlg==0)
00388 return;
00389
00390 if (type==TMCB_RESPONSE_FWDED) {
00391 run_dlg_callbacks(DLGCB_RESPONSE_WITHIN, dlg, param->rpl,
00392 DLG_DIR_DOWNSTREAM, 0);
00393 return;
00394 }
00395
00396 return;
00397 }
00398
00399
00400 inline static int get_dlg_timeout(struct sip_msg *req)
00401 {
00402 pv_value_t pv_val;
00403
00404 if( timeout_avp && pv_get_spec_value( req, timeout_avp, &pv_val)==0
00405 && pv_val.flags&PV_VAL_INT && pv_val.ri>0 ) {
00406 return pv_val.ri;
00407 }
00408 LM_DBG("invalid AVP value, use default timeout");
00409 return default_timeout;
00410 }
00411
00412
00413
00414 void dlg_onreq(struct cell* t, int type, struct tmcb_params *param)
00415 {
00416 struct sip_msg *msg;
00417 msg = param->req;
00418 if((msg->flags&dlg_flag)!=dlg_flag)
00419 return;
00420 if (current_dlg_pointer!=NULL)
00421 return;
00422 dlg_new_dialog(msg, t);
00423 }
00424
00425 void unref_new_dialog(void *dialog)
00426 {
00427 struct tmcb_params p;
00428
00429 p.param = (void*)&dialog;
00430 dlg_onreply(0, TMCB_TRANS_DELETED, &p);
00431 }
00432
00433
00434 int dlg_new_dialog(struct sip_msg *msg, struct cell *t)
00435 {
00436 struct dlg_cell *dlg;
00437 str s;
00438
00439 if((msg->to==NULL && parse_headers(msg, HDR_TO_F,0)<0) || msg->to==NULL)
00440 {
00441 LM_ERR("bad request or missing TO hdr\n");
00442 return -1;
00443 }
00444 s = get_to(msg)->tag_value;
00445 if(s.s!=0 && s.len!=0)
00446 return -1;
00447
00448 if(msg->first_line.u.request.method_value==METHOD_CANCEL)
00449 return -1;
00450
00451 if(parse_from_header(msg))
00452 {
00453 LM_ERR("bad request or missing FROM hdr\n");
00454 return -1;
00455 }
00456 if((msg->callid==NULL && parse_headers(msg,HDR_CALLID_F,0)<0)
00457 || msg->callid==NULL){
00458 LM_ERR("bad request or missing CALLID hdr\n");
00459 return -1;
00460 }
00461 s = msg->callid->body;
00462 trim(&s);
00463
00464
00465 if (s.len==0 || get_from(msg)->tag_value.len==0) {
00466 LM_ERR("invalid request -> callid (%d) or from TAG (%d) empty\n",
00467 s.len, get_from(msg)->tag_value.len);
00468 return -1;
00469 }
00470
00471 dlg = build_new_dlg(&s , &(get_from(msg)->uri) ,
00472 &(get_to(msg)->uri) ,
00473 &(get_from(msg)->tag_value) );
00474 if (dlg==0) {
00475 LM_ERR("failed to create new dialog\n");
00476 return -1;
00477 }
00478
00479
00480 if (populate_leg_info(dlg, msg, t, DLG_CALLER_LEG,
00481 &(get_from(msg)->tag_value)) !=0)
00482 {
00483 LM_ERR("could not add further info to the dialog\n");
00484 shm_free(dlg);
00485 return -1;
00486 }
00487
00488 current_dlg_pointer = dlg;
00489 _dlg_ctx.dlg = dlg;
00490
00491 link_dlg(dlg, 2);
00492
00493
00494 if ( seq_match_mode!=SEQ_MATCH_NO_ID &&
00495 add_dlg_rr_param( msg, dlg->h_entry, dlg->h_id)<0 ) {
00496 LM_ERR("failed to add RR param\n");
00497 goto error;
00498 }
00499
00500 if ( d_tmb.register_tmcb( msg, t,
00501 TMCB_RESPONSE_PRE_OUT|TMCB_RESPONSE_FWDED,
00502 dlg_onreply, (void*)dlg, unref_new_dialog)<0 ) {
00503 LM_ERR("failed to register TMCB\n");
00504 goto error;
00505 }
00506
00507 dlg->lifetime = get_dlg_timeout(msg);
00508 dlg->toroute = _dlg_ctx.to_route;
00509 dlg->sflags |= _dlg_ctx.flags;
00510
00511 if (_dlg_ctx.to_bye!=0)
00512 dlg->dflags |= DLG_FLAG_TOBYE;
00513
00514 if (t)
00515 t->dialog_ctx = (void*) dlg;
00516
00517 run_create_callbacks( dlg, msg);
00518
00519 if_update_stat( dlg_enable_stats, processed_dlgs, 1);
00520
00521 return 0;
00522 error:
00523 unref_dlg(dlg,1);
00524 profile_cleanup(msg, NULL);
00525 update_stat(failed_dlgs, 1);
00526 return -1;
00527 }
00528
00529
00530 static inline int parse_dlg_rr_param(char *p, char *end,
00531 int *h_entry, int *h_id)
00532 {
00533 char *s;
00534
00535 for ( s=p ; p<end && *p!=DLG_SEPARATOR ; p++ );
00536 if (*p!=DLG_SEPARATOR) {
00537 LM_ERR("malformed rr param '%.*s'\n", (int)(long)(end-s), s);
00538 return -1;
00539 }
00540
00541 if ( (*h_entry=reverse_hex2int( s, p-s))<0 ) {
00542 LM_ERR("invalid hash entry '%.*s'\n", (int)(long)(p-s), s);
00543 return -1;
00544 }
00545
00546 if ( (*h_id=reverse_hex2int( p+1, end-(p+1)))<0 ) {
00547 LM_ERR("invalid hash id '%.*s'\n", (int)(long)(end-(p+1)), p+1 );
00548 return -1;
00549 }
00550
00551 return 0;
00552 }
00553
00554
00555 static inline int pre_match_parse( struct sip_msg *req, str *callid,
00556 str *ftag, str *ttag)
00557 {
00558 if (parse_headers(req,HDR_CALLID_F|HDR_TO_F,0)<0 || !req->callid ||
00559 !req->to ) {
00560 LM_ERR("bad request or missing CALLID/TO hdr :-/\n");
00561 return -1;
00562 }
00563
00564 if (get_to(req)->tag_value.len==0) {
00565
00566 return -1;
00567 }
00568
00569 if (parse_from_header(req)<0 || get_from(req)->tag_value.len==0) {
00570 LM_ERR("failed to get From header\n");
00571 return -1;
00572 }
00573
00574
00575 *callid = req->callid->body;
00576 trim(callid);
00577
00578 *ttag = get_to(req)->tag_value;
00579
00580 *ftag = get_from(req)->tag_value;
00581 return 0;
00582 }
00583
00584
00585 static inline int update_cseqs(struct dlg_cell *dlg, struct sip_msg *req,
00586 unsigned int dir)
00587 {
00588 if ( (!req->cseq && parse_headers(req,HDR_CSEQ_F,0)<0) || !req->cseq ||
00589 !req->cseq->parsed) {
00590 LM_ERR("bad sip message or missing CSeq hdr :-/\n");
00591 return -1;
00592 }
00593
00594 if ( dir==DLG_DIR_UPSTREAM) {
00595 return dlg_update_cseq(dlg, DLG_CALLEE_LEG,&((get_cseq(req))->number));
00596 } else if ( dir==DLG_DIR_DOWNSTREAM) {
00597 return dlg_update_cseq(dlg, DLG_CALLER_LEG,&((get_cseq(req))->number));
00598 } else {
00599 LM_CRIT("dir is not set!\n");
00600 return -1;
00601 }
00602 }
00603
00604
00605 static void
00606 unreference_dialog(void *dialog)
00607 {
00608
00609 if (!d_table)
00610 return;
00611 unref_dlg((struct dlg_cell*)dialog, 1);
00612 }
00613
00614
00615 void dlg_onroute(struct sip_msg* req, str *route_params, void *param)
00616 {
00617 struct dlg_cell *dlg;
00618 str val;
00619 str callid;
00620 str ftag;
00621 str ttag;
00622 int h_entry;
00623 int h_id;
00624 int new_state;
00625 int old_state;
00626 int unref;
00627 int event;
00628 int timeout;
00629 unsigned int dir;
00630 int ret = 0;
00631
00632 if (current_dlg_pointer!=NULL)
00633 return;
00634
00635
00636
00637 if ( (!req->to && parse_headers(req, HDR_TO_F,0)<0) || !req->to ) {
00638 LM_ERR("bad request or missing TO hdr :-/\n");
00639 return;
00640 }
00641 if ( get_to(req)->tag_value.len==0 )
00642 return;
00643
00644 dlg = 0;
00645 dir = DLG_DIR_NONE;
00646
00647 if ( seq_match_mode!=SEQ_MATCH_NO_ID ) {
00648 if( d_rrb.get_route_param( req, &rr_param, &val)!=0) {
00649 LM_DBG("Route param '%.*s' not found\n", rr_param.len,rr_param.s);
00650 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
00651 return;
00652 } else {
00653 LM_DBG("route param is '%.*s' (len=%d)\n",val.len,val.s,val.len);
00654
00655 if ( parse_dlg_rr_param( val.s, val.s+val.len, &h_entry, &h_id)<0 )
00656 return;
00657
00658 dlg = lookup_dlg( h_entry, h_id);
00659 if (dlg==0) {
00660 LM_WARN("unable to find dialog for %.*s "
00661 "with route param '%.*s' [%u:%u]\n",
00662 req->first_line.u.request.method.len,
00663 req->first_line.u.request.method.s,
00664 val.len,val.s, h_entry, h_id);
00665 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
00666 return;
00667 } else {
00668
00669 if (pre_match_parse( req, &callid, &ftag, &ttag)<0) {
00670 unref_dlg(dlg, 1);
00671 return;
00672 }
00673 if (match_dialog( dlg, &callid, &ftag, &ttag, &dir )==0) {
00674 LM_WARN("tight matching failed for %.*s with callid='%.*s'/%d, "
00675 "ftag='%.*s'/%d, ttag='%.*s'/%d and direction=%d\n",
00676 req->first_line.u.request.method.len,
00677 req->first_line.u.request.method.s,
00678 callid.len, callid.s, callid.len,
00679 ftag.len, ftag.s, ftag.len,
00680 ttag.len, ttag.s, ttag.len, dir);
00681 LM_WARN("dialog identification elements are callid='%.*s'/%d, "
00682 "caller tag='%.*s'/%d, callee tag='%.*s'/%d\n",
00683 dlg->callid.len, dlg->callid.s, dlg->callid.len,
00684 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00685 dlg->tag[DLG_CALLER_LEG].len,
00686 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s,
00687 dlg->tag[DLG_CALLEE_LEG].len);
00688 unref_dlg(dlg, 1);
00689
00690
00691 dlg = 0;
00692 dir = DLG_DIR_NONE;
00693
00694 if (seq_match_mode==SEQ_MATCH_STRICT_ID )
00695 return;
00696 }
00697 }
00698 }
00699 }
00700
00701 if (dlg==0) {
00702 if (pre_match_parse( req, &callid, &ftag, &ttag)<0)
00703 return;
00704
00705
00706 dlg = get_dlg(&callid, &ftag, &ttag, &dir);
00707 if (!dlg){
00708 LM_DBG("Callid '%.*s' not found\n",
00709 req->callid->body.len, req->callid->body.s);
00710 return;
00711 }
00712 }
00713
00714
00715 switch ( req->first_line.u.request.method_value ) {
00716 case METHOD_PRACK:
00717 event = DLG_EVENT_REQPRACK; break;
00718 case METHOD_ACK:
00719 event = DLG_EVENT_REQACK; break;
00720 case METHOD_BYE:
00721 event = DLG_EVENT_REQBYE; break;
00722 default:
00723 event = DLG_EVENT_REQ;
00724 }
00725
00726 next_state_dlg( dlg, event, &old_state, &new_state, &unref);
00727
00728 CURR_DLG_ID = req->id;
00729 CURR_DLG_LIFETIME = (unsigned int)(time(0))-dlg->start_ts;
00730 CURR_DLG_STATUS = new_state;
00731
00732
00733 set_current_dialog( req, dlg);
00734 _dlg_ctx.dlg = dlg;
00735
00736
00737 if (event==DLG_EVENT_REQBYE && new_state==DLG_STATE_DELETED &&
00738 old_state!=DLG_STATE_DELETED) {
00739 LM_DBG("BYE successfully processed\n");
00740
00741 ret = remove_dialog_timer(&dlg->tl);
00742 if (ret < 0) {
00743 LM_CRIT("unable to unlink the timer on dlg %p [%u:%u] "
00744 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00745 dlg, dlg->h_entry, dlg->h_id,
00746 dlg->callid.len, dlg->callid.s,
00747 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00748 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00749 } else if (ret > 0) {
00750 LM_WARN("inconsitent dlg timer data on dlg %p [%u:%u] "
00751 "with clid '%.*s' and tags '%.*s' '%.*s'\n",
00752 dlg, dlg->h_entry, dlg->h_id,
00753 dlg->callid.len, dlg->callid.s,
00754 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00755 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00756 } else {
00757 unref++;
00758 }
00759
00760 run_dlg_callbacks( DLGCB_TERMINATED, dlg, req, dir, 0);
00761
00762
00763 if (dlg_db_mode)
00764 remove_dialog_from_db(dlg);
00765
00766
00767 unref_dlg(dlg, unref);
00768
00769 if_update_stat( dlg_enable_stats, active_dlgs, -1);
00770 return;
00771 }
00772
00773 if ( (event==DLG_EVENT_REQ || event==DLG_EVENT_REQACK)
00774 && new_state==DLG_STATE_CONFIRMED) {
00775 LM_DBG("sequential request successfully processed\n");
00776 timeout = get_dlg_timeout(req);
00777
00778 if (timeout!=default_timeout) {
00779 dlg->lifetime = timeout;
00780 if (update_dlg_timer( &dlg->tl, dlg->lifetime )==-1)
00781 LM_ERR("failed to update dialog lifetime\n");
00782 }
00783 if (update_cseqs(dlg, req, dir)!=0) {
00784 LM_ERR("cseqs update failed\n");
00785 } else {
00786 dlg->dflags |= DLG_FLAG_CHANGED;
00787 if ( dlg_db_mode==DB_MODE_REALTIME )
00788 update_dialog_dbinfo(dlg);
00789 }
00790
00791
00792 run_dlg_callbacks( DLGCB_REQ_WITHIN, dlg, req, dir, 0);
00793
00794 if ( (event!=DLG_EVENT_REQACK) &&
00795 (dlg->cbs.types)&DLGCB_RESPONSE_WITHIN ) {
00796
00797
00798 ref_dlg( dlg , 1);
00799
00800 if ( d_tmb.register_tmcb( req, 0, TMCB_RESPONSE_FWDED,
00801 (dir==DLG_DIR_UPSTREAM)?dlg_seq_down_onreply:dlg_seq_up_onreply,
00802 (void*)dlg, unreference_dialog)<0 ) {
00803 LM_ERR("failed to register TMCB (2)\n");
00804 unref_dlg( dlg , 1);
00805 }
00806 }
00807 }
00808
00809 if(new_state==DLG_STATE_CONFIRMED && old_state==DLG_STATE_CONFIRMED_NA){
00810 dlg->dflags |= DLG_FLAG_CHANGED;
00811 if(dlg_db_mode == DB_MODE_REALTIME)
00812 update_dialog_dbinfo(dlg);
00813 }
00814
00815 return;
00816 }
00817
00818
00819
00820 #define get_dlg_tl_payload(_tl_) ((struct dlg_cell*)((char *)(_tl_)- \
00821 (unsigned long)(&((struct dlg_cell*)0)->tl)))
00822
00823 void dlg_ontimeout( struct dlg_tl *tl)
00824 {
00825 struct dlg_cell *dlg;
00826 int new_state;
00827 int old_state;
00828 int unref;
00829 struct sip_msg *fmsg;
00830
00831 dlg = get_dlg_tl_payload(tl);
00832
00833 if(dlg->toroute>0 && dlg->toroute<RT_NO)
00834 {
00835 dlg_set_ctx_dialog(dlg);
00836 fmsg = faked_msg_next();
00837 if (exec_pre_req_cb(fmsg)>0)
00838 {
00839 LM_DBG("executing route %d on timeout\n", dlg->toroute);
00840 set_route_type(REQUEST_ROUTE);
00841 run_top_route(rlist[dlg->toroute], fmsg);
00842 exec_post_req_cb(fmsg);
00843 }
00844 }
00845
00846 if ((dlg->dflags&DLG_FLAG_TOBYE)
00847 && (dlg->state==DLG_STATE_CONFIRMED_NA
00848 || dlg->state==DLG_STATE_CONFIRMED))
00849 {
00850 dlg_bye_all(dlg, NULL);
00851 unref_dlg(dlg, 1);
00852 if_update_stat(dlg_enable_stats, expired_dlgs, 1);
00853 return;
00854 }
00855
00856 next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref);
00857
00858 if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) {
00859 LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n",
00860 dlg->callid.len, dlg->callid.s,
00861 dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s,
00862 dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s);
00863
00864
00865 run_dlg_callbacks( DLGCB_EXPIRED, dlg, 0, DLG_DIR_NONE, 0);
00866
00867
00868 if (dlg_db_mode)
00869 remove_dialog_from_db(dlg);
00870
00871 unref_dlg(dlg, unref+1);
00872
00873 if_update_stat( dlg_enable_stats, expired_dlgs, 1);
00874 if_update_stat( dlg_enable_stats, active_dlgs, -1);
00875 } else {
00876 unref_dlg(dlg, 1);
00877 }
00878
00879 return;
00880 }
00881
00882
00883
00884 int pv_get_dlg_lifetime(struct sip_msg *msg, pv_param_t *param,
00885 pv_value_t *res)
00886 {
00887 int l = 0;
00888 char *ch = NULL;
00889
00890 if(msg==NULL || res==NULL)
00891 return -1;
00892
00893 if (CURR_DLG_ID!=msg->id)
00894 return pv_get_null( msg, param, res);
00895
00896 res->ri = CURR_DLG_LIFETIME;
00897 ch = int2str( (unsigned long)res->ri, &l);
00898
00899 res->rs.s = ch;
00900 res->rs.len = l;
00901
00902 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00903
00904 return 0;
00905 }
00906
00907
00908 int pv_get_dlg_status(struct sip_msg *msg, pv_param_t *param,
00909 pv_value_t *res)
00910 {
00911 int l = 0;
00912 char *ch = NULL;
00913
00914 if(msg==NULL || res==NULL)
00915 return -1;
00916
00917 if (CURR_DLG_ID!=msg->id)
00918 return pv_get_null( msg, param, res);
00919
00920 res->ri = CURR_DLG_STATUS;
00921 ch = int2str( (unsigned long)res->ri, &l);
00922
00923 res->rs.s = ch;
00924 res->rs.len = l;
00925
00926 res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;
00927
00928 return 0;
00929 }
00930