summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/ari/resource_asterisk.h8
-rw-r--r--res/ari/resource_bridges.c89
-rw-r--r--res/ari/resource_bridges.h16
-rw-r--r--res/ari/resource_events.c37
-rw-r--r--res/ari/resource_events.h8
-rw-r--r--res/ari/resource_sounds.h2
-rw-r--r--res/res_ari_asterisk.c63
-rw-r--r--res/res_ari_bridges.c136
-rw-r--r--res/res_ari_channels.c136
-rw-r--r--res/res_ari_endpoints.c24
-rw-r--r--res/res_ari_events.c80
-rw-r--r--res/res_ari_playback.c27
-rw-r--r--res/res_ari_recordings.c85
-rw-r--r--res/res_ari_sounds.c19
-rw-r--r--rest-api-templates/ari_resource.h.mustache12
-rw-r--r--rest-api-templates/param_cleanup.mustache26
-rw-r--r--rest-api-templates/param_parsing.mustache42
-rw-r--r--rest-api-templates/res_ari_resource.c.mustache50
-rw-r--r--rest-api/api-docs/bridges.json8
-rw-r--r--rest-api/api-docs/channels.json2
-rw-r--r--rest-api/api-docs/events.json2
-rw-r--r--rest-api/api-docs/sounds.json2
22 files changed, 682 insertions, 192 deletions
diff --git a/res/ari/resource_asterisk.h b/res/ari/resource_asterisk.h
index 69539525e..d2f316a6b 100644
--- a/res/ari/resource_asterisk.h
+++ b/res/ari/resource_asterisk.h
@@ -41,8 +41,12 @@
/*! \brief Argument struct for ast_ari_get_asterisk_info() */
struct ast_get_asterisk_info_args {
- /*! \brief Filter information returned */
- const char *only;
+ /*! \brief Array of Filter information returned */
+ const char **only;
+ /*! \brief Length of only array. */
+ size_t only_count;
+ /*! \brief Parsing context for only. */
+ char *only_parse;
};
/*!
* \brief Gets Asterisk system information.
diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c
index 7730d0cd9..e4c7194ff 100644
--- a/res/ari/resource_bridges.c
+++ b/res/ari/resource_bridges.c
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
@@ -107,33 +107,95 @@ static struct stasis_app_control *find_channel_control(
return control;
}
+struct control_list {
+ size_t count;
+ struct stasis_app_control *controls[];
+};
+
+static void control_list_dtor(void *obj) {
+ struct control_list *list = obj;
+ size_t i;
+
+ for (i = 0; i < list->count; ++i) {
+ ao2_cleanup(list->controls[i]);
+ list->controls[i] = NULL;
+ }
+}
+
+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]) {
+ 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_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_channel_to_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
+ size_t i;
+
if (!bridge) {
+ /* Response filled in by find_bridge */
return;
}
- control = find_channel_control(response, args->channel);
- if (!control) {
+ list = control_list_create(response, args->channel_count, args->channel);
+ if (!list) {
+ /* Response filled in by control_list_create() */
return;
}
- stasis_app_control_add_channel_to_bridge(control, bridge);
+ for (i = 0; i < list->count; ++i) {
+ stasis_app_control_add_channel_to_bridge(list->controls[i], bridge);
+ }
+
ast_ari_response_no_content(response);
}
void ast_ari_remove_channel_from_bridge(struct ast_variable *headers, struct ast_remove_channel_from_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
+ size_t i;
+
if (!bridge) {
+ /* Response filled in by find_bridge */
return;
}
- control = find_channel_control(response, args->channel);
- if (!control) {
+ list = control_list_create(response, args->channel_count, args->channel);
+ if (!list) {
+ /* Response filled in by control_list_create() */
return;
}
@@ -141,9 +203,14 @@ void ast_ari_remove_channel_from_bridge(struct ast_variable *headers, struct ast
* the bridge the channel is in. This will be possible once the bridge uniqueid
* is added to the channel snapshot. A 409 response should be issued if the bridge
* uniqueids don't match */
- if (stasis_app_control_remove_channel_from_bridge(control, bridge)) {
- ast_ari_response_error(response, 500, "Internal Error",
- "Could not remove channel from bridge");
+ for (i = 0; i < list->count; ++i) {
+ if (stasis_app_control_remove_channel_from_bridge(list->controls[i], bridge)) {
+ ast_ari_response_error(response, 500, "Internal Error",
+ "Could not remove channel from bridge");
+ }
+ }
+
+ if (response->response_code) {
return;
}
diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h
index 892a3f269..d12432413 100644
--- a/res/ari/resource_bridges.h
+++ b/res/ari/resource_bridges.h
@@ -97,8 +97,12 @@ void ast_ari_delete_bridge(struct ast_variable *headers, struct ast_delete_bridg
struct ast_add_channel_to_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
- /*! \brief Channel's id */
- const char *channel;
+ /*! \brief Array of Ids of channels to add to bridge */
+ const char **channel;
+ /*! \brief Length of channel array. */
+ size_t channel_count;
+ /*! \brief Parsing context for channel. */
+ char *channel_parse;
};
/*!
* \brief Add a channel to a bridge.
@@ -112,8 +116,12 @@ void ast_ari_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_
struct ast_remove_channel_from_bridge_args {
/*! \brief Bridge's id */
const char *bridge_id;
- /*! \brief Channel's id */
- const char *channel;
+ /*! \brief Array of Ids of channels to remove from bridge */
+ const char **channel;
+ /*! \brief Length of channel array. */
+ size_t channel_count;
+ /*! \brief Parsing context for channel. */
+ char *channel_parse;
};
/*!
* \brief Remove a channel from a bridge.
diff --git a/res/ari/resource_events.c b/res/ari/resource_events.c
index e5490b546..dd474c3ce 100644
--- a/res/ari/resource_events.c
+++ b/res/ari/resource_events.c
@@ -143,35 +143,28 @@ static void app_handler(void *data, const char *app_name,
/*!
* \brief Register for all of the apps given.
* \param session Session info struct.
- * \param app_list Comma seperated list of app names to register.
+ * \param app_name Name of application to register.
*/
-static int session_register_apps(struct event_session *session,
- const char *app_list)
+static int session_register_app(struct event_session *session,
+ const char *app_name)
{
- RAII_VAR(char *, to_free, NULL, ast_free);
- char *apps, *app_name;
SCOPED_AO2LOCK(lock, session);
ast_assert(session->ws_session != NULL);
ast_assert(session->websocket_apps != NULL);
- if (!app_list) {
+ if (ast_strlen_zero(app_name)) {
return -1;
}
- to_free = apps = ast_strdup(app_list);
- if (!apps) {
- ast_ari_websocket_session_write(session->ws_session, ast_ari_oom_json());
+ if (ast_str_container_add(session->websocket_apps, app_name)) {
+ ast_ari_websocket_session_write(session->ws_session,
+ ast_ari_oom_json());
return -1;
}
- while ((app_name = strsep(&apps, ","))) {
- if (ast_str_container_add(session->websocket_apps, app_name)) {
- ast_ari_websocket_session_write(session->ws_session, ast_ari_oom_json());
- return -1;
- }
- stasis_app_register(app_name, app_handler, session);
- }
+ stasis_app_register(app_name, app_handler, session);
+
return 0;
}
@@ -182,6 +175,7 @@ void ast_ari_websocket_event_websocket(struct ast_ari_websocket_session *ws_sess
RAII_VAR(struct event_session *, session, NULL, session_cleanup);
struct ast_json *msg;
int res;
+ size_t i;
ast_debug(3, "/events WebSocket connection\n");
@@ -191,7 +185,15 @@ void ast_ari_websocket_event_websocket(struct ast_ari_websocket_session *ws_sess
return;
}
- if (!args->app) {
+ res = 0;
+ for (i = 0; i < args->app_count; ++i) {
+ if (ast_strlen_zero(args->app[i])) {
+ continue;
+ }
+ res |= session_register_app(session, args->app[i]);
+ }
+
+ if (ao2_container_count(session->websocket_apps) == 0) {
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
msg = ast_json_pack("{s: s, s: [s]}",
@@ -205,7 +207,6 @@ void ast_ari_websocket_event_websocket(struct ast_ari_websocket_session *ws_sess
return;
}
- res = session_register_apps(session, args->app);
if (res != 0) {
ast_ari_websocket_session_write(ws_session, ast_ari_oom_json());
return;
diff --git a/res/ari/resource_events.h b/res/ari/resource_events.h
index 554ed9a87..ac7600e03 100644
--- a/res/ari/resource_events.h
+++ b/res/ari/resource_events.h
@@ -41,8 +41,12 @@
/*! \brief Argument struct for ast_ari_event_websocket() */
struct ast_event_websocket_args {
- /*! \brief Comma seperated list of applications to subscribe to. */
- const char *app;
+ /*! \brief Array of Applications to subscribe to. */
+ const char **app;
+ /*! \brief Length of app array. */
+ size_t app_count;
+ /*! \brief Parsing context for app. */
+ char *app_parse;
};
/*!
* \brief WebSocket connection for events.
diff --git a/res/ari/resource_sounds.h b/res/ari/resource_sounds.h
index 7cb22fb71..fa7cda23c 100644
--- a/res/ari/resource_sounds.h
+++ b/res/ari/resource_sounds.h
@@ -41,7 +41,9 @@
/*! \brief Argument struct for ast_ari_get_sounds() */
struct ast_get_sounds_args {
+ /*! \brief Lookup sound for a specific language. */
const char *lang;
+ /*! \brief Lookup sound in a specific format. */
const char *format;
};
/*!
diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c
index 2c125188b..dce634e8a 100644
--- a/res/res_ari_asterisk.c
+++ b/res/res_ari_asterisk.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_asterisk.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /asterisk/info.
* \param get_params GET parameters in the HTTP request.
@@ -59,17 +62,48 @@ static void ast_ari_get_asterisk_info_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_asterisk_info_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_asterisk_info_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "only") == 0) {
- args.only = (i->value);
+ /* Parse comma separated list */
+ char *vals[MAX_VALS];
+ size_t j;
+
+ args.only_parse = ast_strdup(i->value);
+ if (!args.only_parse) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ args.only_count = ast_app_separate_args(
+ args.only_parse, ',', vals, ARRAY_LEN(vals));
+ if (args.only_count == 0) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ if (args.only_count >= MAX_VALS) {
+ ast_ari_response_error(response, 400,
+ "Bad Request",
+ "Too many values for only");
+ goto fin;
+ }
+
+ args.only = ast_malloc(sizeof(*args.only) * args.only_count);
+ if (!args.only) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ for (j = 0; j < args.only_count; ++j) {
+ args.only[j] = (vals[j]);
+ }
} else
{}
}
@@ -101,6 +135,11 @@ static void ast_ari_get_asterisk_info_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ ast_free(args.only_parse);
+ ast_free(args.only);
+ return;
}
/*!
* \brief Parameter parsing callback for /asterisk/variable.
@@ -113,14 +152,13 @@ static void ast_ari_get_global_var_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_global_var_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_global_var_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "variable") == 0) {
args.variable = (i->value);
@@ -155,6 +193,9 @@ static void ast_ari_get_global_var_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /asterisk/variable.
@@ -167,14 +208,13 @@ static void ast_ari_set_global_var_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_set_global_var_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_set_global_var_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "variable") == 0) {
args.variable = (i->value);
@@ -212,6 +252,9 @@ static void ast_ari_set_global_var_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/asterisk.{format} */
diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c
index f2ee8c03a..57dc6a48d 100644
--- a/res/res_ari_bridges.c
+++ b/res/res_ari_bridges.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_bridges.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /bridges.
* \param get_params GET parameters in the HTTP request.
@@ -59,12 +62,12 @@ static void ast_ari_get_bridges_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_bridges_args args = {};
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_bridges_args args = {};
ast_ari_get_bridges(headers, &args, response);
#if defined(AST_DEVMODE)
code = response->response_code;
@@ -93,6 +96,9 @@ static void ast_ari_get_bridges_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges.
@@ -105,14 +111,13 @@ static void ast_ari_new_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_new_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_new_bridge_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "type") == 0) {
args.type = (i->value);
@@ -147,6 +152,9 @@ static void ast_ari_new_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}.
@@ -159,14 +167,13 @@ static void ast_ari_get_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_bridge_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "bridgeId") == 0) {
args.bridge_id = (i->value);
@@ -202,6 +209,9 @@ static void ast_ari_get_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}.
@@ -214,14 +224,13 @@ static void ast_ari_delete_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_delete_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_delete_bridge_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "bridgeId") == 0) {
args.bridge_id = (i->value);
@@ -257,6 +266,9 @@ static void ast_ari_delete_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
@@ -269,17 +281,48 @@ static void ast_ari_add_channel_to_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_add_channel_to_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_add_channel_to_bridge_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "channel") == 0) {
- args.channel = (i->value);
+ /* 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;
+ }
+
+ 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
{}
}
@@ -320,6 +363,11 @@ static void ast_ari_add_channel_to_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ ast_free(args.channel_parse);
+ ast_free(args.channel);
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
@@ -332,17 +380,48 @@ static void ast_ari_remove_channel_from_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_remove_channel_from_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_remove_channel_from_bridge_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "channel") == 0) {
- args.channel = (i->value);
+ /* 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;
+ }
+
+ 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
{}
}
@@ -380,6 +459,11 @@ static void ast_ari_remove_channel_from_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ ast_free(args.channel_parse);
+ ast_free(args.channel);
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}/play.
@@ -392,14 +476,13 @@ static void ast_ari_play_on_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_play_on_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_play_on_bridge_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "media") == 0) {
args.media = (i->value);
@@ -451,6 +534,9 @@ static void ast_ari_play_on_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /bridges/{bridgeId}/record.
@@ -463,14 +549,13 @@ static void ast_ari_record_bridge_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_record_bridge_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_record_bridge_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "name") == 0) {
args.name = (i->value);
@@ -529,6 +614,9 @@ static void ast_ari_record_bridge_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/bridges.{format} */
diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c
index 4c322ea2a..8a6687bc2 100644
--- a/res/res_ari_channels.c
+++ b/res/res_ari_channels.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_channels.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /channels.
* \param get_params GET parameters in the HTTP request.
@@ -59,12 +62,12 @@ static void ast_ari_get_channels_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_channels_args args = {};
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_channels_args args = {};
ast_ari_get_channels(headers, &args, response);
#if defined(AST_DEVMODE)
code = response->response_code;
@@ -93,6 +96,9 @@ static void ast_ari_get_channels_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels.
@@ -105,14 +111,13 @@ static void ast_ari_originate_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_originate_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_originate_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "endpoint") == 0) {
args.endpoint = (i->value);
@@ -169,6 +174,9 @@ static void ast_ari_originate_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}.
@@ -181,14 +189,13 @@ static void ast_ari_get_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -224,6 +231,9 @@ static void ast_ari_get_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}.
@@ -236,14 +246,13 @@ static void ast_ari_delete_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_delete_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_delete_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -279,6 +288,9 @@ static void ast_ari_delete_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/dial.
@@ -291,14 +303,13 @@ static void ast_ari_dial_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_dial_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_dial_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "endpoint") == 0) {
args.endpoint = (i->value);
@@ -350,6 +361,9 @@ static void ast_ari_dial_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/continue.
@@ -362,14 +376,13 @@ static void ast_ari_continue_in_dialplan_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_continue_in_dialplan_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_continue_in_dialplan_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "context") == 0) {
args.context = (i->value);
@@ -418,6 +431,9 @@ static void ast_ari_continue_in_dialplan_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/answer.
@@ -430,14 +446,13 @@ static void ast_ari_answer_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_answer_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_answer_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -474,6 +489,9 @@ static void ast_ari_answer_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/mute.
@@ -486,14 +504,13 @@ static void ast_ari_mute_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_mute_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_mute_channel_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "direction") == 0) {
args.direction = (i->value);
@@ -536,6 +553,9 @@ static void ast_ari_mute_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/unmute.
@@ -548,14 +568,13 @@ static void ast_ari_unmute_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_unmute_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_unmute_channel_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "direction") == 0) {
args.direction = (i->value);
@@ -598,6 +617,9 @@ static void ast_ari_unmute_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/hold.
@@ -610,14 +632,13 @@ static void ast_ari_hold_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_hold_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_hold_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -654,6 +675,9 @@ static void ast_ari_hold_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/unhold.
@@ -666,14 +690,13 @@ static void ast_ari_unhold_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_unhold_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_unhold_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -710,6 +733,9 @@ static void ast_ari_unhold_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/mohstart.
@@ -722,14 +748,13 @@ static void ast_ari_moh_start_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_moh_start_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_moh_start_channel_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "mohClass") == 0) {
args.moh_class = (i->value);
@@ -772,6 +797,9 @@ static void ast_ari_moh_start_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/mohstop.
@@ -784,14 +812,13 @@ static void ast_ari_moh_stop_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_moh_stop_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_moh_stop_channel_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "channelId") == 0) {
args.channel_id = (i->value);
@@ -828,6 +855,9 @@ static void ast_ari_moh_stop_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/play.
@@ -840,14 +870,13 @@ static void ast_ari_play_on_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_play_on_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_play_on_channel_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "media") == 0) {
args.media = (i->value);
@@ -899,6 +928,9 @@ static void ast_ari_play_on_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/record.
@@ -911,14 +943,13 @@ static void ast_ari_record_channel_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_record_channel_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_record_channel_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "name") == 0) {
args.name = (i->value);
@@ -980,6 +1011,9 @@ static void ast_ari_record_channel_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/variable.
@@ -992,14 +1026,13 @@ static void ast_ari_get_channel_var_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_channel_var_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_channel_var_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "variable") == 0) {
args.variable = (i->value);
@@ -1042,6 +1075,9 @@ static void ast_ari_get_channel_var_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /channels/{channelId}/variable.
@@ -1054,14 +1090,13 @@ static void ast_ari_set_channel_var_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_set_channel_var_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_set_channel_var_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "variable") == 0) {
args.variable = (i->value);
@@ -1107,6 +1142,9 @@ static void ast_ari_set_channel_var_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/channels.{format} */
diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c
index 8aa758929..a1dd759eb 100644
--- a/res/res_ari_endpoints.c
+++ b/res/res_ari_endpoints.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_endpoints.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /endpoints.
* \param get_params GET parameters in the HTTP request.
@@ -59,12 +62,12 @@ static void ast_ari_get_endpoints_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_endpoints_args args = {};
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_endpoints_args args = {};
ast_ari_get_endpoints(headers, &args, response);
#if defined(AST_DEVMODE)
code = response->response_code;
@@ -93,6 +96,9 @@ static void ast_ari_get_endpoints_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /endpoints/{tech}.
@@ -105,14 +111,13 @@ static void ast_ari_get_endpoints_by_tech_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_endpoints_by_tech_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_endpoints_by_tech_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "tech") == 0) {
args.tech = (i->value);
@@ -147,6 +152,9 @@ static void ast_ari_get_endpoints_by_tech_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /endpoints/{tech}/{resource}.
@@ -159,14 +167,13 @@ static void ast_ari_get_endpoint_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_endpoint_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_endpoint_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "tech") == 0) {
args.tech = (i->value);
@@ -204,6 +211,9 @@ static void ast_ari_get_endpoint_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/endpoints.{format} */
diff --git a/res/res_ari_events.c b/res/res_ari_events.c
index c310fa5f9..5cea06f0e 100644
--- a/res/res_ari_events.c
+++ b/res/res_ari_events.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_events.h"
@@ -48,20 +49,23 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
static void ast_ari_event_websocket_ws_cb(struct ast_websocket *ws_session,
struct ast_variable *get_params, struct ast_variable *headers)
{
- RAII_VAR(struct ast_websocket *, s, ws_session, ast_websocket_unref);
- RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
struct ast_event_websocket_args args = {};
+ RAII_VAR(struct ast_ari_response *, response, NULL, ast_free);
struct ast_variable *i;
+ RAII_VAR(struct ast_websocket *, s, ws_session, ast_websocket_unref);
+ RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
- for (i = get_params; i; i = i->next) {
- if (strcmp(i->name, "app") == 0) {
- args.app = (i->value);
- } else
- {}
+ response = ast_calloc(1, sizeof(*response));
+ if (!response) {
+ ast_log(LOG_ERROR, "Failed to create response.\n");
+ goto fin;
}
+
#if defined(AST_DEVMODE)
session = ast_ari_websocket_session_create(ws_session,
ast_ari_validate_message_fn());
@@ -70,9 +74,69 @@ static void ast_ari_event_websocket_ws_cb(struct ast_websocket *ws_session,
#endif
if (!session) {
ast_log(LOG_ERROR, "Failed to create ARI session\n");
- return;
+ goto fin;
+ }
+
+ for (i = get_params; i; i = i->next) {
+ if (strcmp(i->name, "app") == 0) {
+ /* Parse comma separated list */
+ char *vals[MAX_VALS];
+ size_t j;
+
+ args.app_parse = ast_strdup(i->value);
+ if (!args.app_parse) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ args.app_count = ast_app_separate_args(
+ args.app_parse, ',', vals, ARRAY_LEN(vals));
+ if (args.app_count == 0) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ if (args.app_count >= MAX_VALS) {
+ ast_ari_response_error(response, 400,
+ "Bad Request",
+ "Too many values for app");
+ goto fin;
+ }
+
+ args.app = ast_malloc(sizeof(*args.app) * args.app_count);
+ if (!args.app) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ for (j = 0; j < args.app_count; ++j) {
+ args.app[j] = (vals[j]);
+ }
+ } else
+ {}
}
+
ast_ari_websocket_event_websocket(session, headers, &args);
+
+fin: __attribute__((unused))
+ if (response && response->response_code != 0) {
+ /* Param parsing failure */
+ /* TODO - ideally, this would return the error code to the
+ * HTTP client; but we've already done the WebSocket
+ * negotiation. Param parsing should happen earlier, but we
+ * need a way to pass it through the WebSocket code to the
+ * callback */
+ RAII_VAR(char *, msg, NULL, ast_free);
+ if (response->message) {
+ msg = ast_json_dump_string(response->message);
+ } else {
+ msg = ast_strdup("?");
+ }
+ ast_websocket_write(ws_session, AST_WEBSOCKET_OPCODE_TEXT, msg,
+ strlen(msg));
+ }
+ ast_free(args.app_parse);
+ ast_free(args.app);
}
/*! \brief REST handler for /api-docs/events.{format} */
diff --git a/res/res_ari_playback.c b/res/res_ari_playback.c
index 0dc76aff9..55da058a8 100644
--- a/res/res_ari_playback.c
+++ b/res/res_ari_playback.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_playback.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /playback/{playbackId}.
* \param get_params GET parameters in the HTTP request.
@@ -59,14 +62,13 @@ static void ast_ari_get_playback_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_playback_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_playback_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "playbackId") == 0) {
args.playback_id = (i->value);
@@ -101,6 +103,9 @@ static void ast_ari_get_playback_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /playback/{playbackId}.
@@ -113,14 +118,13 @@ static void ast_ari_stop_playback_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_stop_playback_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_stop_playback_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "playbackId") == 0) {
args.playback_id = (i->value);
@@ -155,6 +159,9 @@ static void ast_ari_stop_playback_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /playback/{playbackId}/control.
@@ -167,14 +174,13 @@ static void ast_ari_control_playback_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_control_playback_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_control_playback_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "operation") == 0) {
args.operation = (i->value);
@@ -218,6 +224,9 @@ static void ast_ari_control_playback_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/playback.{format} */
diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c
index a63f37b18..01ad49a65 100644
--- a/res/res_ari_recordings.c
+++ b/res/res_ari_recordings.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_recordings.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /recordings/stored.
* \param get_params GET parameters in the HTTP request.
@@ -59,12 +62,12 @@ static void ast_ari_get_stored_recordings_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_stored_recordings_args args = {};
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_stored_recordings_args args = {};
ast_ari_get_stored_recordings(headers, &args, response);
#if defined(AST_DEVMODE)
code = response->response_code;
@@ -93,6 +96,9 @@ static void ast_ari_get_stored_recordings_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/stored/{recordingName}.
@@ -105,14 +111,13 @@ static void ast_ari_get_stored_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_stored_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_stored_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -147,6 +152,9 @@ static void ast_ari_get_stored_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/stored/{recordingName}.
@@ -159,14 +167,13 @@ static void ast_ari_delete_stored_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_delete_stored_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_delete_stored_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -201,6 +208,9 @@ static void ast_ari_delete_stored_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live.
@@ -213,12 +223,12 @@ static void ast_ari_get_live_recordings_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_live_recordings_args args = {};
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_live_recordings_args args = {};
ast_ari_get_live_recordings(headers, &args, response);
#if defined(AST_DEVMODE)
code = response->response_code;
@@ -247,6 +257,9 @@ static void ast_ari_get_live_recordings_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}.
@@ -259,14 +272,13 @@ static void ast_ari_get_live_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_live_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_live_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -301,6 +313,9 @@ static void ast_ari_get_live_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}.
@@ -313,14 +328,13 @@ static void ast_ari_cancel_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_cancel_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_cancel_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -355,6 +369,9 @@ static void ast_ari_cancel_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}/stop.
@@ -367,14 +384,13 @@ 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 */
- struct ast_stop_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -409,6 +425,9 @@ static void ast_ari_stop_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}/pause.
@@ -421,14 +440,13 @@ static void ast_ari_pause_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_pause_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_pause_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -463,6 +481,9 @@ static void ast_ari_pause_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}/unpause.
@@ -475,14 +496,13 @@ static void ast_ari_unpause_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_unpause_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_unpause_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -517,6 +537,9 @@ static void ast_ari_unpause_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}/mute.
@@ -529,14 +552,13 @@ static void ast_ari_mute_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_mute_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_mute_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -571,6 +593,9 @@ static void ast_ari_mute_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /recordings/live/{recordingName}/unmute.
@@ -583,14 +608,13 @@ static void ast_ari_unmute_recording_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_unmute_recording_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_unmute_recording_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "recordingName") == 0) {
args.recording_name = (i->value);
@@ -625,6 +649,9 @@ static void ast_ari_unmute_recording_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/recordings.{format} */
diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c
index a7411b5bf..0b817c309 100644
--- a/res/res_ari_sounds.c
+++ b/res/res_ari_sounds.c
@@ -41,6 +41,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_sounds.h"
@@ -48,6 +49,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
/*!
* \brief Parameter parsing callback for /sounds.
* \param get_params GET parameters in the HTTP request.
@@ -59,14 +62,13 @@ static void ast_ari_get_sounds_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_sounds_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_sounds_args args = {};
- struct ast_variable *i;
-
for (i = get_params; i; i = i->next) {
if (strcmp(i->name, "lang") == 0) {
args.lang = (i->value);
@@ -104,6 +106,9 @@ static void ast_ari_get_sounds_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*!
* \brief Parameter parsing callback for /sounds/{soundId}.
@@ -116,14 +121,13 @@ static void ast_ari_get_stored_sound_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_get_stored_sound_args args = {};
+ struct ast_variable *i;
#if defined(AST_DEVMODE)
int is_valid;
int code;
#endif /* AST_DEVMODE */
- struct ast_get_stored_sound_args args = {};
- struct ast_variable *i;
-
for (i = path_vars; i; i = i->next) {
if (strcmp(i->name, "soundId") == 0) {
args.sound_id = (i->value);
@@ -158,6 +162,9 @@ static void ast_ari_get_stored_sound_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+ return;
}
/*! \brief REST handler for /api-docs/sounds.{format} */
diff --git a/rest-api-templates/ari_resource.h.mustache b/rest-api-templates/ari_resource.h.mustache
index 6396e2b73..8b4b0acec 100644
--- a/rest-api-templates/ari_resource.h.mustache
+++ b/rest-api-templates/ari_resource.h.mustache
@@ -44,9 +44,21 @@
struct ast_{{c_nickname}}_args {
{{#parameters}}
{{#description}}
+{{/description}}
+{{^allow_multiple}}
+{{#description}}
/*! \brief {{{description}}} */
{{/description}}
{{c_data_type}}{{c_space}}{{c_name}};
+{{/allow_multiple}}
+{{#allow_multiple}}
+ /*! \brief Array of {{{description}}} */
+ {{c_data_type}}{{c_space}}*{{c_name}};
+ /*! \brief Length of {{c_name}} array. */
+ size_t {{c_name}}_count;
+ /*! \brief Parsing context for {{c_name}}. */
+ char *{{c_name}}_parse;
+{{/allow_multiple}}
{{/parameters}}
};
{{#is_req}}
diff --git a/rest-api-templates/param_cleanup.mustache b/rest-api-templates/param_cleanup.mustache
new file mode 100644
index 000000000..46edb417c
--- /dev/null
+++ b/rest-api-templates/param_cleanup.mustache
@@ -0,0 +1,26 @@
+{{!
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * David M. Lee, II <dlee@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+}}
+{{!
+ * Snippet for cleaning up an _args struct.
+}}
+{{#query_parameters}}
+{{#allow_multiple}}
+ ast_free(args.{{c_name}}_parse);
+ ast_free(args.{{c_name}});
+{{/allow_multiple}}
+{{/query_parameters}}
diff --git a/rest-api-templates/param_parsing.mustache b/rest-api-templates/param_parsing.mustache
index d43dcdce2..59c59e958 100644
--- a/rest-api-templates/param_parsing.mustache
+++ b/rest-api-templates/param_parsing.mustache
@@ -18,15 +18,48 @@
{{!
* Snippet for decoding parameters into an _args struct.
}}
- struct ast_{{c_nickname}}_args args = {};
-{{#has_parameters}}
- struct ast_variable *i;
-
{{#has_query_parameters}}
for (i = get_params; i; i = i->next) {
{{#query_parameters}}
if (strcmp(i->name, "{{name}}") == 0) {
+{{^allow_multiple}}
args.{{c_name}} = {{c_convert}}(i->value);
+{{/allow_multiple}}
+{{#allow_multiple}}
+ /* Parse comma separated list */
+ char *vals[MAX_VALS];
+ size_t j;
+
+ args.{{c_name}}_parse = ast_strdup(i->value);
+ if (!args.{{c_name}}_parse) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ args.{{c_name}}_count = ast_app_separate_args(
+ args.{{c_name}}_parse, ',', vals, ARRAY_LEN(vals));
+ if (args.{{c_name}}_count == 0) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ if (args.{{c_name}}_count >= MAX_VALS) {
+ ast_ari_response_error(response, 400,
+ "Bad Request",
+ "Too many values for {{c_name}}");
+ goto fin;
+ }
+
+ args.{{c_name}} = ast_malloc(sizeof(*args.{{c_name}}) * args.{{c_name}}_count);
+ if (!args.{{c_name}}) {
+ ast_ari_response_alloc_failed(response);
+ goto fin;
+ }
+
+ for (j = 0; j < args.{{c_name}}_count; ++j) {
+ args.{{c_name}}[j] = {{c_convert}}(vals[j]);
+ }
+{{/allow_multiple}}
} else
{{/query_parameters}}
{}
@@ -42,4 +75,3 @@
{}
}
{{/has_path_parameters}}
-{{/has_parameters}}
diff --git a/rest-api-templates/res_ari_resource.c.mustache b/rest-api-templates/res_ari_resource.c.mustache
index 4f1986c7d..906d55f0d 100644
--- a/rest-api-templates/res_ari_resource.c.mustache
+++ b/rest-api-templates/res_ari_resource.c.mustache
@@ -46,6 +46,7 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/app.h"
#include "asterisk/module.h"
#include "asterisk/stasis_app.h"
#include "ari/resource_{{name}}.h"
@@ -53,6 +54,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "ari/ari_model_validators.h"
#endif
+#define MAX_VALS 128
+
{{#apis}}
{{#operations}}
{{#is_req}}
@@ -67,6 +70,10 @@ static void ast_ari_{{c_nickname}}_cb(
struct ast_variable *get_params, struct ast_variable *path_vars,
struct ast_variable *headers, struct ast_ari_response *response)
{
+ struct ast_{{c_nickname}}_args args = {};
+{{#has_parameters}}
+ struct ast_variable *i;
+{{/has_parameters}}
#if defined(AST_DEVMODE)
int is_valid;
int code;
@@ -112,12 +119,21 @@ static void ast_ari_{{c_nickname}}_cb(
"Internal Server Error", "Response validation failed");
}
#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+{{> param_cleanup}}
+ return;
}
{{/is_req}}
{{#is_websocket}}
static void ast_ari_{{c_nickname}}_ws_cb(struct ast_websocket *ws_session,
struct ast_variable *get_params, struct ast_variable *headers)
{
+ struct ast_{{c_nickname}}_args args = {};
+{{#has_parameters}}
+ RAII_VAR(struct ast_ari_response *, response, NULL, ast_free);
+ struct ast_variable *i;
+{{/has_parameters}}
RAII_VAR(struct ast_websocket *, s, ws_session, ast_websocket_unref);
RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
{{#has_path_parameters}}
@@ -126,7 +142,15 @@ static void ast_ari_{{c_nickname}}_ws_cb(struct ast_websocket *ws_session,
* just punt. */
struct ast_variable *path_vars = NULL;
{{/has_path_parameters}}
-{{> param_parsing}}
+
+{{#has_parameters}}
+ response = ast_calloc(1, sizeof(*response));
+ if (!response) {
+ ast_log(LOG_ERROR, "Failed to create response.\n");
+ goto fin;
+ }
+{{/has_parameters}}
+
#if defined(AST_DEVMODE)
session = ast_ari_websocket_session_create(ws_session,
ast_ari_validate_{{response_class.c_name}}_fn());
@@ -135,9 +159,31 @@ static void ast_ari_{{c_nickname}}_ws_cb(struct ast_websocket *ws_session,
#endif
if (!session) {
ast_log(LOG_ERROR, "Failed to create ARI session\n");
- return;
+ goto fin;
}
+
+{{> param_parsing}}
+
ast_ari_websocket_{{c_nickname}}(session, headers, &args);
+
+fin: __attribute__((unused))
+ if (response && response->response_code != 0) {
+ /* Param parsing failure */
+ /* TODO - ideally, this would return the error code to the
+ * HTTP client; but we've already done the WebSocket
+ * negotiation. Param parsing should happen earlier, but we
+ * need a way to pass it through the WebSocket code to the
+ * callback */
+ RAII_VAR(char *, msg, NULL, ast_free);
+ if (response->message) {
+ msg = ast_json_dump_string(response->message);
+ } else {
+ msg = ast_strdup("?");
+ }
+ ast_websocket_write(ws_session, AST_WEBSOCKET_OPCODE_TEXT, msg,
+ strlen(msg));
+ }
+{{> param_cleanup}}
}
{{/is_websocket}}
{{/operations}}
diff --git a/rest-api/api-docs/bridges.json b/rest-api/api-docs/bridges.json
index 7b3c4a37b..57954dd27 100644
--- a/rest-api/api-docs/bridges.json
+++ b/rest-api/api-docs/bridges.json
@@ -114,7 +114,7 @@
},
{
"name": "channel",
- "description": "Channel's id",
+ "description": "Ids of channels to add to bridge",
"paramType": "query",
"required": true,
"allowMultiple": true,
@@ -158,7 +158,7 @@
},
{
"name": "channel",
- "description": "Channel's id",
+ "description": "Ids of channels to remove from bridge",
"paramType": "query",
"required": true,
"allowMultiple": true,
@@ -277,7 +277,7 @@
"description": "Format to encode audio in",
"paramType": "query",
"required": true,
- "allowMultiple": true,
+ "allowMultiple": false,
"dataType": "string"
},
{
@@ -389,7 +389,7 @@
},
"channels": {
"type": "List[string]",
- "description": "Id's of channels participating in this bridge",
+ "description": "Ids of channels participating in this bridge",
"required": true
}
}
diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json
index e54b02772..41b6cc08c 100644
--- a/rest-api/api-docs/channels.json
+++ b/rest-api/api-docs/channels.json
@@ -634,7 +634,7 @@
"description": "Format to encode audio in",
"paramType": "query",
"required": true,
- "allowMultiple": true,
+ "allowMultiple": false,
"dataType": "string"
},
{
diff --git a/rest-api/api-docs/events.json b/rest-api/api-docs/events.json
index 519bb7ae7..a2ac0b3d0 100644
--- a/rest-api/api-docs/events.json
+++ b/rest-api/api-docs/events.json
@@ -21,7 +21,7 @@
"parameters": [
{
"name": "app",
- "description": "Comma seperated list of applications to subscribe to.",
+ "description": "Applications to subscribe to.",
"paramType": "query",
"required": true,
"allowMultiple": true,
diff --git a/rest-api/api-docs/sounds.json b/rest-api/api-docs/sounds.json
index 103738c45..fe0b09fd4 100644
--- a/rest-api/api-docs/sounds.json
+++ b/rest-api/api-docs/sounds.json
@@ -19,12 +19,14 @@
"parameters": [
{
"name": "lang",
+ "description": "Lookup sound for a specific language.",
"paramType": "query",
"dataType": "string",
"required": false
},
{
"name": "format",
+ "description": "Lookup sound in a specific format.",
"paramType": "query",
"dataType": "string",
"required": false,