/*! * \brief Execute event routes based on new state * */ void dlg_run_event_route(dlg_cell_t *dlg, sip_msg_t *msg, int ostate, int nstate) { sip_msg_t *fmsg; int rt; int bkroute; if(dlg==NULL) return; if(ostate==nstate) return; rt = -1; if(nstate==DLG_STATE_CONFIRMED_NA) { rt = dlg_event_rt[DLG_EVENTRT_START]; } else if(nstate==DLG_STATE_DELETED) { if(ostate==DLG_STATE_CONFIRMED || ostate==DLG_STATE_CONFIRMED_NA) rt = dlg_event_rt[DLG_EVENTRT_END]; else if(ostate==DLG_STATE_UNCONFIRMED || ostate==DLG_STATE_EARLY) rt = dlg_event_rt[DLG_EVENTRT_FAILED]; } if(rt==-1 || event_rt.rlist[rt]==NULL) return; if(msg==NULL) fmsg = faked_msg_next(); else fmsg = msg; if (exec_pre_script_cb(fmsg, LOCAL_CB_TYPE)>0) { dlg_ref(dlg, 1); dlg_set_ctx_iuid(dlg); LM_DBG("executing event_route %d on state %d\n", rt, nstate); bkroute = get_route_type(); set_route_type(LOCAL_ROUTE); run_top_route(event_rt.rlist[rt], fmsg, 0); dlg_reset_ctx_iuid(); exec_post_script_cb(fmsg, LOCAL_CB_TYPE); dlg_unref(dlg, 1); set_route_type(bkroute); } }
/*! * \brief Timer function that removes expired dialogs, run timeout route * \param tl dialog timer list */ void dlg_ontimeout(struct dlg_tl *tl) { dlg_cell_t *dlg; int new_state, old_state, unref; sip_msg_t *fmsg; void* timeout_cb = 0; /* get the dialog tl payload */ dlg = ((struct dlg_cell*)((char *)(tl) - (unsigned long)(&((struct dlg_cell*)0)->tl))); /* mark dialog as expired */ dlg->dflags |= DLG_FLAG_EXPIRED; if(dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { if(dlg->toroute>0 && dlg->toroute<main_rt.entries && main_rt.rlist[dlg->toroute]!=NULL) { fmsg = faked_msg_next(); if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0) { dlg_ref(dlg, 1); dlg_set_ctx_iuid(dlg); LM_DBG("executing route %d on timeout\n", dlg->toroute); set_route_type(REQUEST_ROUTE); run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0); dlg_reset_ctx_iuid(); exec_post_script_cb(fmsg, REQUEST_CB_TYPE); dlg_unref(dlg, 1); } } if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE) { /* set the dialog context so that it's available in * tm:local-request event route */ dlg_set_ctx_iuid(dlg); if(dlg_bye_all(dlg, NULL)<0) dlg_unref(dlg, 1); dlg_reset_ctx_iuid(); dlg_unref(dlg, 1); if_update_stat(dlg_enable_stats, expired_dlgs, 1); return; } } next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref); /* used for computing duration for timed out acknowledged dialog */ if (DLG_STATE_CONFIRMED == old_state) { timeout_cb = (void *)CONFIRMED_DIALOG_STATE; } dlg_run_event_route(dlg, NULL, old_state, new_state); if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n", dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); /* dialog timeout */ run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, timeout_cb); dlg_unref(dlg, unref+1); if_update_stat( dlg_enable_stats, expired_dlgs, 1); if_update_stat( dlg_enable_stats, active_dlgs, -1); } else { dlg_unref(dlg, 1); } return; }
/*! * \brief Timer function that removes expired dialogs, run timeout route * \param tl dialog timer list */ void dlg_ontimeout(struct dlg_tl *tl) { dlg_cell_t *dlg; int new_state, old_state, unref; sip_msg_t *fmsg; /* get the dialog tl payload */ dlg = ((struct dlg_cell*)((char *)(tl) - (unsigned long)(&((struct dlg_cell*)0)->tl))); if(dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED) { if(dlg->toroute>0 && dlg->toroute<main_rt.entries && main_rt.rlist[dlg->toroute]!=NULL) { fmsg = faked_msg_next(); if (exec_pre_script_cb(fmsg, REQUEST_CB_TYPE)>0) { dlg_ref(dlg, 1); dlg_set_ctx_iuid(dlg); LM_DBG("executing route %d on timeout\n", dlg->toroute); set_route_type(REQUEST_ROUTE); run_top_route(main_rt.rlist[dlg->toroute], fmsg, 0); dlg_reset_ctx_iuid(); exec_post_script_cb(fmsg, REQUEST_CB_TYPE); dlg_unref(dlg, 1); } } if(dlg->iflags&DLG_IFLAG_TIMEOUTBYE) { dlg_bye_all(dlg, NULL); /* run event route for end of dlg */ dlg_run_event_route(dlg, NULL, dlg->state, DLG_STATE_DELETED); dlg_unref(dlg, 1); if_update_stat(dlg_enable_stats, expired_dlgs, 1); return; } } next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref); dlg_run_event_route(dlg, NULL, old_state, new_state); if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_WARN("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n", dlg->callid.len, dlg->callid.s, dlg->tag[DLG_CALLER_LEG].len, dlg->tag[DLG_CALLER_LEG].s, dlg->tag[DLG_CALLEE_LEG].len, dlg->tag[DLG_CALLEE_LEG].s); /* dialog timeout */ run_dlg_callbacks( DLGCB_EXPIRED, dlg, NULL, NULL, DLG_DIR_NONE, 0); dlg_unref(dlg, unref+1); if_update_stat( dlg_enable_stats, expired_dlgs, 1); if_update_stat( dlg_enable_stats, active_dlgs, -1); } else { dlg_unref(dlg, 1); } return; }