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

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 1 14:49:29 CDT 2013


Author: dlee
Date: Mon Apr  1 14:49:24 2013
New Revision: 384485

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=384485
Log:
Merged stasis-http config from kharwell's branch.

Added some basic configuration to stasis http.  Namely two global
options:

enabled - defaults to yes and when set to no, stasis-http support is
disabled.
pretty - defaults to no (compact format) otherwise when set to yes,
responses from stasis-http are formatted to be human readable.

Review: https://reviewboard.asterisk.org/r/2413/

Modified:
    team/dlee/stasis-http/include/asterisk/json.h
    team/dlee/stasis-http/main/json.c
    team/dlee/stasis-http/res/res_stasis_http.c

Modified: team/dlee/stasis-http/include/asterisk/json.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/include/asterisk/json.h?view=diff&rev=384485&r1=384484&r2=384485
==============================================================================
--- team/dlee/stasis-http/include/asterisk/json.h (original)
+++ team/dlee/stasis-http/include/asterisk/json.h Mon Apr  1 14:49:24 2013
@@ -586,16 +586,33 @@
 /*!@{*/
 
 /*!
+ * \brief Encoding format type.
+ * \since 12.0.0
+ */
+enum ast_json_encoding_format
+{
+	/*! Compact format, low human readability */
+	AST_JSON_COMPACT,
+	/*! Formatted for human readability */
+	AST_JSON_PRETTY,
+};
+
+#define ast_json_dump_string(root) ast_json_dump_string_format(root, AST_JSON_COMPACT)
+
+/*!
  * \brief Encode a JSON value to a string.
  * \since 12.0.0
  *
  * Returned string must be freed by calling ast_free().
  *
- * \param JSON value.
+ * \param root JSON value.
+ * \param format encoding format type.
  * \return String encoding of \a root.
  * \return \c NULL on error.
  */
-char *ast_json_dump_string(struct ast_json *root);
+char *ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format);
+
+#define ast_json_dump_str(root, dst) ast_json_dump_str_format(root, dst, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to an \ref ast_str.
@@ -605,10 +622,13 @@
  *
  * \param root JSON value.
  * \param dst \ref ast_str to store JSON encoding.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a dst are undefined.
  */
-int ast_json_dump_str(struct ast_json *root, struct ast_str **dst);
+int ast_json_dump_str_format(struct ast_json *root, struct ast_str **dst, enum ast_json_encoding_format format);
+
+#define ast_json_dump_file(root, output) ast_json_dump_file_format(root, output, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to a \c FILE.
@@ -616,10 +636,13 @@
  *
  * \param root JSON value.
  * \param output File to write JSON encoding to.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a output are undefined.
  */
-int ast_json_dump_file(struct ast_json *root, FILE *output);
+int ast_json_dump_file_format(struct ast_json *root, FILE *output, enum ast_json_encoding_format format);
+
+#define ast_json_dump_new_file(root, path) ast_json_dump_new_file_format(root, path, AST_JSON_COMPACT)
 
 /*!
  * \brief Encode a JSON value to a file at the given location.
@@ -627,10 +650,11 @@
  *
  * \param root JSON value.
  * \param path Path to file to write JSON encoding to.
+ * \param format encoding format type.
  * \return 0 on success.
  * \return -1 on error. The contents of \a output are undefined.
  */
-int ast_json_dump_new_file(struct ast_json *root, const char *path);
+int ast_json_dump_new_file_format(struct ast_json *root, const char *path, enum ast_json_encoding_format format);
 
 #define AST_JSON_ERROR_TEXT_LENGTH    160
 #define AST_JSON_ERROR_SOURCE_LENGTH   80

Modified: team/dlee/stasis-http/main/json.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/main/json.c?view=diff&rev=384485&r1=384484&r2=384485
==============================================================================
--- team/dlee/stasis-http/main/json.c (original)
+++ team/dlee/stasis-http/main/json.c Mon Apr  1 14:49:24 2013
@@ -338,20 +338,15 @@
 /*!
  * \brief Default flags for JSON encoding.
  */
-static size_t dump_flags(void)
-{
-	/* There's a chance this could become a runtime flag */
-	int flags = JSON_COMPACT;
-#ifdef AST_DEVMODE
-	/* In dev mode, write readable JSON */
-	flags = JSON_INDENT(2) | JSON_PRESERVE_ORDER;
-#endif
-	return flags;
-}
-
-char *ast_json_dump_string(struct ast_json *root)
-{
-	return json_dumps((json_t *)root, dump_flags());
+static size_t dump_flags(enum ast_json_encoding_format format)
+{
+	return format == AST_JSON_PRETTY ?
+		JSON_INDENT(2) | JSON_PRESERVE_ORDER : JSON_COMPACT;
+}
+
+char *ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
+{
+	return json_dumps((json_t *)root, dump_flags(format));
 }
 
 static int write_to_ast_str(const char *buffer, size_t size, void *data)
@@ -385,25 +380,25 @@
 	return 0;
 }
 
-int ast_json_dump_str(struct ast_json *root, struct ast_str **dst)
-{
-	return json_dump_callback((json_t *)root, write_to_ast_str, dst, dump_flags());
-}
-
-
-int ast_json_dump_file(struct ast_json *root, FILE *output)
+int ast_json_dump_str_format(struct ast_json *root, struct ast_str **dst, enum ast_json_encoding_format format)
+{
+	return json_dump_callback((json_t *)root, write_to_ast_str, dst, dump_flags(format));
+}
+
+
+int ast_json_dump_file_format(struct ast_json *root, FILE *output, enum ast_json_encoding_format format)
 {
 	if (!root || !output) {
 		return -1;
 	}
-	return json_dumpf((json_t *)root, output, dump_flags());
-}
-int ast_json_dump_new_file(struct ast_json *root, const char *path)
+	return json_dumpf((json_t *)root, output, dump_flags(format));
+}
+int ast_json_dump_new_file_format(struct ast_json *root, const char *path, enum ast_json_encoding_format format)
 {
 	if (!root || !path) {
 		return -1;
 	}
-	return json_dump_file((json_t *)root, path, dump_flags());
+	return json_dump_file((json_t *)root, path, dump_flags(format));
 }
 
 /*!

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=384485&r1=384484&r2=384485
==============================================================================
--- team/dlee/stasis-http/res/res_stasis_http.c (original)
+++ team/dlee/stasis-http/res/res_stasis_http.c Mon Apr  1 14:49:24 2013
@@ -70,6 +70,23 @@
 	<support_level>core</support_level>
  ***/
 
+/*** DOCUMENTATION
+	<configInfo name="res_stasis_http" language="en_US">
+		<synopsis>HTTP binding for the Stasis API</synopsis>
+		<configFile name="stasis_http.conf">
+			<configObject name="global">
+				<synopsis>Global configuration settings</synopsis>
+				<configOption name="enabled">
+					<synopsis>Enable/disable the stasis-http module</synopsis>
+				</configOption>
+				<configOption name="pretty">
+					<synopsis>Responses from stasis-http are formatted to be human readable</synopsis>
+				</configOption>
+			</configObject>
+		</configFile>
+	</configInfo>
+***/
+
 #include "asterisk.h"
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
@@ -77,10 +94,110 @@
 #include "asterisk/module.h"
 #include "asterisk/paths.h"
 #include "asterisk/stasis_http.h"
+#include "asterisk/config_options.h"
 
 #include <string.h>
 #include <sys/stat.h>
 #include <unistd.h>
+
+/*! \brief Global configuration options for stasis http. */
+struct conf_global_options {
+	/*! Enabled by default, disabled if false. */
+	int enabled:1;
+	/*! Encoding format used during output (default compact). */
+	enum ast_json_encoding_format format;
+};
+
+/*! \brief All configuration options for stasis http. */
+struct conf {
+	/*! The general section configuration options. */
+	struct conf_global_options *global;
+};
+
+/*! \brief Locking container for safe configuration access. */
+static AO2_GLOBAL_OBJ_STATIC(confs);
+
+/*! \brief Mapping of the stasis http conf struct's globals to the
+ *         general context in the config file. */
+static struct aco_type global_option = {
+	.type = ACO_GLOBAL,
+	.name = "global",
+	.item_offset = offsetof(struct conf, global),
+	.category = "^general$",
+	.category_match = ACO_WHITELIST
+};
+
+static struct aco_type *global_options[] = ACO_TYPES(&global_option);
+
+/*! \brief Disposes of the stasis http conf object */
+static void conf_destructor(void *obj)
+{
+    struct conf *cfg = obj;
+    ao2_cleanup(cfg->global);
+}
+
+/*! \brief Creates the statis http conf object. */
+static void *conf_alloc(void)
+{
+    struct conf *cfg;
+
+    if (!(cfg = ao2_alloc(sizeof(*cfg), conf_destructor))) {
+        return NULL;
+    }
+
+    if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) {
+        ao2_ref(cfg, -1);
+        return NULL;
+    }
+    return cfg;
+}
+
+/*! \brief The conf file that's processed for the module. */
+static struct aco_file conf_file = {
+	/*! The config file name. */
+	.filename = "stasis_http.conf",
+	/*! The mapping object types to be processed. */
+	.types = ACO_TYPES(&global_option),
+};
+
+CONFIG_INFO_STANDARD(cfg_info, confs, conf_alloc,
+		     .files = ACO_FILES(&conf_file));
+
+/*! \brief Bitfield handler since it is not possible to take address. */
+static int conf_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	struct conf_global_options *global = obj;
+
+	if (!strcasecmp(var->name, "enabled")) {
+		global->enabled = ast_true(var->value);
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*! \brief Encoding format handler converts from boolean to enum. */
+static int encoding_format_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	struct conf_global_options *global = obj;
+
+	if (!strcasecmp(var->name, "pretty")) {
+		global->format = ast_true(var->value) ? AST_JSON_PRETTY : AST_JSON_COMPACT;
+	} else {
+		return -1;
+	}
+
+	return 0;
+}
+
+/*! \brief Helper function to check if module is enabled. */
+static char is_enabled(void)
+{
+	RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup);
+
+	return cfg->global->enabled;
+}
 
 /*! Handler for root RESTful resource. */
 static struct stasis_rest_handlers *root_handler;
@@ -571,6 +688,7 @@
 				struct ast_variable *get_params,
 				struct ast_variable *headers)
 {
+	RAII_VAR(struct conf *, cfg, ao2_global_obj_ref(confs), ao2_cleanup);
 	RAII_VAR(struct ast_str *, response_headers, ast_str_create(40), ast_free);
 	RAII_VAR(struct ast_str *, response_body, ast_str_create(256), ast_free);
 	struct stasis_http_response response = {};
@@ -617,7 +735,7 @@
 	if (response.message && !ast_json_is_null(response.message)) {
 		ast_str_append(&response_headers, 0,
 			       "Content-type: application/json\r\n");
-		if (ast_json_dump_str(response.message, &response_body) != 0) {
+		if (ast_json_dump_str_format(response.message, &response_body, cfg->global->format) != 0) {
 			/* Error encoding response */
 			response.response_code = 500;
 			response.response_text = "Internal Server Error";
@@ -658,29 +776,69 @@
 
 static int load_module(void)
 {
-	int r = 0;
+	if (aco_info_init(&cfg_info)) {
+		aco_info_destroy(&cfg_info);
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	aco_option_register_custom(&cfg_info, "enabled", ACO_EXACT, global_options,
+				   "yes", conf_bitfield_handler, 0);
+	aco_option_register_custom(&cfg_info, "pretty", ACO_EXACT, global_options,
+				   "no",  encoding_format_handler, 0);
+
+	if (aco_process_config(&cfg_info, 0)) {
+		aco_info_destroy(&cfg_info);
+		return AST_MODULE_LOAD_DECLINE;
+	}
 
 	alloc_failed_message = ast_json_pack("{s: s}",
 					     "message", "Allocation failed");
 
 	stasis_set_root_handler(stasis_default_root_handler());
-	r |= ast_http_uri_link(&http_uri);
-	return r;
+
+	if (is_enabled()) {
+		ast_http_uri_link(&http_uri);
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
 }
 
 static int unload_module(void)
 {
-	int r = 0;
-
 	ast_json_unref(alloc_failed_message);
 	alloc_failed_message = NULL;
-	ast_http_uri_unlink(&http_uri);
-	return r;
+
+	if (is_enabled()) {
+		ast_http_uri_unlink(&http_uri);
+	}
+
+	aco_info_destroy(&cfg_info);
+	ao2_global_obj_release(confs);
+
+	return 0;
+}
+
+static int reload_module(void)
+{
+	char was_enabled = is_enabled();
+
+	if (aco_process_config(&cfg_info, 1)) {
+		return AST_MODULE_LOAD_DECLINE;
+	}
+
+	if (was_enabled && !is_enabled()) {
+		ast_http_uri_unlink(&http_uri);
+	} else if (!was_enabled && is_enabled()) {
+		ast_http_uri_link(&http_uri);
+	}
+
+	return AST_MODULE_LOAD_SUCCESS;
 }
 
 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS,
 		"Stasis HTTP bindings",
 		.load = load_module,
 		.unload = unload_module,
+		.reload = reload_module,
 		.nonoptreq = "app_stasis"
 	);




More information about the asterisk-commits mailing list