summaryrefslogtreecommitdiff
path: root/res/ari
diff options
context:
space:
mode:
Diffstat (limited to 'res/ari')
-rw-r--r--res/ari/ari_model_validators.c228
-rw-r--r--res/ari/ari_model_validators.h68
-rw-r--r--res/ari/resource_channels.c34
-rw-r--r--res/ari/resource_endpoints.c105
-rw-r--r--res/ari/resource_endpoints.h60
5 files changed, 463 insertions, 32 deletions
diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c
index 0302db327..10fd3bd83 100644
--- a/res/ari/ari_model_validators.c
+++ b/res/ari/ari_model_validators.c
@@ -588,6 +588,140 @@ ari_validator ast_ari_validate_endpoint_fn(void)
return ast_ari_validate_endpoint;
}
+int ast_ari_validate_text_message(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_body = 0;
+ int has_from = 0;
+ int has_to = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("body", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_body = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessage field body failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("from", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_from = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessage field from failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("to", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_to = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessage field to failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("variables", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_list(
+ ast_json_object_iter_value(iter),
+ ast_ari_validate_text_message_variable);
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessage field variables failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI TextMessage has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_body) {
+ ast_log(LOG_ERROR, "ARI TextMessage missing required field body\n");
+ res = 0;
+ }
+
+ if (!has_from) {
+ ast_log(LOG_ERROR, "ARI TextMessage missing required field from\n");
+ res = 0;
+ }
+
+ if (!has_to) {
+ ast_log(LOG_ERROR, "ARI TextMessage missing required field to\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_text_message_fn(void)
+{
+ return ast_ari_validate_text_message;
+}
+
+int ast_ari_validate_text_message_variable(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_key = 0;
+ int has_value = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("key", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_key = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageVariable field key failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("value", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_value = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageVariable field value failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI TextMessageVariable has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_key) {
+ ast_log(LOG_ERROR, "ARI TextMessageVariable missing required field key\n");
+ res = 0;
+ }
+
+ if (!has_value) {
+ ast_log(LOG_ERROR, "ARI TextMessageVariable missing required field value\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_text_message_variable_fn(void)
+{
+ return ast_ari_validate_text_message_variable;
+}
+
int ast_ari_validate_caller_id(struct ast_json *json)
{
int res = 1;
@@ -3890,6 +4024,9 @@ int ast_ari_validate_event(struct ast_json *json)
if (strcmp("StasisStart", discriminator) == 0) {
return ast_ari_validate_stasis_start(json);
} else
+ if (strcmp("TextMessageReceived", discriminator) == 0) {
+ return ast_ari_validate_text_message_received(json);
+ } else
{
ast_log(LOG_ERROR, "ARI Event has undocumented subtype %s\n",
discriminator);
@@ -4061,6 +4198,9 @@ int ast_ari_validate_message(struct ast_json *json)
if (strcmp("StasisStart", discriminator) == 0) {
return ast_ari_validate_stasis_start(json);
} else
+ if (strcmp("TextMessageReceived", discriminator) == 0) {
+ return ast_ari_validate_text_message_received(json);
+ } else
{
ast_log(LOG_ERROR, "ARI Message has undocumented subtype %s\n",
discriminator);
@@ -4724,6 +4864,94 @@ ari_validator ast_ari_validate_stasis_start_fn(void)
return ast_ari_validate_stasis_start;
}
+int ast_ari_validate_text_message_received(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_type = 0;
+ int has_application = 0;
+ int has_message = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("type", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_type = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived field type failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("application", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_application = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived field application failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_date(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived field timestamp failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("endpoint", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_endpoint(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived field endpoint failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("message", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_message = 1;
+ prop_is_valid = ast_ari_validate_text_message(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived field message failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI TextMessageReceived has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_type) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived missing required field type\n");
+ res = 0;
+ }
+
+ if (!has_application) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived missing required field application\n");
+ res = 0;
+ }
+
+ if (!has_message) {
+ ast_log(LOG_ERROR, "ARI TextMessageReceived missing required field message\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_text_message_received_fn(void)
+{
+ return ast_ari_validate_text_message_received;
+}
+
int ast_ari_validate_application(struct ast_json *json)
{
int res = 1;
diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h
index 0186168b2..beace67b2 100644
--- a/res/ari/ari_model_validators.h
+++ b/res/ari/ari_model_validators.h
@@ -299,6 +299,42 @@ int ast_ari_validate_endpoint(struct ast_json *json);
ari_validator ast_ari_validate_endpoint_fn(void);
/*!
+ * \brief Validator for TextMessage.
+ *
+ * A text message.
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_text_message(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_text_message().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_text_message_fn(void);
+
+/*!
+ * \brief Validator for TextMessageVariable.
+ *
+ * A key/value pair variable in a text message.
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_text_message_variable(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_text_message_variable().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_text_message_variable_fn(void);
+
+/*!
* \brief Validator for CallerID.
*
* Caller identification
@@ -1097,6 +1133,24 @@ int ast_ari_validate_stasis_start(struct ast_json *json);
ari_validator ast_ari_validate_stasis_start_fn(void);
/*!
+ * \brief Validator for TextMessageReceived.
+ *
+ * A text message was received from an endpoint.
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_text_message_received(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_text_message_received().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_text_message_received_fn(void);
+
+/*!
* \brief Validator for Application.
*
* Details of a Stasis application
@@ -1152,6 +1206,14 @@ ari_validator ast_ari_validate_application_fn(void);
* - resource: string (required)
* - state: string
* - technology: string (required)
+ * TextMessage
+ * - body: string (required)
+ * - from: string (required)
+ * - to: string (required)
+ * - variables: List[TextMessageVariable]
+ * TextMessageVariable
+ * - key: string (required)
+ * - value: string (required)
* CallerID
* - name: string (required)
* - number: string (required)
@@ -1405,6 +1467,12 @@ ari_validator ast_ari_validate_application_fn(void);
* - timestamp: Date
* - args: List[string] (required)
* - channel: Channel (required)
+ * TextMessageReceived
+ * - type: string (required)
+ * - application: string (required)
+ * - timestamp: Date
+ * - endpoint: Endpoint
+ * - message: TextMessage (required)
* Application
* - bridge_ids: List[string] (required)
* - channel_ids: List[string] (required)
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c
index cef1e7130..d0a1be32e 100644
--- a/res/ari/resource_channels.c
+++ b/res/ari/resource_channels.c
@@ -723,36 +723,6 @@ void ast_ari_channels_list(struct ast_variable *headers,
ast_ari_response_ok(response, ast_json_ref(json));
}
-static int json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
-{
- struct ast_variable *current = NULL;
- struct ast_json_iter *it_json_var;
-
- 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)) {
- struct ast_variable *new_var;
-
- new_var = ast_variable_new(ast_json_object_iter_key(it_json_var),
- ast_json_string_get(ast_json_object_iter_value(it_json_var)),
- "");
- if (!new_var) {
- ast_variables_destroy(*variables);
- *variables = NULL;
- return 1;
- }
-
- if (!current) {
- *variables = new_var;
- current = *variables;
- } else {
- current->next = new_var;
- current = new_var;
- }
- }
-
- return 0;
-}
-
static void ari_channels_handle_originate_with_id(const char *args_endpoint,
const char *args_extension,
const char *args_context,
@@ -894,7 +864,7 @@ 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 (json_to_ast_variables(json_variables, &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;
@@ -930,7 +900,7 @@ 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 (json_to_ast_variables(json_variables, &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;
diff --git a/res/ari/resource_endpoints.c b/res/ari/resource_endpoints.c
index ff2b150dd..4f91e781d 100644
--- a/res/ari/resource_endpoints.c
+++ b/res/ari/resource_endpoints.c
@@ -174,3 +174,108 @@ void ast_ari_endpoints_get(struct ast_variable *headers,
ast_ari_response_ok(response, json);
}
+
+static void send_message(const char *to, const char *from, const char *body, struct ast_variable *variables, struct ast_ari_response *response)
+{
+ struct ast_variable *current;
+ struct ast_msg *msg;
+ int res = 0;
+
+ if (ast_strlen_zero(to)) {
+ ast_ari_response_error(response, 400, "Bad Request",
+ "To must be specified");
+ return;
+ }
+
+ msg = ast_msg_alloc();
+ if (!msg) {
+ ast_ari_response_alloc_failed(response);
+ return;
+ }
+
+ res |= ast_msg_set_from(msg, "%s", from);
+ res |= ast_msg_set_to(msg, "%s", to);
+
+ if (!ast_strlen_zero(body)) {
+ res |= ast_msg_set_body(msg, "%s", body);
+ }
+
+ for (current = variables; current; current = current->next) {
+ res |= ast_msg_set_var_outbound(msg, current->name, current->value);
+ }
+
+ if (res) {
+ ast_ari_response_alloc_failed(response);
+ ast_msg_destroy(msg);
+ return;
+ }
+
+ if (ast_msg_send(msg, to, from)) {
+ ast_ari_response_error(response, 404, "Not Found",
+ "Endpoint not found");
+ }
+
+ response->message = ast_json_null();
+ response->response_code = 202;
+ response->response_text = "Accepted";
+}
+
+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);
+
+ 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;
+ }
+ }
+ }
+
+ send_message(args->to, args->from, args->body, variables, response);
+}
+
+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);
+ char msg_to[128];
+ char *tech = ast_strdupa(args->tech);
+
+ /* Really, we just want to know if this thing exists */
+ snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource);
+ if (!snapshot) {
+ ast_ari_response_error(response, 404, "Not Found",
+ "Endpoint not found");
+ return;
+ }
+
+ 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;
+ }
+ }
+ }
+
+ 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);
+}
diff --git a/res/ari/resource_endpoints.h b/res/ari/resource_endpoints.h
index 3af81a66f..4391b36e6 100644
--- a/res/ari/resource_endpoints.h
+++ b/res/ari/resource_endpoints.h
@@ -50,6 +50,35 @@ struct ast_ari_endpoints_list_args {
* \param[out] response HTTP response
*/
void ast_ari_endpoints_list(struct ast_variable *headers, struct ast_ari_endpoints_list_args *args, struct ast_ari_response *response);
+/*! Argument struct for ast_ari_endpoints_send_message() */
+struct ast_ari_endpoints_send_message_args {
+ /*! The endpoint resource or technology specific URI to send the message to. Valid resources are sip, pjsip, and xmpp. */
+ const char *to;
+ /*! The endpoint resource or technology specific identity to send this message from. Valid resources are sip, pjsip, and xmpp. */
+ const char *from;
+ /*! The body of the message */
+ const char *body;
+ struct ast_json *variables;
+};
+/*!
+ * \brief Body parsing function for /endpoints/sendMessage.
+ * \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_endpoints_send_message_parse_body(
+ struct ast_json *body,
+ struct ast_ari_endpoints_send_message_args *args);
+
+/*!
+ * \brief Send a message to some technology URI or endpoint.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_endpoints_send_message(struct ast_variable *headers, struct ast_ari_endpoints_send_message_args *args, struct ast_ari_response *response);
/*! Argument struct for ast_ari_endpoints_list_by_tech() */
struct ast_ari_endpoints_list_by_tech_args {
/*! Technology of the endpoints (sip,iax2,...) */
@@ -78,5 +107,36 @@ struct ast_ari_endpoints_get_args {
* \param[out] response HTTP response
*/
void ast_ari_endpoints_get(struct ast_variable *headers, struct ast_ari_endpoints_get_args *args, struct ast_ari_response *response);
+/*! Argument struct for ast_ari_endpoints_send_message_to_endpoint() */
+struct ast_ari_endpoints_send_message_to_endpoint_args {
+ /*! Technology of the endpoint */
+ const char *tech;
+ /*! ID of the endpoint */
+ const char *resource;
+ /*! The endpoint resource or technology specific identity to send this message from. Valid resources are sip, pjsip, and xmpp. */
+ const char *from;
+ /*! The body of the message */
+ const char *body;
+ struct ast_json *variables;
+};
+/*!
+ * \brief Body parsing function for /endpoints/{tech}/{resource}/sendMessage.
+ * \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_endpoints_send_message_to_endpoint_parse_body(
+ struct ast_json *body,
+ struct ast_ari_endpoints_send_message_to_endpoint_args *args);
+
+/*!
+ * \brief Send a message to some endpoint in a technology.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+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);
#endif /* _ASTERISK_RESOURCE_ENDPOINTS_H */