summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMatthew Jordan <mjordan@digium.com>2013-10-04 16:01:48 +0000
committerMatthew Jordan <mjordan@digium.com>2013-10-04 16:01:48 +0000
commit8d7873b836999b09caad87abec27579f1f065b84 (patch)
treecdf683ab18142553b42102de6c5ca52fc71b22a2 /main
parentb52c972b172087d27178c0e60127d486d4e500f8 (diff)
ARI: Add subscription support
This patch adds an /applications API to ARI, allowing explicit management of Stasis applications. * GET /applications - list current applications * GET /applications/{applicationName} - get details of a specific application * POST /applications/{applicationName}/subscription - explicitly subscribe to a channel, bridge or endpoint * DELETE /applications/{applicationName}/subscription - explicitly unsubscribe from a channel, bridge or endpoint Subscriptions work by a reference counting mechanism: if you subscript to an event source X number of times, you must unsubscribe X number of times to stop receiveing events for that event source. Review: https://reviewboard.asterisk.org/r/2862 (issue ASTERISK-22451) Reported by: Matt Jordan ........ Merged revisions 400522 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400523 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r--main/asterisk.c6
-rw-r--r--main/endpoints.c110
-rw-r--r--main/json.c8
3 files changed, 116 insertions, 8 deletions
diff --git a/main/asterisk.c b/main/asterisk.c
index 7e581513c..95355e42f 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -247,6 +247,7 @@ int daemon(int, int); /* defined in libresolv of all places */
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_system.h"
#include "asterisk/security_events.h"
+#include "asterisk/endpoints.h"
#include "../defaults.h"
@@ -4340,6 +4341,11 @@ int main(int argc, char *argv[])
ast_channels_init();
+ if (ast_endpoint_init()) {
+ printf ("%s", term_quit());
+ exit(1);
+ }
+
if ((moduleresult = load_modules(1))) { /* Load modules, pre-load only */
printf("%s", term_quit());
exit(moduleresult == -2 ? 2 : 1);
diff --git a/main/endpoints.c b/main/endpoints.c
index bdcf401ba..9eeadfeef 100644
--- a/main/endpoints.c
+++ b/main/endpoints.c
@@ -38,10 +38,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_endpoints.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/stringfields.h"
+#include "asterisk/_private.h"
/*! Buckets for endpoint->channel mappings. Keep it prime! */
+#define ENDPOINT_CHANNEL_BUCKETS 127
+
+/*! Buckets for endpoint hash. Keep it prime! */
#define ENDPOINT_BUCKETS 127
+static struct ao2_container *endpoints;
+
struct ast_endpoint {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(tech); /*!< Technology (SIP, IAX2, etc.). */
@@ -65,6 +71,59 @@ struct ast_endpoint {
struct ao2_container *channel_ids;
};
+static int endpoint_hash(const void *obj, int flags)
+{
+ const struct ast_endpoint *endpoint;
+ const char *key;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_KEY:
+ key = obj;
+ return ast_str_hash(key);
+ case OBJ_SEARCH_OBJECT:
+ endpoint = obj;
+ return ast_str_hash(endpoint->id);
+ default:
+ /* Hash can only work on something with a full key. */
+ ast_assert(0);
+ return 0;
+ }
+}
+
+static int endpoint_cmp(void *obj, void *arg, int flags)
+{
+ const struct ast_endpoint *left = obj;
+ const struct ast_endpoint *right = arg;
+ const char *right_key = arg;
+ int cmp;
+
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right->id;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left->id, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left->id, right_key, strlen(right_key));
+ break;
+ default:
+ ast_assert(0);
+ cmp = 0;
+ break;
+ }
+ if (cmp) {
+ return 0;
+ }
+
+ return CMP_MATCH;
+}
+
+struct ast_endpoint *ast_endpoint_find_by_id(const char *id)
+{
+ return ao2_find(endpoints, id, OBJ_KEY);
+}
+
struct stasis_topic *ast_endpoint_topic(struct ast_endpoint *endpoint)
{
if (!endpoint) {
@@ -218,7 +277,7 @@ struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource)
/* All access to channel_ids should be covered by the endpoint's
* lock; no extra lock needed. */
endpoint->channel_ids = ast_str_container_alloc_options(
- AO2_ALLOC_OPT_LOCK_NOLOCK, ENDPOINT_BUCKETS);
+ AO2_ALLOC_OPT_LOCK_NOLOCK, ENDPOINT_CHANNEL_BUCKETS);
if (!endpoint->channel_ids) {
return NULL;
}
@@ -241,16 +300,12 @@ struct ast_endpoint *ast_endpoint_create(const char *tech, const char *resource)
endpoint_publish_snapshot(endpoint);
+ ao2_link(endpoints, endpoint);
+
ao2_ref(endpoint, +1);
return endpoint;
}
-const char *ast_endpoint_get_tech(const struct ast_endpoint *endpoint)
-{
- ast_assert(endpoint != NULL);
- return endpoint->tech;
-}
-
static struct stasis_message *create_endpoint_snapshot_message(struct ast_endpoint *endpoint)
{
RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
@@ -270,6 +325,8 @@ void ast_endpoint_shutdown(struct ast_endpoint *endpoint)
return;
}
+ ao2_unlink(endpoints, endpoint);
+
clear_msg = create_endpoint_snapshot_message(endpoint);
if (clear_msg) {
RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
@@ -284,11 +341,30 @@ void ast_endpoint_shutdown(struct ast_endpoint *endpoint)
stasis_message_router_unsubscribe(endpoint->router);
}
+const char *ast_endpoint_get_tech(const struct ast_endpoint *endpoint)
+{
+ if (!endpoint) {
+ return NULL;
+ }
+ return endpoint->tech;
+}
+
const char *ast_endpoint_get_resource(const struct ast_endpoint *endpoint)
{
+ if (!endpoint) {
+ return NULL;
+ }
return endpoint->resource;
}
+const char *ast_endpoint_get_id(const struct ast_endpoint *endpoint)
+{
+ if (!endpoint) {
+ return NULL;
+ }
+ return endpoint->id;
+}
+
void ast_endpoint_set_state(struct ast_endpoint *endpoint,
enum ast_endpoint_state state)
{
@@ -354,3 +430,23 @@ struct ast_endpoint_snapshot *ast_endpoint_snapshot_create(
ao2_ref(snapshot, +1);
return snapshot;
}
+
+static void endpoint_cleanup(void)
+{
+ ao2_cleanup(endpoints);
+ endpoints = NULL;
+}
+
+int ast_endpoint_init(void)
+{
+ ast_register_cleanup(endpoint_cleanup);
+
+ endpoints = ao2_container_alloc(ENDPOINT_BUCKETS, endpoint_hash,
+ endpoint_cmp);
+
+ if (!endpoints) {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/main/json.c b/main/json.c
index e3ef3d001..ce4c6cfc9 100644
--- a/main/json.c
+++ b/main/json.c
@@ -686,9 +686,15 @@ struct ast_json *ast_json_pack(char const *format, ...)
}
struct ast_json *ast_json_vpack(char const *format, va_list ap)
{
+ json_error_t error;
struct ast_json *r = NULL;
if (format) {
- r = (struct ast_json *)json_vpack_ex(NULL, 0, format, ap);
+ r = (struct ast_json *)json_vpack_ex(&error, 0, format, ap);
+ if (!r) {
+ ast_log(LOG_ERROR,
+ "Error building JSON from '%s': %s.\n",
+ format, error.text);
+ }
}
return r;
}