[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