[asterisk-commits] dlee: trunk r387932 - in /trunk: channels/ channels/sip/include/ include/aste...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 8 08:39:21 CDT 2013


Author: dlee
Date: Wed May  8 08:39:08 2013
New Revision: 387932

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=387932
Log:
Initial support for endpoints.

An endpoint is an external device/system that may offer/accept
channels to/from Asterisk. While this is a very useful concept for end
users, it is surprisingly not a core concept within Asterisk itself.

This patch defines ast_endpoint as a separate object, which channel
drivers may use to expose their concept of an endpoint. As the channel
driver creates channels, it can use ast_endpoint_add_channel() to
associate channels to the endpoint. This updated the endpoint
appropriately, and forwards all of the channel's events to the
endpoint's topic.

In order to avoid excessive locking on the endpoint object itself, the
mutable state is not accessible via getters. Instead, you can create a
snapshot using ast_endpoint_snapshot_create() to get a consistent
snapshot of the internal state.

This patch also includes a set of topics and messages associated with
endpoints, and implementations of the endpoint-related RESTful
API. chan_sip was updated to create endpoints with SIP peers, but the
state of the endpoints is not updated with the state of the peer.

Along for the ride in this patch is a Stasis test API. This is a
stasis_message_sink object, which can be subscribed to a Stasis
topic. It has functions for blocking while waiting for conditions in
the message sink to be fulfilled.

(closes issue ASTERISK-21421)
Review: https://reviewboard.asterisk.org/r/2492/


Added:
    trunk/include/asterisk/endpoints.h
      - copied unchanged from r387931, team/dlee/endpoints/include/asterisk/endpoints.h
    trunk/include/asterisk/stasis_endpoints.h
      - copied unchanged from r387931, team/dlee/endpoints/include/asterisk/stasis_endpoints.h
    trunk/include/asterisk/stasis_test.h
      - copied unchanged from r387931, team/dlee/endpoints/include/asterisk/stasis_test.h
    trunk/main/endpoints.c
      - copied unchanged from r387931, team/dlee/endpoints/main/endpoints.c
    trunk/main/stasis_endpoints.c
      - copied unchanged from r387931, team/dlee/endpoints/main/stasis_endpoints.c
    trunk/res/res_stasis_test.c
      - copied unchanged from r387931, team/dlee/endpoints/res/res_stasis_test.c
    trunk/res/res_stasis_test.exports.in
      - copied unchanged from r387931, team/dlee/endpoints/res/res_stasis_test.exports.in
    trunk/tests/test_endpoints.c
      - copied unchanged from r387931, team/dlee/endpoints/tests/test_endpoints.c
    trunk/tests/test_stasis_endpoints.c
      - copied unchanged from r387931, team/dlee/endpoints/tests/test_stasis_endpoints.c
Modified:
    trunk/channels/chan_sip.c
    trunk/channels/sip/include/sip.h
    trunk/include/asterisk/astobj2.h
    trunk/include/asterisk/stasis.h
    trunk/main/asterisk.c
    trunk/main/astobj2.c
    trunk/main/channel_internal_api.c
    trunk/main/stasis_cache.c
    trunk/res/res_stasis_http_endpoints.c
    trunk/res/stasis_http/resource_endpoints.c
    trunk/res/stasis_http/resource_endpoints.h
    trunk/rest-api/api-docs/endpoints.json

Modified: trunk/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/chan_sip.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed May  8 08:39:08 2013
@@ -295,6 +295,7 @@
 #include "sip/include/security_events.h"
 #include "asterisk/sip_api.h"
 #include "asterisk/app.h"
+#include "asterisk/stasis_endpoints.h"
 
 /*** DOCUMENTATION
 	<application name="SIPDtmfMode" language="en_US">
@@ -5326,6 +5327,9 @@
 	peer->caps = ast_format_cap_destroy(peer->caps);
 
 	ast_rtp_dtls_cfg_free(&peer->dtls_cfg);
+
+	ast_endpoint_shutdown(peer->endpoint);
+	peer->endpoint = NULL;
 }
 
 /*! \brief Update peer data in database (if used) */
@@ -8012,6 +8016,14 @@
 		return NULL;
 	}
 
+	if (i->relatedpeer) {
+		if (ast_endpoint_add_channel(i->relatedpeer->endpoint, tmp)) {
+			ast_channel_unref(tmp);
+			sip_pvt_lock(i);
+			return NULL;
+		}
+	}
+
 	/* If we sent in a callid, bind it to the channel. */
 	if (callid) {
 		ast_channel_callid_set(tmp, callid);
@@ -30768,6 +30780,9 @@
 			firstpass = 0;
 	} else {
 		if (!(peer = ao2_t_alloc(sizeof(*peer), sip_destroy_peer_fn, "allocate a peer struct"))) {
+			return NULL;
+		}
+		if (!(peer->endpoint = ast_endpoint_create("SIP", name))) {
 			return NULL;
 		}
 		if (!(peer->caps = ast_format_cap_alloc_nolock())) {

Modified: trunk/channels/sip/include/sip.h
URL: http://svnview.digium.com/svn/asterisk/trunk/channels/sip/include/sip.h?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/channels/sip/include/sip.h (original)
+++ trunk/channels/sip/include/sip.h Wed May  8 08:39:08 2013
@@ -1377,6 +1377,8 @@
 	unsigned int disallowed_methods;
 	struct ast_cc_config_params *cc_params;
 
+	struct ast_endpoint *endpoint;
+
 	struct ast_rtp_dtls_cfg dtls_cfg;
 };
 

Modified: trunk/include/asterisk/astobj2.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/astobj2.h?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/include/asterisk/astobj2.h (original)
+++ trunk/include/asterisk/astobj2.h Wed May  8 08:39:08 2013
@@ -1890,4 +1890,55 @@
 #define ao2_cleanup(obj) __ao2_cleanup(obj)
 #endif
 void ao2_iterator_cleanup(struct ao2_iterator *iter);
+
+
+/* XXX TODO BUGBUG and all the other things...
+ * These functions should eventually be moved elsewhere, but the utils folder
+ * won't compile with them in strings.h
+ */
+
+/*!
+ * \since 12
+ * \brief Allocates a hash container for bare strings
+ *
+ * \param buckets The number of buckets to use for the hash container
+ *
+ * \retval AO2 container for strings
+ * \retval NULL if allocation failed
+ */
+#define ast_str_container_alloc(buckets) ast_str_container_alloc_options(AO2_ALLOC_OPT_LOCK_MUTEX, buckets)
+
+/*!
+ * \since 12
+ * \brief Allocates a hash container for bare strings
+ *
+ * \param opts Options to be provided to the container
+ * \param buckets The number of buckets to use for the hash container
+ *
+ * \retval AO2 container for strings
+ * \retval NULL if allocation failed
+ */
+struct ao2_container *ast_str_container_alloc_options(enum ao2_container_opts opts, int buckets);
+
+/*!
+ * \since 12
+ * \brief Adds a string to a string container allocated by ast_str_container_alloc
+ *
+ * \param str_container The container to which to add a string
+ * \param add The string to add to the container
+ *
+ * \retval zero on success
+ * \retval non-zero if the operation failed
+ */
+int ast_str_container_add(struct ao2_container *str_container, const char *add);
+
+/*!
+ * \since 12
+ * \brief Removes a string from a string container allocated by ast_str_container_alloc
+ *
+ * \param str_container The container from which to remove a string
+ * \param remove The string to remove from the container
+ */
+void ast_str_container_remove(struct ao2_container *str_container, const char *remove);
+
 #endif /* _ASTERISK_ASTOBJ2_H */

Modified: trunk/include/asterisk/stasis.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/stasis.h?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/include/asterisk/stasis.h (original)
+++ trunk/include/asterisk/stasis.h Wed May  8 08:39:08 2013
@@ -431,6 +431,22 @@
 };
 
 /*!
+ * \brief Cache clear message.
+ */
+struct stasis_cache_clear {
+	/*! Type of object being cleared from the cache */
+	struct stasis_message_type *type;
+	/*! Id of the object being cleared from the cache */
+	char id[];
+};
+
+/*!
+ * \brief Message type for \ref stasis_cache_clear.
+ * \since 12
+ */
+struct stasis_message_type *stasis_cache_clear_type(void);
+
+/*!
  * \brief A message which instructs the caching topic to remove an entry from its cache.
  * \param type Message type.
  * \param id Unique id of the snapshot to clear.

Modified: trunk/main/asterisk.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/asterisk.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/main/asterisk.c (original)
+++ trunk/main/asterisk.c Wed May  8 08:39:08 2013
@@ -242,6 +242,7 @@
 #include "asterisk/sorcery.h"
 #include "asterisk/stasis.h"
 #include "asterisk/json.h"
+#include "asterisk/stasis_endpoints.h"
 
 #include "../defaults.h"
 
@@ -4174,6 +4175,11 @@
 		exit(1);
 	}
 
+	if (ast_endpoint_stasis_init()) {
+		printf("Endpoint initialization failed.\n%s", term_quit());
+		exit(1);
+	}
+
 	ast_makesocket();
 	sigemptyset(&sigs);
 	sigaddset(&sigs, SIGHUP);

Modified: trunk/main/astobj2.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/astobj2.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/main/astobj2.c (original)
+++ trunk/main/astobj2.c Wed May  8 08:39:08 2013
@@ -5780,3 +5780,41 @@
 
 	return 0;
 }
+
+/* XXX TODO BUGBUG and all the other things...
+ * These functions should eventually be moved elsewhere, but the utils folder
+ * won't compile with them in strings.h
+ */
+static int str_hash(const void *obj, const int flags)
+{
+	return ast_str_hash(obj);
+}
+
+static int str_cmp(void *lhs, void *rhs, int flags)
+{
+	return strcmp(lhs, rhs) ? 0 : CMP_MATCH;
+}
+
+struct ao2_container *ast_str_container_alloc_options(enum ao2_container_opts opts, int buckets)
+{
+	return ao2_container_alloc_options(opts, buckets, str_hash, str_cmp);
+}
+
+int ast_str_container_add(struct ao2_container *str_container, const char *add)
+{
+	RAII_VAR(char *, ao2_add, ao2_alloc(strlen(add) + 1, NULL), ao2_cleanup);
+
+	if (!ao2_add) {
+		return -1;
+	}
+
+	/* safe strcpy */
+	strcpy(ao2_add, add);
+	ao2_link(str_container, ao2_add);
+	return 0;
+}
+
+void ast_str_container_remove(struct ao2_container *str_container, const char *remove)
+{
+	ao2_find(str_container, remove, OBJ_KEY | OBJ_NODATA | OBJ_UNLINK);
+}

Modified: trunk/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/channel_internal_api.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/main/channel_internal_api.c (original)
+++ trunk/main/channel_internal_api.c Wed May  8 08:39:08 2013
@@ -39,11 +39,13 @@
 #include <fcntl.h>
 
 #include "asterisk/channel.h"
-#include "asterisk/stringfields.h"
+#include "asterisk/channel_internal.h"
 #include "asterisk/data.h"
+#include "asterisk/endpoints.h"
 #include "asterisk/indications.h"
 #include "asterisk/stasis_channels.h"
-#include "asterisk/channel_internal.h"
+#include "asterisk/stasis_endpoints.h"
+#include "asterisk/stringfields.h"
 #include "asterisk/test.h"
 
 /*!
@@ -198,6 +200,7 @@
 	struct timeval sending_dtmf_tv;		/*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
 	struct stasis_topic *topic;			/*!< Topic for all channel's events */
 	struct stasis_subscription *forwarder;		/*!< Subscription for event forwarding to all topic */
+	struct stasis_subscription *endpoint_forward;	/*!< Subscription for event forwarding to endpoint's topic */
 };
 
 /* AST_DATA definitions, which will probably have to be re-thought since the channel will be opaque */
@@ -1369,6 +1372,7 @@
 	ast_string_field_free_memory(chan);
 
 	chan->forwarder = stasis_unsubscribe(chan->forwarder);
+	chan->endpoint_forward = stasis_unsubscribe(chan->endpoint_forward);
 
 	ao2_cleanup(chan->topic);
 	chan->topic = NULL;
@@ -1387,6 +1391,37 @@
 struct stasis_topic *ast_channel_topic(struct ast_channel *chan)
 {
 	return chan ? chan->topic : ast_channel_topic_all();
+}
+
+int ast_endpoint_add_channel(struct ast_endpoint *endpoint,
+	struct ast_channel *chan)
+{
+	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+
+	ast_assert(chan != NULL);
+	ast_assert(endpoint != NULL);
+
+	snapshot = ast_channel_snapshot_create(chan);
+	if (!snapshot) {
+		return -1;
+	}
+
+	msg = stasis_message_create(ast_channel_snapshot_type(), snapshot);
+	if (!msg) {
+		return -1;
+	}
+
+	chan->endpoint_forward =
+		stasis_forward_all(chan->topic, ast_endpoint_topic(endpoint));
+
+	if (chan->endpoint_forward == NULL) {
+		return -1;
+	}
+
+	stasis_publish(ast_endpoint_topic(endpoint), msg);
+
+	return 0;
 }
 
 void ast_channel_internal_setup_topics(struct ast_channel *chan)

Modified: trunk/main/stasis_cache.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/stasis_cache.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/main/stasis_cache.c (original)
+++ trunk/main/stasis_cache.c Wed May  8 08:39:08 2013
@@ -240,54 +240,45 @@
 	return cache_dump.cached;
 }
 
-static struct stasis_message_type *__cache_clear_data;
-
-static struct stasis_message_type *cache_clear_data(void)
-{
-	ast_assert(__cache_clear_data != NULL);
-	return __cache_clear_data;
-}
-
-static struct stasis_message_type *__cache_update;
+static struct stasis_message_type *cache_clear_type;
+
+struct stasis_message_type *stasis_cache_clear_type(void)
+{
+	ast_assert(cache_clear_type != NULL);
+	return cache_clear_type;
+}
+
+static struct stasis_message_type *cache_update_type;
 
 struct stasis_message_type *stasis_cache_update_type(void)
 {
-	ast_assert(__cache_update != NULL);
-	return __cache_update;
-}
-
-struct cache_clear_data {
-	struct stasis_message_type *type;
-	char *id;
-};
-
-static void cache_clear_data_dtor(void *obj)
-{
-	struct cache_clear_data *ev = obj;
-	ast_free(ev->id);
-	ev->id = NULL;
+	ast_assert(cache_update_type != NULL);
+	return cache_update_type;
+}
+
+static void cache_clear_dtor(void *obj)
+{
+	struct stasis_cache_clear *ev = obj;
 	ao2_cleanup(ev->type);
 	ev->type = NULL;
 }
 
 struct stasis_message *stasis_cache_clear_create(struct stasis_message_type *type, const char *id)
 {
-	RAII_VAR(struct cache_clear_data *, ev, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_cache_clear *, ev, NULL, ao2_cleanup);
 	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
 
-	ev = ao2_alloc(sizeof(*ev), cache_clear_data_dtor);
+	ev = ao2_alloc(sizeof(*ev) + strlen(id) + 1, cache_clear_dtor);
 	if (!ev) {
 		return NULL;
 	}
 
-	ev->id = ast_strdup(id);
-	if (!ev->id) {
-		return NULL;
-	}
+	/* strcpy safe */
+	strcpy(ev->id, id);
 	ao2_ref(type, +1);
 	ev->type = type;
 
-	msg = stasis_message_create(cache_clear_data(), ev);
+	msg = stasis_message_create(stasis_cache_clear_type(), ev);
 
 	if (!msg) {
 		return NULL;
@@ -363,10 +354,10 @@
 	}
 
 	/* Handle cache clear event */
-	if (cache_clear_data() == stasis_message_type(message)) {
+	if (stasis_cache_clear_type() == stasis_message_type(message)) {
 		RAII_VAR(struct stasis_message *, old_snapshot, NULL, ao2_cleanup);
 		RAII_VAR(struct stasis_message *, update, NULL, ao2_cleanup);
-		struct cache_clear_data *clear = stasis_message_data(message);
+		struct stasis_cache_clear *clear = stasis_message_data(message);
 		ast_assert(clear->type != NULL);
 		ast_assert(clear->id != NULL);
 		old_snapshot = cache_put(caching_topic, clear->type, clear->id, NULL);
@@ -374,7 +365,9 @@
 			update = update_create(topic, old_snapshot, NULL);
 			stasis_publish(caching_topic->topic, update);
 		} else {
-			ast_log(LOG_ERROR,
+			/* While this could be a problem, it's very likely to
+			 * happen with message forwarding */
+			ast_debug(1,
 				"Attempting to remove an item from the cache that isn't there: %s %s\n",
 				stasis_message_type_name(clear->type), clear->id);
 		}
@@ -449,28 +442,28 @@
 
 static void stasis_cache_exit(void)
 {
-	ao2_cleanup(__cache_clear_data);
-	__cache_clear_data = NULL;
-	ao2_cleanup(__cache_update);
-	__cache_update = NULL;
+	ao2_cleanup(cache_clear_type);
+	cache_clear_type = NULL;
+	ao2_cleanup(cache_update_type);
+	cache_update_type = NULL;
 }
 
 int stasis_cache_init(void)
 {
 	ast_register_atexit(stasis_cache_exit);
 
-	if (__cache_clear_data || __cache_update) {
+	if (cache_clear_type || cache_update_type) {
 		ast_log(LOG_ERROR, "Stasis cache double initialized\n");
 		return -1;
 	}
 
-	__cache_update = stasis_message_type_create("stasis_cache_update");
-	if (!__cache_update) {
+	cache_update_type = stasis_message_type_create("stasis_cache_update");
+	if (!cache_update_type) {
 		return -1;
 	}
 
-	__cache_clear_data = stasis_message_type_create("StasisCacheClear");
-	if (!__cache_clear_data) {
+	cache_clear_type = stasis_message_type_create("StasisCacheClear");
+	if (!cache_clear_type) {
 		return -1;
 	}
 	return 0;

Modified: trunk/res/res_stasis_http_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_stasis_http_endpoints.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/res/res_stasis_http_endpoints.c (original)
+++ trunk/res/res_stasis_http_endpoints.c Wed May  8 08:39:08 2013
@@ -55,18 +55,32 @@
     struct ast_variable *headers, struct stasis_http_response *response)
 {
 	struct ast_get_endpoints_args args = {};
+	stasis_http_get_endpoints(headers, &args, response);
+}
+/*!
+ * \brief Parameter parsing callback for /endpoints/{tech}.
+ * \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 stasis_http_get_endpoints_by_tech_cb(
+    struct ast_variable *get_params, struct ast_variable *path_vars,
+    struct ast_variable *headers, struct stasis_http_response *response)
+{
+	struct ast_get_endpoints_by_tech_args args = {};
 	struct ast_variable *i;
 
-	for (i = get_params; i; i = i->next) {
-		if (strcmp(i->name, "withType") == 0) {
-			args.with_type = (i->value);
+	for (i = path_vars; i; i = i->next) {
+		if (strcmp(i->name, "tech") == 0) {
+			args.tech = (i->value);
 		} else
 		{}
 	}
-	stasis_http_get_endpoints(headers, &args, response);
+	stasis_http_get_endpoints_by_tech(headers, &args, response);
 }
 /*!
- * \brief Parameter parsing callback for /endpoints/{endpointId}.
+ * \brief Parameter parsing callback for /endpoints/{tech}/{resource}.
  * \param get_params GET parameters in the HTTP request.
  * \param path_vars Path variables extracted from the request.
  * \param headers HTTP headers.
@@ -80,8 +94,11 @@
 	struct ast_variable *i;
 
 	for (i = path_vars; i; i = i->next) {
-		if (strcmp(i->name, "endpointId") == 0) {
-			args.endpoint_id = (i->value);
+		if (strcmp(i->name, "tech") == 0) {
+			args.tech = (i->value);
+		} else
+		if (strcmp(i->name, "resource") == 0) {
+			args.resource = (i->value);
 		} else
 		{}
 	}
@@ -89,8 +106,8 @@
 }
 
 /*! \brief REST handler for /api-docs/endpoints.{format} */
-static struct stasis_rest_handlers endpoints_endpointId = {
-	.path_segment = "endpointId",
+static struct stasis_rest_handlers endpoints_tech_resource = {
+	.path_segment = "resource",
 	.is_wildcard = 1,
 	.callbacks = {
 		[AST_HTTP_GET] = stasis_http_get_endpoint_cb,
@@ -99,13 +116,23 @@
 	.children = {  }
 };
 /*! \brief REST handler for /api-docs/endpoints.{format} */
+static struct stasis_rest_handlers endpoints_tech = {
+	.path_segment = "tech",
+	.is_wildcard = 1,
+	.callbacks = {
+		[AST_HTTP_GET] = stasis_http_get_endpoints_by_tech_cb,
+	},
+	.num_children = 1,
+	.children = { &endpoints_tech_resource, }
+};
+/*! \brief REST handler for /api-docs/endpoints.{format} */
 static struct stasis_rest_handlers endpoints = {
 	.path_segment = "endpoints",
 	.callbacks = {
 		[AST_HTTP_GET] = stasis_http_get_endpoints_cb,
 	},
 	.num_children = 1,
-	.children = { &endpoints_endpointId, }
+	.children = { &endpoints_tech, }
 };
 
 static int load_module(void)

Modified: trunk/res/stasis_http/resource_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_http/resource_endpoints.c?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/res/stasis_http/resource_endpoints.c (original)
+++ trunk/res/stasis_http/resource_endpoints.c Wed May  8 08:39:08 2013
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 2012 - 2013, Digium, Inc.
@@ -18,14 +18,10 @@
 
 /*! \file
  *
- * \brief Implementation for stasis-http stubs.
+ * \brief /api-docs/endpoints.{format} implementation- Endpoint resources
  *
  * \author David M. Lee, II <dlee at digium.com>
  */
-
-/*** MODULEINFO
-	<support_level>core</support_level>
- ***/
 
 #include "asterisk.h"
 
@@ -33,11 +29,129 @@
 
 #include "resource_endpoints.h"
 
-void stasis_http_get_endpoint(struct ast_variable *headers, struct ast_get_endpoint_args *args, struct stasis_http_response *response)
+#include "asterisk/astobj2.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_endpoints.h"
+
+void stasis_http_get_endpoints(struct ast_variable *headers,
+	struct ast_get_endpoints_args *args,
+	struct stasis_http_response *response)
 {
-	ast_log(LOG_ERROR, "TODO: stasis_http_get_endpoint\n");
+	RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
+	RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	struct ao2_iterator i;
+	void *obj;
+
+	caching_topic = ast_endpoint_topic_all_cached();
+	if (!caching_topic) {
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Message bus not initialized");
+		return;
+	}
+	ao2_ref(caching_topic, +1);
+
+	snapshots = stasis_cache_dump(caching_topic, ast_endpoint_snapshot_type());
+	if (!snapshots) {
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	json = ast_json_array_create();
+	if (!json) {
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	i = ao2_iterator_init(snapshots, 0);
+	while ((obj = ao2_iterator_next(&i))) {
+		RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
+		struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
+		int r = ast_json_array_append(
+			json, ast_endpoint_snapshot_to_json(snapshot));
+		if (r != 0) {
+			stasis_http_response_alloc_failed(response);
+			return;
+		}
+	}
+	ao2_iterator_destroy(&i);
+
+	stasis_http_response_ok(response, ast_json_ref(json));
 }
-void stasis_http_get_endpoints(struct ast_variable *headers, struct ast_get_endpoints_args *args, struct stasis_http_response *response)
+void stasis_http_get_endpoints_by_tech(struct ast_variable *headers,
+	struct ast_get_endpoints_by_tech_args *args,
+	struct stasis_http_response *response)
 {
-	ast_log(LOG_ERROR, "TODO: stasis_http_get_endpoints\n");
+	RAII_VAR(struct stasis_caching_topic *, caching_topic, NULL, ao2_cleanup);
+	RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	struct ao2_iterator i;
+	void *obj;
+
+	/* TODO - if tech isn't a recognized type of endpoint, it should 404 */
+
+	caching_topic = ast_endpoint_topic_all_cached();
+	if (!caching_topic) {
+		stasis_http_response_error(
+			response, 500, "Internal Server Error",
+			"Message bus not initialized");
+		return;
+	}
+	ao2_ref(caching_topic, +1);
+
+	snapshots = stasis_cache_dump(caching_topic, ast_endpoint_snapshot_type());
+	if (!snapshots) {
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	json = ast_json_array_create();
+	if (!json) {
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	i = ao2_iterator_init(snapshots, 0);
+	while ((obj = ao2_iterator_next(&i))) {
+		RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
+		struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
+		int r;
+
+		if (strcmp(args->tech, snapshot->tech) != 0) {
+			continue;
+		}
+
+		r = ast_json_array_append(
+			json, ast_endpoint_snapshot_to_json(snapshot));
+		if (r != 0) {
+			stasis_http_response_alloc_failed(response);
+			return;
+		}
+	}
+	ao2_iterator_destroy(&i);
+
+	stasis_http_response_ok(response, ast_json_ref(json));
 }
+void stasis_http_get_endpoint(struct ast_variable *headers,
+	struct ast_get_endpoint_args *args,
+	struct stasis_http_response *response)
+{
+	RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+	RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
+
+	snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource);
+	if (!snapshot) {
+		stasis_http_response_error(response, 404, "Not Found",
+			"Endpoint not found");
+		return;
+	}
+
+	json = ast_endpoint_snapshot_to_json(snapshot);
+	if (!json) {
+		stasis_http_response_alloc_failed(response);
+		return;
+	}
+
+	stasis_http_response_ok(response, ast_json_ref(json));
+}

Modified: trunk/res/stasis_http/resource_endpoints.h
URL: http://svnview.digium.com/svn/asterisk/trunk/res/stasis_http/resource_endpoints.h?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/res/stasis_http/resource_endpoints.h (original)
+++ trunk/res/stasis_http/resource_endpoints.h Wed May  8 08:39:08 2013
@@ -41,21 +41,34 @@
 
 /*! \brief Argument struct for stasis_http_get_endpoints() */
 struct ast_get_endpoints_args {
-	/*! \brief Filter endpoints by type (sip,iax2,dhadi,...) */
-	const char *with_type;
 };
 /*!
- * \brief List available endoints.
+ * \brief List all endoints.
  *
  * \param headers HTTP headers
  * \param args Swagger parameters
  * \param[out] response HTTP response
  */
 void stasis_http_get_endpoints(struct ast_variable *headers, struct ast_get_endpoints_args *args, struct stasis_http_response *response);
+/*! \brief Argument struct for stasis_http_get_endpoints_by_tech() */
+struct ast_get_endpoints_by_tech_args {
+	/*! \brief Technology of the endpoints (sip,iax2,...) */
+	const char *tech;
+};
+/*!
+ * \brief List available endoints for a given endpoint technology.
+ *
+ * \param headers HTTP headers
+ * \param args Swagger parameters
+ * \param[out] response HTTP response
+ */
+void stasis_http_get_endpoints_by_tech(struct ast_variable *headers, struct ast_get_endpoints_by_tech_args *args, struct stasis_http_response *response);
 /*! \brief Argument struct for stasis_http_get_endpoint() */
 struct ast_get_endpoint_args {
+	/*! \brief Technology of the endpoint */
+	const char *tech;
 	/*! \brief ID of the endpoint */
-	const char *endpoint_id;
+	const char *resource;
 };
 /*!
  * \brief Details for an endpoint.

Modified: trunk/rest-api/api-docs/endpoints.json
URL: http://svnview.digium.com/svn/asterisk/trunk/rest-api/api-docs/endpoints.json?view=diff&rev=387932&r1=387931&r2=387932
==============================================================================
--- trunk/rest-api/api-docs/endpoints.json (original)
+++ trunk/rest-api/api-docs/endpoints.json Wed May  8 08:39:08 2013
@@ -13,16 +13,26 @@
 			"operations": [
 				{
 					"httpMethod": "GET",
-					"summary": "List available endoints.",
+					"summary": "List all endoints.",
 					"nickname": "getEndpoints",
+					"responseClass": "List[Endpoint]"
+				}
+			]
+		},
+		{
+			"path": "/endpoints/{tech}",
+			"description": "Asterisk endpoints",
+			"operations": [
+				{
+					"httpMethod": "GET",
+					"summary": "List available endoints for a given endpoint technology.",
+					"nickname": "getEndpointsByTech",
 					"responseClass": "List[Endpoint]",
 					"parameters": [
 						{
-							"name": "withType",
-							"description": "Filter endpoints by type (sip,iax2,dhadi,...)",
-							"paramType": "query",
-							"required": false,
-							"allowMultiple": true,
+							"name": "tech",
+							"description": "Technology of the endpoints (sip,iax2,...)",
+							"paramType": "path",
 							"dataType": "string"
 						}
 					]
@@ -30,7 +40,7 @@
 			]
 		},
 		{
-			"path": "/endpoints/{endpointId}",
+			"path": "/endpoints/{tech}/{resource}",
 			"description": "Single endpoint",
 			"operations": [
 				{
@@ -40,7 +50,13 @@
 					"responseClass": "Endpoint",
 					"parameters": [
 						{
-							"name": "endpointId",
+							"name": "tech",
+							"description": "Technology of the endpoint",
+							"paramType": "path",
+							"dataType": "string"
+						},
+						{
+							"name": "resource",
 							"description": "ID of the endpoint",
 							"paramType": "path",
 							"dataType": "string"
@@ -53,13 +69,16 @@
 	"models": {
 		"Endpoint": {
 			"id": "Endpoint",
+			"description": "A snapshot of an endpoint. Unlike most resources, which have a single unique identifier, an endpoint is uniquely identified by the technology/resource pair.",
 			"properties": {
 				"technology": {
 					"type": "string",
+					"description": "Technology of the endpoint",
 					"required": true
 				},
-				"name": {
+				"resource": {
 					"type": "string",
+					"description": "Identifier of the endpoint, specific to the given technology.",
 					"required": true
 				}
 			}




More information about the asterisk-commits mailing list