[asterisk-commits] dlee: trunk r396122 - in /trunk: ./ res/ res/ari/ rest-api-templates/ rest-ap...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Aug 2 09:36:39 CDT 2013


Author: dlee
Date: Fri Aug  2 09:36:32 2013
New Revision: 396122

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396122
Log:
ARI - implement allowMultiple for parameters

Swagger allows parameters to be specified as 'allowMultiple', meaning
that the parameter may be specified as a comma separated list of
values.

I had written some of the API docs using that, but promptly forgot
about implementing it. This patch finally fills in that gap.

The codegen template was updated to represent 'allowMultiple' fields
as array/size fields in the _args structs. It also parses the comma
separated list using ast_app_separate_args(), so quoted strings in the
argument will be handled properly.

Review: https://reviewboard.asterisk.org/r/2698/

Added:
    trunk/rest-api-templates/param_cleanup.mustache
      - copied unchanged from r396121, team/dlee/allow-multiple/rest-api-templates/param_cleanup.mustache
Modified:
    trunk/   (props changed)
    trunk/res/ari/resource_asterisk.h
    trunk/res/ari/resource_bridges.c
    trunk/res/ari/resource_bridges.h
    trunk/res/ari/resource_events.c
    trunk/res/ari/resource_events.h
    trunk/res/ari/resource_sounds.h
    trunk/res/res_ari_asterisk.c
    trunk/res/res_ari_bridges.c
    trunk/res/res_ari_channels.c
    trunk/res/res_ari_endpoints.c
    trunk/res/res_ari_events.c
    trunk/res/res_ari_playback.c
    trunk/res/res_ari_recordings.c
    trunk/res/res_ari_sounds.c
    trunk/rest-api-templates/ari_resource.h.mustache
    trunk/rest-api-templates/param_parsing.mustache
    trunk/rest-api-templates/res_ari_resource.c.mustache
    trunk/rest-api/api-docs/bridges.json
    trunk/rest-api/api-docs/channels.json
    trunk/rest-api/api-docs/events.json
    trunk/rest-api/api-docs/sounds.json

Propchange: trunk/
------------------------------------------------------------------------------
    svnmerge-integrated = /trunk:1-396120

Modified: trunk/res/ari/resource_asterisk.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_asterisk.h?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_asterisk.h (original)
+++ trunk/res/ari/resource_asterisk.h Fri Aug  2 09:36:32 2013
@@ -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.

Modified: trunk/res/ari/resource_bridges.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_bridges.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_bridges.c (original)
+++ trunk/res/ari/resource_bridges.c Fri Aug  2 09:36:32 2013
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 2012 - 2013, Digium, Inc.
@@ -107,33 +107,95 @@
 	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) {
-		return;
-	}
-
-	control = find_channel_control(response, args->channel);
-	if (!control) {
-		return;
-	}
-
-	stasis_app_control_add_channel_to_bridge(control, bridge);
+		/* Response filled in by find_bridge */
+		return;
+	}
+
+	list = control_list_create(response, args->channel_count, args->channel);
+	if (!list) {
+		/* Response filled in by control_list_create() */
+		return;
+	}
+
+	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) {
-		return;
-	}
-
-	control = find_channel_control(response, args->channel);
-	if (!control) {
+		/* Response filled in by find_bridge */
+		return;
+	}
+
+	list = control_list_create(response, args->channel_count, args->channel);
+	if (!list) {
+		/* Response filled in by control_list_create() */
 		return;
 	}
 
@@ -141,9 +203,14 @@
 	 * 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;
 	}
 

Modified: trunk/res/ari/resource_bridges.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_bridges.h?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_bridges.h (original)
+++ trunk/res/ari/resource_bridges.h Fri Aug  2 09:36:32 2013
@@ -97,8 +97,12 @@
 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 @@
 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.

Modified: trunk/res/ari/resource_events.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_events.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_events.c (original)
+++ trunk/res/ari/resource_events.c Fri Aug  2 09:36:32 2013
@@ -143,35 +143,28 @@
 /*!
  * \brief Register for all of the apps given.
  * \param session Session info struct.
- * \param app_list Comma seperated list of app names to register.
- */
-static int session_register_apps(struct event_session *session,
-				 const char *app_list)
-{
-	RAII_VAR(char *, to_free, NULL, ast_free);
-	char *apps, *app_name;
+ * \param app_name Name of application to register.
+ */
+static int session_register_app(struct event_session *session,
+				 const char *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 @@
 	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 @@
 		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 @@
 		return;
 	}
 
-	res = session_register_apps(session, args->app);
 	if (res != 0) {
 		ast_ari_websocket_session_write(ws_session, ast_ari_oom_json());
 		return;

Modified: trunk/res/ari/resource_events.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_events.h?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_events.h (original)
+++ trunk/res/ari/resource_events.h Fri Aug  2 09:36:32 2013
@@ -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.

Modified: trunk/res/ari/resource_sounds.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_sounds.h?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/ari/resource_sounds.h (original)
+++ trunk/res/ari/resource_sounds.h Fri Aug  2 09:36:32 2013
@@ -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;
 };
 /*!

Modified: trunk/res/res_ari_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_asterisk.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/res_ari_asterisk.c (original)
+++ trunk/res/res_ari_asterisk.c Fri Aug  2 09:36:32 2013
@@ -41,12 +41,15 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include "asterisk/app.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
 #include "ari/resource_asterisk.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif
+
+#define MAX_VALS 128
 
 /*!
  * \brief Parameter parsing callback for /asterisk/info.
@@ -59,17 +62,48 @@
 	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 @@
 			"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,13 +152,12 @@
 	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) {
@@ -155,6 +193,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /asterisk/variable.
@@ -167,13 +208,12 @@
 	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) {
@@ -212,6 +252,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 
 /*! \brief REST handler for /api-docs/asterisk.{format} */

Modified: trunk/res/res_ari_bridges.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_bridges.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/res_ari_bridges.c (original)
+++ trunk/res/res_ari_bridges.c Fri Aug  2 09:36:32 2013
@@ -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 @@
 #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 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_get_bridges_args args = {};
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
+
 	ast_ari_get_bridges(headers, &args, response);
 #if defined(AST_DEVMODE)
 	code = response->response_code;
@@ -93,6 +96,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /bridges.
@@ -105,13 +111,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_new_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "type") == 0) {
@@ -147,6 +152,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /bridges/{bridgeId}.
@@ -159,13 +167,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_get_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "bridgeId") == 0) {
@@ -202,6 +209,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /bridges/{bridgeId}.
@@ -214,13 +224,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_delete_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "bridgeId") == 0) {
@@ -257,6 +266,9 @@
 			"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 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_add_channel_to_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "channel") == 0) {
-			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 @@
 			"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 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_remove_channel_from_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "channel") == 0) {
-			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 @@
 			"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,13 +476,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_play_on_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "media") == 0) {
@@ -451,6 +534,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /bridges/{bridgeId}/record.
@@ -463,13 +549,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_record_bridge_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "name") == 0) {
@@ -529,6 +614,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 
 /*! \brief REST handler for /api-docs/bridges.{format} */

Modified: trunk/res/res_ari_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_channels.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/res_ari_channels.c (original)
+++ trunk/res/res_ari_channels.c Fri Aug  2 09:36:32 2013
@@ -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 @@
 #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 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_get_channels_args args = {};
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
+
 	ast_ari_get_channels(headers, &args, response);
 #if defined(AST_DEVMODE)
 	code = response->response_code;
@@ -93,6 +96,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels.
@@ -105,13 +111,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_originate_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "endpoint") == 0) {
@@ -169,6 +174,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}.
@@ -181,13 +189,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_get_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -224,6 +231,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}.
@@ -236,13 +246,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_delete_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -279,6 +288,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/dial.
@@ -291,13 +303,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_dial_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "endpoint") == 0) {
@@ -350,6 +361,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/continue.
@@ -362,13 +376,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_continue_in_dialplan_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "context") == 0) {
@@ -418,6 +431,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/answer.
@@ -430,13 +446,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_answer_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -474,6 +489,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/mute.
@@ -486,13 +504,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_mute_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "direction") == 0) {
@@ -536,6 +553,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/unmute.
@@ -548,13 +568,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_unmute_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "direction") == 0) {
@@ -598,6 +617,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/hold.
@@ -610,13 +632,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_hold_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -654,6 +675,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/unhold.
@@ -666,13 +690,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_unhold_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -710,6 +733,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/mohstart.
@@ -722,13 +748,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_moh_start_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "mohClass") == 0) {
@@ -772,6 +797,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/mohstop.
@@ -784,13 +812,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_moh_stop_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = path_vars; i; i = i->next) {
 		if (strcmp(i->name, "channelId") == 0) {
@@ -828,6 +855,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/play.
@@ -840,13 +870,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_play_on_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "media") == 0) {
@@ -899,6 +928,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/record.
@@ -911,13 +943,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_record_channel_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "name") == 0) {
@@ -980,6 +1011,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/variable.
@@ -992,13 +1026,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_get_channel_var_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "variable") == 0) {
@@ -1042,6 +1075,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /channels/{channelId}/variable.
@@ -1054,13 +1090,12 @@
 	struct ast_variable *get_params, struct ast_variable *path_vars,
 	struct ast_variable *headers, struct ast_ari_response *response)
 {
-#if defined(AST_DEVMODE)
-	int is_valid;
-	int code;
-#endif /* AST_DEVMODE */
-
 	struct ast_set_channel_var_args args = {};
 	struct ast_variable *i;
+#if defined(AST_DEVMODE)
+	int is_valid;
+	int code;
+#endif /* AST_DEVMODE */
 
 	for (i = get_params; i; i = i->next) {
 		if (strcmp(i->name, "variable") == 0) {
@@ -1107,6 +1142,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 
 /*! \brief REST handler for /api-docs/channels.{format} */

Modified: trunk/res/res_ari_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_endpoints.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/res_ari_endpoints.c (original)
+++ trunk/res/res_ari_endpoints.c Fri Aug  2 09:36:32 2013
@@ -41,12 +41,15 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include "asterisk/app.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
 #include "ari/resource_endpoints.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif
+
+#define MAX_VALS 128
 
 /*!
  * \brief Parameter parsing callback for /endpoints.
@@ -59,12 +62,12 @@
 	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 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /endpoints/{tech}.
@@ -105,13 +111,12 @@
 	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) {
@@ -147,6 +152,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 /*!
  * \brief Parameter parsing callback for /endpoints/{tech}/{resource}.
@@ -159,13 +167,12 @@
 	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) {
@@ -204,6 +211,9 @@
 			"Internal Server Error", "Response validation failed");
 	}
 #endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
 }
 
 /*! \brief REST handler for /api-docs/endpoints.{format} */

Modified: trunk/res/res_ari_events.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_events.c?view=diff&rev=396122&r1=396121&r2=396122
==============================================================================
--- trunk/res/res_ari_events.c (original)
+++ trunk/res/res_ari_events.c Fri Aug  2 09:36:32 2013
@@ -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 @@
 #include "ari/ari_model_validators.h"
 #endif
 
+#define MAX_VALS 128
+

[... 893 lines stripped ...]



More information about the asterisk-commits mailing list