Example #1
0
struct ast_endpoint_snapshot *ast_endpoint_latest_snapshot(const char *tech,
	const char *name)
{
	RAII_VAR(char *, id, NULL, ast_free);
	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
	struct ast_endpoint_snapshot *snapshot;

	if (ast_strlen_zero(name)) {
		ast_asprintf(&id, "%s", tech);
	} else {
		ast_asprintf(&id, "%s/%s", tech, name);
	}
	if (!id) {
		return NULL;
	}
	ast_tech_to_upper(id);

	msg = stasis_cache_get(ast_endpoint_cache(),
		ast_endpoint_snapshot_type(), id);
	if (!msg) {
		return NULL;
	}

	snapshot = stasis_message_data(msg);
	ast_assert(snapshot != NULL);

	ao2_ref(snapshot, +1);
	return snapshot;
}
Example #2
0
struct stasis_cp_all *stasis_cp_all_create(const char *name,
	snapshot_get_id id_fn)
{
	RAII_VAR(char *, cached_name, NULL, ast_free);
	RAII_VAR(struct stasis_cp_all *, all, NULL, ao2_cleanup);

	all = ao2_alloc(sizeof(*all), all_dtor);
	if (!all) {
		return NULL;
	}

	ast_asprintf(&cached_name, "%s-cached", name);
	if (!cached_name) {
		return NULL;
	}

	all->topic = stasis_topic_create(name);
	all->topic_cached = stasis_topic_create(cached_name);
	all->cache = stasis_cache_create(id_fn);
	all->forward_all_to_cached =
		stasis_forward_all(all->topic, all->topic_cached);

	if (!all->topic || !all->topic_cached || !all->cache ||
		!all->forward_all_to_cached) {
		return NULL;
	}

	ao2_ref(all, +1);
	return all;
}
Example #3
0
static int setup_mixmonitor_ds(struct mixmonitor *mixmonitor, struct ast_channel *chan, char **datastore_id)
{
	struct ast_datastore *datastore = NULL;
	struct mixmonitor_ds *mixmonitor_ds;

	if (!(mixmonitor_ds = ast_calloc(1, sizeof(*mixmonitor_ds)))) {
		return -1;
	}

	if (ast_asprintf(datastore_id, "%p", mixmonitor_ds) == -1) {
		ast_log(LOG_ERROR, "Failed to allocate memory for MixMonitor ID.\n");
	}

	ast_mutex_init(&mixmonitor_ds->lock);
	ast_cond_init(&mixmonitor_ds->destruction_condition, NULL);

	if (!(datastore = ast_datastore_alloc(&mixmonitor_ds_info, *datastore_id))) {
		ast_mutex_destroy(&mixmonitor_ds->lock);
		ast_cond_destroy(&mixmonitor_ds->destruction_condition);
		ast_free(mixmonitor_ds);
		return -1;
	}


	mixmonitor_ds->samp_rate = 8000;
	mixmonitor_ds->audiohook = &mixmonitor->audiohook;
	datastore->data = mixmonitor_ds;

	ast_channel_lock(chan);
	ast_channel_datastore_add(chan, datastore);
	ast_channel_unlock(chan);

	mixmonitor->mixmonitor_ds = mixmonitor_ds;
	return 0;
}
Example #4
0
struct stasis_cp_all *stasis_cp_all_create(const char *name,
	snapshot_get_id id_fn)
{
	char *cached_name = NULL;
	struct stasis_cp_all *all;
	static int cache_id;

	all = ao2_t_alloc(sizeof(*all), all_dtor, name);
	if (!all) {
		return NULL;
	}

	ast_asprintf(&cached_name, "cache_pattern:%d/%s", ast_atomic_fetchadd_int(&cache_id, +1), name);
	if (!cached_name) {
		ao2_ref(all, -1);

		return NULL;
	}

	all->topic = stasis_topic_create(name);
	all->topic_cached = stasis_topic_create(cached_name);
	ast_free(cached_name);
	all->cache = stasis_cache_create(id_fn);
	all->forward_all_to_cached =
		stasis_forward_all(all->topic, all->topic_cached);

	if (!all->topic || !all->topic_cached || !all->cache ||
		!all->forward_all_to_cached) {
		ao2_ref(all, -1);

		return NULL;
	}

	return all;
}
Example #5
0
/**
 * Get all plan info.
 * @return
 */
struct ast_json* get_plans_all(void)
{
	char* sql;
	struct ast_json* j_res;
	struct ast_json* j_tmp;
	db_res_t* db_res;

	ast_asprintf(&sql, "select * from plan where in_use=%d;", E_DL_USE_OK);

	db_res = db_query(sql);
	ast_free(sql);
	if(db_res == NULL) {
		ast_log(LOG_ERROR, "Could not get plan all info.\n");
		return NULL;
	}

	j_res = ast_json_array_create();
	while(1) {
		j_tmp = db_get_record(db_res);
		if(j_tmp == NULL) {
			break;
		}
		ast_json_array_append(j_res, j_tmp);
	}
	db_free(db_res);

	return j_res;
}
Example #6
0
int delete_queue(const char* uuid)
{
	struct ast_json* j_tmp;
	char* tmp;
	char* sql;
	int ret;

	if(uuid == NULL) {
		// invalid parameter.
		return false;
	}

	j_tmp = ast_json_object_create();
	tmp = get_utc_timestamp();
	ast_json_object_set(j_tmp, "tm_delete", ast_json_string_create(tmp));
	ast_json_object_set(j_tmp, "in_use", ast_json_integer_create(E_DL_USE_NO));
	ast_free(tmp);

	tmp = db_get_update_str(j_tmp);
	AST_JSON_UNREF(j_tmp);
	ast_asprintf(&sql, "update queue set %s where uuid=\"%s\";", tmp, uuid);
	ast_free(tmp);

	ret = db_exec(sql);
	ast_free(sql);
	if(ret == false) {
		ast_log(LOG_WARNING, "Could not delete queue. uuid[%s]\n", uuid);
		return false;
	}

	// send notification
	send_manager_evt_out_queue_delete(uuid);

	return true;
}
Example #7
0
static void manager_park_bridged(struct mansession *s, const struct message *m,
		struct ast_channel *chan, struct ast_channel *parker_chan,
		const char *parkinglot, int timeout_override)
{
	struct ast_bridge_channel *bridge_channel;
	char *app_data;

	if (timeout_override != -1) {
		if (ast_asprintf(&app_data, "%s,t(%d)", parkinglot, timeout_override) == -1) {
			astman_send_error(s, m, "Park action failed\n");
			return;
		}
	} else {
		if (ast_asprintf(&app_data, "%s", parkinglot) == -1) {
			astman_send_error(s, m, "Park action failed\n");
			return;
		}
	}

	ast_channel_lock(parker_chan);
	bridge_channel = ast_channel_get_bridge_channel(parker_chan);
	ast_channel_unlock(parker_chan);

	if (!bridge_channel) {
		ast_free(app_data);
		astman_send_error(s, m, "Park action failed\n");
		return;
	}

	/* Subscribe to park messages for the channel being parked */
	if (create_parked_subscription(parker_chan, ast_channel_uniqueid(chan), 1)) {
		ast_free(app_data);
		astman_send_error(s, m, "Park action failed\n");
		ao2_cleanup(bridge_channel);
		return;
	}

	ast_bridge_channel_write_park(bridge_channel, ast_channel_uniqueid(chan),
			ast_channel_uniqueid(parker_chan), app_data);

	ast_free(app_data);

	astman_send_ack(s, m, "Park successful\n");
	ao2_cleanup(bridge_channel);
}
Example #8
0
static int rtt_start_to_str(const void *obj, const intptr_t *args, char **buf)
{
	const struct ast_sip_contact_status *status = obj;

	if (ast_asprintf(buf, "%ld.%06ld", (long)status->rtt_start.tv_sec, (long)status->rtt_start.tv_usec) == -1) {
		return -1;
	}

	return 0;
}
Example #9
0
static int convert_bdb_to_sqlite3(void)
{
	char *cmd;
	int res;

	ast_asprintf(&cmd, "%s/astdb2sqlite3 '%s'\n", ast_config_AST_SBIN_DIR, ast_config_AST_DB);
	res = ast_safe_system(cmd);
	ast_free(cmd);

	return res;
}
Example #10
0
/*!
 * \brief Performs common setup for a bridge playback operation
 * with both new controls and when existing controls are  found.
 *
 * \param args_media medias to play
 * \param args_media_count number of media items in \c media
 * \param args_lang language string split from arguments
 * \param args_offset_ms milliseconds offset split from arguments
 * \param args_playback_id string to use for playback split from
 *        arguments (null valid)
 * \param response ARI response being built
 * \param bridge Bridge the playback is being peformed on
 * \param control Control being used for the playback channel
 * \param json contents of the response to ARI
 * \param playback_url stores playback URL for use with response
 *
 * \retval -1 operation failed
 * \retval operation was successful
 */
static int ari_bridges_play_helper(const char **args_media,
	size_t args_media_count,
	const char *args_lang,
	int args_offset_ms,
	int args_skipms,
	const char *args_playback_id,
	struct ast_ari_response *response,
	struct ast_bridge *bridge,
	struct stasis_app_control *control,
	struct ast_json **json,
	char **playback_url)
{
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);

	const char *language;

	snapshot = stasis_app_control_get_snapshot(control);
	if (!snapshot) {
		ast_ari_response_error(
			response, 500, "Internal Error", "Failed to get control snapshot");
		return -1;
	}

	language = S_OR(args_lang, snapshot->language);

	playback = stasis_app_control_play_uri(control, args_media, args_media_count,
		language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,
		args_offset_ms, args_playback_id);

	if (!playback) {
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	if (ast_asprintf(playback_url, "/playbacks/%s",
			stasis_app_playback_get_id(playback)) == -1) {
		playback_url = NULL;
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	*json = stasis_app_playback_to_json(playback);
	if (!*json) {
		ast_ari_response_alloc_failed(response);
		return -1;
	}

	return 0;
}
Example #11
0
/*! \internal \brief convert multi object blob to ami string */
static struct ast_str *multi_object_blob_to_ami(void *obj)
{
	struct ast_str *ami_str=ast_str_create(1024);
	struct ast_str *ami_snapshot;
	const struct ast_multi_object_blob *multi = obj;
	enum stasis_user_multi_object_snapshot_type type;
	int i;

	if (!ami_str) {
		return NULL;
	}
	if (!multi) {
		ast_free(ami_str);
		return NULL;
	}

	for (type = 0; type < STASIS_UMOS_MAX; ++type) {
		for (i = 0; i < AST_VECTOR_SIZE(&multi->snapshots[type]); ++i) {
			char *name = "";
			void *snapshot = AST_VECTOR_GET(&multi->snapshots[type], i);
			ami_snapshot = NULL;

			if (i > 0) {
				ast_asprintf(&name, "%d", i + 1);
			}

			switch (type) {
			case STASIS_UMOS_CHANNEL:
				ami_snapshot = ast_manager_build_channel_state_string_prefix(snapshot, name);
				break;

			case STASIS_UMOS_BRIDGE:
				ami_snapshot = ast_manager_build_bridge_state_string_prefix(snapshot, name);
				break;

			case STASIS_UMOS_ENDPOINT:
				/* currently not sending endpoint snapshots to AMI */
				break;
			}
			if (ami_snapshot) {
				ast_str_append(&ami_str, 0, "%s", ast_str_buffer(ami_snapshot));
				ast_free(ami_snapshot);
			}
		}
	}

	return ami_str;
}
Example #12
0
int ast_sdp_crypto_build_offer(struct ast_sdp_crypto *p, int taglen)
{
	/* Rebuild the crypto line */
	if (p->a_crypto) {
		ast_free(p->a_crypto);
	}

	if (ast_asprintf(&p->a_crypto, "%d AES_CM_128_HMAC_SHA1_%i inline:%s",
			 p->tag, taglen, p->local_key64) == -1) {
			ast_log(LOG_ERROR, "Could not allocate memory for crypto line\n");
		return -1;
	}

	ast_debug(1, "Crypto line: a=crypto:%s\n", p->a_crypto);

	return 0;
}
Example #13
0
struct stasis_caching_topic *stasis_caching_topic_create(struct stasis_topic *original_topic, struct stasis_cache *cache)
{
	RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
	struct stasis_subscription *sub;
	RAII_VAR(char *, new_name, NULL, ast_free);
	int ret;

	ret = ast_asprintf(&new_name, "%s-cached", stasis_topic_name(original_topic));
	if (ret < 0) {
		return NULL;
	}

	caching_topic = ao2_alloc_options(sizeof(*caching_topic),
		stasis_caching_topic_dtor, AO2_ALLOC_OPT_LOCK_NOLOCK);
	if (caching_topic == NULL) {
		return NULL;
	}

	caching_topic->topic = stasis_topic_create(new_name);
	if (caching_topic->topic == NULL) {
		return NULL;
	}

	ao2_ref(cache, +1);
	caching_topic->cache = cache;

	sub = internal_stasis_subscribe(original_topic, caching_topic_exec, caching_topic, 0);
	if (sub == NULL) {
		return NULL;
	}

	ao2_ref(original_topic, +1);
	caching_topic->original_topic = original_topic;

	/* This is for the reference contained in the subscription above */
	ao2_ref(caching_topic, +1);
	caching_topic->sub = sub;

	/* The subscription holds the reference, so no additional ref bump. */
	return caching_topic;
}
Example #14
0
int update_queue(struct ast_json* j_queue)
{
	char* tmp;
	char* sql;
	struct ast_json* j_tmp;
	int ret;
	const char* uuid;

	uuid = ast_json_string_get(ast_json_object_get(j_queue, "uuid"));
	if(uuid == NULL) {
		ast_log(LOG_WARNING, "Could not get uuid.\n");
		return false;
	}

	tmp = db_get_update_str(j_queue);
	if(tmp == NULL) {
		ast_log(LOG_WARNING, "Could not get update str.\n");
		return false;
	}

	ast_asprintf(&sql, "update queue set %s where in_use=%d and uuid=\"%s\";", tmp, E_DL_USE_OK, uuid);
	ast_free(tmp);

	ret = db_exec(sql);
	ast_free(sql);
	if(ret == false) {
		ast_log(LOG_WARNING, "Could not update queue info. uuid[%s]\n", uuid);
		return false;
	}

	j_tmp = get_queue(uuid);
	if(j_tmp == NULL) {
		ast_log(LOG_WARNING, "Could not get update queue info. uuid[%s]\n", uuid);
		return false;
	}
	send_manager_evt_out_queue_update(j_tmp);
	AST_JSON_UNREF(j_tmp);

	return true;
}
Example #15
0
static void update_all_unqualified_endpoints(void)
{
	struct ao2_container *aors;
	struct ao2_container *contacts;
	RAII_VAR(struct ast_variable *, var_aor, NULL, ast_variables_destroy);
	RAII_VAR(struct ast_variable *, var_contact, NULL, ast_variables_destroy);
	RAII_VAR(char *, time_now, NULL, ast_free);
	struct timeval tv = ast_tvnow();

	if (!(var_aor = ast_variable_new("contact !=", "", ""))) {
		return;
	}
	if (!(var_aor->next = ast_variable_new("qualify_frequency <=", "0", ""))) {
		return;
	}

	if (ast_asprintf(&time_now, "%ld", tv.tv_sec) == -1) {
		return;
	}
	if (!(var_contact = ast_variable_new("expiration_time >", time_now, ""))) {
		return;
	}
	if (!(var_contact->next = ast_variable_new("qualify_frequency <=", "0", ""))) {
		return;
	}

	aors = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"aor", AST_RETRIEVE_FLAG_MULTIPLE, var_aor);
	if (aors) {
		ao2_callback(aors, OBJ_NODATA, on_aor_update_endpoint_state, NULL);
		ao2_ref(aors, -1);
	}

	contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(),
		"contact", AST_RETRIEVE_FLAG_MULTIPLE, var_contact);
	if (contacts) {
		ao2_callback(contacts, OBJ_NODATA, contact_update_endpoint_state, NULL);
		ao2_ref(contacts, -1);
	}
}
Example #16
0
/**
 * Get deleted plan info.
 * @param uuid
 * @return
 */
static struct ast_json* get_plan_deleted(const char* uuid)
{
	char* sql;
	struct ast_json* j_res;
	db_res_t* db_res;

	if(uuid == NULL) {
		ast_log(LOG_WARNING, "Invalid input parameters.\n");
		return NULL;
	}
	ast_asprintf(&sql, "select * from plan where in_use=%d and uuid=\"%s\";", E_DL_USE_NO, uuid);

	db_res = db_query(sql);
	ast_free(sql);
	if(db_res == NULL) {
		ast_log(LOG_ERROR, "Could not get plan info. uuid[%s]\n", uuid);
		return NULL;
	}

	j_res = db_get_record(db_res);
	db_free(db_res);

	return j_res;
}
Example #17
0
/*! \brief Custom handler for translating from an actual structure timeval to string */
static int expiration_struct2str(const void *obj, const intptr_t *args, char **buf)
{
	const struct ast_sip_contact *contact = obj;
	return (ast_asprintf(buf, "%ld", contact->expiration_time.tv_sec) < 0) ? -1 : 0;
}
struct stasis_app_recording *stasis_app_control_record(
	struct stasis_app_control *control,
	struct stasis_app_recording_options *options)
{
	struct stasis_app_recording *recording;
	char *last_slash;

	errno = 0;

	if (options == NULL ||
		ast_strlen_zero(options->name) ||
		ast_strlen_zero(options->format) ||
		options->max_silence_seconds < 0 ||
		options->max_duration_seconds < 0) {
		errno = EINVAL;
		return NULL;
	}

	ast_debug(3, "%s: Sending record(%s.%s) command\n",
		stasis_app_control_get_channel_id(control), options->name,
		options->format);

	recording = ao2_alloc(sizeof(*recording), recording_dtor);
	if (!recording) {
		errno = ENOMEM;
		return NULL;
	}
	recording->duration.total = -1;
	recording->duration.energy_only = -1;

	ast_asprintf(&recording->absolute_name, "%s/%s",
		ast_config_AST_RECORDING_DIR, options->name);

	if (recording->absolute_name == NULL) {
		errno = ENOMEM;
		ao2_ref(recording, -1);
		return NULL;
	}

	if ((last_slash = strrchr(recording->absolute_name, '/'))) {
		*last_slash = '\0';
		if (ast_safe_mkdir(ast_config_AST_RECORDING_DIR,
				recording->absolute_name, 0777) != 0) {
			/* errno set by ast_mkdir */
			ao2_ref(recording, -1);
			return NULL;
		}
		*last_slash = '/';
	}

	ao2_ref(options, +1);
	recording->options = options;
	recording->control = control;
	recording->state = STASIS_APP_RECORDING_STATE_QUEUED;

	if ((recording->options->if_exists == AST_RECORD_IF_EXISTS_FAIL) &&
			(ast_fileexists(recording->absolute_name, NULL, NULL))) {
		ast_log(LOG_WARNING, "Recording file '%s' already exists and ifExists option is failure.\n",
			recording->absolute_name);
		errno = EEXIST;
		ao2_ref(recording, -1);
		return NULL;
	}

	{
		RAII_VAR(struct stasis_app_recording *, old_recording, NULL,
			ao2_cleanup);

		SCOPED_AO2LOCK(lock, recordings);

		old_recording = ao2_find(recordings, options->name,
			OBJ_KEY | OBJ_NOLOCK);
		if (old_recording) {
			ast_log(LOG_WARNING,
				"Recording %s already in progress\n",
				recording->options->name);
			errno = EEXIST;
			ao2_ref(recording, -1);
			return NULL;
		}
		ao2_link(recordings, recording);
	}

	stasis_app_control_register_add_rule(control, &rule_recording);

	stasis_app_send_command_async(control, record_file, ao2_bump(recording), recording_cleanup);

	return recording;
}
Example #19
0
void ast_ari_bridges_record(struct ast_variable *headers,
	struct ast_ari_bridges_record_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
	RAII_VAR(struct ast_channel *, record_channel, NULL, ast_hangup);
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
	RAII_VAR(char *, recording_url, NULL, ast_free);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	RAII_VAR(struct stasis_app_recording_options *, options, NULL, ao2_cleanup);
	RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
	RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel);

	struct stasis_topic *channel_topic;
	struct stasis_topic *bridge_topic;
	size_t uri_name_maxlen;
	struct bridge_channel_control_thread_data *thread_data;
	pthread_t threadid;

	ast_assert(response != NULL);

	if (bridge == NULL) {
		return;
	}

	if (!(record_channel = prepare_bridge_media_channel("Recorder"))) {
		ast_ari_response_error(
			response, 500, "Internal Server Error", "Failed to create recording channel");
		return;
	}

	bridge_topic = ast_bridge_topic(bridge);
	channel_topic = ast_channel_topic(record_channel);

	/* Forward messages from the recording channel topic to the bridge topic so that anything listening for
	 * messages on the bridge topic will receive the recording start/stop messages. Other messages that would
	 * go to this channel will be suppressed since the channel is marked as internal.
	 */
	if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) {
		ast_ari_response_error(
			response, 500, "Internal Error", "Could not forward record channel stasis messages to bridge topic");
		return;
	}

	if (ast_unreal_channel_push_to_bridge(record_channel, bridge,
		AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) {
		ast_ari_response_error(
			response, 500, "Internal Error", "Failed to put recording channel into the bridge");
		return;
	}

	control = stasis_app_control_create(record_channel);
	if (control == NULL) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	options = stasis_app_recording_options_create(args->name, args->format);
	if (options == NULL) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	ast_string_field_build(options, target, "bridge:%s", args->bridge_id);
	options->max_silence_seconds = args->max_silence_seconds;
	options->max_duration_seconds = args->max_duration_seconds;
	options->terminate_on =
		stasis_app_recording_termination_parse(args->terminate_on);
	options->if_exists =
		stasis_app_recording_if_exists_parse(args->if_exists);
	options->beep = args->beep;

	if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"terminateOn invalid");
		return;
	}

	if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"ifExists invalid");
		return;
	}

	if (!ast_get_format_for_file_ext(options->format)) {
		ast_ari_response_error(
			response, 422, "Unprocessable Entity",
			"specified format is unknown on this system");
		return;
	}

	recording = stasis_app_control_record(control, options);
	if (recording == NULL) {
		switch(errno) {
		case EINVAL:
			/* While the arguments are invalid, we should have
			 * caught them prior to calling record.
			 */
			ast_ari_response_error(
				response, 500, "Internal Server Error",
				"Error parsing request");
			break;
		case EEXIST:
			ast_ari_response_error(response, 409, "Conflict",
				"Recording '%s' already exists and can not be overwritten",
				args->name);
			break;
		case ENOMEM:
			ast_ari_response_alloc_failed(response);
			break;
		case EPERM:
			ast_ari_response_error(
				response, 400, "Bad Request",
				"Recording name invalid");
			break;
		default:
			ast_log(LOG_WARNING,
				"Unrecognized recording error: %s\n",
				strerror(errno));
			ast_ari_response_error(
				response, 500, "Internal Server Error",
				"Internal Server Error");
			break;
		}
		return;
	}

	uri_name_maxlen = strlen(args->name) * 3;
	uri_encoded_name = ast_malloc(uri_name_maxlen);
	if (!uri_encoded_name) {
		ast_ari_response_alloc_failed(response);
		return;
	}
	ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen, ast_uri_http);

	if (ast_asprintf(&recording_url, "/recordings/live/%s",
			uri_encoded_name) == -1) {
		recording_url = NULL;
		ast_ari_response_alloc_failed(response);
		return;
	}

	json = stasis_app_recording_to_json(recording);
	if (!json) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	thread_data = ast_calloc(1, sizeof(*thread_data));
	if (!thread_data) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	thread_data->bridge_channel = record_channel;
	thread_data->control = control;
	thread_data->forward = channel_forward;

	if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) {
		ast_ari_response_alloc_failed(response);
		ast_free(thread_data);
		return;
	}

	/* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */
	record_channel = NULL;
	control = NULL;
	channel_forward = NULL;

	ast_ari_response_created(response, recording_url, ast_json_ref(json));
}
Example #20
0
/**
 * Update plan
 * @param j_plan
 * @return
 */
bool update_plan(const struct ast_json* j_plan)
{
	char* tmp;
	const char* tmp_const;
	char* sql;
	struct ast_json* j_tmp;
	int ret;
	char* uuid;

	if(j_plan == NULL) {
		return false;
	}

	j_tmp = ast_json_deep_copy(j_plan);
	if(j_tmp == NULL) {
		return false;
	}

	tmp_const = ast_json_string_get(ast_json_object_get(j_tmp, "uuid"));
	if(tmp_const == NULL) {
		ast_log(LOG_WARNING, "Could not get uuid.\n");
		AST_JSON_UNREF(j_tmp);
		return false;
	}
	uuid = ast_strdup(tmp_const);

	tmp = get_utc_timestamp();
	ast_json_object_set(j_tmp, "tm_update", ast_json_string_create(tmp));
	ast_free(tmp);

	tmp = db_get_update_str(j_tmp);
	if(tmp == NULL) {
		ast_log(LOG_WARNING, "Could not get update str.\n");
		AST_JSON_UNREF(j_tmp);
		ast_free(uuid);
		return false;
	}
	AST_JSON_UNREF(j_tmp);

	ast_asprintf(&sql, "update plan set %s where in_use=%d and uuid=\"%s\";", tmp, E_DL_USE_OK, uuid);
	ast_free(tmp);

	ret = db_exec(sql);
	ast_free(sql);
	if(ret == false) {
		ast_log(LOG_WARNING, "Could not update plan info. uuid[%s]\n", uuid);
		ast_free(uuid);
		return false;
	}

	j_tmp = get_plan(uuid);
	ast_free(uuid);
	if(j_tmp == NULL) {
		ast_log(LOG_WARNING, "Could not get updated plan info.\n");
		return false;
	}
	send_manager_evt_out_plan_update(j_tmp);
	AST_JSON_UNREF(j_tmp);

	return true;
}
static void mcd_set_operation_result(struct ast_channel *chan, int result) {
	char *numresult = NULL;
	ast_asprintf(&numresult, "%d", result);
	pbx_builtin_setvar_helper(chan, "MCDRESULT", numresult);
}
Example #22
0
struct stasis_app_recording *stasis_app_control_record(
	struct stasis_app_control *control,
	struct stasis_app_recording_options *options)
{
	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
	char *last_slash;

	errno = 0;

	if (options == NULL ||
		ast_strlen_zero(options->name) ||
		ast_strlen_zero(options->format) ||
		options->max_silence_seconds < 0 ||
		options->max_duration_seconds < 0) {
		errno = EINVAL;
		return NULL;
	}

	ast_debug(3, "%s: Sending record(%s.%s) command\n",
		stasis_app_control_get_channel_id(control), options->name,
		options->format);

	recording = ao2_alloc(sizeof(*recording), recording_dtor);
	if (!recording) {
		errno = ENOMEM;
		return NULL;
	}

	ast_asprintf(&recording->absolute_name, "%s/%s",
		ast_config_AST_RECORDING_DIR, options->name);

	if (recording->absolute_name == NULL) {
		errno = ENOMEM;
		return NULL;
	}

	if ((last_slash = strrchr(recording->absolute_name, '/'))) {
		*last_slash = '\0';
		if (ast_safe_mkdir(ast_config_AST_RECORDING_DIR,
				recording->absolute_name, 0777) != 0) {
			/* errno set by ast_mkdir */
			return NULL;
		}
		*last_slash = '/';
	}

	ao2_ref(options, +1);
	recording->options = options;
	recording->control = control;
	recording->state = STASIS_APP_RECORDING_STATE_QUEUED;

	{
		RAII_VAR(struct stasis_app_recording *, old_recording, NULL,
			ao2_cleanup);

		SCOPED_AO2LOCK(lock, recordings);

		old_recording = ao2_find(recordings, options->name,
			OBJ_KEY | OBJ_NOLOCK);
		if (old_recording) {
			ast_log(LOG_WARNING,
				"Recording %s already in progress\n",
				recording->options->name);
			errno = EEXIST;
			return NULL;
		}
		ao2_link(recordings, recording);
	}

	/* A ref is kept in the recordings container; no need to bump */
	stasis_app_send_command_async(control, record_file, recording);

	/* Although this should be bumped for the caller */
	ao2_ref(recording, +1);
	return recording;
}
void ast_ari_channels_record(struct ast_variable *headers,
	struct ast_ari_channels_record_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
	RAII_VAR(char *, recording_url, NULL, ast_free);
	struct ast_json *json;
	RAII_VAR(struct stasis_app_recording_options *, options, NULL,
		ao2_cleanup);
	RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
	size_t uri_name_maxlen;

	ast_assert(response != NULL);

	if (args->max_duration_seconds < 0) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"max_duration_seconds cannot be negative");
		return;
	}

	if (args->max_silence_seconds < 0) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"max_silence_seconds cannot be negative");
		return;
	}

	control = find_control(response, args->channel_id);
	if (control == NULL) {
		/* Response filled in by find_control */
		return;
	}

	options = stasis_app_recording_options_create(args->name, args->format);
	if (options == NULL) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
	}
	ast_string_field_build(options, target, "channel:%s", args->channel_id);
	options->max_silence_seconds = args->max_silence_seconds;
	options->max_duration_seconds = args->max_duration_seconds;
	options->terminate_on =
		stasis_app_recording_termination_parse(args->terminate_on);
	options->if_exists =
		stasis_app_recording_if_exists_parse(args->if_exists);
	options->beep = args->beep;

	if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"terminateOn invalid");
		return;
	}

	if (options->if_exists == -1) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"ifExists invalid");
		return;
	}

	if (!ast_get_format_for_file_ext(options->format)) {
		ast_ari_response_error(
			response, 422, "Unprocessable Entity",
			"specified format is unknown on this system");
		return;
	}

	recording = stasis_app_control_record(control, options);
	if (recording == NULL) {
		switch(errno) {
		case EINVAL:
			/* While the arguments are invalid, we should have
			 * caught them prior to calling record.
			 */
			ast_ari_response_error(
				response, 500, "Internal Server Error",
				"Error parsing request");
			break;
		case EEXIST:
			ast_ari_response_error(response, 409, "Conflict",
				"Recording '%s' already exists and can not be overwritten",
				args->name);
			break;
		case ENOMEM:
			ast_ari_response_error(
				response, 500, "Internal Server Error",
				"Out of memory");
			break;
		case EPERM:
			ast_ari_response_error(
				response, 400, "Bad Request",
				"Recording name invalid");
			break;
		default:
			ast_log(LOG_WARNING,
				"Unrecognized recording error: %s\n",
				strerror(errno));
			ast_ari_response_error(
				response, 500, "Internal Server Error",
				"Internal Server Error");
			break;
		}
		return;
	}

	uri_name_maxlen = strlen(args->name) * 3;
	uri_encoded_name = ast_malloc(uri_name_maxlen);
	if (!uri_encoded_name) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
		return;
	}
	ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
		ast_uri_http);

	if (ast_asprintf(&recording_url, "/recordings/live/%s",
			uri_encoded_name) == -1) {
		recording_url = NULL;
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
		return;
	}

	json = stasis_app_recording_to_json(recording);
	if (!json) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
		return;
	}

	ast_ari_response_created(response, recording_url, json);
}
Example #24
0
static void *hook_launch_thread(void *data)
{
	struct hook_thread_arg *arg = data;
	struct ast_variable hook_id = {
		.name = "HOOK_ID",
		.value = arg->hook_id,
	};
	struct ast_variable chan_name_var = {
		.name = "HOOK_CHANNEL",
		.value = arg->chan_name,
		.next = &hook_id,
	};

	ast_pbx_outgoing_exten("Local", NULL, full_exten_name, 60,
			arg->context, arg->exten, 1, NULL, AST_OUTGOING_NO_WAIT,
			NULL, NULL, &chan_name_var, NULL, NULL, 1, NULL);

	hook_thread_arg_destroy(arg);

	return NULL;
}

static struct hook_thread_arg *hook_thread_arg_alloc(struct ast_channel *chan,
		struct hook_state *state)
{
	struct hook_thread_arg *arg;

	if (!(arg = ast_calloc(1, sizeof(*arg)))) {
		return NULL;
	}

	ast_channel_lock(chan);
	arg->chan_name = ast_strdup(ast_channel_name(chan));
	ast_channel_unlock(chan);
	if (!arg->chan_name) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (ast_asprintf(&arg->hook_id, "%u", state->hook_id) == -1) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (!(arg->context = ast_strdup(state->context))) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	if (!(arg->exten = ast_strdup(state->exten))) {
		hook_thread_arg_destroy(arg);
		return NULL;
	}

	return arg;
}

static int do_hook(struct ast_channel *chan, struct hook_state *state)
{
	pthread_t t;
	struct hook_thread_arg *arg;
	int res;

	if (!(arg = hook_thread_arg_alloc(chan, state))) {
		return -1;
	}

	/*
	 * We don't want to block normal frame processing *at all* while we kick
	 * this off, so do it in a new thread.
	 */
	res = ast_pthread_create_detached_background(&t, NULL, hook_launch_thread, arg);
	if (res != 0) {
		hook_thread_arg_destroy(arg);
	}

	return res;
}

static int hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan,
		struct ast_frame *frame, enum ast_audiohook_direction direction)
{
	struct hook_state *state = (struct hook_state *) audiohook; /* trust me. */
	struct timeval now;
	int res = 0;

	if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE || state->disabled) {
		return 0;
	}

	now = ast_tvnow();
	if (ast_tvdiff_ms(now, state->last_hook) > state->interval * 1000) {
		if ((res = do_hook(chan, state))) {
			const char *name;
			ast_channel_lock(chan);
			name = ast_strdupa(ast_channel_name(chan));
			ast_channel_unlock(chan);
			ast_log(LOG_WARNING, "Failed to run hook on '%s'\n", name);
		}
		state->last_hook = now;
	}

	return res;
}

static struct hook_state *hook_state_alloc(const char *context, const char *exten,
		unsigned int interval, unsigned int hook_id)
{
	struct hook_state *state;

	if (!(state = ast_calloc(1, sizeof(*state)))) {
		return NULL;
	}

	state->context = ast_strdup(context);
	state->exten = ast_strdup(exten);
	state->interval = interval;
	state->hook_id = hook_id;

	ast_audiohook_init(&state->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE,
			AST_MODULE, AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
	state->audiohook.manipulate_callback = hook_callback;

	return state;
}

static int init_hook(struct ast_channel *chan, const char *context, const char *exten,
		unsigned int interval, unsigned int hook_id)
{
	struct hook_state *state;
	struct ast_datastore *datastore;
	char uid[32];

	snprintf(uid, sizeof(uid), "%u", hook_id);

	if (!(datastore = ast_datastore_alloc(&hook_datastore, uid))) {
		return -1;
	}
	ast_module_ref(ast_module_info->self);
	if (!(state = hook_state_alloc(context, exten, interval, hook_id))) {
		ast_datastore_free(datastore);
		return -1;
	}
	datastore->data = state;

	ast_channel_lock(chan);
	ast_channel_datastore_add(chan, datastore);
	ast_audiohook_attach(chan, &state->audiohook);
	ast_channel_unlock(chan);

	return 0;
}

static int hook_on(struct ast_channel *chan, const char *data, unsigned int hook_id)
{
	char *parse = ast_strdupa(S_OR(data, ""));
	AST_DECLARE_APP_ARGS(args,
		AST_APP_ARG(context);
		AST_APP_ARG(exten);
		AST_APP_ARG(interval);
	);
static void ari_channels_handle_play(
	const char *args_channel_id,
	const char *args_media,
	const char *args_lang,
	int args_offsetms,
	int args_skipms,
	const char *args_playback_id,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
	RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
	RAII_VAR(char *, playback_url, NULL, ast_free);
	struct ast_json *json;
	const char *language;

	ast_assert(response != NULL);

	control = find_control(response, args_channel_id);
	if (control == NULL) {
		/* Response filled in by find_control */
		return;
	}

	snapshot = stasis_app_control_get_snapshot(control);
	if (!snapshot) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"Channel not found");
		return;
	}

	if (args_skipms < 0) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"skipms cannot be negative");
		return;
	}

	if (args_offsetms < 0) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"offsetms cannot be negative");
		return;
	}

	language = S_OR(args_lang, snapshot->language);

	playback = stasis_app_control_play_uri(control, args_media, language,
		args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
	if (!playback) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Failed to queue media for playback");
		return;
	}

	if (ast_asprintf(&playback_url, "/playback/%s",
			stasis_app_playback_get_id(playback)) == -1) {
		playback_url = NULL;
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
		return;
	}

	json = stasis_app_playback_to_json(playback);
	if (!json) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Out of memory");
		return;
	}

	ast_ari_response_created(response, playback_url, json);
}