[asterisk-commits] mmichelson: branch mmichelson/queue_bugbug r396133 - in /team/mmichelson/queu...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Aug 2 10:35:27 CDT 2013
Author: mmichelson
Date: Fri Aug 2 10:35:25 2013
New Revision: 396133
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396133
Log:
resolve conflict
Added:
team/mmichelson/queue_bugbug/rest-api-templates/param_cleanup.mustache
- copied unchanged from r396126, trunk/rest-api-templates/param_cleanup.mustache
Modified:
team/mmichelson/queue_bugbug/ (props changed)
team/mmichelson/queue_bugbug/include/asterisk/json.h
team/mmichelson/queue_bugbug/main/cel.c
team/mmichelson/queue_bugbug/main/json.c
team/mmichelson/queue_bugbug/res/ari/ari_model_validators.c
team/mmichelson/queue_bugbug/res/ari/ari_model_validators.h
team/mmichelson/queue_bugbug/res/ari/ari_websockets.c
team/mmichelson/queue_bugbug/res/ari/resource_asterisk.c
team/mmichelson/queue_bugbug/res/ari/resource_asterisk.h
team/mmichelson/queue_bugbug/res/ari/resource_bridges.c
team/mmichelson/queue_bugbug/res/ari/resource_bridges.h
team/mmichelson/queue_bugbug/res/ari/resource_events.c
team/mmichelson/queue_bugbug/res/ari/resource_events.h
team/mmichelson/queue_bugbug/res/ari/resource_sounds.h
team/mmichelson/queue_bugbug/res/res_ari_asterisk.c
team/mmichelson/queue_bugbug/res/res_ari_bridges.c
team/mmichelson/queue_bugbug/res/res_ari_channels.c
team/mmichelson/queue_bugbug/res/res_ari_endpoints.c
team/mmichelson/queue_bugbug/res/res_ari_events.c
team/mmichelson/queue_bugbug/res/res_ari_playback.c
team/mmichelson/queue_bugbug/res/res_ari_recordings.c
team/mmichelson/queue_bugbug/res/res_ari_sounds.c
team/mmichelson/queue_bugbug/res/res_sorcery_astdb.c
team/mmichelson/queue_bugbug/res/snmp/agent.c
team/mmichelson/queue_bugbug/rest-api-templates/ari_resource.h.mustache
team/mmichelson/queue_bugbug/rest-api-templates/param_parsing.mustache
team/mmichelson/queue_bugbug/rest-api-templates/res_ari_resource.c.mustache
team/mmichelson/queue_bugbug/rest-api/api-docs/asterisk.json
team/mmichelson/queue_bugbug/rest-api/api-docs/bridges.json
team/mmichelson/queue_bugbug/rest-api/api-docs/channels.json
team/mmichelson/queue_bugbug/rest-api/api-docs/events.json
team/mmichelson/queue_bugbug/rest-api/api-docs/sounds.json
team/mmichelson/queue_bugbug/tests/test_json.c
Propchange: team/mmichelson/queue_bugbug/
------------------------------------------------------------------------------
automerge = *
Propchange: team/mmichelson/queue_bugbug/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Aug 2 10:35:25 2013
@@ -1,1 +1,1 @@
-/trunk:1-396115
+/trunk:1-396132
Modified: team/mmichelson/queue_bugbug/include/asterisk/json.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/include/asterisk/json.h?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/include/asterisk/json.h (original)
+++ team/mmichelson/queue_bugbug/include/asterisk/json.h Fri Aug 2 10:35:25 2013
@@ -42,6 +42,37 @@
* In the cases where you have a need to introduce intermediate objects, just
* wrap them with json_ref() when passing them to other \c ast_json_*()
* functions.
+ *
+ * \par Thread Safety
+ *
+ * Jansson (as of 2.4) provides fairly weak thread safety guarantees. The
+ * Asterisk wrapper improves upon that slightly. The remaining refcounting
+ * problems are issues when slicing/sharing/mixing instances between JSON
+ * objects and arrays, which we avoid.
+ *
+ * The \c ast_json_dump_* functions are thread safe for multiple concurrent
+ * dumps of the same object, so long as the concurrent dumps start from the same
+ * \c root object. But if an object is shared by other JSON objects/arrays, then
+ * concurrent dumps of the outer objects/arrays are not thread safe. This can be
+ * avoided by using ast_json_deep_copy() when sharing JSON instances between
+ * objects.
+ *
+ * The ast_json_ref() and ast_json_unref() functions are thread safe. Since the
+ * Asterisk wrapper exclusively uses the reference stealing API, Jansson won't
+ * be performing many refcount modifications behind our backs. There are a few
+ * exceptions.
+ *
+ * The first is the transitive json_decref() that occurs when \ref
+ * AST_JSON_OBJECT and \ref AST_JSON_ARRAY instances are deleted. This can be
+ * avoided by using ast_json_deep_copy() when sharing JSON instances between
+ * objects.
+ *
+ * The second is when using the reference borrowing specifier in
+ * ast_json_pack() (capital \c O). This can be avoided by using the reference
+ * stealing specifier (lowercase \c o) and wrapping the JSON object parameter
+ * with ast_json_ref() for an explicit ref-bump.
+ *
+ * \par Example code
*
* \code
* // Example of how to use the Asterisk JSON API
@@ -105,6 +136,20 @@
* ast_free().
*/
void ast_json_reset_alloc_funcs(void);
+
+/*!
+ * \brief Asterisk's custom JSON allocator. Exposed for use by unit tests.
+ * \since 12.0.0
+ * \internal
+ */
+void *ast_json_malloc(size_t size);
+
+/*!
+ * \brief Asterisk's custom JSON allocator. Exposed for use by unit tests.
+ * \since 12.0.0
+ * \internal
+ */
+void ast_json_free(void *p);
/*!
* \struct ast_json
@@ -683,13 +728,23 @@
AST_JSON_PRETTY,
};
+/*!
+ * \brief Encode a JSON value to a compact string.
+ * \since 12.0.0
+ *
+ * Returned string must be freed by calling ast_json_free().
+ *
+ * \param root JSON value.
+ * \return String encoding of \a root.
+ * \return \c NULL on error.
+ */
#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().
+ * Returned string must be freed by calling ast_json_free().
*
* \param root JSON value.
* \param format encoding format type.
Modified: team/mmichelson/queue_bugbug/main/cel.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/main/cel.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/main/cel.c (original)
+++ team/mmichelson/queue_bugbug/main/cel.c Fri Aug 2 10:35:25 2013
@@ -638,7 +638,7 @@
struct ast_json *extra, const char *peer_name)
{
struct timeval eventtime = ast_tvnow();
- RAII_VAR(char *, extra_txt, NULL, ast_free);
+ RAII_VAR(char *, extra_txt, NULL, ast_json_free);
if (extra) {
extra_txt = ast_json_dump_string(extra);
}
Modified: team/mmichelson/queue_bugbug/main/json.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/main/json.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/main/json.c (original)
+++ team/mmichelson/queue_bugbug/main/json.c Fri Aug 2 10:35:25 2013
@@ -20,8 +20,8 @@
*
* \brief JSON abstraction layer.
*
- * This is a very thin wrapper around the Jansson API. For more details on it, see its
- * docs at http://www.digip.org/jansson/doc/2.4/apiref.html.
+ * This is a very thin wrapper around the Jansson API. For more details on it,
+ * see its docs at http://www.digip.org/jansson/doc/2.4/apiref.html.
*
* \author David M. Lee, II <dlee at digium.com>
*/
@@ -46,20 +46,148 @@
#include <jansson.h>
#include <time.h>
+/*! \brief Magic number, for safety checks. */
+#define JSON_MAGIC 0x1541992
+
+/*! \brief Internal structure for allocated memory blocks */
+struct json_mem {
+ /*! Magic number, for safety checks */
+ uint32_t magic;
+ /*! Mutext for locking this memory block */
+ ast_mutex_t mutex;
+ /*! Linked list pointer for the free list */
+ AST_LIST_ENTRY(json_mem) list;
+ /*! Data section of the allocation; void pointer for proper alignment */
+ void *data[];
+};
+
+/*! \brief Free a \ref json_mem block. */
+static void json_mem_free(struct json_mem *mem)
+{
+ mem->magic = 0;
+ ast_mutex_destroy(&mem->mutex);
+ ast_free(mem);
+}
+
/*!
- * \brief Function wrapper around ast_malloc macro.
- */
-static void *json_malloc(size_t size)
-{
- return ast_malloc(size);
+ * \brief Get the \ref json_mem block for a pointer allocated via
+ * ast_json_malloc().
+ *
+ * This function properly handles Jansson singletons (null, true, false), and
+ * \c NULL.
+ *
+ * \param p Pointer, usually to a \c json_t or \ref ast_json.
+ * \return \ref json_mem object with extra allocation info.
+ */
+static inline struct json_mem *to_json_mem(void *p)
+{
+ struct json_mem *mem;
+ /* Avoid ref'ing the singleton values */
+ if (p == NULL || p == json_null() || p == json_true() ||
+ p == json_false()) {
+ return NULL;
+ }
+ mem = (struct json_mem *)((char *) (p) - sizeof(*mem));
+ ast_assert(mem->magic == JSON_MAGIC);
+ return mem;
}
/*!
- * \brief Function wrapper around ast_free macro.
- */
-static void json_free(void *p)
-{
- ast_free(p);
+ * \brief Lock an \ref ast_json instance.
+ *
+ * If \a json is an immutable singleton (null, true, false), this function
+ * safely ignores it and returns \c NULL. Otherwise, \a json must have been
+ * allocates using ast_json_malloc().
+ *
+ * \param json JSON instance to lock.
+ * \return \ref Corresponding \ref json_mem block.
+ * \return \c NULL if \a json was not allocated.
+ */
+static struct json_mem *json_mem_lock(struct ast_json *json)
+{
+ struct json_mem *mem = to_json_mem(json);
+ if (!mem) {
+ return NULL;
+ }
+ ast_mutex_lock(&mem->mutex);
+ return mem;
+}
+
+/*!
+ * \brief Unlock a \ref json_mem instance.
+ *
+ * \param mem \ref json_mem, usually returned from json_mem_lock().
+ */
+static void json_mem_unlock(struct json_mem *mem)
+{
+ if (!mem) {
+ return;
+ }
+ ast_mutex_unlock(&mem->mutex);
+}
+
+/*!
+ * \brief Scoped lock for a \ref ast_json instance.
+ *
+ * \param json JSON instance to lock.
+ */
+#define SCOPED_JSON_LOCK(json) \
+ RAII_VAR(struct json_mem *, __mem_ ## __LINE__, \
+ json_mem_lock(json), json_mem_unlock)
+
+void *ast_json_malloc(size_t size)
+{
+ struct json_mem *mem = ast_malloc(size + sizeof(*mem));
+ if (!mem) {
+ return NULL;
+ }
+ mem->magic = JSON_MAGIC;
+ ast_mutex_init(&mem->mutex);
+ return mem->data;
+}
+
+AST_THREADSTORAGE(json_free_list_ts);
+
+/*!
+ * \brief Struct for a linked list of \ref json_mem.
+ */
+AST_LIST_HEAD_NOLOCK(json_mem_list, json_mem);
+
+/*!
+ * \brief Thread local list of \ref json_mem blocks to free at the end of an
+ * unref.
+ */
+static struct json_mem_list *json_free_list(void)
+{
+ return ast_threadstorage_get(&json_free_list_ts,
+ sizeof(struct json_mem_list));
+}
+
+void ast_json_free(void *p)
+{
+ struct json_mem *mem;
+ struct json_mem_list *free_list;
+ mem = to_json_mem(p);
+
+ if (!mem) {
+ return;
+ }
+
+ /* Since the unref is holding a lock in mem, we can't free it
+ * immediately. Store it off on a thread local list to be freed by
+ * ast_json_unref().
+ */
+ free_list = json_free_list();
+ if (!free_list) {
+ ast_log(LOG_ERROR, "Error allocating free list\n");
+ ast_assert(0);
+ /* It's not ideal to free the memory immediately, but that's the
+ * best we can do if the threadlocal allocation fails */
+ json_mem_free(mem);
+ return;
+ }
+
+ AST_LIST_INSERT_HEAD(free_list, mem, list);
}
void ast_json_set_alloc_funcs(void *(*malloc_fn)(size_t), void (*free_fn)(void*))
@@ -69,21 +197,41 @@
void ast_json_reset_alloc_funcs(void)
{
- json_set_alloc_funcs(json_malloc, json_free);
+ json_set_alloc_funcs(ast_json_malloc, ast_json_free);
}
struct ast_json *ast_json_ref(struct ast_json *json)
{
+ /* Jansson refcounting is non-atomic; lock it. */
+ SCOPED_JSON_LOCK(json);
json_incref((json_t *)json);
return json;
}
void ast_json_unref(struct ast_json *json)
{
- if (!json) {
+ struct json_mem_list *free_list;
+ struct json_mem *mem;
+
+ /* Jansson refcounting is non-atomic; lock it. */
+ {
+ SCOPED_JSON_LOCK(json);
+ if (!json) {
+ return;
+ }
+ json_decref((json_t *)json);
+ }
+
+ /* Now free any objects that were ast_json_free()'s while the lock was
+ * held */
+ free_list = json_free_list();
+ if (!free_list) {
return;
}
- json_decref((json_t *)json);
+
+ while ((mem = AST_LIST_REMOVE_HEAD(free_list, list))) {
+ json_mem_free(mem);
+ }
}
enum ast_json_type ast_json_typeof(const struct ast_json *json)
@@ -383,6 +531,10 @@
char *ast_json_dump_string_format(struct ast_json *root, enum ast_json_encoding_format format)
{
+ /* Jansson's json_dump*, even though it's a read operation, isn't
+ * thread safe for concurrent reads. Locking is necessary.
+ * See http://www.digip.org/jansson/doc/2.4/portability.html#thread-safety. */
+ SCOPED_JSON_LOCK(root);
return json_dumps((json_t *)root, dump_flags(format));
}
@@ -419,12 +571,20 @@
int ast_json_dump_str_format(struct ast_json *root, struct ast_str **dst, enum ast_json_encoding_format format)
{
+ /* Jansson's json_dump*, even though it's a read operation, isn't
+ * thread safe for concurrent reads. Locking is necessary.
+ * See http://www.digip.org/jansson/doc/2.4/portability.html#thread-safety. */
+ SCOPED_JSON_LOCK(root);
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)
{
+ /* Jansson's json_dump*, even though it's a read operation, isn't
+ * thread safe for concurrent reads. Locking is necessary.
+ * See http://www.digip.org/jansson/doc/2.4/portability.html#thread-safety. */
+ SCOPED_JSON_LOCK(root);
if (!root || !output) {
return -1;
}
@@ -432,6 +592,10 @@
}
int ast_json_dump_new_file_format(struct ast_json *root, const char *path, enum ast_json_encoding_format format)
{
+ /* Jansson's json_dump*, even though it's a read operation, isn't
+ * thread safe for concurrent reads. Locking is necessary.
+ * See http://www.digip.org/jansson/doc/2.4/portability.html#thread-safety. */
+ SCOPED_JSON_LOCK(root);
if (!root || !path) {
return -1;
}
Modified: team/mmichelson/queue_bugbug/res/ari/ari_model_validators.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/ari_model_validators.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/ari_model_validators.c (original)
+++ team/mmichelson/queue_bugbug/res/ari/ari_model_validators.c Fri Aug 2 10:35:25 2013
@@ -41,6 +41,42 @@
struct ast_json_iter *iter;
for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("build", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_build_info(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI AsteriskInfo field build failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("config", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_config_info(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI AsteriskInfo field config failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("status", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_status_info(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI AsteriskInfo field status failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("system", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_system_info(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI AsteriskInfo field system failed validation\n");
+ res = 0;
+ }
+ } else
{
ast_log(LOG_ERROR,
"ARI AsteriskInfo has undocumented field %s\n",
@@ -55,6 +91,383 @@
ari_validator ast_ari_validate_asterisk_info_fn(void)
{
return ast_ari_validate_asterisk_info;
+}
+
+int ast_ari_validate_build_info(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_date = 0;
+ int has_kernel = 0;
+ int has_machine = 0;
+ int has_options = 0;
+ int has_os = 0;
+ int has_user = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("date", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_date = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field date failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("kernel", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_kernel = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field kernel failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("machine", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_machine = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field machine failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("options", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_options = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field options failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("os", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_os = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field os failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("user", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_user = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI BuildInfo field user failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI BuildInfo has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_date) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field date\n");
+ res = 0;
+ }
+
+ if (!has_kernel) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field kernel\n");
+ res = 0;
+ }
+
+ if (!has_machine) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field machine\n");
+ res = 0;
+ }
+
+ if (!has_options) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field options\n");
+ res = 0;
+ }
+
+ if (!has_os) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field os\n");
+ res = 0;
+ }
+
+ if (!has_user) {
+ ast_log(LOG_ERROR, "ARI BuildInfo missing required field user\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_build_info_fn(void)
+{
+ return ast_ari_validate_build_info;
+}
+
+int ast_ari_validate_config_info(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_default_language = 0;
+ int has_name = 0;
+ int has_setid = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("default_language", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_default_language = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field default_language failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("max_channels", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_int(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field max_channels failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("max_load", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_double(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field max_load failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("max_open_files", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ prop_is_valid = ast_ari_validate_int(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field max_open_files failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("name", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_name = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field name failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("setid", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_setid = 1;
+ prop_is_valid = ast_ari_validate_set_id(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo field setid failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI ConfigInfo has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_default_language) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo missing required field default_language\n");
+ res = 0;
+ }
+
+ if (!has_name) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo missing required field name\n");
+ res = 0;
+ }
+
+ if (!has_setid) {
+ ast_log(LOG_ERROR, "ARI ConfigInfo missing required field setid\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_config_info_fn(void)
+{
+ return ast_ari_validate_config_info;
+}
+
+int ast_ari_validate_set_id(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_group = 0;
+ int has_user = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("group", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_group = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI SetId field group failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("user", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_user = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI SetId field user failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI SetId has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_group) {
+ ast_log(LOG_ERROR, "ARI SetId missing required field group\n");
+ res = 0;
+ }
+
+ if (!has_user) {
+ ast_log(LOG_ERROR, "ARI SetId missing required field user\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_set_id_fn(void)
+{
+ return ast_ari_validate_set_id;
+}
+
+int ast_ari_validate_status_info(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_last_reload_time = 0;
+ int has_startup_time = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("last_reload_time", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_last_reload_time = 1;
+ prop_is_valid = ast_ari_validate_date(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI StatusInfo field last_reload_time failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("startup_time", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_startup_time = 1;
+ prop_is_valid = ast_ari_validate_date(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI StatusInfo field startup_time failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI StatusInfo has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_last_reload_time) {
+ ast_log(LOG_ERROR, "ARI StatusInfo missing required field last_reload_time\n");
+ res = 0;
+ }
+
+ if (!has_startup_time) {
+ ast_log(LOG_ERROR, "ARI StatusInfo missing required field startup_time\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_status_info_fn(void)
+{
+ return ast_ari_validate_status_info;
+}
+
+int ast_ari_validate_system_info(struct ast_json *json)
+{
+ int res = 1;
+ struct ast_json_iter *iter;
+ int has_entity_id = 0;
+ int has_version = 0;
+
+ for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
+ if (strcmp("entity_id", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_entity_id = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI SystemInfo field entity_id failed validation\n");
+ res = 0;
+ }
+ } else
+ if (strcmp("version", ast_json_object_iter_key(iter)) == 0) {
+ int prop_is_valid;
+ has_version = 1;
+ prop_is_valid = ast_ari_validate_string(
+ ast_json_object_iter_value(iter));
+ if (!prop_is_valid) {
+ ast_log(LOG_ERROR, "ARI SystemInfo field version failed validation\n");
+ res = 0;
+ }
+ } else
+ {
+ ast_log(LOG_ERROR,
+ "ARI SystemInfo has undocumented field %s\n",
+ ast_json_object_iter_key(iter));
+ res = 0;
+ }
+ }
+
+ if (!has_entity_id) {
+ ast_log(LOG_ERROR, "ARI SystemInfo missing required field entity_id\n");
+ res = 0;
+ }
+
+ if (!has_version) {
+ ast_log(LOG_ERROR, "ARI SystemInfo missing required field version\n");
+ res = 0;
+ }
+
+ return res;
+}
+
+ari_validator ast_ari_validate_system_info_fn(void)
+{
+ return ast_ari_validate_system_info;
}
int ast_ari_validate_variable(struct ast_json *json)
Modified: team/mmichelson/queue_bugbug/res/ari/ari_model_validators.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/ari_model_validators.h?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/ari_model_validators.h (original)
+++ team/mmichelson/queue_bugbug/res/ari/ari_model_validators.h Fri Aug 2 10:35:25 2013
@@ -162,6 +162,96 @@
ari_validator ast_ari_validate_asterisk_info_fn(void);
/*!
+ * \brief Validator for BuildInfo.
+ *
+ * Info about how Asterisk was built
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_build_info(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_build_info().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_build_info_fn(void);
+
+/*!
+ * \brief Validator for ConfigInfo.
+ *
+ * Info about Asterisk configuration
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_config_info(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_config_info().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_config_info_fn(void);
+
+/*!
+ * \brief Validator for SetId.
+ *
+ * Effective user/group id
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_set_id(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_set_id().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_set_id_fn(void);
+
+/*!
+ * \brief Validator for StatusInfo.
+ *
+ * Info about Asterisk status
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_status_info(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_status_info().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_status_info_fn(void);
+
+/*!
+ * \brief Validator for SystemInfo.
+ *
+ * Info about Asterisk
+ *
+ * \param json JSON object to validate.
+ * \returns True (non-zero) if valid.
+ * \returns False (zero) if invalid.
+ */
+int ast_ari_validate_system_info(struct ast_json *json);
+
+/*!
+ * \brief Function pointer to ast_ari_validate_system_info().
+ *
+ * See \ref ast_ari_model_validators.h for more details.
+ */
+ari_validator ast_ari_validate_system_info_fn(void);
+
+/*!
* \brief Validator for Variable.
*
* The value of a channel variable
@@ -785,6 +875,33 @@
* JSON models
*
* AsteriskInfo
+ * - build: BuildInfo
+ * - config: ConfigInfo
+ * - status: StatusInfo
+ * - system: SystemInfo
+ * BuildInfo
+ * - date: string (required)
+ * - kernel: string (required)
+ * - machine: string (required)
+ * - options: string (required)
+ * - os: string (required)
+ * - user: string (required)
+ * ConfigInfo
+ * - default_language: string (required)
+ * - max_channels: int
+ * - max_load: double
+ * - max_open_files: int
+ * - name: string (required)
+ * - setid: SetId (required)
+ * SetId
+ * - group: string (required)
+ * - user: string (required)
+ * StatusInfo
+ * - last_reload_time: Date (required)
+ * - startup_time: Date (required)
+ * SystemInfo
+ * - entity_id: string (required)
+ * - version: string (required)
* Variable
* - value: string (required)
* Endpoint
Modified: team/mmichelson/queue_bugbug/res/ari/ari_websockets.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/ari_websockets.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/ari_websockets.c (original)
+++ team/mmichelson/queue_bugbug/res/ari/ari_websockets.c Fri Aug 2 10:35:25 2013
@@ -142,7 +142,7 @@
int ast_ari_websocket_session_write(struct ast_ari_websocket_session *session,
struct ast_json *message)
{
- RAII_VAR(char *, str, NULL, ast_free);
+ RAII_VAR(char *, str, NULL, ast_json_free);
#ifdef AST_DEVMODE
if (!session->validator(message)) {
Modified: team/mmichelson/queue_bugbug/res/ari/resource_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/resource_asterisk.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/resource_asterisk.c (original)
+++ team/mmichelson/queue_bugbug/res/ari/resource_asterisk.c Fri Aug 2 10:35:25 2013
@@ -31,12 +31,113 @@
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+#include "asterisk/ast_version.h"
+#include "asterisk/buildinfo.h"
+#include "asterisk/paths.h"
+#include "asterisk/pbx.h"
#include "resource_asterisk.h"
-#include "asterisk/pbx.h"
-void ast_ari_get_asterisk_info(struct ast_variable *headers, struct ast_get_asterisk_info_args *args, struct ast_ari_response *response)
+void ast_ari_get_asterisk_info(struct ast_variable *headers,
+ struct ast_get_asterisk_info_args *args,
+ struct ast_ari_response *response)
{
- ast_log(LOG_ERROR, "TODO: ari_get_asterisk_info\n");
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ int show_all = args->only_count == 0;
+ int show_build = show_all;
+ int show_system = show_all;
+ int show_config = show_all;
+ int show_status = show_all;
+ size_t i;
+ int res = 0;
+
+ for (i = 0; i < args->only_count; ++i) {
+ if (strcasecmp("build", args->only[i]) == 0) {
+ show_build = 1;
+ } else if (strcasecmp("system", args->only[i]) == 0) {
+ show_system = 1;
+ } else if (strcasecmp("config", args->only[i]) == 0) {
+ show_config = 1;
+ } else if (strcasecmp("status", args->only[i]) == 0) {
+ show_status = 1;
+ } else {
+ ast_log(LOG_WARNING, "Unrecognized info section '%s'\n",
+ args->only[i]);
+ }
+ }
+
+ json = ast_json_object_create();
+
+ if (show_build) {
+ res |= ast_json_object_set(json, "build",
+ ast_json_pack(
+ "{ s: s, s: s, s: s,"
+ " s: s, s: s, s: s }",
+
+ "os", ast_build_os,
+ "kernel", ast_build_kernel,
+ "machine", ast_build_machine,
+
+ "options", AST_BUILDOPTS,
+ "date", ast_build_date,
+ "user", ast_build_user));
+ }
+
+ if (show_system) {
+ char eid_str[128];
+
+ ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
+
+ res |= ast_json_object_set(json, "system",
+ ast_json_pack("{ s: s, s: s }",
+ "version", ast_get_version(),
+ "entity_id", eid_str));
+ }
+
+ if (show_config) {
+ struct ast_json *config = ast_json_pack(
+ "{ s: s, s: s,"
+ " s: { s: s, s: s } }",
+
+ "name", ast_config_AST_SYSTEM_NAME,
+ "default_language", defaultlanguage,
+
+ "setid",
+ "user", ast_config_AST_RUN_USER,
+ "group", ast_config_AST_RUN_GROUP);
+
+ res |= ast_json_object_set(json, "config", config);
+
+ if (option_maxcalls) {
+ res |= ast_json_object_set(config, "max_channels",
+ ast_json_integer_create(option_maxcalls));
+ }
+
+ if (option_maxfiles) {
+ res |= ast_json_object_set(config, "max_open_files",
+ ast_json_integer_create(option_maxfiles));
+ }
+
+ if (option_maxload) {
+ res |= ast_json_object_set(config, "max_load",
+ ast_json_real_create(option_maxload));
+ }
+ }
+
+ if (show_status) {
+ res |= ast_json_object_set(json, "status",
+ ast_json_pack("{ s: o, s: o }",
+ "startup_time",
+ ast_json_timeval(ast_startuptime, NULL),
+ "last_reload_time",
+ ast_json_timeval(ast_lastreloadtime, NULL)));
+ }
+
+ if (res != 0) {
+ ast_ari_response_alloc_failed(response);
+ return;
+ }
+
+ ast_ari_response_ok(response, ast_json_ref(json));
}
void ast_ari_get_global_var(struct ast_variable *headers, struct ast_get_global_var_args *args, struct ast_ari_response *response)
Modified: team/mmichelson/queue_bugbug/res/ari/resource_asterisk.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/resource_asterisk.h?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/resource_asterisk.h (original)
+++ team/mmichelson/queue_bugbug/res/ari/resource_asterisk.h Fri Aug 2 10:35:25 2013
@@ -41,8 +41,12 @@
/*! \brief Argument struct for ast_ari_get_asterisk_info() */
struct ast_get_asterisk_info_args {
- /*! \brief Filter information returned */
- const char *only;
+ /*! \brief Array of Filter information returned */
+ const char **only;
+ /*! \brief Length of only array. */
+ size_t only_count;
+ /*! \brief Parsing context for only. */
+ char *only_parse;
};
/*!
* \brief Gets Asterisk system information.
Modified: team/mmichelson/queue_bugbug/res/ari/resource_bridges.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/resource_bridges.c?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/resource_bridges.c (original)
+++ team/mmichelson/queue_bugbug/res/ari/resource_bridges.c Fri Aug 2 10:35:25 2013
@@ -1,4 +1,4 @@
-/* -*- C -*-
+/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2012 - 2013, Digium, Inc.
@@ -107,33 +107,95 @@
return control;
}
+struct control_list {
+ size_t count;
+ struct stasis_app_control *controls[];
+};
+
+static void control_list_dtor(void *obj) {
+ struct control_list *list = obj;
+ size_t i;
+
+ for (i = 0; i < list->count; ++i) {
+ ao2_cleanup(list->controls[i]);
+ list->controls[i] = NULL;
+ }
+}
+
+static struct control_list *control_list_create(struct ast_ari_response *response, size_t count, const char **channels) {
+ RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
+ size_t i;
+
+ if (count == 0 || !channels) {
+ ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
+ return NULL;
+ }
+
+ list = ao2_alloc(sizeof(*list) + count * sizeof(list->controls[0]), control_list_dtor);
+ if (!list) {
+ ast_ari_response_alloc_failed(response);
+ return NULL;
+ }
+
+ for (i = 0; i < count; ++i) {
+ if (ast_strlen_zero(channels[i])) {
+ continue;
+ }
+ list->controls[list->count] =
+ find_channel_control(response, channels[i]);
+ if (!list->controls[list->count]) {
+ return NULL;
+ }
+ ++list->count;
+ }
+
+ if (list->count == 0) {
+ ast_ari_response_error(response, 400, "Bad Request", "Missing parameter channel");
+ return NULL;
+ }
+
+ ao2_ref(list, +1);
+ return list;
+}
+
void ast_ari_add_channel_to_bridge(struct ast_variable *headers, struct ast_add_channel_to_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
+ size_t i;
+
if (!bridge) {
- return;
- }
-
- control = find_channel_control(response, args->channel);
- if (!control) {
- return;
- }
-
- stasis_app_control_add_channel_to_bridge(control, bridge);
+ /* Response filled in by find_bridge */
+ return;
+ }
+
+ list = control_list_create(response, args->channel_count, args->channel);
+ if (!list) {
+ /* Response filled in by control_list_create() */
+ return;
+ }
+
+ for (i = 0; i < list->count; ++i) {
+ stasis_app_control_add_channel_to_bridge(list->controls[i], bridge);
+ }
+
ast_ari_response_no_content(response);
}
void ast_ari_remove_channel_from_bridge(struct ast_variable *headers, struct ast_remove_channel_from_bridge_args *args, struct ast_ari_response *response)
{
RAII_VAR(struct ast_bridge *, bridge, find_bridge(response, args->bridge_id), ao2_cleanup);
- RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+ RAII_VAR(struct control_list *, list, NULL, ao2_cleanup);
+ size_t i;
+
if (!bridge) {
- return;
- }
-
- control = find_channel_control(response, args->channel);
- if (!control) {
+ /* Response filled in by find_bridge */
+ return;
+ }
+
+ list = control_list_create(response, args->channel_count, args->channel);
+ if (!list) {
+ /* Response filled in by control_list_create() */
return;
}
@@ -141,9 +203,14 @@
* the bridge the channel is in. This will be possible once the bridge uniqueid
* is added to the channel snapshot. A 409 response should be issued if the bridge
* uniqueids don't match */
- if (stasis_app_control_remove_channel_from_bridge(control, bridge)) {
- ast_ari_response_error(response, 500, "Internal Error",
- "Could not remove channel from bridge");
+ for (i = 0; i < list->count; ++i) {
+ if (stasis_app_control_remove_channel_from_bridge(list->controls[i], bridge)) {
+ ast_ari_response_error(response, 500, "Internal Error",
+ "Could not remove channel from bridge");
+ }
+ }
+
+ if (response->response_code) {
return;
}
Modified: team/mmichelson/queue_bugbug/res/ari/resource_bridges.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/queue_bugbug/res/ari/resource_bridges.h?view=diff&rev=396133&r1=396132&r2=396133
==============================================================================
--- team/mmichelson/queue_bugbug/res/ari/resource_bridges.h (original)
[... 2355 lines stripped ...]
More information about the asterisk-commits
mailing list