[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