[asterisk-commits] dlee: branch dlee/stasis-http r384293 - in /team/dlee/stasis-http: ./ res/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Mar 28 13:33:59 CDT 2013
Author: dlee
Date: Thu Mar 28 13:33:56 2013
New Revision: 384293
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384293
Log:
Merged revisions 384286-384291 from http://svn.asterisk.org/svn/asterisk/team/dlee/stasis-app
Modified:
team/dlee/stasis-http/ (props changed)
team/dlee/stasis-http/res/res_stasis_websocket.c
Propchange: team/dlee/stasis-http/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Mar 28 13:33:56 2013
@@ -1,1 +1,1 @@
-/team/dlee/stasis-app:1-384235 /trunk:1-384219
+/team/dlee/stasis-app:1-384291 /trunk:1-384219
Modified: team/dlee/stasis-http/res/res_stasis_websocket.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/res_stasis_websocket.c?view=diff&rev=384293&r1=384292&r2=384293
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_websocket.c (original)
+++ team/dlee/stasis-http/res/res_stasis_websocket.c Thu Mar 28 13:33:56 2013
@@ -44,43 +44,17 @@
/*! WebSocket protocol for Stasis */
static const char * const ws_protocol = "stasis";
-/*! Number of buckets for the Stasis application hash table. Remember to keep it a prime number! */
+/*! 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!
+ */
#define APPS_NUM_BUCKETS 7
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
@@ -90,7 +64,8 @@
* \return 0 on success.
* \return -1 on error.
*/
-static int websocket_write_json(struct ast_websocket *session, struct ast_json *message)
+static int websocket_write_json(struct ast_websocket *session,
+ struct ast_json *message)
{
RAII_VAR(char *, str, ast_json_dump_string(message), ast_free);
@@ -99,7 +74,8 @@
return -1;
}
- return ast_websocket_write(session, AST_WEBSOCKET_OPCODE_TEXT, str, strlen(str));
+ return ast_websocket_write(session, AST_WEBSOCKET_OPCODE_TEXT, str,
+ strlen(str));
}
/*! Hash function for websocket_app */
@@ -136,131 +112,92 @@
struct ao2_container *websocket_apps;
};
-static void app_handler(void *data, const char *app_name, struct ast_json *message)
+static void app_handler(void *data, const char *app_name,
+ struct ast_json *message)
{
struct stasis_ws_session_info *session = data;
int res;
- res = ast_json_object_set(message, "application", ast_json_string_create(app_name));
+ res = ast_json_object_set(message, "application",
+ ast_json_string_create(app_name));
ast_assert(res == 0);
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);
- }
-}
-
-static void websocket_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers)
+ }
+ return 0;
+}
+
+static void websocket_callback(struct ast_websocket *session,
+ struct ast_variable *parameters,
+ struct ast_variable *headers)
{
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");
if (ast_websocket_set_nonblock(session) != 0) {
- ast_log(LOG_ERROR, "Stasis web socket failed to set nonblock; closing\n");
+ ast_log(LOG_ERROR,
+ "Stasis web socket failed to set nonblock; closing\n");
goto end;
}
- stasis_session.websocket_apps = ao2_container_alloc(APPS_NUM_BUCKETS, hash_app, compare_app);
+ 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;
uint64_t payload_len;
enum ast_websocket_opcode opcode;
int fragmented;
-
- if (ast_websocket_read(session, &payload, &payload_len, &opcode, &fragmented)) {
- ast_log(LOG_ERROR, "Stasis WebSocket read error; closing\n");
+ int read = ast_websocket_read(session, &payload, &payload_len,
+ &opcode, &fragmented);
+
+ if (read) {
+ ast_log(LOG_ERROR,
+ "Stasis WebSocket read error; closing\n");
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, ast_strndup(payload, payload_len), ast_free);
- 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;
}
}
@@ -281,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;
}
@@ -289,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 asterisk-commits
mailing list