Example #1
0
/*!
 * \brief Terminate all or selected dialogs via the MI interface
 * \param cmd_tree MI command tree
 * \param param unused
 * \return mi node with the dialog information, or NULL on failure
 */
struct mi_root * mi_terminate_dlgs(struct mi_root *cmd_tree, void *param )
{
	struct mi_root* rpl_tree= NULL;
	struct dlg_cell* dlg = NULL;
	str headers = {0, 0};

	rpl_tree = process_mi_params( cmd_tree, &dlg);
	if (rpl_tree)
		/* param error */
		return rpl_tree;
	if (dlg==NULL)
		return init_mi_tree( 400, MI_SSTR(MI_MISSING_PARM));

	rpl_tree = init_mi_tree( 200, MI_SSTR(MI_OK));
	if (rpl_tree==0)
		return 0;
	if (dlg_bye_all(dlg, &headers)!=0)
		goto error;
	return rpl_tree;
error:
	free_mi_tree(rpl_tree);
	return NULL;
}
Example #2
0
/*!
 * \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;
}
Example #3
0
/* side =
 * 0: caller
 * 1: callee
 * 2: all
 */
int dlg_terminate(struct dlg_cell *dlg, struct sip_msg *msg, str *reason, int side, str *extra_hdrs) {

    struct cell* t;
    str default_reason = {"call failed", 11};
    int cfg_cmd = 0;
    str default_extra_headers = {0,0};

    if (!dlg) {
        LM_ERR("calling end_dialog with NULL pointer dlg\n");
        return -1;
    }

    if (!extra_hdrs)
        extra_hdrs = &default_extra_headers;


    if (msg) {
        //assume called from cfg command -> dlg_terminate, as opposed to internal API or mi interface
        cfg_cmd = 1;
    }

    if (!reason || reason->len <= 0 || !reason->s) {
        reason = &default_reason;
    }

    if (dlg->state != DLG_STATE_CONFIRMED) {
        if (side != 2) {
            LM_ERR("can't terminate only 1 side of an early dialog\n");
            return -1;
        }
        if (dlg->transaction) {
            LM_DBG("terminating early dialog with %d outbound forks\n",
                    dlg->transaction->nr_of_outgoings);

            t = dlg->transaction;

            if (t && t!=(void*) -1  && t->uas.request) {
                if (t->method.len!=6 || t->method.s[0]!='I' || t->method.s[1]!='N' || t->method.s[2]!='V')
		{
			//well this is the transaction of a subsequent request within the dialog
			//and the dialog is not confirmed yet, so its a PRACK or an UPDATE
			//could also be an options, but the important thing is how am i going to get
			//the transaction of the invite, that is the one i have to cancel
			LM_WARN("this is not my transaction so where am i?\n");
                        return 1; //TODO - need to check why we got in here once before? this crashed on t_reply as t seemed invalid
		}

                //TODO: here we are assuming none of the CALLEE's have sent a 200, in
                //which case we would have to send an ACK, BYE
                //so right now - we are sending 488 to caller and CANCEL's to all CALLEEs

                LM_DBG("tearing down dialog in EARLY state - no clients responded > 199\n");
                if (cfg_cmd) {
                        d_tmb.t_reply(msg,488,reason->s);
                        d_tmb.t_release(msg);
                } else {
                        d_tmb.t_reply(t->uas.request,488,reason->s);
                        d_tmb.t_release(t->uas.request);
                }
            }
        } else {
            LM_WARN("can't terminate early dialog without a transaction\n");
            return -1;
        }
    } else {
        LM_DBG("terminating confirmed dialog\n");
        if (side == DLG_CALLER_LEG /* 0 */ || side == DLG_CALLEE_LEG /* 1 */) {
            if (dlg_bye(dlg, (extra_hdrs->len > 0) ? extra_hdrs : NULL, side) < 0)
                return -1;

        } else {
            if (dlg_bye_all(dlg, (extra_hdrs->len > 0) ? extra_hdrs : NULL) < 0)
                return -1;
        }
    }
    return 1;
}
Example #4
0
/*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,0};
	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 = dlg_lookup(h_entry, h_id);

	// lookup_dlg has incremented the reference count

	if(dlg){
		if(dlg_bye_all(dlg,(mi_extra_hdrs.len>0)?&mi_extra_hdrs:NULL)<0) {
			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;
		}

		dlg_release(dlg);

		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);

}
Example #5
0
/*!
 * \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;
}