/* When done, this function also has the job to unref the dialog as removed * from timer list. This must be done in all cases!! */ void dlg_ontimeout( struct dlg_tl *tl) { struct dlg_cell *dlg; int new_state; int old_state; int unref; dlg = get_dlg_tl_payload(tl); LM_DBG("byeontimeout ? %d , state = %d\n",dlg->flags,dlg->state); if ( (dlg->flags&DLG_FLAG_BYEONTIMEOUT) && (dlg->state==DLG_STATE_CONFIRMED_NA || dlg->state==DLG_STATE_CONFIRMED)) { init_dlg_term_reason(dlg,"Lifetime Timeout",sizeof("Lifetime Timeout")-1); /* we just send the BYEs in both directions */ dlg_end_dlg( dlg, NULL); /* dialog is no longer refed by timer; from now one it is refed by the send_bye functions */ unref_dlg( dlg, 1); /* is not 100% sure, but do it */ if_update_stat( dlg_enable_stats, expired_dlgs, 1); return ; } next_state_dlg( dlg, DLG_EVENT_REQBYE, &old_state, &new_state, &unref); if (new_state==DLG_STATE_DELETED && old_state!=DLG_STATE_DELETED) { LM_DBG("timeout for dlg with CallID '%.*s' and tags '%.*s' '%.*s'\n", dlg->callid.len, dlg->callid.s, dlg->legs[DLG_CALLER_LEG].tag.len, dlg->legs[DLG_CALLER_LEG].tag.s, dlg->legs[callee_idx(dlg)].tag.len, ZSW(dlg->legs[callee_idx(dlg)].tag.s)); /*destroy linkers */ destroy_linkers(dlg->profile_links); dlg->profile_links = NULL; /* dialog timeout */ run_dlg_callbacks( DLGCB_EXPIRED, dlg, 0, DLG_DIR_NONE, 0); /* delete the dialog from DB */ if (should_remove_dlg_db()) remove_dialog_from_db(dlg); unref_dlg(dlg, unref + 1 /*timer list*/); if_update_stat( dlg_enable_stats, expired_dlgs, 1); if_update_stat( dlg_enable_stats, active_dlgs, -1); } else { unref_dlg(dlg, 1 /*just timer list*/); } return; }
void dlg_ping_routine(unsigned int ticks , void * attr) { struct dlg_ping_list *expired,*it,*curr; struct dlg_cell *dlg; expired = get_timeout_dlgs(); it = expired; while (it) { dlg = it->dlg; LM_DBG("dialog %p has expired\n",dlg); curr = it->next; shm_free(it); dlg->pl = 0; it = curr; /* no longer reffed in list */ unref_dlg(dlg,1); /* dlg is still reffed in TM callback. deletion from memory * will happen only on 408 timeout */ /* FIXME - maybe better not to send BYE both ways as we know for sure one * end in down . */ dlg_end_dlg(dlg,0); } /* ping_timer->first now contains all active dialogs */ it = ping_timer->first; while (it) { dlg = it->dlg; /* do not ping ended dialogs */ if (dlg->state != DLG_STATE_DELETED) { if (dlg->flags & DLG_FLAG_PING_CALLER) { ref_dlg(dlg,1); if (send_leg_msg(dlg,&options_str,callee_idx(dlg), DLG_CALLER_LEG,0,0,reply_from_caller,dlg,unref_dlg_cb) < 0) { LM_ERR("failed to ping caller\n"); unref_dlg(dlg,1); } } if (dlg->flags & DLG_FLAG_PING_CALLEE) { ref_dlg(dlg,1); if (send_leg_msg(dlg,&options_str,DLG_CALLER_LEG, callee_idx(dlg),0,0,reply_from_callee,dlg,unref_dlg_cb) < 0) { LM_ERR("failed to ping callee\n"); unref_dlg(dlg,1); } } } it = it->next; } }
int terminate_dlg(unsigned int h_entry, unsigned int h_id,str *reason) { struct dlg_cell * dlg = NULL; int ret = 0; dlg = lookup_dlg(h_entry, h_id); if(!dlg) return 0; init_dlg_term_reason(dlg,reason->s,reason->len); if ( dlg_end_dlg( dlg, 0) ) { LM_ERR("Failed to end dialog"); ret = -1; } unref_dlg(dlg, 1); return ret; }
/*parameters from MI: h_entry, h_id of the requested dialog*/ struct mi_root * mi_terminate_dlg(struct mi_root *cmd_tree, void *param ){ struct mi_node* node; unsigned int h_entry, h_id; struct dlg_cell * dlg = NULL; str *mi_extra_hdrs = NULL; int status, msg_len; char *msg; if( d_table ==NULL) goto end; node = cmd_tree->node.kids; h_entry = h_id = 0; if (node==NULL || node->next==NULL) return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN); if (!node->value.s|| !node->value.len|| strno2int(&node->value,&h_entry)<0) goto error; node = node->next; if ( !node->value.s || !node->value.len || strno2int(&node->value,&h_id)<0) goto error; if (node->next) { node = node->next; if (node->value.len && node->value.s) mi_extra_hdrs = &node->value; } LM_DBG("h_entry %u h_id %u\n", h_entry, h_id); dlg = lookup_dlg(h_entry, h_id); /* lookup_dlg has incremented the reference count !! */ if(dlg){ init_dlg_term_reason(dlg,"MI Termination",sizeof("MI Termination")-1); if ( dlg_end_dlg( dlg, mi_extra_hdrs) ) { status = 500; msg = MI_DLG_OPERATION_ERR; msg_len = MI_DLG_OPERATION_ERR_LEN; } else { status = 200; msg = MI_OK_S; msg_len = MI_OK_LEN; } unref_dlg(dlg, 1); return init_mi_tree(status, msg, msg_len); } end: return init_mi_tree(404, MI_DIALOG_NOT_FOUND, MI_DIALOG_NOT_FOUND_LEN); error: return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN); }