示例#1
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;
}
void ast_ari_device_states_delete(struct ast_variable *headers,
	struct ast_ari_device_states_delete_args *args,
	struct ast_ari_response *response)
{
	switch (stasis_app_device_state_delete(args->device_name)) {
	case STASIS_DEVICE_STATE_NOT_CONTROLLED:
		ast_ari_response_error(response, 409,
			"Conflict", "Uncontrolled device specified");
		return;
	case STASIS_DEVICE_STATE_MISSING:
		ast_ari_response_error(response, 404,
			"Not Found", "Device name is missing");
		return;
	case STASIS_DEVICE_STATE_SUBSCRIBERS:
		ast_ari_response_error(response, 500,
			"Internal Server Error",
			"Cannot delete device with subscribers");
		return;
	case STASIS_DEVICE_STATE_OK:
	case STASIS_DEVICE_STATE_UNKNOWN:
		ast_ari_response_no_content(response);
	}
}
示例#3
0
void ast_ari_sounds_get(struct ast_variable *headers,
	struct ast_ari_sounds_get_args *args,
	struct ast_ari_response *response)
{
	struct ast_json *sound_blob;

	sound_blob = create_sound_blob(args->sound_id, NULL);
	if (!sound_blob) {
		ast_ari_response_error(response, 404, "Not Found", "Sound not found");
		return;
	}

	ast_ari_response_ok(response, sound_blob);
}
示例#4
0
void ast_ari_playbacks_get(struct ast_variable *headers,
                           struct ast_ari_playbacks_get_args *args,
                           struct ast_ari_response *response)
{
    RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
    struct ast_json *json;

    playback = stasis_app_playback_find_by_id(args->playback_id);
    if (playback == NULL) {
        ast_ari_response_error(response, 404, "Not Found",
                               "Playback not found");
        return;
    }

    json = stasis_app_playback_to_json(playback);
    if (json == NULL) {
        ast_ari_response_error(response, 500,
                               "Internal Server Error", "Error building response");
        return;
    }

    ast_ari_response_ok(response, json);
}
void ast_ari_device_states_update(struct ast_variable *headers,
	struct ast_ari_device_states_update_args *args,
	struct ast_ari_response *response)
{
	switch (stasis_app_device_state_update(
			args->device_name, args->device_state)) {
	case STASIS_DEVICE_STATE_NOT_CONTROLLED:
		ast_ari_response_error(response, 409,
			"Conflict", "Uncontrolled device specified");
		return;
	case STASIS_DEVICE_STATE_MISSING:
		ast_ari_response_error(response, 404,
			"Not Found", "Device name is missing");
		return;
	case STASIS_DEVICE_STATE_UNKNOWN:
		ast_ari_response_error(response, 500, "Internal Server Error",
				       "Unknown device");
		return;
	case STASIS_DEVICE_STATE_OK:
	case STASIS_DEVICE_STATE_SUBSCRIBERS: /* shouldn't be returned for update */
		ast_ari_response_no_content(response);
	}
}
示例#6
0
/*!
 * \brief Parameter parsing callback for /recordings/live/{recordingName}/stop.
 * \param get_params GET parameters in the HTTP request.
 * \param path_vars Path variables extracted from the request.
 * \param headers HTTP headers.
 * \param[out] response Response to the HTTP request.
 */
static void ast_ari_stop_recording_cb(
	struct ast_variable *get_params, struct ast_variable *path_vars,
	struct ast_variable *headers, struct ast_ari_response *response)
{
	struct ast_stop_recording_args args = {};
	struct ast_variable *i;
#if defined(AST_DEVMODE)
	int is_valid;
	int code;
#endif /* AST_DEVMODE */

	for (i = path_vars; i; i = i->next) {
		if (strcmp(i->name, "recordingName") == 0) {
			args.recording_name = (i->value);
		} else
		{}
	}
	ast_ari_stop_recording(headers, &args, response);
#if defined(AST_DEVMODE)
	code = response->response_code;

	switch (code) {
	case 0: /* Implementation is still a stub, or the code wasn't set */
		is_valid = response->message == NULL;
		break;
	case 500: /* Internal Server Error */
	case 501: /* Not Implemented */
	case 404: /* Recording not found */
		is_valid = 1;
		break;
	default:
		if (200 <= code && code <= 299) {
			is_valid = ast_ari_validate_void(
				response->message);
		} else {
			ast_log(LOG_ERROR, "Invalid error response %d for /recordings/live/{recordingName}/stop\n", code);
			is_valid = 0;
		}
	}

	if (!is_valid) {
		ast_log(LOG_ERROR, "Response validation failed for /recordings/live/{recordingName}/stop\n");
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Response validation failed");
	}
#endif /* AST_DEVMODE */

fin: __attribute__((unused))
	return;
}
void ast_ari_mailboxes_list(struct ast_variable *headers,
	struct ast_ari_mailboxes_list_args *args,
	struct ast_ari_response *response)
{
	struct ast_json *json;

	if (!(json = stasis_app_mailboxes_to_json())) {
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Error building response");
		return;
	}

	ast_ari_response_ok(response, json);
}
示例#8
0
/*!
 * \brief Parameter parsing callback for /sounds/{soundId}.
 * \param get_params GET parameters in the HTTP request.
 * \param path_vars Path variables extracted from the request.
 * \param headers HTTP headers.
 * \param[out] response Response to the HTTP request.
 */
static void ast_ari_sounds_get_cb(
	struct ast_tcptls_session_instance *ser,
	struct ast_variable *get_params, struct ast_variable *path_vars,
	struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
{
	struct ast_ari_sounds_get_args args = {};
	struct ast_variable *i;
#if defined(AST_DEVMODE)
	int is_valid;
	int code;
#endif /* AST_DEVMODE */

	for (i = path_vars; i; i = i->next) {
		if (strcmp(i->name, "soundId") == 0) {
			args.sound_id = (i->value);
		} else
		{}
	}
	ast_ari_sounds_get(headers, &args, response);
#if defined(AST_DEVMODE)
	code = response->response_code;

	switch (code) {
	case 0: /* Implementation is still a stub, or the code wasn't set */
		is_valid = response->message == NULL;
		break;
	case 500: /* Internal Server Error */
	case 501: /* Not Implemented */
		is_valid = 1;
		break;
	default:
		if (200 <= code && code <= 299) {
			is_valid = ast_ari_validate_sound(
				response->message);
		} else {
			ast_log(LOG_ERROR, "Invalid error response %d for /sounds/{soundId}\n", code);
			is_valid = 0;
		}
	}

	if (!is_valid) {
		ast_log(LOG_ERROR, "Response validation failed for /sounds/{soundId}\n");
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Response validation failed");
	}
#endif /* AST_DEVMODE */

fin: __attribute__((unused))
	return;
}
示例#9
0
void ast_ari_recordings_get_live(struct ast_variable *headers,
	struct ast_ari_recordings_get_live_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
	struct ast_json *json;

	recording = stasis_app_recording_find_by_name(args->recording_name);
	if (recording == NULL) {
		ast_ari_response_error(response, 404, "Not Found",
			"Recording not found");
		return;
	}

	json = stasis_app_recording_to_json(recording);
	if (json == NULL) {
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Error building response");
		return;
	}

	ast_ari_response_ok(response, json);
}
示例#10
0
void ast_ari_channels_redirect(struct ast_variable *headers,
	struct ast_ari_channels_redirect_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
	char *tech;
	char *resource;
	int tech_len;

	control = find_control(response, args->channel_id);
	if (!control) {
		return;
	}

	if (ast_strlen_zero(args->endpoint)) {
		ast_ari_response_error(response, 400, "Not Found",
			"Required parameter 'endpoint' not provided.");
		return;
	}

	tech = ast_strdupa(args->endpoint);
	if (!(resource = strchr(tech, '/')) || !(tech_len = resource - tech)) {
		ast_ari_response_error(response, 422, "Unprocessable Entity",
			"Endpoint parameter '%s' does not contain tech/resource", args->endpoint);
		return;
	}

	*resource++ = '\0';
	if (ast_strlen_zero(resource)) {
		ast_ari_response_error(response, 422, "Unprocessable Entity",
			"No resource provided in endpoint parameter '%s'", args->endpoint);
		return;
	}

	chan_snapshot = ast_channel_snapshot_get_latest(args->channel_id);
	if (!chan_snapshot) {
		ast_ari_response_error(response, 500, "Internal Server Error",
			"Unable to find channel snapshot for '%s'", args->channel_id);
		return;
	}

	if (strncasecmp(chan_snapshot->type, tech, tech_len)) {
		ast_ari_response_error(response, 422, "Unprocessable Entity",
			"Endpoint technology '%s' does not match channel technology '%s'",
			tech, chan_snapshot->type);
		return;
	}

	if (stasis_app_control_redirect(control, resource)) {
		ast_ari_response_error(response, 500, "Internal Server Error",
			"Failed to redirect channel");
		return;
	}

	ast_ari_response_no_content(response);
}
void ast_ari_channels_unmute(struct ast_variable *headers,
	struct ast_ari_channels_unmute_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	unsigned int direction = 0;
	enum ast_frame_type frametype = AST_FRAME_VOICE;

	control = find_control(response, args->channel_id);
	if (control == NULL) {
		return;
	}

	if (ast_strlen_zero(args->direction)) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"Direction is required");
		return;
	}

	if (!strcmp(args->direction, "in")) {
		direction = AST_MUTE_DIRECTION_READ;
	} else if (!strcmp(args->direction, "out")) {
		direction = AST_MUTE_DIRECTION_WRITE;
	} else if (!strcmp(args->direction, "both")) {
		direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
	} else {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"Invalid direction specified");
		return;
	}

	stasis_app_control_unmute(control, direction, frametype);

	ast_ari_response_no_content(response);
}
void ast_ari_device_states_get(struct ast_variable *headers,
	struct ast_ari_device_states_get_args *args,
	struct ast_ari_response *response)
{
	struct ast_json *json;

	if (!(json = stasis_app_device_state_to_json(
		      args->device_name, ast_device_state(args->device_name)))) {
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Error building response");
		return;
	}

	ast_ari_response_ok(response, json);
}
示例#13
0
void ast_ari_set_global_var(struct ast_variable *headers, struct ast_set_global_var_args *args, struct ast_ari_response *response)
{
	ast_assert(response != NULL);

	if (ast_strlen_zero(args->variable)) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"Variable name is required");
		return;
	}

	pbx_builtin_setvar_helper(NULL, args->variable, args->value);

	ast_ari_response_no_content(response);
}
示例#14
0
void ast_ari_asterisk_rotate_log(struct ast_variable *headers,
	struct ast_ari_asterisk_rotate_log_args *args,
	struct ast_ari_response *response)
{
	int res;

	ast_assert(response != NULL);

	res = ast_logger_rotate_channel(args->log_channel_name);

	if (res == AST_LOGGER_FAILURE) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"Log channel does not exist");
		return;
	} else if (res == AST_LOGGER_ALLOC_ERROR) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Allocation failed");
		return;
	}

	ast_ari_response_no_content(response);
}
示例#15
0
void ast_ari_bridges_get(struct ast_variable *headers,
	struct ast_ari_bridges_get_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_bridge_snapshot *, snapshot, ast_bridge_snapshot_get_latest(args->bridge_id), ao2_cleanup);
	if (!snapshot) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"Bridge not found");
		return;
	}

	ast_ari_response_ok(response,
		ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer()));
}
示例#16
0
void ast_ari_asterisk_load_module(struct ast_variable *headers,
	struct ast_ari_asterisk_load_module_args *args,
	struct ast_ari_response *response)
{
	enum ast_module_load_result load_result;

	ast_assert(response != NULL);

	if (ast_module_check(args->module_name)) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module is already loaded");
		return;
	}

	load_result = ast_load_resource(args->module_name);

	if (load_result == AST_MODULE_LOAD_DECLINE) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module load declined");
		return;
	} else if (load_result == AST_MODULE_LOAD_SKIP) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module was skipped");
		return;
	} else if (load_result == AST_MODULE_LOAD_FAILURE) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module could not be loaded properly");
		return;
	}

	ast_ari_response_no_content(response);
}
示例#17
0
static int check_add_remove_channel(struct ast_ari_response *response,
				    struct stasis_app_control *control,
				    enum stasis_app_control_channel_result result)
{
	switch (result) {
	case STASIS_APP_CHANNEL_RECORDING :
		ast_ari_response_error(
			response, 409, "Conflict", "Channel %s currently recording",
			stasis_app_control_get_channel_id(control));
		return -1;
	case STASIS_APP_CHANNEL_OKAY:
		return 0;
	}
	return 0;
}
示例#18
0
static struct control_list *control_list_create(struct ast_ari_response *response, size_t count, const char **channels) {
	RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
	size_t i;

	if (count == 0 || !channels) {
		ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
		return NULL;
	}

	list = ao2_alloc(sizeof(*list) + count * sizeof(list->controls[0]), control_list_dtor);
	if (!list) {
		ast_ari_response_alloc_failed(response);
		return NULL;
	}

	for (i = 0; i < count; ++i) {
		if (ast_strlen_zero(channels[i])) {
			continue;
		}
		list->controls[list->count] =
			find_channel_control(response, channels[i]);
		if (!list->controls[list->count]) {
			/* response filled in by find_channel_control() */
			return NULL;
		}
		++list->count;
	}

	if (list->count == 0) {
		ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
		return NULL;
	}

	ao2_ref(list, +1);
	return list;
}
示例#19
0
void ast_ari_bridges_list(struct ast_variable *headers,
	struct ast_ari_bridges_list_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
	RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	struct ao2_iterator i;
	void *obj;

	cache = ast_bridge_cache();
	if (!cache) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Message bus not initialized");
		return;
	}
	ao2_ref(cache, +1);

	snapshots = stasis_cache_dump(cache, ast_bridge_snapshot_type());
	if (!snapshots) {
		ast_ari_response_alloc_failed(response);
		return;
	}

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

	i = ao2_iterator_init(snapshots, 0);
	while ((obj = ao2_iterator_next(&i))) {
		RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
		struct ast_bridge_snapshot *snapshot = stasis_message_data(msg);
		struct ast_json *json_bridge = ast_bridge_snapshot_to_json(snapshot, stasis_app_get_sanitizer());

		if (!json_bridge || ast_json_array_append(json, json_bridge)) {
			ao2_iterator_destroy(&i);
			ast_ari_response_alloc_failed(response);
			return;
		}
	}
	ao2_iterator_destroy(&i);

	ast_ari_response_ok(response, ast_json_ref(json));
}
示例#20
0
void ast_ari_events_user_event(struct ast_variable *headers,
	struct ast_ari_events_user_event_args *args,
	struct ast_ari_response *response)
{
	enum stasis_app_user_event_res res;
	struct ast_json *json_variables = NULL;

	if (args->variables) {
		ast_ari_events_user_event_parse_body(args->variables, args);
		json_variables = ast_json_object_get(args->variables, "variables");
	}

	if (ast_strlen_zero(args->application)) {
		ast_ari_response_error(response, 400, "Bad Request",
			"Missing parameter application");
		return;
	}

	res = stasis_app_user_event(args->application,
		args->event_name,
		args->source, args->source_count,
		json_variables);

	switch (res) {
	case STASIS_APP_USER_OK:
		ast_ari_response_no_content(response);
		break;

	case STASIS_APP_USER_APP_NOT_FOUND:
		ast_ari_response_error(response, 404, "Not Found",
			"Application not found");
		break;

	case STASIS_APP_USER_EVENT_SOURCE_NOT_FOUND:
		ast_ari_response_error(response, 422, "Unprocessable Entity",
			"Event source was not found");
		break;

	case STASIS_APP_USER_EVENT_SOURCE_BAD_SCHEME:
		ast_ari_response_error(response, 400, "Bad Request",
			"Invalid event source URI scheme");
		break;

	case STASIS_APP_USER_USEREVENT_INVALID:
		ast_ari_response_error(response, 400, "Bad Request",
			"Invalid userevnet data");
		break;

	case STASIS_APP_USER_INTERNAL_ERROR:
	default:
		ast_ari_response_error(response, 500, "Internal Server Error",
			"Error processing request");
	}
}
示例#21
0
/*!
 * \brief Parameter parsing callback for /bridges.
 * \param get_params GET parameters in the HTTP request.
 * \param path_vars Path variables extracted from the request.
 * \param headers HTTP headers.
 * \param[out] response Response to the HTTP request.
 */
static void ast_ari_bridges_list_cb(
	struct ast_tcptls_session_instance *ser,
	struct ast_variable *get_params, struct ast_variable *path_vars,
	struct ast_variable *headers, struct ast_ari_response *response)
{
	struct ast_ari_bridges_list_args args = {};
	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
#if defined(AST_DEVMODE)
	int is_valid;
	int code;
#endif /* AST_DEVMODE */

	ast_ari_bridges_list(headers, &args, response);
#if defined(AST_DEVMODE)
	code = response->response_code;

	switch (code) {
	case 0: /* Implementation is still a stub, or the code wasn't set */
		is_valid = response->message == NULL;
		break;
	case 500: /* Internal Server Error */
	case 501: /* Not Implemented */
		is_valid = 1;
		break;
	default:
		if (200 <= code && code <= 299) {
			is_valid = ast_ari_validate_list(response->message,
				ast_ari_validate_bridge_fn());
		} else {
			ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
			is_valid = 0;
		}
	}

	if (!is_valid) {
		ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Response validation failed");
	}
#endif /* AST_DEVMODE */

fin: __attribute__((unused))
	return;
}
示例#22
0
void ast_ari_asterisk_reload_module(struct ast_variable *headers,
	struct ast_ari_asterisk_reload_module_args *args,
	struct ast_ari_response *response)
{
	enum ast_module_reload_result reload_result;

	ast_assert(response != NULL);

	if (!ast_module_check(args->module_name)) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"Module not found in running modules");
		return;
	}

	reload_result = ast_module_reload(args->module_name);

	if (reload_result == AST_MODULE_RELOAD_NOT_FOUND) {
		ast_ari_response_error(
			response, 404, "Not Found",
			"Module could not be found");
		return;
	} else if (reload_result == AST_MODULE_RELOAD_ERROR) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"An unknown error occurred while reloading the module");
		return;
	} else if (reload_result == AST_MODULE_RELOAD_IN_PROGRESS) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Another reload is currently in progress");
		return;
	} else if (reload_result == AST_MODULE_RELOAD_UNINITIALIZED) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module has not been initialized");
		return;
	} else if (reload_result == AST_MODULE_RELOAD_NOT_IMPLEMENTED) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Module does not support reloading");
		return;
	} else if (reload_result == AST_MODULE_RELOAD_QUEUED) {
		ast_ari_response_accepted(response);
		return;
	}

	ast_ari_response_no_content(response);
}
void ast_ari_channels_answer(struct ast_variable *headers,
	struct ast_ari_channels_answer_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);

	control = find_control(response, args->channel_id);
	if (control == NULL) {
		return;
	}

	if (stasis_app_control_answer(control) != 0) {
		ast_ari_response_error(
			response, 500, "Internal Server Error",
			"Failed to answer channel");
		return;
	}

	ast_ari_response_no_content(response);
}
示例#24
0
void ast_ari_bridges_stop_moh(struct ast_variable *headers,
	struct ast_ari_bridges_stop_moh_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);

	if (!bridge) {
		/* the response is provided by find_bridge() */
		return;
	}

	if (stasis_app_bridge_moh_stop(bridge)) {
		ast_ari_response_error(
			response, 409, "Conflict",
			"Bridge isn't playing music");
		return;
	}

	ast_ari_response_no_content(response);
}
示例#25
0
/*!
 * \brief Performs common setup for a bridge playback operation
 * with both new controls and when existing controls are  found.
 *
 * \param args_media media string split from arguments
 * \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 found_channel The channel that was found controlling playback
 *
 * \retval PLAY_FOUND_SUCCESS The operation was successful
 * \retval PLAY_FOUND_FAILURE The operation failed (terminal failure)
 * \retval PLAY_FOUND_CHANNEL_UNAVAILABLE The operation failed because
 * the channel requested to playback with is breaking down.
 */
static enum play_found_result ari_bridges_play_found(const char *args_media,
	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 ast_channel *found_channel)
{
	RAII_VAR(struct ast_channel *, play_channel, found_channel, ao2_cleanup);
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
	RAII_VAR(char *, playback_url, NULL, ast_free);
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);

	control = stasis_app_control_find_by_channel(play_channel);
	if (!control) {
		ast_ari_response_error(
			response, 500, "Internal Error", "Failed to get control snapshot");
		return PLAY_FOUND_FAILURE;
	}

	ao2_lock(control);
	if (stasis_app_control_is_done(control)) {
		/* We failed to queue the action. Bailout and return that we aren't terminal. */
		ao2_unlock(control);
		return PLAY_FOUND_CHANNEL_UNAVAILABLE;
	}

	if (ari_bridges_play_helper(args_media, args_lang, args_offset_ms,
			args_skipms, args_playback_id, response, bridge, control,
			&json, &playback_url)) {
		ao2_unlock(control);
		return PLAY_FOUND_FAILURE;
	}
	ao2_unlock(control);

	ast_ari_response_created(response, playback_url, ast_json_ref(json));
	return PLAY_FOUND_SUCCESS;
}
示例#26
0
void ast_ari_endpoints_get(struct ast_variable *headers,
	struct ast_ari_endpoints_get_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
	RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);

	snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource);
	if (!snapshot) {
		ast_ari_response_error(response, 404, "Not Found",
			"Endpoint not found");
		return;
	}

	json = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
	if (!json) {
		ast_ari_response_alloc_failed(response);
		return;
	}

	ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_channels_send_dtmf(struct ast_variable *headers,
	struct ast_ari_channels_send_dtmf_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);

	control = find_control(response, args->channel_id);
	if (control == NULL) {
		return;
	}

	if (ast_strlen_zero(args->dtmf)) {
		ast_ari_response_error(
			response, 400, "Bad Request",
			"DTMF is required");
		return;
	}

	stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);

	ast_ari_response_no_content(response);
}
示例#28
0
void ast_ari_bridges_remove_channel(struct ast_variable *headers,
	struct ast_ari_bridges_remove_channel_args *args,
	struct ast_ari_response *response)
{
	RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
	RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
	size_t i;

	if (!bridge) {
		/* Response filled in by find_bridge() */
		return;
	}

	list = control_list_create(response, args->channel_count, args->channel);
	if (!list) {
		/* Response filled in by control_list_create() */
		return;
	}

	/* Make sure all of the channels are in this bridge */
	for (i = 0; i < list->count; ++i) {
		if (stasis_app_get_bridge(list->controls[i]) != bridge) {
			ast_log(LOG_WARNING, "Channel %s not in bridge %s\n",
				args->channel[i], args->bridge_id);
			ast_ari_response_error(response, 422,
				"Unprocessable Entity",
				"Channel not in this bridge");
			return;
		}
	}

	/* Now actually remove it */
	for (i = 0; i < list->count; ++i) {
		stasis_app_control_remove_channel_from_bridge(list->controls[i],
			bridge);
	}

	ast_ari_response_no_content(response);
}
示例#29
0
/*!
 * \brief Parameter parsing callback for /bridges/{bridgeId}/play.
 * \param get_params GET parameters in the HTTP request.
 * \param path_vars Path variables extracted from the request.
 * \param headers HTTP headers.
 * \param[out] response Response to the HTTP request.
 */
static void ast_ari_bridges_play_cb(
	struct ast_tcptls_session_instance *ser,
	struct ast_variable *get_params, struct ast_variable *path_vars,
	struct ast_variable *headers, struct ast_ari_response *response)
{
	struct ast_ari_bridges_play_args args = {};
	struct ast_variable *i;
	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
#if defined(AST_DEVMODE)
	int is_valid;
	int code;
#endif /* AST_DEVMODE */

	for (i = get_params; i; i = i->next) {
		if (strcmp(i->name, "media") == 0) {
			args.media = (i->value);
		} else
		if (strcmp(i->name, "lang") == 0) {
			args.lang = (i->value);
		} else
		if (strcmp(i->name, "offsetms") == 0) {
			args.offsetms = atoi(i->value);
		} else
		if (strcmp(i->name, "skipms") == 0) {
			args.skipms = atoi(i->value);
		} else
		if (strcmp(i->name, "playbackId") == 0) {
			args.playback_id = (i->value);
		} else
		{}
	}
	for (i = path_vars; i; i = i->next) {
		if (strcmp(i->name, "bridgeId") == 0) {
			args.bridge_id = (i->value);
		} else
		{}
	}
	/* Look for a JSON request entity */
	body = ast_http_get_json(ser, headers);
	if (!body) {
		switch (errno) {
		case EFBIG:
			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
			goto fin;
		case ENOMEM:
			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
			goto fin;
		case EIO:
			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
			goto fin;
		}
	}
	if (ast_ari_bridges_play_parse_body(body, &args)) {
		ast_ari_response_alloc_failed(response);
		goto fin;
	}
	ast_ari_bridges_play(headers, &args, response);
#if defined(AST_DEVMODE)
	code = response->response_code;

	switch (code) {
	case 0: /* Implementation is still a stub, or the code wasn't set */
		is_valid = response->message == NULL;
		break;
	case 500: /* Internal Server Error */
	case 501: /* Not Implemented */
	case 404: /* Bridge not found */
	case 409: /* Bridge not in a Stasis application */
		is_valid = 1;
		break;
	default:
		if (200 <= code && code <= 299) {
			is_valid = ast_ari_validate_playback(
				response->message);
		} else {
			ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play\n", code);
			is_valid = 0;
		}
	}

	if (!is_valid) {
		ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play\n");
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Response validation failed");
	}
#endif /* AST_DEVMODE */

fin: __attribute__((unused))
	return;
}
示例#30
0
/*!
 * \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
 * \param get_params GET parameters in the HTTP request.
 * \param path_vars Path variables extracted from the request.
 * \param headers HTTP headers.
 * \param[out] response Response to the HTTP request.
 */
static void ast_ari_bridges_remove_channel_cb(
	struct ast_tcptls_session_instance *ser,
	struct ast_variable *get_params, struct ast_variable *path_vars,
	struct ast_variable *headers, struct ast_ari_response *response)
{
	struct ast_ari_bridges_remove_channel_args args = {};
	struct ast_variable *i;
	RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
#if defined(AST_DEVMODE)
	int is_valid;
	int code;
#endif /* AST_DEVMODE */

	for (i = get_params; i; i = i->next) {
		if (strcmp(i->name, "channel") == 0) {
			/* Parse comma separated list */
			char *vals[MAX_VALS];
			size_t j;

			args.channel_parse = ast_strdup(i->value);
			if (!args.channel_parse) {
				ast_ari_response_alloc_failed(response);
				goto fin;
			}

			if (strlen(args.channel_parse) == 0) {
				/* ast_app_separate_args can't handle "" */
				args.channel_count = 1;
				vals[0] = args.channel_parse;
			} else {
				args.channel_count = ast_app_separate_args(
					args.channel_parse, ',', vals,
					ARRAY_LEN(vals));
			}

			if (args.channel_count == 0) {
				ast_ari_response_alloc_failed(response);
				goto fin;
			}

			if (args.channel_count >= MAX_VALS) {
				ast_ari_response_error(response, 400,
					"Bad Request",
					"Too many values for channel");
				goto fin;
			}

			args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
			if (!args.channel) {
				ast_ari_response_alloc_failed(response);
				goto fin;
			}

			for (j = 0; j < args.channel_count; ++j) {
				args.channel[j] = (vals[j]);
			}
		} else
		{}
	}
	for (i = path_vars; i; i = i->next) {
		if (strcmp(i->name, "bridgeId") == 0) {
			args.bridge_id = (i->value);
		} else
		{}
	}
	/* Look for a JSON request entity */
	body = ast_http_get_json(ser, headers);
	if (!body) {
		switch (errno) {
		case EFBIG:
			ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
			goto fin;
		case ENOMEM:
			ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
			goto fin;
		case EIO:
			ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
			goto fin;
		}
	}
	if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
		ast_ari_response_alloc_failed(response);
		goto fin;
	}
	ast_ari_bridges_remove_channel(headers, &args, response);
#if defined(AST_DEVMODE)
	code = response->response_code;

	switch (code) {
	case 0: /* Implementation is still a stub, or the code wasn't set */
		is_valid = response->message == NULL;
		break;
	case 500: /* Internal Server Error */
	case 501: /* Not Implemented */
	case 400: /* Channel not found */
	case 404: /* Bridge not found */
	case 409: /* Bridge not in Stasis application */
	case 422: /* Channel not in this bridge */
		is_valid = 1;
		break;
	default:
		if (200 <= code && code <= 299) {
			is_valid = ast_ari_validate_void(
				response->message);
		} else {
			ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
			is_valid = 0;
		}
	}

	if (!is_valid) {
		ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
		ast_ari_response_error(response, 500,
			"Internal Server Error", "Response validation failed");
	}
#endif /* AST_DEVMODE */

fin: __attribute__((unused))
	ast_free(args.channel_parse);
	ast_free(args.channel);
	return;
}