/*! * \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); } }
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); }
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); } }
/*! * \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); }
/*! * \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; }
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); }
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); }
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); }
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); }
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())); }
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); }
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; }
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; }
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)); }
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"); } }
/*! * \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; }
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); }
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); }
/*! * \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; }
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); }
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); }
/*! * \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; }
/*! * \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; }