[asterisk-commits] dlee: branch dlee/ASTERISK-22451-ari-subscribe r398693 - in /team/dlee/ASTERI...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Sep 9 16:48:33 CDT 2013


Author: dlee
Date: Mon Sep  9 16:48:31 2013
New Revision: 398693

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=398693
Log:
API

Modified:
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.c
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.h
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.c
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.h
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.c
    team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.h
    team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_channels.c
    team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_endpoints.c
    team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/channels.json
    team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/endpoints.json

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.c?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.c (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.c Mon Sep  9 16:48:31 2013
@@ -588,6 +588,45 @@
 	return ast_ari_validate_endpoint;
 }
 
+int ast_ari_validate_endpoint_subscriptions(struct ast_json *json)
+{
+	int res = 1;
+	struct ast_json_iter *iter;
+	int has_applications = 0;
+
+	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+		if (strcmp("applications", ast_json_object_iter_key(iter)) == 0) {
+			int prop_is_valid;
+			has_applications = 1;
+			prop_is_valid = ast_ari_validate_list(
+				ast_json_object_iter_value(iter),
+				ast_ari_validate_string);
+			if (!prop_is_valid) {
+				ast_log(LOG_ERROR, "ARI EndpointSubscriptions field applications failed validation\n");
+				res = 0;
+			}
+		} else
+		{
+			ast_log(LOG_ERROR,
+				"ARI EndpointSubscriptions has undocumented field %s\n",
+				ast_json_object_iter_key(iter));
+			res = 0;
+		}
+	}
+
+	if (!has_applications) {
+		ast_log(LOG_ERROR, "ARI EndpointSubscriptions missing required field applications\n");
+		res = 0;
+	}
+
+	return res;
+}
+
+ari_validator ast_ari_validate_endpoint_subscriptions_fn(void)
+{
+	return ast_ari_validate_endpoint_subscriptions;
+}
+
 int ast_ari_validate_caller_id(struct ast_json *json)
 {
 	int res = 1;
@@ -792,6 +831,45 @@
 	return ast_ari_validate_channel;
 }
 
+int ast_ari_validate_channel_subscriptions(struct ast_json *json)
+{
+	int res = 1;
+	struct ast_json_iter *iter;
+	int has_applications = 0;
+
+	for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+		if (strcmp("applications", ast_json_object_iter_key(iter)) == 0) {
+			int prop_is_valid;
+			has_applications = 1;
+			prop_is_valid = ast_ari_validate_list(
+				ast_json_object_iter_value(iter),
+				ast_ari_validate_string);
+			if (!prop_is_valid) {
+				ast_log(LOG_ERROR, "ARI ChannelSubscriptions field applications failed validation\n");
+				res = 0;
+			}
+		} else
+		{
+			ast_log(LOG_ERROR,
+				"ARI ChannelSubscriptions has undocumented field %s\n",
+				ast_json_object_iter_key(iter));
+			res = 0;
+		}
+	}
+
+	if (!has_applications) {
+		ast_log(LOG_ERROR, "ARI ChannelSubscriptions missing required field applications\n");
+		res = 0;
+	}
+
+	return res;
+}
+
+ari_validator ast_ari_validate_channel_subscriptions_fn(void)
+{
+	return ast_ari_validate_channel_subscriptions;
+}
+
 int ast_ari_validate_dialed(struct ast_json *json)
 {
 	int res = 1;

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.h?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.h (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/ari_model_validators.h Mon Sep  9 16:48:31 2013
@@ -290,6 +290,24 @@
 ari_validator ast_ari_validate_endpoint_fn(void);
 
 /*!
+ * \brief Validator for EndpointSubscriptions.
+ *
+ * List of applications subscribed to a endpoint
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_endpoint_subscriptions(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_endpoint_subscriptions().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_endpoint_subscriptions_fn(void);
+
+/*!
  * \brief Validator for CallerID.
  *
  * Caller identification
@@ -324,6 +342,24 @@
  * See \ref ast_ari_model_validators.h for more details.
  */
 ari_validator ast_ari_validate_channel_fn(void);
+
+/*!
+ * \brief Validator for ChannelSubscriptions.
+ *
+ * List of applications subscribed to a channel
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_channel_subscriptions(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_channel_subscriptions().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_channel_subscriptions_fn(void);
 
 /*!
  * \brief Validator for Dialed.
@@ -909,6 +945,8 @@
  * - resource: string (required)
  * - state: string
  * - technology: string (required)
+ * EndpointSubscriptions
+ * - applications: List[string] (required)
  * CallerID
  * - name: string (required)
  * - number: string (required)
@@ -921,6 +959,8 @@
  * - id: string (required)
  * - name: string (required)
  * - state: string (required)
+ * ChannelSubscriptions
+ * - applications: List[string] (required)
  * Dialed
  * DialplanCEP
  * - context: string (required)

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.c?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.c (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.c Mon Sep  9 16:48:31 2013
@@ -700,3 +700,20 @@
 	ast_ari_response_no_content(response);
 }
 
+void ast_ari_get_channel_subscriptions(struct ast_variable *headers,
+	struct ast_get_channel_subscriptions_args *args,
+	struct ast_ari_response *response)
+{
+}
+
+void ast_ari_channel_subscribe(struct ast_variable *headers,
+	struct ast_channel_subscribe_args *args,
+	struct ast_ari_response *response)
+{
+}
+
+void ast_ari_channel_unsubscribe(struct ast_variable *headers,
+	struct ast_channel_unsubscribe_args *args,
+	struct ast_ari_response *response)
+{
+}

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.h?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.h (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_channels.h Mon Sep  9 16:48:31 2013
@@ -328,5 +328,56 @@
  * \param[out] response HTTP response
  */
 void ast_ari_set_channel_var(struct ast_variable *headers, struct ast_set_channel_var_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_get_channel_subscriptions() */
+struct ast_get_channel_subscriptions_args {
+	/*! \brief Channel's id */
+	const char *channel_id;
+};
+/*!
+ * \brief Returns the current subscriptions for a channel.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_get_channel_subscriptions(struct ast_variable *headers, struct ast_get_channel_subscriptions_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_channel_subscribe() */
+struct ast_channel_subscribe_args {
+	/*! \brief Channel's id */
+	const char *channel_id;
+	/*! \brief Array of Application(s) which to subscribe to a channel */
+	const char **application;
+	/*! \brief Length of application array. */
+	size_t application_count;
+	/*! \brief Parsing context for application. */
+	char *application_parse;
+};
+/*!
+ * \brief Create a new subscription for a channel.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_channel_subscribe(struct ast_variable *headers, struct ast_channel_subscribe_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_channel_unsubscribe() */
+struct ast_channel_unsubscribe_args {
+	/*! \brief Channel's id */
+	const char *channel_id;
+	/*! \brief Array of Application(s) which to subscribe to a channel */
+	const char **application;
+	/*! \brief Length of application array. */
+	size_t application_count;
+	/*! \brief Parsing context for application. */
+	char *application_parse;
+};
+/*!
+ * \brief Remove a subscription for a channel.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_channel_unsubscribe(struct ast_variable *headers, struct ast_channel_unsubscribe_args *args, struct ast_ari_response *response);
 
 #endif /* _ASTERISK_RESOURCE_CHANNELS_H */

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.c?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.c (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.c Mon Sep  9 16:48:31 2013
@@ -155,3 +155,21 @@
 
 	ast_ari_response_ok(response, ast_json_ref(json));
 }
+
+void ast_ari_get_endpoint_subscriptions(struct ast_variable *headers,
+	struct ast_get_endpoint_subscriptions_args *args,
+	struct ast_ari_response *response)
+{
+}
+
+void ast_ari_endpoint_subscribe(struct ast_variable *headers,
+	struct ast_endpoint_subscribe_args *args,
+	struct ast_ari_response *response)
+{
+}
+
+void ast_ari_endpoint_unsubscribe(struct ast_variable *headers,
+	struct ast_endpoint_unsubscribe_args *args,
+	struct ast_ari_response *response)
+{
+}

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.h?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.h (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/ari/resource_endpoints.h Mon Sep  9 16:48:31 2013
@@ -78,5 +78,62 @@
  * \param[out] response HTTP response
  */
 void ast_ari_get_endpoint(struct ast_variable *headers, struct ast_get_endpoint_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_get_endpoint_subscriptions() */
+struct ast_get_endpoint_subscriptions_args {
+	/*! \brief Technology of the endpoint */
+	const char *tech;
+	/*! \brief ID of the endpoint */
+	const char *resource;
+};
+/*!
+ * \brief Returns the current subscriptions for a endpoint.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_get_endpoint_subscriptions(struct ast_variable *headers, struct ast_get_endpoint_subscriptions_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_endpoint_subscribe() */
+struct ast_endpoint_subscribe_args {
+	/*! \brief Technology of the endpoint */
+	const char *tech;
+	/*! \brief ID of the endpoint */
+	const char *resource;
+	/*! \brief Array of Application(s) which to subscribe to a endpoint */
+	const char **application;
+	/*! \brief Length of application array. */
+	size_t application_count;
+	/*! \brief Parsing context for application. */
+	char *application_parse;
+};
+/*!
+ * \brief Create a new subscription for a endpoint.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_endpoint_subscribe(struct ast_variable *headers, struct ast_endpoint_subscribe_args *args, struct ast_ari_response *response);
+/*! \brief Argument struct for ast_ari_endpoint_unsubscribe() */
+struct ast_endpoint_unsubscribe_args {
+	/*! \brief Technology of the endpoint */
+	const char *tech;
+	/*! \brief ID of the endpoint */
+	const char *resource;
+	/*! \brief Array of Application(s) which to subscribe to a endpoint */
+	const char **application;
+	/*! \brief Length of application array. */
+	size_t application_count;
+	/*! \brief Parsing context for application. */
+	char *application_parse;
+};
+/*!
+ * \brief Remove a subscription for a endpoint.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void ast_ari_endpoint_unsubscribe(struct ast_variable *headers, struct ast_endpoint_unsubscribe_args *args, struct ast_ari_response *response);
 
 #endif /* _ASTERISK_RESOURCE_ENDPOINTS_H */

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_channels.c?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_channels.c (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_channels.c Mon Sep  9 16:48:31 2013
@@ -1146,6 +1146,276 @@
 #endif /* AST_DEVMODE */
 
 fin: __attribute__((unused))
+	return;
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_get_channel_subscriptions_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_get_channel_subscriptions_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) {
+			args.channel_id = (i->value);
+		} else
+		{}
+	}
+	ast_ari_get_channel_subscriptions(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_channel_subscriptions(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_channel_subscribe_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_channel_subscribe_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, "application") == 0) {
+			/* Parse comma separated list */
+			char *vals[MAX_VALS];
+			size_t j;
+
+			args.application_parse = ast_strdup(i->value);
+			if (!args.application_parse) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (strlen(args.application_parse) == 0) {
+				/* ast_app_separate_args can't handle "" */
+				args.application_count = 1;
+				vals[0] = args.application_parse;
+			} else {
+				args.application_count = ast_app_separate_args(
+					args.application_parse, ',', vals,
+					ARRAY_LEN(vals));
+			}
+
+			if (args.application_count == 0) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (args.application_count >= MAX_VALS) {
+				ast_ari_response_error(response, 400,
+					"Bad Request",
+					"Too many values for application");
+				goto fin;
+			}
+
+			args.application = ast_malloc(sizeof(*args.application) * args.application_count);
+			if (!args.application) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			for (j = 0; j < args.application_count; ++j) {
+				args.application[j] = (vals[j]);
+			}
+		} else
+		{}
+	}
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "channelId") == 0) {
+			args.channel_id = (i->value);
+		} else
+		{}
+	}
+	ast_ari_channel_subscribe(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+	case 404: /* Channel not found. */
+	case 409: /* Application alreadt subscribed to this channel */
+	case 422: /* Application not found. */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_void(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	ast_free(args.application_parse);
+	ast_free(args.application);
+	return;
+}
+/*!
+ * \brief Parameter parsing callback for /channels/{channelId}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_channel_unsubscribe_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_channel_unsubscribe_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, "application") == 0) {
+			/* Parse comma separated list */
+			char *vals[MAX_VALS];
+			size_t j;
+
+			args.application_parse = ast_strdup(i->value);
+			if (!args.application_parse) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (strlen(args.application_parse) == 0) {
+				/* ast_app_separate_args can't handle "" */
+				args.application_count = 1;
+				vals[0] = args.application_parse;
+			} else {
+				args.application_count = ast_app_separate_args(
+					args.application_parse, ',', vals,
+					ARRAY_LEN(vals));
+			}
+
+			if (args.application_count == 0) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (args.application_count >= MAX_VALS) {
+				ast_ari_response_error(response, 400,
+					"Bad Request",
+					"Too many values for application");
+				goto fin;
+			}
+
+			args.application = ast_malloc(sizeof(*args.application) * args.application_count);
+			if (!args.application) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			for (j = 0; j < args.application_count; ++j) {
+				args.application[j] = (vals[j]);
+			}
+		} else
+		{}
+	}
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "channelId") == 0) {
+			args.channel_id = (i->value);
+		} else
+		{}
+	}
+	ast_ari_channel_unsubscribe(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+	case 404: /* Channel not found. */
+	case 409: /* Application not subscribed to this channel */
+	case 422: /* Application not found. */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_void(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /channels/{channelId}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /channels/{channelId}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	ast_free(args.application_parse);
+	ast_free(args.application);
 	return;
 }
 
@@ -1259,6 +1529,17 @@
 	.children = {  }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
+static struct stasis_rest_handlers channels_channelId_subscriptions = {
+	.path_segment = "subscriptions",
+	.callbacks = {
+		[AST_HTTP_GET] = ast_ari_get_channel_subscriptions_cb,
+		[AST_HTTP_POST] = ast_ari_channel_subscribe_cb,
+		[AST_HTTP_DELETE] = ast_ari_channel_unsubscribe_cb,
+	},
+	.num_children = 0,
+	.children = {  }
+};
+/*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels_channelId = {
 	.path_segment = "channelId",
 	.is_wildcard = 1,
@@ -1266,8 +1547,8 @@
 		[AST_HTTP_GET] = ast_ari_get_channel_cb,
 		[AST_HTTP_DELETE] = ast_ari_delete_channel_cb,
 	},
-	.num_children = 12,
-	.children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable, }
+	.num_children = 13,
+	.children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_mohstart,&channels_channelId_mohstop,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable,&channels_channelId_subscriptions, }
 };
 /*! \brief REST handler for /api-docs/channels.{format} */
 static struct stasis_rest_handlers channels = {

Modified: team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_endpoints.c?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_endpoints.c (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/res/res_ari_endpoints.c Mon Sep  9 16:48:31 2013
@@ -215,7 +215,297 @@
 fin: __attribute__((unused))
 	return;
 }
-
+/*!
+ * \brief Parameter parsing callback for /endpoints/{tech}/{resource}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_get_endpoint_subscriptions_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_get_endpoint_subscriptions_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, "tech") == 0) {
+			args.tech = (i->value);
+		} else
+		if (strcmp(i->name, "resource") == 0) {
+			args.resource = (i->value);
+		} else
+		{}
+	}
+	ast_ari_get_endpoint_subscriptions(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_endpoint_subscriptions(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	return;
+}
+/*!
+ * \brief Parameter parsing callback for /endpoints/{tech}/{resource}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_endpoint_subscribe_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_endpoint_subscribe_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, "application") == 0) {
+			/* Parse comma separated list */
+			char *vals[MAX_VALS];
+			size_t j;
+
+			args.application_parse = ast_strdup(i->value);
+			if (!args.application_parse) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (strlen(args.application_parse) == 0) {
+				/* ast_app_separate_args can't handle "" */
+				args.application_count = 1;
+				vals[0] = args.application_parse;
+			} else {
+				args.application_count = ast_app_separate_args(
+					args.application_parse, ',', vals,
+					ARRAY_LEN(vals));
+			}
+
+			if (args.application_count == 0) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (args.application_count >= MAX_VALS) {
+				ast_ari_response_error(response, 400,
+					"Bad Request",
+					"Too many values for application");
+				goto fin;
+			}
+
+			args.application = ast_malloc(sizeof(*args.application) * args.application_count);
+			if (!args.application) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			for (j = 0; j < args.application_count; ++j) {
+				args.application[j] = (vals[j]);
+			}
+		} else
+		{}
+	}
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "tech") == 0) {
+			args.tech = (i->value);
+		} else
+		if (strcmp(i->name, "resource") == 0) {
+			args.resource = (i->value);
+		} else
+		{}
+	}
+	ast_ari_endpoint_subscribe(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+	case 404: /* Endpoint not found. */
+	case 409: /* Application alreadt subscribed to this endpoint */
+	case 422: /* Application not found. */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_void(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	ast_free(args.application_parse);
+	ast_free(args.application);
+	return;
+}
+/*!
+ * \brief Parameter parsing callback for /endpoints/{tech}/{resource}/subscriptions.
+ * \param get_params GET parameters in the HTTP request.
+ * \param path_vars Path variables extracted from the request.
+ * \param headers HTTP headers.
+ * \param[out] response Response to the HTTP request.
+ */
+static void ast_ari_endpoint_unsubscribe_cb(
+	struct ast_variable *get_params, struct ast_variable *path_vars,
+	struct ast_variable *headers, struct ast_ari_response *response)
+{
+	struct ast_endpoint_unsubscribe_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, "application") == 0) {
+			/* Parse comma separated list */
+			char *vals[MAX_VALS];
+			size_t j;
+
+			args.application_parse = ast_strdup(i->value);
+			if (!args.application_parse) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (strlen(args.application_parse) == 0) {
+				/* ast_app_separate_args can't handle "" */
+				args.application_count = 1;
+				vals[0] = args.application_parse;
+			} else {
+				args.application_count = ast_app_separate_args(
+					args.application_parse, ',', vals,
+					ARRAY_LEN(vals));
+			}
+
+			if (args.application_count == 0) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			if (args.application_count >= MAX_VALS) {
+				ast_ari_response_error(response, 400,
+					"Bad Request",
+					"Too many values for application");
+				goto fin;
+			}
+
+			args.application = ast_malloc(sizeof(*args.application) * args.application_count);
+			if (!args.application) {
+				ast_ari_response_alloc_failed(response);
+				goto fin;
+			}
+
+			for (j = 0; j < args.application_count; ++j) {
+				args.application[j] = (vals[j]);
+			}
+		} else
+		{}
+	}
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "tech") == 0) {
+			args.tech = (i->value);
+		} else
+		if (strcmp(i->name, "resource") == 0) {
+			args.resource = (i->value);
+		} else
+		{}
+	}
+	ast_ari_endpoint_unsubscribe(headers, &args, response);
+#if defined(AST_DEVMODE)
+	code = response->response_code;
+
+	switch (code) {
+	case 0: /* Implementation is still a stub, or the code wasn't set */
+		is_valid = response->message == NULL;
+		break;
+	case 500: /* Internal Server Error */
+	case 501: /* Not Implemented */
+	case 404: /* Endpoint not found. */
+	case 409: /* Application not subscribed to this endpoint */
+	case 422: /* Application not found. */
+		is_valid = 1;
+		break;
+	default:
+		if (200 <= code && code <= 299) {
+			is_valid = ast_ari_validate_void(
+				response->message);
+		} else {
+			ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}/subscriptions\n", code);
+			is_valid = 0;
+		}
+	}
+
+	if (!is_valid) {
+		ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}/subscriptions\n");
+		ast_ari_response_error(response, 500,
+			"Internal Server Error", "Response validation failed");
+	}
+#endif /* AST_DEVMODE */
+
+fin: __attribute__((unused))
+	ast_free(args.application_parse);
+	ast_free(args.application);
+	return;
+}
+
+/*! \brief REST handler for /api-docs/endpoints.{format} */
+static struct stasis_rest_handlers endpoints_tech_resource_subscriptions = {
+	.path_segment = "subscriptions",
+	.callbacks = {
+		[AST_HTTP_GET] = ast_ari_get_endpoint_subscriptions_cb,
+		[AST_HTTP_POST] = ast_ari_endpoint_subscribe_cb,
+		[AST_HTTP_DELETE] = ast_ari_endpoint_unsubscribe_cb,
+	},
+	.num_children = 0,
+	.children = {  }
+};
 /*! \brief REST handler for /api-docs/endpoints.{format} */
 static struct stasis_rest_handlers endpoints_tech_resource = {
 	.path_segment = "resource",
@@ -223,8 +513,8 @@
 	.callbacks = {
 		[AST_HTTP_GET] = ast_ari_get_endpoint_cb,
 	},
-	.num_children = 0,
-	.children = {  }
+	.num_children = 1,
+	.children = { &endpoints_tech_resource_subscriptions, }
 };
 /*! \brief REST handler for /api-docs/endpoints.{format} */
 static struct stasis_rest_handlers endpoints_tech = {

Modified: team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/channels.json
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/channels.json?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/channels.json (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/channels.json Mon Sep  9 16:48:31 2013
@@ -811,6 +811,104 @@
 						{
 							"code": 409,
 							"reason": "Channel not in a Stasis application"
+						}
+					]
+				}
+			]
+		},
+		{
+			"path": "/channels/{channelId}/subscriptions",
+			"description": "Manually manage Stasis application subscriptions for a channel",
+			"operations": [
+				{
+					"httpMethod": "GET",
+					"summary": "Returns the current subscriptions for a channel.",
+					"nickname": "getChannelSubscriptions",
+					"responseClass": "ChannelSubscriptions",
+					"parameters": [
+						{
+							"name": "channelId",
+							"description": "Channel's id",
+							"paramType": "path",
+							"required": true,
+							"allowMultiple": false,
+							"dataType": "string"
+						}
+					]
+				},
+				{
+					"httpMethod": "POST",
+					"summary": "Create a new subscription for a channel.",
+					"nickname": "channelSubscribe",
+					"responseClass": "void",
+					"parameters": [
+						{
+							"name": "channelId",
+							"description": "Channel's id",
+							"paramType": "path",
+							"required": true,
+							"allowMultiple": false,
+							"dataType": "string"
+						},
+						{
+							"name": "application",
+							"description": "Application(s) which to subscribe to a channel",
+							"paramType": "query",
+							"required": true,
+							"allowMultiple": true,
+							"dataType": "string"
+						}
+					],
+					"errorResponses": [
+						{
+							"code": 404,
+							"reason": "Channel not found."
+						},
+						{
+							"code": 409,
+							"reason": "Application alreadt subscribed to this channel"
+						},
+						{
+							"code": 422,
+							"reason": "Application not found."
+						}
+					]
+				},
+				{
+					"httpMethod": "DELETE",
+					"summary": "Remove a subscription for a channel.",
+					"nickname": "channelUnsubscribe",
+					"responseClass": "void",
+					"parameters": [
+						{
+							"name": "channelId",
+							"description": "Channel's id",
+							"paramType": "path",
+							"required": true,
+							"allowMultiple": false,
+							"dataType": "string"
+						},
+						{
+							"name": "application",
+							"description": "Application(s) which to subscribe to a channel",
+							"paramType": "query",
+							"required": true,
+							"allowMultiple": true,
+							"dataType": "string"
+						}
+					],
+					"errorResponses": [
+						{
+							"code": 404,
+							"reason": "Channel not found."
+						},
+						{
+							"code": 409,
+							"reason": "Application not subscribed to this channel"
+						},
+						{
+							"code": 422,
+							"reason": "Application not found."
 						}
 					]
 				}
@@ -915,6 +1013,17 @@
 					"description": "Timestamp when channel was created"
 				}
 			}
+		},
+		"ChannelSubscriptions": {
+			"id": "ChannelSubscriptions",
+			"description": "List of applications subscribed to a channel",
+			"properties": {
+				"applications": {
+					"required": true,
+					"type": "List[string]",
+					"description": "List of applications subscribed to this channel"
+				}
+			}
 		}
 	}
 }

Modified: team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/endpoints.json
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/endpoints.json?view=diff&rev=398693&r1=398692&r2=398693
==============================================================================
--- team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/endpoints.json (original)
+++ team/dlee/ASTERISK-22451-ari-subscribe/rest-api/api-docs/endpoints.json Mon Sep  9 16:48:31 2013
@@ -60,6 +60,116 @@
 							"description": "ID of the endpoint",
 							"paramType": "path",
 							"dataType": "string"
+						}
+					]
+				}
+			]
+		},
+		{
+			"path": "/endpoints/{tech}/{resource}/subscriptions",
+			"description": "Manually manage Stasis application subscriptions for an endpoint",
+			"operations": [
+				{
+					"httpMethod": "GET",
+					"summary": "Returns the current subscriptions for a endpoint.",
+					"nickname": "getEndpointSubscriptions",
+					"responseClass": "EndpointSubscriptions",
+					"parameters": [
+						{
+							"name": "tech",
+							"description": "Technology of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "resource",
+							"description": "ID of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						}
+					]
+				},
+				{
+					"httpMethod": "POST",
+					"summary": "Create a new subscription for a endpoint.",
+					"nickname": "endpointSubscribe",
+					"responseClass": "void",
+					"parameters": [
+						{
+							"name": "tech",
+							"description": "Technology of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "resource",
+							"description": "ID of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "application",
+							"description": "Application(s) which to subscribe to a endpoint",
+							"paramType": "query",
+							"required": true,
+							"allowMultiple": true,
+							"dataType": "string"
+						}
+					],
+					"errorResponses": [
+						{
+							"code": 404,
+							"reason": "Endpoint not found."
+						},
+						{
+							"code": 409,
+							"reason": "Application alreadt subscribed to this endpoint"
+						},
+						{
+							"code": 422,
+							"reason": "Application not found."
+						}
+					]
+				},
+				{
+					"httpMethod": "DELETE",
+					"summary": "Remove a subscription for a endpoint.",
+					"nickname": "endpointUnsubscribe",
+					"responseClass": "void",
+					"parameters": [
+						{
+							"name": "tech",
+							"description": "Technology of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "resource",
+							"description": "ID of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "application",

[... 41 lines stripped ...]



More information about the asterisk-commits mailing list