Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions res/ari/ari_model_validators.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,44 @@ ari_validator ast_ari_validate_variable_fn(void)
return ast_ari_validate_variable;
}

int ast_ari_validate_variables(struct ast_json *json)
{
int res = 1;
struct ast_json_iter *iter;
int has_variables = 0;

for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
if (strcmp("variables", ast_json_object_iter_key(iter)) == 0) {
int prop_is_valid;
has_variables = 1;
prop_is_valid = ast_ari_validate_object(
ast_json_object_iter_value(iter));
if (!prop_is_valid) {
ast_log(LOG_ERROR, "ARI Variables field variables failed validation\n");
res = 0;
}
} else
{
ast_log(LOG_ERROR,
"ARI Variables has undocumented field %s\n",
ast_json_object_iter_key(iter));
res = 0;
}
}

if (!has_variables) {
ast_log(LOG_ERROR, "ARI Variables missing required field variables\n");
res = 0;
}

return res;
}

ari_validator ast_ari_validate_variables_fn(void)
{
return ast_ari_validate_variables;
}

int ast_ari_validate_endpoint(struct ast_json *json)
{
int res = 1;
Expand Down
18 changes: 18 additions & 0 deletions res/ari/ari_model_validators.h
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,22 @@ int ast_ari_validate_variable(struct ast_json *json);
*/
ari_validator ast_ari_validate_variable_fn(void);

/*!
* \brief Validator for Variables.
*
* A dictionary of channel variables
*
* \param json JSON object to validate.
* \retval True (non-zero) if valid.
* \retval False (zero) if invalid.
*/
int ast_ari_validate_variables(struct ast_json *json);

/*!
* \brief Function pointer to ast_ari_validate_variables().
*/
ari_validator ast_ari_validate_variables_fn(void);

/*!
* \brief Validator for Endpoint.
*
Expand Down Expand Up @@ -1522,6 +1538,8 @@ ari_validator ast_ari_validate_application_fn(void);
* - version: string (required)
* Variable
* - value: string (required)
* Variables
* - variables: object (required)
* Endpoint
* - channel_ids: List[string] (required)
* - resource: string (required)
Expand Down
188 changes: 188 additions & 0 deletions res/ari/resource_channels.c
Original file line number Diff line number Diff line change
Expand Up @@ -1559,6 +1559,98 @@ void ast_ari_channels_get_channel_var(struct ast_variable *headers,
ast_ari_response_ok(response, ast_json_ref(json));
}

void ast_ari_channels_get_channel_vars(struct ast_variable *headers,
struct ast_ari_channels_get_channel_vars_args *args,
struct ast_ari_response *response)
{
int res;
RAII_VAR(struct ast_json *, json, ast_json_object_create(), ast_json_unref);
RAII_VAR(struct ast_json *, inner_json, ast_json_object_create(), ast_json_unref);
RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);

ast_assert(response != NULL);

if (!json || !inner_json || !value) {
ast_ari_response_alloc_failed(response);
return;
}

if (args->variables_count == 0) {
ast_ari_response_error(
response, 400, "Bad Request",
"At least one variable name is required");
return;
}

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

channel = ast_channel_get_by_name(args->channel_id);
if (!channel) {
ast_ari_response_error(
response, 404, "Channel Not Found",
"Provided channel was not found");
return;
}

for (int i = 0; i < args->variables_count; i++) {
struct ast_json *json_str;
char buf[strlen(args->variables[i]) + 1];
char *variable;

strcpy(buf, args->variables[i]);
variable = ast_strip(buf);
if (ast_strlen_zero(variable)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Variable names are required");
return;
}

if (variable[strlen(variable) - 1] == ')') {
if (ast_func_read2(channel, variable, &value, 0)) {
ast_ari_response_error(
response, 500, "Error With Function",
"Unable to read provided function");
return;
}
} else {
if (!ast_str_retrieve_variable(&value, 0, channel, NULL, variable)) {
ast_ari_response_error(
response, 404, "Variable Not Found",
"Provided variable was not found");
return;
}
}

json_str = ast_json_string_create(ast_str_buffer(value));
if (!json_str) {
ast_ari_response_alloc_failed(response);
return;
}

res = ast_json_object_set(inner_json, variable, json_str);
if (res) {
ast_ari_response_alloc_failed(response);
ast_json_unref(json_str);
return;
}
}

res = ast_json_object_set(json, "variables", ast_json_ref(inner_json));
if (res) {
ast_ari_response_alloc_failed(response);
return;
}

ast_ari_response_ok(response, ast_json_ref(json));
}

void ast_ari_channels_set_channel_var(struct ast_variable *headers,
struct ast_ari_channels_set_channel_var_args *args,
struct ast_ari_response *response)
Expand Down Expand Up @@ -1590,6 +1682,102 @@ void ast_ari_channels_set_channel_var(struct ast_variable *headers,
ast_ari_response_no_content(response);
}

void ast_ari_channels_set_channel_vars(struct ast_variable *headers,
struct ast_ari_channels_set_channel_vars_args *args,
struct ast_ari_response *response)
{
struct ast_json *json_variables;
struct ast_json_iter *it_json_var;
struct ast_variable *var = NULL;
RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);

ast_assert(response != NULL);

if (!args->variables) {
ast_ari_response_error(
response, 400, "Bad Request",
"The 'variables' field is required");
return;
}

channel = ast_channel_get_by_name(args->channel_id);
if (!channel) {
ast_ari_response_error(
response, 404, "Channel Not Found",
"Provided channel was not found");
return;
}

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

json_variables = ast_json_object_get(args->variables, "variables");
for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
const char *key = ast_json_object_iter_key(it_json_var);
char buf[strlen(key) + 1];
char *stripped_key;
struct ast_json *json_value;
const char *value;
struct ast_variable *new_var;

strcpy(buf, key);
stripped_key = ast_strip(buf);
if (ast_strlen_zero(stripped_key)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Variable names are required");
return;
}

json_value = ast_json_object_iter_value(it_json_var);
if (ast_json_typeof(json_value) != AST_JSON_STRING) {
ast_ari_response_error(
response, 400, "Bad Request",
"Variable values must be strings");
return;
}

value = ast_json_string_get(json_value);
if (!value) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Could not get string value from JSON string");
return;
}

new_var = ast_variable_new(stripped_key, value, "");
if (!new_var) {
ast_ari_response_error(
response, 500, "Internal Server Error",
"Could not create internal variable");
return;
}

/* Append to the tail */
var = ast_variable_list_append_hint(&variables, var, new_var);
}

/* We loop twice to preserve variable state if something goes wrong. If something
* goes wrong in this loop, something went VERY wrong.
*/
for (var = variables; var; var = var->next) {
if (stasis_app_control_set_channel_var(control, var->name, var->value)) {
ast_ari_response_error(
response, 400, "Bad Request",
"Failed to execute function");
return;
}
}

ast_ari_response_no_content(response);
}

static void ari_channels_handle_snoop_channel(
const char *args_channel_id,
const char *args_spy,
Expand Down
56 changes: 56 additions & 0 deletions res/ari/resource_channels.h
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,62 @@ int ast_ari_channels_set_channel_var_parse_body(
* \param[out] response HTTP response
*/
void ast_ari_channels_set_channel_var(struct ast_variable *headers, struct ast_ari_channels_set_channel_var_args *args, struct ast_ari_response *response);
/*! Argument struct for ast_ari_channels_get_channel_vars() */
struct ast_ari_channels_get_channel_vars_args {
/*! Channel's id */
const char *channel_id;
/*! Array of The channel variables or functions to get */
const char **variables;
/*! Length of variables array. */
size_t variables_count;
/*! Parsing context for variables. */
char *variables_parse;
};
/*!
* \brief Body parsing function for /channels/{channelId}/variables.
* \param body The JSON body from which to parse parameters.
* \param[out] args The args structure to parse into.
* \retval zero on success
* \retval non-zero on failure
*/
int ast_ari_channels_get_channel_vars_parse_body(
struct ast_json *body,
struct ast_ari_channels_get_channel_vars_args *args);

/*!
* \brief Get the value of multiple channel variables or functions.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_channels_get_channel_vars(struct ast_variable *headers, struct ast_ari_channels_get_channel_vars_args *args, struct ast_ari_response *response);
/*! Argument struct for ast_ari_channels_set_channel_vars() */
struct ast_ari_channels_set_channel_vars_args {
/*! Channel's id */
const char *channel_id;
/*! The "variables" key in the body object holds variable key/value pairs to set on the channel. Ex. { "variables": { "CALLERID(name)": "Alice" } } */
struct ast_json *variables;
};
/*!
* \brief Body parsing function for /channels/{channelId}/variables.
* \param body The JSON body from which to parse parameters.
* \param[out] args The args structure to parse into.
* \retval zero on success
* \retval non-zero on failure
*/
int ast_ari_channels_set_channel_vars_parse_body(
struct ast_json *body,
struct ast_ari_channels_set_channel_vars_args *args);

/*!
* \brief Set the values of multiple channel variables or functions.
*
* \param headers HTTP headers
* \param args Swagger parameters
* \param[out] response HTTP response
*/
void ast_ari_channels_set_channel_vars(struct ast_variable *headers, struct ast_ari_channels_set_channel_vars_args *args, struct ast_ari_response *response);
/*! Argument struct for ast_ari_channels_snoop_channel() */
struct ast_ari_channels_snoop_channel_args {
/*! Channel's id */
Expand Down
Loading
Loading