Example #1
0
static void internal_bridge_after_cb(struct ast_channel *chan, void *data,
	enum ast_bridge_after_cb_reason reason)
{
	struct stasis_app_control *control = data;
	SCOPED_AO2LOCK(lock, control);
	struct ast_bridge_channel *bridge_channel;

	ast_debug(3, "%s, %s: %s\n",
		ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown",
			ast_bridge_after_cb_reason_string(reason));

	if (reason == AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED) {
		/* The impart actually failed so control->bridge isn't valid. */
		control->bridge = NULL;
	}

	ast_assert(chan == control->channel);

	/* Restore the channel's PBX */
	ast_channel_pbx_set(control->channel, control->pbx);
	control->pbx = NULL;

	if (control->bridge) {
		app_unsubscribe_bridge(control->app, control->bridge);

		/* No longer in the bridge */
		control->bridge = NULL;

		/* Get the bridge channel so we don't depart from the wrong bridge */
		ast_channel_lock(chan);
		bridge_channel = ast_channel_get_bridge_channel(chan);
		ast_channel_unlock(chan);

		/* Depart this channel from the bridge using the command queue if possible */
		stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup);
	}

	if (stasis_app_channel_is_stasis_end_published(chan)) {
		/* The channel has had a StasisEnd published on it, but until now had remained in
		 * the bridging system. This means that the channel moved from a Stasis bridge to a
		 * non-Stasis bridge and is now exiting the bridging system. Because of this, the
		 * channel needs to exit the Stasis application and go to wherever the non-Stasis
		 * bridge has directed it to go. If the non-Stasis bridge has not set up an after
		 * bridge destination, then the channel should be hung up.
		 */
		int hangup_flag;

		hangup_flag = ast_bridge_setup_after_goto(chan) ? AST_SOFTHANGUP_DEV : AST_SOFTHANGUP_ASYNCGOTO;
		ast_channel_lock(chan);
		ast_softhangup_nolock(chan, hangup_flag);
		ast_channel_unlock(chan);
	}
}
Example #2
0
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook)
{
	int res = 0;

	ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan));

	ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE);
	res = ast_audiohook_attach(autochan->chan, audiohook);

	if (!res) {
		ast_channel_lock(autochan->chan);
		if (ast_channel_is_bridged(autochan->chan)) {
			ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE);
		}
		ast_channel_unlock(autochan->chan);
	}
	return res;
}
Example #3
0
static int pickdown_channel(struct ast_channel *chan, void *pattern)
{
	int ret = 0;
	struct ast_module_user *u;
	struct ast_channel *cur;
	u = ast_module_user_add(chan);
	cur = find_matching_channel(chan, pattern, AST_STATE_RINGING);
	if (cur) {
                ast_verbose(VERBOSE_PREFIX_3 
			"Channel %s hung up ringing channel %s\n",
			chan->name, cur->name);
		pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", cur->name);
		ast_softhangup_nolock(cur, AST_SOFTHANGUP_DEV);
		ast_mutex_unlock(&cur->lock);
	} else {
		pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", "");
	}
	ast_module_user_remove(u);
	return(ret);
}
Example #4
0
int ast_pbx_hangup_handler_run(struct ast_channel *chan)
{
	struct ast_hangup_handler_list *handlers;
	struct ast_hangup_handler *h_handler;

	ast_channel_lock(chan);
	handlers = ast_channel_hangup_handlers(chan);
	if (AST_LIST_EMPTY(handlers)) {
		ast_channel_unlock(chan);
		return 0;
	}

	/*
	 * Make sure that the channel is marked as hungup since we are
	 * going to run the hangup handlers on it.
	 */
	ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC);

	for (;;) {
		handlers = ast_channel_hangup_handlers(chan);
		h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
		if (!h_handler) {
			break;
		}

		publish_hangup_handler_message("run", chan, h_handler->args);
		ast_channel_unlock(chan);

		ast_app_exec_sub(NULL, chan, h_handler->args, 1);
		ast_free(h_handler);

		ast_channel_lock(chan);
	}
	ast_channel_unlock(chan);
	return 1;
}