Ejemplo n.º 1
0
static void *app_control_dial(struct stasis_app_control *control,
	struct ast_channel *chan, void *data)
{
	RAII_VAR(struct ast_dial *, dial, ast_dial_create(), ast_dial_destroy);
	RAII_VAR(struct stasis_app_control_dial_data *, dial_data, data, ast_free);
	enum ast_dial_result res;
	char *tech, *resource;

	struct ast_channel *new_chan;
	struct ast_bridge *bridge;

	tech = dial_data->endpoint;
	if (!(resource = strchr(tech, '/'))) {
		return NULL;
	}
	*resource++ = '\0';

	if (!dial) {
		ast_log(LOG_ERROR, "Failed to create dialing structure.\n");
		return NULL;
	}

	if (ast_dial_append(dial, tech, resource) < 0) {
		ast_log(LOG_ERROR, "Failed to add %s/%s to dialing structure.\n", tech, resource);
		return NULL;
	}

	ast_dial_set_global_timeout(dial, dial_data->timeout);

	res = ast_dial_run(dial, NULL, 0);
	if (res != AST_DIAL_RESULT_ANSWERED || !(new_chan = ast_dial_answered_steal(dial))) {
		return NULL;
	}

	if (!(bridge = ast_bridge_basic_new())) {
		ast_log(LOG_ERROR, "Failed to create basic bridge.\n");
		return NULL;
	}

	if (ast_bridge_impart(bridge, new_chan, NULL, NULL,
		AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
		ast_hangup(new_chan);
	} else {
		stasis_app_control_add_channel_to_bridge(control, bridge);
	}

	return NULL;
}
Ejemplo n.º 2
0
/*!
 * \brief Bridge channels together
 * \param s
 * \param m
 *
 * Make sure valid channels were specified,
 * send errors if any of the channels could not be found/locked, answer channels if needed,
 * create the placeholder channels and grab the other channels
 * make the channels compatible, send error if we fail doing so
 * setup the bridge thread object and start the bridge.
 *
 * \retval 0
 */
static int action_bridge(struct mansession *s, const struct message *m)
{
	const char *channela = astman_get_header(m, "Channel1");
	const char *channelb = astman_get_header(m, "Channel2");
	enum play_tone_action playtone = parse_playtone(astman_get_header(m, "Tone"));
	RAII_VAR(struct ast_channel *, chana, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel *, chanb, NULL, ao2_cleanup);
	const char *chana_exten;
	const char *chana_context;
	int chana_priority;
	const char *chanb_exten;
	const char *chanb_context;
	int chanb_priority;
	struct ast_bridge *bridge;
	char buf[256];
	RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_a, NULL, ao2_cleanup);
	RAII_VAR(struct ast_features_xfer_config *, xfer_cfg_b, NULL, ao2_cleanup);

	/* make sure valid channels were specified */
	if (ast_strlen_zero(channela) || ast_strlen_zero(channelb)) {
		astman_send_error(s, m, "Missing channel parameter in request");
		return 0;
	}

	ast_debug(1, "Performing Bridge action on %s and %s\n", channela, channelb);

	/* Start with chana */
	chana = ast_channel_get_by_name_prefix(channela, strlen(channela));
	if (!chana) {
		snprintf(buf, sizeof(buf), "Channel1 does not exist: %s", channela);
		astman_send_error(s, m, buf);
		return 0;
	}
	ast_channel_lock(chana);
	xfer_cfg_a = ast_get_chan_features_xfer_config(chana);
	chana_exten = ast_strdupa(ast_channel_exten(chana));
	chana_context = ast_strdupa(ast_channel_context(chana));
	chana_priority = ast_channel_priority(chana);
	if (!ast_test_flag(ast_channel_flags(chana), AST_FLAG_IN_AUTOLOOP)) {
		chana_priority++;
	}
	ast_channel_unlock(chana);

	chanb = ast_channel_get_by_name_prefix(channelb, strlen(channelb));
	if (!chanb) {
		snprintf(buf, sizeof(buf), "Channel2 does not exist: %s", channelb);
		astman_send_error(s, m, buf);
		return 0;
	}
	ast_channel_lock(chanb);
	xfer_cfg_b = ast_get_chan_features_xfer_config(chanb);
	chanb_exten = ast_strdupa(ast_channel_exten(chanb));
	chanb_context = ast_strdupa(ast_channel_context(chanb));
	chanb_priority = ast_channel_priority(chanb);
	if (!ast_test_flag(ast_channel_flags(chanb), AST_FLAG_IN_AUTOLOOP)) {
		chanb_priority++;
	}
	ast_channel_unlock(chanb);

	bridge = ast_bridge_basic_new();
	if (!bridge) {
		astman_send_error(s, m, "Unable to create bridge\n");
		return 0;
	}

	ast_bridge_set_after_go_on(chana, chana_context, chana_exten, chana_priority, NULL);
	if (ast_bridge_add_channel(bridge, chana, NULL, playtone & PLAYTONE_CHANNEL1, xfer_cfg_a ? xfer_cfg_a->xfersound : NULL)) {
		snprintf(buf, sizeof(buf), "Unable to add Channel1 to bridge: %s", ast_channel_name(chana));
		astman_send_error(s, m, buf);
		ast_bridge_destroy(bridge, 0);
		return 0;
	}

	ast_bridge_set_after_go_on(chanb, chanb_context, chanb_exten, chanb_priority, NULL);
	if (ast_bridge_add_channel(bridge, chanb, NULL, playtone & PLAYTONE_CHANNEL2, xfer_cfg_b ? xfer_cfg_b->xfersound : NULL)) {
		snprintf(buf, sizeof(buf), "Unable to add Channel2 to bridge: %s", ast_channel_name(chanb));
		astman_send_error(s, m, buf);
		ast_bridge_destroy(bridge, 0);
		return 0;
	}

	astman_send_ack(s, m, "Channels have been bridged");
	ao2_cleanup(bridge);

	return 0;
}
Ejemplo n.º 3
0
int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags)
{
	int res;
	struct ast_bridge *bridge;
	struct ast_bridge_features chan_features;
	struct ast_bridge_features *peer_features;

	/* Setup features. */
	res = ast_bridge_features_init(&chan_features);
	peer_features = ast_bridge_features_new();
	if (res || !peer_features) {
		ast_bridge_features_destroy(peer_features);
		ast_bridge_features_cleanup(&chan_features);
		bridge_failed_peer_goto(chan, peer);
		return -1;
	}

	if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features)) {
		ast_bridge_features_destroy(peer_features);
		ast_bridge_features_cleanup(&chan_features);
		bridge_failed_peer_goto(chan, peer);
		return -1;
	}

	/* Create bridge */
	bridge = ast_bridge_basic_new();
	if (!bridge) {
		ast_bridge_features_destroy(peer_features);
		ast_bridge_features_cleanup(&chan_features);
		bridge_failed_peer_goto(chan, peer);
		return -1;
	}

	ast_bridge_basic_set_flags(bridge, flags);

	/* Put peer into the bridge */
	if (ast_bridge_impart(bridge, peer, NULL, peer_features,
		AST_BRIDGE_IMPART_CHAN_INDEPENDENT | AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP)) {
		ast_bridge_destroy(bridge, 0);
		ast_bridge_features_cleanup(&chan_features);
		bridge_failed_peer_goto(chan, peer);
		return -1;
	}

	/* Join bridge */
	ast_bridge_join(bridge, chan, NULL, &chan_features, NULL,
		AST_BRIDGE_JOIN_PASS_REFERENCE | AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP);

	/*
	 * If the bridge was broken for a hangup that isn't real, then
	 * don't run the h extension, because the channel isn't really
	 * hung up.  This should really only happen with
	 * AST_SOFTHANGUP_ASYNCGOTO.
	 */
	res = -1;
	ast_channel_lock(chan);
	if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
		res = 0;
	}
	ast_channel_unlock(chan);

	ast_bridge_features_cleanup(&chan_features);

	if (res && config->end_bridge_callback) {
		config->end_bridge_callback(config->end_bridge_callback_data);
	}

	return res;
}