Add channel events for res_stasis apps

This change adds a framework in res_stasis for handling events from
channel topics. JSON event generation and validation code is created
from event documentation in rest-api/api-docs/events.json to assist in
JSON event generation, ensure consistency, and ensure that accurate
documentation is available for ALL events that are received by
res_stasis applications.

The userevent application has been refactored along with the code that
handles userevent channel blob events to pass the headers as key/value
pairs in the JSON blob. As a side-effect, app_userevent now handles
duplicate keys by overwriting the previous value.

Review: https://reviewboard.asterisk.org/r/2428/
(closes issue ASTERISK-21180)
Patch-By: Kinsey Moore <kmoore@digium.com>


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@388275 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Kinsey Moore
2013-05-10 13:13:06 +00:00
parent 2cfedc12ad
commit 7ce05bfb9b
18 changed files with 1593 additions and 292 deletions

View File

@@ -52,10 +52,6 @@ static struct ast_json *oom_json;
*/
#define APPS_NUM_BUCKETS 7
struct websocket_app {
char *name;
};
/*!
* \internal
* \brief Helper to write a JSON object to a WebSocket.
@@ -78,35 +74,6 @@ static int websocket_write_json(struct ast_websocket *session,
strlen(str));
}
/*! Hash function for websocket_app */
static int hash_app(const void *obj, const int flags)
{
const struct websocket_app *app = obj;
const char *name = flags & OBJ_KEY ? obj : app->name;
return ast_str_hash(name);
}
/*! Comparison function for websocket_app */
static int compare_app(void *lhs, void *rhs, int flags)
{
const struct websocket_app *lhs_app = lhs;
const struct websocket_app *rhs_app = rhs;
const char *rhs_name = flags & OBJ_KEY ? rhs : rhs_app->name;
if (strcmp(lhs_app->name, rhs_name) == 0) {
return CMP_MATCH;
} else {
return 0;
}
}
static void app_dtor(void *obj)
{
struct websocket_app *app = obj;
ast_free(app->name);
}
struct stasis_ws_session_info {
struct ast_websocket *ws_session;
struct ao2_container *websocket_apps;
@@ -132,7 +99,7 @@ static struct stasis_ws_session_info *session_create(
session->ws_session = ws_session;
session->websocket_apps =
ao2_container_alloc(APPS_NUM_BUCKETS, hash_app, compare_app);
ast_str_container_alloc(APPS_NUM_BUCKETS);
if (!session->websocket_apps) {
return NULL;
@@ -154,12 +121,12 @@ static struct stasis_ws_session_info *session_create(
static void session_shutdown(struct stasis_ws_session_info *session)
{
struct ao2_iterator i;
struct websocket_app *app;
char *app;
SCOPED_AO2LOCK(lock, session);
i = ao2_iterator_init(session->websocket_apps, 0);
while ((app = ao2_iterator_next(&i))) {
stasis_app_unregister(app->name);
stasis_app_unregister(app);
ao2_cleanup(app);
}
ao2_iterator_destroy(&i);
@@ -212,15 +179,10 @@ static int session_register_apps(struct stasis_ws_session_info *session,
return -1;
}
while ((app_name = strsep(&apps, ","))) {
RAII_VAR(struct websocket_app *, app, NULL, ao2_cleanup);
app = ao2_alloc(sizeof(*app), app_dtor);
if (!app) {
if (ast_str_container_add(session->websocket_apps, app_name)) {
websocket_write_json(session->ws_session, oom_json);
return -1;
}
app->name = ast_strdup(app_name);
ao2_link(session->websocket_apps, app);
stasis_app_register(app_name, app_handler, session);
}