Пример #1
0
static int func_channel_write_real(struct ast_channel *chan, const char *function,
			      char *data, const char *value)
{
	int ret = 0;
	signed char gainset;

	if (!strcasecmp(data, "language"))
		locked_string_field_set(chan, language, value);
	else if (!strcasecmp(data, "parkinglot"))
		locked_string_field_set(chan, parkinglot, value);
	else if (!strcasecmp(data, "musicclass"))
		locked_string_field_set(chan, musicclass, value);
	else if (!strcasecmp(data, "accountcode"))
		locked_string_field_set(chan, accountcode, value);
	else if (!strcasecmp(data, "userfield"))
		locked_string_field_set(chan, userfield, value);
	else if (!strcasecmp(data, "after_bridge_goto")) {
		if (ast_strlen_zero(value)) {
			ast_bridge_discard_after_goto(chan);
		} else {
			ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
		}
	} else if (!strcasecmp(data, "amaflags")) {
		ast_channel_lock(chan);
		if (isdigit(*value)) {
			int amaflags;
			sscanf(value, "%30d", &amaflags);
			ast_channel_amaflags_set(chan, amaflags);
		} else if (!strcasecmp(value,"OMIT")){
			ast_channel_amaflags_set(chan, 1);
		} else if (!strcasecmp(value,"BILLING")){
			ast_channel_amaflags_set(chan, 2);
		} else if (!strcasecmp(value,"DOCUMENTATION")){
			ast_channel_amaflags_set(chan, 3);
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "peeraccount"))
		locked_string_field_set(chan, peeraccount, value);
	else if (!strcasecmp(data, "hangupsource"))
		/* XXX - should we be forcing this here? */
		ast_set_hangupsource(chan, value, 0);
#ifdef CHANNEL_TRACE
	else if (!strcasecmp(data, "trace")) {
		ast_channel_lock(chan);
		if (ast_true(value))
			ret = ast_channel_trace_enable(chan);
		else if (ast_false(value))
			ret = ast_channel_trace_disable(chan);
		else {
			ret = -1;
			ast_log(LOG_WARNING, "Invalid value for CHANNEL(trace).\n");
		}
		ast_channel_unlock(chan);
	}
#endif
	else if (!strcasecmp(data, "tonezone")) {
		struct ast_tone_zone *new_zone;
		if (!(new_zone = ast_get_indication_zone(value))) {
			ast_log(LOG_ERROR, "Unknown country code '%s' for tonezone. Check indications.conf for available country codes.\n", value);
			ret = -1;
		} else {
			ast_channel_lock(chan);
			if (ast_channel_zone(chan)) {
				ast_channel_zone_set(chan, ast_tone_zone_unref(ast_channel_zone(chan)));
			}
			ast_channel_zone_set(chan, ast_tone_zone_ref(new_zone));
			ast_channel_unlock(chan);
			new_zone = ast_tone_zone_unref(new_zone);
		}
	} else if (!strcasecmp(data, "dtmf_features")) {
		ret = ast_bridge_features_ds_set_string(chan, value);
	} else if (!strcasecmp(data, "callgroup")) {
		ast_channel_lock(chan);
		ast_channel_callgroup_set(chan, ast_get_group(value));
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "pickupgroup")) {
		ast_channel_lock(chan);
		ast_channel_pickupgroup_set(chan, ast_get_group(value));
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "namedcallgroup")) {
		struct ast_namedgroups *groups = ast_get_namedgroups(value);

		ast_channel_lock(chan);
		ast_channel_named_callgroups_set(chan, groups);
		ast_channel_unlock(chan);
		ast_unref_namedgroups(groups);
	} else if (!strcasecmp(data, "namedpickupgroup")) {
		struct ast_namedgroups *groups = ast_get_namedgroups(value);

		ast_channel_lock(chan);
		ast_channel_named_pickupgroups_set(chan, groups);
		ast_channel_unlock(chan);
		ast_unref_namedgroups(groups);
	} else if (!strcasecmp(data, "txgain")) {
		sscanf(value, "%4hhd", &gainset);
		ast_channel_setoption(chan, AST_OPTION_TXGAIN, &gainset, sizeof(gainset), 0);
	} else if (!strcasecmp(data, "rxgain")) {
		sscanf(value, "%4hhd", &gainset);
		ast_channel_setoption(chan, AST_OPTION_RXGAIN, &gainset, sizeof(gainset), 0);
	} else if (!strcasecmp(data, "transfercapability")) {
		unsigned short i;

		ast_channel_lock(chan);
		for (i = 0; i < 0x20; i++) {
			if (!strcasecmp(transfercapability_table[i], value) && strcmp(value, "UNK")) {
				ast_channel_transfercapability_set(chan, i);
				break;
			}
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "hangup_handler_pop")) {
		/* Pop one hangup handler before pushing the new handler. */
		ast_pbx_hangup_handler_pop(chan);
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strcasecmp(data, "hangup_handler_push")) {
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strcasecmp(data, "hangup_handler_wipe")) {
		/* Pop all hangup handlers before pushing the new handler. */
		while (ast_pbx_hangup_handler_pop(chan)) {
		}
		ast_pbx_hangup_handler_push(chan, value);
	} else if (!strncasecmp(data, "secure_bridge_", 14)) {
		struct ast_datastore *ds;
		struct ast_secure_call_store *store;

		if (!chan || !value) {
			return -1;
		}

		ast_channel_lock(chan);
		if (!(ds = ast_channel_datastore_find(chan, &secure_call_info, NULL))) {
			if (!(ds = ast_datastore_alloc(&secure_call_info, NULL))) {
				ast_channel_unlock(chan);
				return -1;
			}
			if (!(store = ast_calloc(1, sizeof(*store)))) {
				ast_channel_unlock(chan);
				ast_free(ds);
				return -1;
			}
			ds->data = store;
			ast_channel_datastore_add(chan, ds);
		} else {
			store = ds->data;
		}

		if (!strcasecmp(data, "secure_bridge_signaling")) {
			store->signaling = ast_true(value) ? 1 : 0;
		} else if (!strcasecmp(data, "secure_bridge_media")) {
			store->media = ast_true(value) ? 1 : 0;
		}
		ast_channel_unlock(chan);
	} else if (!strcasecmp(data, "max_forwards")) {
		int max_forwards;
		if (sscanf(value, "%d", &max_forwards) != 1) {
			ast_log(LOG_WARNING, "Unable to set max forwards to '%s'\n", value);
			ret = -1;
		} else {
			ast_channel_lock(chan);
			ret = ast_max_forwards_set(chan, max_forwards);
			ast_channel_unlock(chan);
		}
	} else if (!ast_channel_tech(chan)->func_channel_write
		 || ast_channel_tech(chan)->func_channel_write(chan, function, data, value)) {
		ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n",
				data);
		ret = -1;
	}

	return ret;
}
Пример #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;
}