summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asterisk/json.h18
-rw-r--r--main/json.c29
-rw-r--r--res/ari/resource_channels.c57
-rw-r--r--res/ari/resource_endpoints.c61
-rw-r--r--res/res_ari_endpoints.c1
-rw-r--r--rest-api/api-docs/endpoints.json4
6 files changed, 129 insertions, 41 deletions
diff --git a/include/asterisk/json.h b/include/asterisk/json.h
index 8cb74a459..28ebfbd51 100644
--- a/include/asterisk/json.h
+++ b/include/asterisk/json.h
@@ -1010,13 +1010,24 @@ struct ast_party_id;
*/
struct ast_json *ast_json_party_id(struct ast_party_id *party);
+enum ast_json_to_ast_vars_code {
+ /*! \brief Conversion successful */
+ AST_JSON_TO_AST_VARS_CODE_SUCCESS,
+ /*!
+ * \brief Conversion failed because invalid value type supplied.
+ * \note Only string values allowed.
+ */
+ AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE,
+ /*! \brief Conversion failed because of allocation failure. (Out Of Memory) */
+ AST_JSON_TO_AST_VARS_CODE_OOM,
+};
+
/*!
* \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
* \since 12.5.0
*
* \param json_variables The JSON blob containing the variable
* \param variables An out reference to the variables to populate.
- * The pointer to the variables should be NULL when calling this.
*
* \code
* struct ast_json *json_variables = ast_json_pack("[ { s: s } ]", "foo", "bar");
@@ -1026,10 +1037,9 @@ struct ast_json *ast_json_party_id(struct ast_party_id *party);
* res = ast_json_to_ast_variables(json_variables, &variables);
* \endcode
*
- * \retval 0 success
- * \retval -1 error
+ * \return Conversion enum ast_json_to_ast_vars_code status
*/
-int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
+enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
/*!@}*/
diff --git a/main/json.c b/main/json.c
index 88e807772..35e6f16ce 100644
--- a/main/json.c
+++ b/main/json.c
@@ -882,32 +882,47 @@ struct ast_json *ast_json_party_id(struct ast_party_id *party)
return ast_json_ref(json_party_id);
}
-int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
+enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
{
struct ast_json_iter *it_json_var;
*variables = NULL;
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)) {
+ it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
struct ast_variable *new_var;
const char *key = ast_json_object_iter_key(it_json_var);
+ const char *value;
+ struct ast_json *json_value;
if (ast_strlen_zero(key)) {
continue;
}
- new_var = ast_variable_new(key,
- ast_json_string_get(ast_json_object_iter_value(it_json_var)),
- "");
+ json_value = ast_json_object_iter_value(it_json_var);
+ if (ast_json_typeof(json_value) != AST_JSON_STRING) {
+ /* Error: Only strings allowed */
+ ast_variables_destroy(*variables);
+ *variables = NULL;
+ return AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE;
+ }
+ value = ast_json_string_get(json_value);
+ /* Should never be NULL. Otherwise, how could it be a string type? */
+ ast_assert(value != NULL);
+ if (!value) {
+ /* To be safe. */
+ continue;
+ }
+ new_var = ast_variable_new(key, value, "");
if (!new_var) {
+ /* Error: OOM */
ast_variables_destroy(*variables);
*variables = NULL;
- return -1;
+ return AST_JSON_TO_AST_VARS_CODE_OOM;
}
ast_variable_list_append(variables, new_var);
}
- return 0;
+ return AST_JSON_TO_AST_VARS_CODE_SUCCESS;
}
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index 693835129..fb1aa039c 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -1147,11 +1147,44 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
return;
}
+/*!
+ * \internal
+ * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
+ * \since 13.3.0
+ *
+ * \param[out] response HTTP response if error
+ * \param json_variables The JSON blob containing the variable
+ * \param[out] variables An out reference to the variables to populate.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
+{
+ enum ast_json_to_ast_vars_code res;
+
+ res = ast_json_to_ast_variables(json_variables, variables);
+ switch (res) {
+ case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
+ return 0;
+ case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
+ ast_ari_response_error(response, 400, "Bad Request",
+ "Only string values in the 'variables' object allowed");
+ break;
+ case AST_JSON_TO_AST_VARS_CODE_OOM:
+ ast_ari_response_alloc_failed(response);
+ break;
+ }
+ ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
+
+ return -1;
+}
+
void ast_ari_channels_originate_with_id(struct ast_variable *headers,
struct ast_ari_channels_originate_with_id_args *args,
struct ast_ari_response *response)
{
- RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+ struct ast_variable *variables = NULL;
/* Parse any query parameters out of the body parameter */
if (args->variables) {
@@ -1159,12 +1192,9 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers,
ast_ari_channels_originate_with_id_parse_body(args->variables, args);
json_variables = ast_json_object_get(args->variables, "variables");
- if (json_variables) {
- if (ast_json_to_ast_variables(json_variables, &variables)) {
- ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
- ast_ari_response_alloc_failed(response);
- return;
- }
+ if (json_variables
+ && json_to_ast_variables(response, json_variables, &variables)) {
+ return;
}
}
@@ -1183,13 +1213,14 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers,
args->other_channel_id,
args->originator,
response);
+ ast_variables_destroy(variables);
}
void ast_ari_channels_originate(struct ast_variable *headers,
struct ast_ari_channels_originate_args *args,
struct ast_ari_response *response)
{
- RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+ struct ast_variable *variables = NULL;
/* Parse any query parameters out of the body parameter */
if (args->variables) {
@@ -1197,12 +1228,9 @@ void ast_ari_channels_originate(struct ast_variable *headers,
ast_ari_channels_originate_parse_body(args->variables, args);
json_variables = ast_json_object_get(args->variables, "variables");
- if (json_variables) {
- if (ast_json_to_ast_variables(json_variables, &variables)) {
- ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
- ast_ari_response_alloc_failed(response);
- return;
- }
+ if (json_variables
+ && json_to_ast_variables(response, json_variables, &variables)) {
+ return;
}
}
@@ -1221,6 +1249,7 @@ void ast_ari_channels_originate(struct ast_variable *headers,
args->other_channel_id,
args->originator,
response);
+ ast_variables_destroy(variables);
}
void ast_ari_channels_get_channel_var(struct ast_variable *headers,
diff --git a/res/ari/resource_endpoints.c b/res/ari/resource_endpoints.c
index 4f91e781d..f794969f2 100644
--- a/res/ari/resource_endpoints.c
+++ b/res/ari/resource_endpoints.c
@@ -220,35 +220,66 @@ static void send_message(const char *to, const char *from, const char *body, str
response->response_text = "Accepted";
}
+/*!
+ * \internal
+ * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
+ * \since 13.3.0
+ *
+ * \param[out] response HTTP response if error
+ * \param json_variables The JSON blob containing the variable
+ * \param[out] variables An out reference to the variables to populate.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
+{
+ enum ast_json_to_ast_vars_code res;
+
+ res = ast_json_to_ast_variables(json_variables, variables);
+ switch (res) {
+ case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
+ return 0;
+ case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
+ ast_ari_response_error(response, 400, "Bad Request",
+ "Only string values in the 'variables' object allowed");
+ break;
+ case AST_JSON_TO_AST_VARS_CODE_OOM:
+ ast_ari_response_alloc_failed(response);
+ break;
+ }
+ ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
+
+ return -1;
+}
+
void ast_ari_endpoints_send_message(struct ast_variable *headers,
struct ast_ari_endpoints_send_message_args *args,
struct ast_ari_response *response)
{
- RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+ struct ast_variable *variables = NULL;
if (args->variables) {
struct ast_json *json_variables;
ast_ari_endpoints_send_message_parse_body(args->variables, args);
json_variables = ast_json_object_get(args->variables, "variables");
- if (json_variables) {
- if (ast_json_to_ast_variables(json_variables, &variables)) {
- ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
- ast_ari_response_alloc_failed(response);
- return;
- }
+ if (json_variables
+ && json_to_ast_variables(response, json_variables, &variables)) {
+ return;
}
}
send_message(args->to, args->from, args->body, variables, response);
+ ast_variables_destroy(variables);
}
void ast_ari_endpoints_send_message_to_endpoint(struct ast_variable *headers,
struct ast_ari_endpoints_send_message_to_endpoint_args *args,
struct ast_ari_response *response)
{
- RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
- RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
+ struct ast_variable *variables = NULL;
+ struct ast_endpoint_snapshot *snapshot;
char msg_to[128];
char *tech = ast_strdupa(args->tech);
@@ -259,23 +290,21 @@ void ast_ari_endpoints_send_message_to_endpoint(struct ast_variable *headers,
"Endpoint not found");
return;
}
+ ao2_ref(snapshot, -1);
if (args->variables) {
struct ast_json *json_variables;
ast_ari_endpoints_send_message_to_endpoint_parse_body(args->variables, args);
json_variables = ast_json_object_get(args->variables, "variables");
-
- if (json_variables) {
- if (ast_json_to_ast_variables(json_variables, &variables)) {
- ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
- ast_ari_response_alloc_failed(response);
- return;
- }
+ if (json_variables
+ && json_to_ast_variables(response, json_variables, &variables)) {
+ return;
}
}
snprintf(msg_to, sizeof(msg_to), "%s:%s", ast_str_to_lower(tech), args->resource);
send_message(msg_to, args->from, args->body, variables, response);
+ ast_variables_destroy(variables);
}
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index 3ebe66858..8d8ed716c 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -181,6 +181,7 @@ static void ast_ari_endpoints_send_message_cb(
break;
case 500: /* Internal Server Error */
case 501: /* Not Implemented */
+ case 400: /* Invalid parameters for sending a message. */
case 404: /* Endpoint not found */
is_valid = 1;
break;
diff --git a/rest-api/api-docs/endpoints.json b/rest-api/api-docs/endpoints.json
index e7b4ba73a..17b884784 100644
--- a/rest-api/api-docs/endpoints.json
+++ b/rest-api/api-docs/endpoints.json
@@ -64,6 +64,10 @@
],
"errorResponses": [
{
+ "code": 400,
+ "reason": "Invalid parameters for sending a message."
+ },
+ {
"code": 404,
"reason": "Endpoint not found"
}