[asterisk-commits] dlee: branch dlee/stasis-http r380571 - in /team/dlee/stasis-http: include/as...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jan 30 14:57:10 CST 2013


Author: dlee
Date: Wed Jan 30 14:57:06 2013
New Revision: 380571

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380571
Log:
The makings of an app

Modified:
    team/dlee/stasis-http/include/asterisk/stasis.h
    team/dlee/stasis-http/res/res_stasis_core.c
    team/dlee/stasis-http/res/res_stasis_http.c
    team/dlee/stasis-http/res/stasis_http_channels.c

Modified: team/dlee/stasis-http/include/asterisk/stasis.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/stasis.h?view=diff&rev=380571&r1=380570&r2=380571
==============================================================================
--- team/dlee/stasis-http/include/asterisk/stasis.h (original)
+++ team/dlee/stasis-http/include/asterisk/stasis.h Wed Jan 30 14:57:06 2013
@@ -19,6 +19,8 @@
 #ifndef _ASTERISK_STASIS_H
 #define _ASTERISK_STASIS_H
 
+#include "asterisk/json.h"
+
 /*! \file
  *
  * \brief Stasis message bus.
@@ -36,4 +38,8 @@
  */
 int stasis_app_invoke(const char *app_name, struct ast_channel *chan, int argc, char *argv[]);
 
+typedef void (*stasis_app_handler)(void *data, struct ast_json *message);
+
+int stasis_app_register(const char *app_name, stasis_app_handler handler, void *data);
+
 #endif /* _ASTERISK_STASIS_H */

Modified: team/dlee/stasis-http/res/res_stasis_core.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/res_stasis_core.c?view=diff&rev=380571&r1=380570&r2=380571
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_core.c (original)
+++ team/dlee/stasis-http/res/res_stasis_core.c Wed Jan 30 14:57:06 2013
@@ -32,7 +32,9 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/astobj2.h"
+#include "asterisk/channel.h"
 #include "asterisk/hashtab.h"
+#include "asterisk/logger.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis.h"
 #include "asterisk/utils.h"
@@ -43,6 +45,8 @@
 /*! Stasis application ref */
 struct stasis_app {
 	const char *name;
+	stasis_app_handler handler;
+	void *data;
 };
 
 /*! Stasis application container */
@@ -52,7 +56,9 @@
 static int hash_app(const void *obj, const int flags)
 {
 	const struct stasis_app *app = obj;
-	return ast_hashtab_hash_string(app->name);
+	const char *name = flags & OBJ_KEY ? obj : app->name;
+
+	return ast_hashtab_hash_string(name);
 }
 
 /*! Comparison function for stasis_app */
@@ -60,26 +66,81 @@
 {
 	const struct stasis_app *lhs_app = lhs;
 	const struct stasis_app *rhs_app = rhs;
-	if (strcmp(lhs_app->name, rhs_app->name) == 0) {
+	const char *rhs_name = flags & OBJ_KEY ? rhs : rhs_app->name;
+
+	if (strcmp(lhs_app->name, rhs_name) == 0) {
 		return CMP_MATCH | CMP_STOP;
 	} else {
 		return 0;
 	}
 }
 
+static void app_dtor(void *app)
+{
+	/* No-op */
+}
+
 int stasis_app_invoke(const char *app_name, struct ast_channel *chan, int argc, char *argv[])
 {
-	struct stasis_app needle = {.name = app_name};
-	struct stasis_app *app = ao2_find(stasis_apps, &needle, OBJ_POINTER);
+	RAII_VAR(struct ao2_container *, apps, stasis_apps, ao2_cleanup);
+	RAII_VAR(struct stasis_app *, app, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
+	struct ast_json *json_args;
+	int i;
+
+	ao2_ref(apps, 1);
+	app = ao2_find(apps, app_name, OBJ_KEY);
 
 	if (!app) {
 		ast_log(LOG_WARNING, "Stasis app '%s' not registered\n", app_name);
 		return -1;
 	}
 
-	ast_log(LOG_WARNING, "TODO: unimplemented\n");
-	ao2_ref(app, -1);
-	return -1;
+	msg = ast_json_pack("{s: s, s: s, s: []}",
+			    "command", "invoke",
+			    "channel", ast_channel_name(chan),
+			    "args");
+	if (!msg) {
+		ast_log(LOG_ERROR, "Couldn't create message for %s\n", app_name);
+		return -1;
+	}
+	json_args = ast_json_object_get(msg, "args");
+	ast_assert(json_args != NULL);
+	for (i = 0; i < argc; ++i) {
+		ast_json_array_append(json_args, ast_json_string_create(argv[i]));
+	}
+
+	app->handler(app->data, msg);
+
+	return 0;
+}
+
+int stasis_app_register(const char *app_name, stasis_app_handler handler, void *data)
+{
+	RAII_VAR(struct ao2_container *, apps, stasis_apps, ao2_cleanup);
+
+	ao2_ref(apps, 1);
+	{
+		RAII_VAR(struct stasis_app *, app, ao2_find(apps, app_name, OBJ_KEY | OBJ_NOLOCK), ao2_cleanup);
+		SCOPED_LOCK(apps_lock, apps, ao2_lock, ao2_unlock);
+
+		if (app) {
+			RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
+			msg = ast_json_pack("{s: s}", "event", "replaced");
+			app->handler(app->data, msg);
+		} else {
+			app = ao2_alloc(sizeof(*app), app_dtor);
+		}
+
+		if (!app) {
+			ast_log(LOG_ERROR, "Failed to allocate stasis_app\n");
+			return -1;
+		}
+
+		app->handler = handler;
+		app->data = data;
+	}
+	return 0;
 }
 
 static int load_module(void)

Modified: team/dlee/stasis-http/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/res_stasis_http.c?view=diff&rev=380571&r1=380570&r2=380571
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_http.c (original)
+++ team/dlee/stasis-http/res/res_stasis_http.c Wed Jan 30 14:57:06 2013
@@ -334,7 +334,8 @@
  * \return 0 on success.
  * \return -1 on error.
  */
-static int ast_websocket_write_json(struct ast_websocket *session, struct ast_json *message) {
+static int ast_websocket_write_json(struct ast_websocket *session, struct ast_json *message)
+{
 	RAII_VAR(char *, str, ast_json_dump_string(message), ast_free);
 
 	if (str == NULL) {
@@ -343,6 +344,58 @@
 	}
 
 	return ast_websocket_write(session, AST_WEBSOCKET_OPCODE_TEXT, str, strlen(str));
+}
+
+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 *stasis_websocket_process_req(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");
+	}
+
+	if (strcmp("ActivateApplication", command) == 0) {
+		const char *app_name = ast_json_string_get(ast_json_object_get(req, "name"));
+		if (ast_strlen_zero(app_name)) {
+			return build_err(id, "Missing application name");
+		}
+		return build_err(id, "TODO");
+	} else if (strcmp("DeactivateApplication", command) == 0) {
+		const char *app_name = ast_json_string_get(ast_json_object_get(req, "name"));
+		if (ast_strlen_zero(app_name)) {
+			return build_err(id, "Missing application name");
+		}
+		return build_err(id, "TODO");
+	} else {
+		return build_err(id, "Unrecognized command: %s", command);
+	}
 }
 
 /*!
@@ -376,25 +429,29 @@
 
 		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(struct ast_json *, resp, NULL, ast_json_unref);
-				resp = ast_json_pack("{ s: o, s: i, s: i, s: s }",
-						     "error", ast_json_stringf("Error parsing message: %s", err.text),
+				resp = ast_json_pack("{ s: { s: o, s: i, s: i, s: o } }",
+						     "error",
+						     "message", ast_json_stringf("Error parsing message: %s", err.text),
 						     "line", err.line,
 						     "column", err.column,
-						     "message", err.text);
-				if (resp) {
-					ast_websocket_write_json(session, resp);
-				} else {
-					ast_log(LOG_ERROR, "Error sending error message. That's just messed up.\n");
+						     "request", ast_json_stringf("%.*s", (int)payload_len, payload));
+				if (!resp) {
+					ast_log(LOG_ERROR, "Error building error message. That's just messed up.\n");
 				}
+			} else {
+				resp = stasis_websocket_process_req(req);
 			}
-			ast_log(LOG_ERROR, "TODO\n");
+
+			if (resp) {
+				ast_websocket_write_json(session, resp);
+			}
 			ast_json_unref(req);
 		} else if (opcode == AST_WEBSOCKET_OPCODE_CLOSE) {
 			break;

Modified: team/dlee/stasis-http/res/stasis_http_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/res/stasis_http_channels.c?view=diff&rev=380571&r1=380570&r2=380571
==============================================================================
--- team/dlee/stasis-http/res/stasis_http_channels.c (original)
+++ team/dlee/stasis-http/res/stasis_http_channels.c Wed Jan 30 14:57:06 2013
@@ -66,6 +66,11 @@
 void stasis_http_get_channels(struct ast_variable *headers, struct ast_get_channels_args *args, struct stasis_http_response *response) {
 	ast_log(LOG_ERROR, "TODO: stasis_http_get_channels\n");
 }
+
 void stasis_http_originate(struct ast_variable *headers, struct ast_originate_args *args, struct stasis_http_response *response) {
-	ast_log(LOG_ERROR, "TODO: stasis_http_originate\n");
+	if (args->endpoint) {
+		ast_log(LOG_DEBUG, "Dialing specific endpoint %s\n", args->endpoint);
+	}
+
+	ast_log(LOG_DEBUG, "Dialing %s@%s\n", args->extension, args->context);
 }




More information about the asterisk-commits mailing list