[svn-commits] dlee: branch dlee/stasis-app r384291 - /team/dlee/stasis-app/res/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Mar 28 13:20:34 CDT 2013
Author: dlee
Date: Thu Mar 28 13:20:31 2013
New Revision: 384291
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384291
Log:
Dramatically changed how app registration work.
Now, instead of sending commands down the websocket, connections specify
thier applications via get parameters. This means the WebSocket is now
strictly events only; there are no commands to confuse things any more.
Modified:
team/dlee/stasis-app/res/res_stasis_websocket.c
Modified: team/dlee/stasis-app/res/res_stasis_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-app/res/res_stasis_websocket.c?view=diff&rev=384291&r1=384290&r2=384291
==============================================================================
--- team/dlee/stasis-app/res/res_stasis_websocket.c (original)
+++ team/dlee/stasis-app/res/res_stasis_websocket.c Thu Mar 28 13:20:31 2013
@@ -44,6 +44,9 @@
/*! WebSocket protocol for Stasis */
static const char * const ws_protocol = "stasis";
+/*! Message to send when out of memory */
+static struct ast_json *oom_json;
+
/*! Number of buckets for the Stasis application hash table. Remember to keep it
* a prime number!
*/
@@ -52,40 +55,6 @@
struct websocket_app {
char *name;
};
-
-static struct ast_json *build_err(int id, const char *msg_format, ...)
- __attribute__((format(printf, 2, 3)));
-
-struct ast_json *build_err(int id, const char *msg_format, ...)
-{
- va_list args;
- struct ast_json *err;
-
- va_start(args, msg_format);
- err = ast_json_pack("{ s: { s: o }, s: i }",
- "error",
- "message", ast_json_vstringf(msg_format, args),
- "id", id);
- va_end(args);
-
- return err;
-}
-
-static struct ast_json *build_success(int id, const char *msg_format, ...)
- __attribute__((format(printf, 2, 3)));
-struct ast_json *build_success(int id, const char *msg_format, ...)
-{
- va_list args;
- struct ast_json *err;
-
- va_start(args, msg_format);
- err = ast_json_pack("{ s: o, s: i }",
- "success", ast_json_vstringf(msg_format, args),
- "id", id);
- va_end(args);
-
- return err;
-}
/*!
* \internal
@@ -156,74 +125,31 @@
websocket_write_json(session->ws_session, message);
}
-
-static struct ast_json *websocket_process_req(
- struct stasis_ws_session_info *session, struct ast_json *req)
-{
- const char *command =
- ast_json_string_get(ast_json_object_get(req, "command"));
- struct ast_json *id_json = ast_json_object_get(req, "id");
- intmax_t id;
-
- if (!id_json || ast_json_typeof(id_json) != AST_JSON_INTEGER) {
- return ast_json_pack("{ s: { s: s, s: o }}",
- "error",
- "message", "Integer id field required",
- "request", req);
- }
-
- id = ast_json_integer_get(id_json);
-
- if (ast_strlen_zero(command)) {
- return build_err(id, "Missing command string");
- }
-
- if (strcmp("ActivateApplication", command) == 0) {
- const char *app_name =
- ast_json_string_get(ast_json_object_get(req, "name"));
+static int register_apps(struct stasis_ws_session_info *session,
+ const char *app_list)
+{
+ RAII_VAR(char *, to_free, NULL, ast_free);
+ char *apps, *app_name;
+
+ to_free = apps = ast_strdup(app_list);
+ if (!apps) {
+ websocket_write_json(session->ws_session, oom_json);
+ return -1;
+ }
+ while ((app_name = strsep(&apps, ","))) {
RAII_VAR(struct websocket_app *, app, NULL, ao2_cleanup);
- if (ast_strlen_zero(app_name)) {
- return build_err(id, "Missing application name");
- }
-
- app = ao2_find(session->websocket_apps, app_name, OBJ_KEY);
- if (app) {
- return build_err(
- id, "Application '%s' already registered",
- app_name);
- }
app = ao2_alloc(sizeof(*app), app_dtor);
if (!app) {
- ast_log(LOG_ERROR, "Failed to construct websocket_app");
- return build_err(id, "Internal error");
+ 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);
-
- return build_success(id, "Application activated");
- } else if (strcmp("DeactivateApplication", command) == 0) {
- const char *app_name =
- ast_json_string_get(ast_json_object_get(req, "name"));
- RAII_VAR(struct websocket_app *, app, NULL, ao2_cleanup);
- if (ast_strlen_zero(app_name)) {
- return build_err(id, "Missing application name");
- }
- app = ao2_find(session->websocket_apps, app_name,
- OBJ_KEY | OBJ_UNLINK);
- if (app == NULL) {
- return build_err(id, "Application '%s' not activated",
- app_name);
- }
-
- stasis_app_unregister(app_name);
-
- return build_success(id, "Application deactivated");
- } else {
- return build_err(id, "Unrecognized command: %s", command);
- }
+ }
+ return 0;
}
static void websocket_callback(struct ast_websocket *session,
@@ -233,6 +159,7 @@
struct stasis_ws_session_info stasis_session = {};
struct ao2_iterator i;
struct websocket_app *app;
+ struct ast_variable *param;
int res;
ast_debug(3, "Stasis web socket connection\n");
@@ -246,6 +173,15 @@
stasis_session.websocket_apps =
ao2_container_alloc(APPS_NUM_BUCKETS, hash_app, compare_app);
stasis_session.ws_session = session;
+
+ for (param = parameters; param; param = param->next) {
+ if (strcmp(param->name, "app") == 0) {
+ int ret = register_apps(&stasis_session, param->value);
+ if (ret != 0) {
+ goto end;
+ }
+ }
+ }
while ((res = ast_wait_for_input(ast_websocket_fd(session), -1)) > 0) {
char *payload;
@@ -261,36 +197,7 @@
break;
}
- if (opcode == AST_WEBSOCKET_OPCODE_TEXT) {
- RAII_VAR(struct ast_json *, req, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, resp, NULL, ast_json_unref);
- struct ast_json_error err = {};
-
- req = ast_json_load_buf(payload, payload_len, &err);
-
- if (req == NULL) {
- /* Parse error */
- RAII_VAR(char *, payloadz, NULL, ast_free);
- payloadz = ast_strndup(payload, payload_len);
- resp = ast_json_pack(
- "{ s: { s: o, s: i, s: i, s: s } }",
- "error",
- "message",ast_json_stringf(
- "Error parsing message: %s",
- err.text),
- "line", err.line,
- "column", err.column,
- "request",
- payloadz ? payloadz : "(null)");
- } else {
- resp = websocket_process_req(&stasis_session,
- req);
- }
-
- if (resp) {
- websocket_write_json(session, resp);
- }
- } else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
+ if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
break;
}
}
@@ -311,6 +218,13 @@
{
int r = 0;
+ oom_json = ast_json_pack(
+ "{s: s}",
+ "error", "Out of memory");
+ if (!oom_json) {
+ /* ironic */
+ return AST_MODULE_LOAD_FAILURE;
+ }
r |= ast_websocket_add_protocol(ws_protocol, websocket_callback);
return r;
}
@@ -319,6 +233,8 @@
{
int r = 0;
+ ast_json_unref(oom_json);
+ oom_json = NULL;
r |= ast_websocket_remove_protocol(ws_protocol, websocket_callback);
return r;
}
More information about the svn-commits
mailing list