[asterisk-commits] dlee: branch dlee/ASTERISK-22296 r397642 - in /team/dlee/ASTERISK-22296: incl...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Aug 26 10:43:13 CDT 2013


Author: dlee
Date: Mon Aug 26 10:43:11 2013
New Revision: 397642

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397642
Log:
Try with less magic

Modified:
    team/dlee/ASTERISK-22296/include/asterisk/ari.h
    team/dlee/ASTERISK-22296/include/asterisk/http_websocket.h
    team/dlee/ASTERISK-22296/include/asterisk/optional_api.h
    team/dlee/ASTERISK-22296/main/loader.c
    team/dlee/ASTERISK-22296/main/optional_api.c
    team/dlee/ASTERISK-22296/res/ari/ari_websockets.c
    team/dlee/ASTERISK-22296/res/res_ari.c
    team/dlee/ASTERISK-22296/res/res_ari_asterisk.c
    team/dlee/ASTERISK-22296/res/res_ari_bridges.c
    team/dlee/ASTERISK-22296/res/res_ari_channels.c
    team/dlee/ASTERISK-22296/res/res_ari_endpoints.c
    team/dlee/ASTERISK-22296/res/res_ari_events.c
    team/dlee/ASTERISK-22296/res/res_ari_playback.c
    team/dlee/ASTERISK-22296/res/res_ari_recordings.c
    team/dlee/ASTERISK-22296/res/res_ari_sounds.c
    team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache

Modified: team/dlee/ASTERISK-22296/include/asterisk/ari.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/include/asterisk/ari.h?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/include/asterisk/ari.h (original)
+++ team/dlee/ASTERISK-22296/include/asterisk/ari.h Mon Aug 26 10:43:11 2013
@@ -31,6 +31,7 @@
 
 #include "asterisk/http.h"
 #include "asterisk/json.h"
+#include "asterisk/http_websocket.h"
 
 /*!
  * \brief Configured encoding format for JSON output.
@@ -51,8 +52,6 @@
 				     struct ast_variable *path_vars,
 				     struct ast_variable *headers,
 				     struct ast_ari_response *response);
-
-struct ast_websocket_server;
 
 /*!
  * \brief Handler for a single RESTful path segment.
@@ -145,8 +144,6 @@
 /*! \brief Abstraction for reading/writing JSON to a WebSocket */
 struct ast_ari_websocket_session;
 
-struct ast_websocket;
-
 /*!
  * \brief Create an ARI WebSocket session.
  *

Modified: team/dlee/ASTERISK-22296/include/asterisk/http_websocket.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/include/asterisk/http_websocket.h?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/include/asterisk/http_websocket.h (original)
+++ team/dlee/ASTERISK-22296/include/asterisk/http_websocket.h Mon Aug 26 10:43:11 2013
@@ -92,7 +92,7 @@
  * \retval 0 success
  * \retval -1 if sub-protocol handler could not be registered
  */
-AST_OPTIONAL_API(int, ast_websocket_add_protocol, (const char *name, ast_websocket_callback callback), {ast_log(LOG_ERROR, "Stubbed!\n"); return -1;});
+AST_OPTIONAL_API(int, ast_websocket_add_protocol, (const char *name, ast_websocket_callback callback), {return -1;});
 
 /*!
  * \brief Remove a sub-protocol handler from the default /ws server.
@@ -103,7 +103,7 @@
  * \retval 0 success
  * \retval -1 if sub-protocol was not found or if callback did not match
  */
-AST_OPTIONAL_API(int, ast_websocket_remove_protocol, (const char *name, ast_websocket_callback callback), {ast_log(LOG_ERROR, "Stubbed!\n"); return -1;});
+AST_OPTIONAL_API(int, ast_websocket_remove_protocol, (const char *name, ast_websocket_callback callback), {return -1;});
 
 /*!
  * \brief Add a sub-protocol handler to the given server.
@@ -143,7 +143,7 @@
  *
  * \note Once an AST_WEBSOCKET_OPCODE_CLOSE opcode is received the socket will be closed
  */
-AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_read, (struct ast_websocket *session, char **payload, uint64_t *payload_len, enum ast_websocket_opcode *opcode, int *fragmented), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Construct and transmit a WebSocket frame
@@ -156,7 +156,7 @@
  * \retval 0 if successfully written
  * \retval -1 if error occurred
  */
-AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_write, (struct ast_websocket *session, enum ast_websocket_opcode opcode, char *payload, uint64_t actual_length), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Close a WebSocket session by sending a message with the CLOSE opcode and an optional code
@@ -167,7 +167,7 @@
  * \retval 0 if successfully written
  * \retval -1 if error occurred
  */
-AST_OPTIONAL_API(int, ast_websocket_close, (struct ast_websocket *session, uint16_t reason), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_close, (struct ast_websocket *session, uint16_t reason), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Enable multi-frame reconstruction up to a certain number of bytes
@@ -176,7 +176,7 @@
  * \param bytes If a reconstructed payload exceeds the specified number of bytes the payload will be returned
  *              and upon reception of the next multi-frame a new reconstructed payload will begin.
  */
-AST_OPTIONAL_API(void, ast_websocket_reconstruct_enable, (struct ast_websocket *session, size_t bytes), {ast_log(LOG_ERROR, "Stubbed!\n"); return;});
+AST_OPTIONAL_API(void, ast_websocket_reconstruct_enable, (struct ast_websocket *session, size_t bytes), {return;});
 
 /*!
  * \brief Disable multi-frame reconstruction
@@ -186,14 +186,14 @@
  * \note If reconstruction is disabled each message that is part of a multi-frame message will be sent up to
  *       the user when ast_websocket_read is called.
  */
-AST_OPTIONAL_API(void, ast_websocket_reconstruct_disable, (struct ast_websocket *session), {ast_log(LOG_ERROR, "Stubbed!\n"); return;});
+AST_OPTIONAL_API(void, ast_websocket_reconstruct_disable, (struct ast_websocket *session), {return;});
 
 /*!
  * \brief Increase the reference count for a WebSocket session
  *
  * \param session Pointer to the WebSocket session
  */
-AST_OPTIONAL_API(void, ast_websocket_ref, (struct ast_websocket *session), {ast_log(LOG_ERROR, "Stubbed!\n"); return;});
+AST_OPTIONAL_API(void, ast_websocket_ref, (struct ast_websocket *session), {return;});
 
 /*!
  * \brief Decrease the reference count for a WebSocket session
@@ -209,14 +209,14 @@
  *
  * \note You must *not* directly read from or write to this file descriptor. It should only be used for polling.
  */
-AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Get the remote address for a WebSocket connected session.
  *
  * \retval ast_sockaddr Remote address
  */
-AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {ast_log(LOG_ERROR, "Stubbed!\n"); return NULL;});
+AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {return NULL;});
 
 /*!
  * \brief Get whether the WebSocket session is using a secure transport or not.
@@ -224,7 +224,7 @@
  * \retval 0 if unsecure
  * \retval 1 if secure
  */
-AST_OPTIONAL_API(int, ast_websocket_is_secure, (struct ast_websocket *session), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_is_secure, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
 
 /*!
  * \brief Set the socket of a WebSocket session to be non-blocking.
@@ -232,6 +232,6 @@
  * \retval 0 on success
  * \retval -1 on failure
  */
-AST_OPTIONAL_API(int, ast_websocket_set_nonblock, (struct ast_websocket *session), { ast_log(LOG_ERROR, "Stubbed!\n"); errno = ENOSYS; return -1;});
+AST_OPTIONAL_API(int, ast_websocket_set_nonblock, (struct ast_websocket *session), { errno = ENOSYS; return -1;});
 
 #endif

Modified: team/dlee/ASTERISK-22296/include/asterisk/optional_api.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/include/asterisk/optional_api.h?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/include/asterisk/optional_api.h (original)
+++ team/dlee/ASTERISK-22296/include/asterisk/optional_api.h Mon Aug 26 10:43:11 2013
@@ -109,9 +109,12 @@
 
 typedef void (*ast_optional_fn)(void);
 
-void ast_optional_api_register(ast_optional_fn *function, ast_optional_fn stub,
-	const char *symname, const char *module);
-void ast_optional_api_unregister(ast_optional_fn *function);
+void ast_optional_api_provide(const char *symname, ast_optional_fn impl);
+void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl);
+void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
+	ast_optional_fn stub, const char *module);
+void ast_optional_api_unuse(const char *symname, ast_optional_fn *function,
+	const char *module);
 
 void optional_api_onload(void);
 void optional_api_onunload(void);
@@ -121,38 +124,51 @@
 #if defined(AST_API_MODULE)
 /* Module defining the API */
 
+#define AST_OPTIONAL_API_IMPL_INIT(name)				\
+	static void __attribute__((constructor)) __init__##name##_impl(void) { \
+		ast_optional_api_provide(#name,				\
+			(ast_optional_fn)AST_OPTIONAL_API_NAME(name));	\
+	}								\
+	static void __attribute__((destructor)) __dtor__##name##_impl(void) { \
+		ast_optional_api_unprovide(#name,			\
+			(ast_optional_fn)AST_OPTIONAL_API_NAME(name));	\
+	}
+
 #define AST_OPTIONAL_API(result, name, proto, stub)			\
 	result AST_OPTIONAL_API_NAME(name) proto;			\
-	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name)
+	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
+	     name = AST_OPTIONAL_API_NAME(name);			\
+	AST_OPTIONAL_API_IMPL_INIT(name)
 
 #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)		\
 	result  __attribute__((attr)) AST_OPTIONAL_API_NAME(name) proto; \
-	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const name = AST_OPTIONAL_API_NAME(name)
+	static attribute_unused typeof(AST_OPTIONAL_API_NAME(name)) * const \
+	     name = AST_OPTIONAL_API_NAME(name);			\
+	AST_OPTIONAL_API_IMPL_INIT(name)
 
 #else
 /* Module using the API */
 
 #define AST_OPTIONAL_API_INIT(name)					\
 	static void __attribute__((constructor)) __init__##name(void) {	\
-		ast_verb(3, "%s: %d - init\n", __FILE__, __LINE__);	\
-		ast_optional_api_register((ast_optional_fn *)&name,	\
-			(ast_optional_fn)__stub__##name, "__" #name,	\
+		ast_optional_api_use(#name, (ast_optional_fn *)&name,	\
+			(ast_optional_fn)__stub__##name,		\
 			AST_MODULE);					\
 	}								\
 	static void __attribute__((destructor)) __dtor__##name(void) {	\
-		ast_verb(3, "%s: %d - dtor\n", __FILE__, __LINE__);	\
-		ast_optional_api_unregister((ast_optional_fn *)&name);	\
+		ast_optional_api_unuse(#name, (ast_optional_fn *)&name, \
+			AST_MODULE);					\
 	}
+
+#define AST_OPTIONAL_API(result, name, proto, stub)			\
+	static result __stub__##name proto stub;			\
+	static attribute_unused						\
+		typeof(__stub__##name) * name;				\
+	AST_OPTIONAL_API_INIT(name)
 
 #define AST_OPTIONAL_API_ATTR(result, attr, name, proto, stub)		\
 	static __attribute__((attr)) result __stub__##name proto stub;	\
 	static attribute_unused	__attribute__((attr))			\
-		typeof(__stub__##name) * name;				\
-	AST_OPTIONAL_API_INIT(name)
-
-#define AST_OPTIONAL_API(result, name, proto, stub)			\
-	static result __stub__##name proto stub;			\
-	static attribute_unused						\
 		typeof(__stub__##name) * name;				\
 	AST_OPTIONAL_API_INIT(name)
 

Modified: team/dlee/ASTERISK-22296/main/loader.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/loader.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/main/loader.c (original)
+++ team/dlee/ASTERISK-22296/main/loader.c Mon Aug 26 10:43:11 2013
@@ -415,7 +415,8 @@
 	if (lib)
 		while (!dlclose(lib));
 
-	/* If mod offered an optional API, it's not there any more! */
+	/* If mod offered an optional API, it's not there any more!
+	 * Scan optional_api users for potential unloads. */
 	optional_api_onunload();
 }
 
@@ -449,7 +450,6 @@
 	if (missing_so)
 		strcat(resource_being_loaded->resource, ".so");
 
-	ast_verb(3, "Inspecting %s\n", fn);
 	if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
 		ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
 		ast_free(resource_being_loaded);
@@ -477,7 +477,6 @@
 	/* if we are being asked only to load modules that provide global symbols,
 	   and this one does not, then close it and return */
 	if (global_symbols_only && !wants_global) {
-		ast_verb(3, "  Unloading %s\n", fn);
 		while (!dlclose(lib));
 		return NULL;
 	}
@@ -503,7 +502,6 @@
 	}
 #endif
 
-	ast_verb(3, "  Unloading %s\n", fn);
 	while (!dlclose(lib));
 	resource_being_loaded = NULL;
 
@@ -515,7 +513,6 @@
 	if (missing_so)
 		strcat(resource_being_loaded->resource, ".so");
 
-	ast_verb(3, "Opening %s\n", fn);
 	if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
 		ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
 		ast_free(resource_being_loaded);
@@ -1104,6 +1101,9 @@
 	if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
 		return -1;
 	}
+
+	ast_verb(1, "Loading modules%s exporting global symbols\n",
+		global_symbols ? "" : " not");
 
 	/* first, add find and add modules to heap */
 	AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
@@ -1279,6 +1279,9 @@
 	if (load_count)
 		ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
 
+	ast_verb(1, "Loading %spreload modules\n",
+		preload_only ? "" : "non-");
+
 	/* first, load only modules that provide global symbols */
 	if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
 		goto done;

Modified: team/dlee/ASTERISK-22296/main/optional_api.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/optional_api.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/main/optional_api.c (original)
+++ team/dlee/ASTERISK-22296/main/optional_api.c Mon Aug 26 10:43:11 2013
@@ -20,144 +20,262 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include "asterisk/astobj2.h"
+#include "asterisk/lock.h"
 #include "asterisk/optional_api.h"
-#include "asterisk/linkedlists.h"
 #include "asterisk/utils.h"
 
-#include <dlfcn.h>
-
-struct optional_ref {
-	AST_LIST_ENTRY(optional_ref) list;
-
-	ast_optional_fn *function;
+struct optional_api_user {
+	ast_optional_fn *optional_ref;
 	ast_optional_fn stub;
-	const char *module;
+	char module[];
+};
+
+struct optional_api {
+	ast_optional_fn impl;
+	struct ao2_container *users;
 	char symname[];
 };
 
-static AST_LIST_HEAD_STATIC(optional_references, optional_ref);
-
-static void optional_ref_dtor(void *obj)
-{
-	struct optional_ref *ref = obj;
-	*(ref->function) = ref->stub;
-}
-
-static struct optional_ref *optional_ref_create(ast_optional_fn *function,
-	ast_optional_fn stub, const char *symname, const char *module)
-{
-	RAII_VAR(struct optional_ref *, ref, NULL, ao2_cleanup);
-
-	size_t size = sizeof(*ref) + strlen(symname) + 1;
-	ref = ao2_alloc(size, optional_ref_dtor);
-	if (!ref) {
-		return NULL;
-	}
-
-	ref->function = function;
-	ref->stub = stub;
-	/* Safe strcpy */
-	strcpy(ref->symname, symname);
-	/* Module name is a #define; safe to reference without copy */
-	ref->module = module;
-
-	return ao2_bump(ref);
-}
-
-static void optional_ref_update(struct optional_ref *ref)
-{
-	void *real_fn;
-
-	if (!ref) {
+static void optional_api_dtor(void *obj)
+{
+	struct optional_api *api = obj;
+
+	ao2_cleanup(api->users);
+	api->users = NULL;
+}
+
+static struct optional_api *optional_api_create(const char *symname)
+{
+	RAII_VAR(struct optional_api *, api, NULL, ao2_cleanup);
+	size_t size;
+
+	if (!symname) {
+		return NULL;
+	}
+	size = sizeof(*api) + strlen(symname) + 1;
+
+	api = ao2_alloc_options(size, optional_api_dtor, OBJ_NOLOCK);
+	if (!api) {
+		return NULL;
+	}
+
+	api->users = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
+		NULL, NULL);
+	if (!api->users) {
+		return NULL;
+	}
+
+	return ao2_bump(api);
+}
+
+static void optional_api_user_dtor(void *obj) {
+	struct optional_api_user *user = obj;
+
+	ast_assert(*user->optional_ref == user->stub);
+}
+
+static struct optional_api_user *optional_api_user_create(
+	ast_optional_fn *optional_ref, ast_optional_fn stub, const char *module)
+{
+	RAII_VAR(struct optional_api_user *, user, NULL, ao2_cleanup);
+	size_t size = sizeof(*user) + strlen(module) + 1;
+
+	user = ao2_alloc_options(size, optional_api_user_dtor,
+		AO2_ALLOC_OPT_LOCK_NOLOCK);
+	if (!user) {
+		return NULL;
+	}
+
+	user->optional_ref = optional_ref;
+	user->stub = stub;
+	/* safe strcpy */
+	strcpy(user->module, module);
+
+	return ao2_bump(user);
+
+}
+
+static struct ao2_container *_apis;
+
+static int optional_api_sort(const void *obj_left, const void *obj_right,
+	int flags)
+{
+	const struct optional_api *object_left = obj_left;
+	const struct optional_api *object_right = obj_right;
+	const char *right_key = obj_right;
+	int cmp;
+
+	switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+	case OBJ_POINTER:
+		right_key = object_right->symname;
+		/* Fall through */
+	case OBJ_KEY:
+		cmp = strcmp(object_left->symname, right_key);
+		break;
+	case OBJ_PARTIAL_KEY:
+		/*
+		 * We could also use a partial key struct containing a length
+		 * so strlen() does not get called for every comparison instead.
+		 */
+		cmp = strncmp(object_left->symname, right_key, strlen(right_key));
+		break;
+	default:
+		/* Sort can only work on something with a full or partial key. */
+		ast_assert(0);
+		cmp = 0;
+		break;
+	}
+	return cmp;
+}
+
+static void optional_api_cleanup(void)
+{
+	ao2_cleanup(_apis);
+	_apis = NULL;
+}
+
+static struct ao2_container *get_apis(void)
+{
+	/* optional_api calls can happen before main() starts, or during
+	 * dlopen() as modules are loaded. These are (or at least should be)
+	 * synchronized, so no lock is needed here.
+	 *
+	 * Which is good, because there's no consistent way to build a global
+	 * mutex that we know will be initialized before get_apis() is first
+	 * called.
+	 */
+	if (_apis) {
+		return _apis;
+	}
+
+	ast_register_cleanup(optional_api_cleanup);
+
+	_apis = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_MUTEX,
+		AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, optional_api_sort,
+		NULL);
+	if (!_apis) {
+		ast_log(LOG_ERROR, "Failed to allocate apis\n");
+		ast_assert(0);
+		return NULL;
+	}
+
+	return 0;
+}
+
+static void optional_api_user_relink(struct optional_api_user *user,
+	struct optional_api *api)
+{
+	if (api->impl) {
+		ast_verb(4, "%s: linking %s\n", api->symname, user->module);
+		*user->optional_ref = api->impl;
+	} else {
+		ast_verb(4, "%s: stubbing %s\n", api->symname, user->module);
+		*user->optional_ref = user->stub;
+	}
+}
+
+static int optional_api_user_relink_cb(void *obj, void *arg, int flags)
+{
+	struct optional_api_user *user = obj;
+	struct optional_api *api = arg;
+
+	optional_api_user_relink(user, api);
+	return 0;
+}
+
+void ast_optional_api_provide(const char *symname, ast_optional_fn impl)
+{
+	RAII_VAR(struct optional_api *, api, NULL, ao2_cleanup);
+	SCOPED_AO2LOCK(lock, get_apis());
+
+	ast_verb(4, "%s: providing\n", symname);
+
+	api = ao2_find(get_apis(), symname, OBJ_NOLOCK);
+	if (!api) {
+		api = optional_api_create(symname);
+		if (!api) {
+			ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
+			return;
+		}
+	}
+
+	api->impl = impl;
+	ao2_callback(api->users, OBJ_NODATA, optional_api_user_relink_cb, impl);
+}
+
+void ast_optional_api_unprovide(const char *symname, ast_optional_fn impl)
+{
+	RAII_VAR(struct optional_api *, api, NULL, ao2_cleanup);
+	SCOPED_AO2LOCK(lock, get_apis());
+
+	ast_verb(4, "%s: un-providing\n", symname);
+
+	api = ao2_find(get_apis(), symname, OBJ_NOLOCK);
+	if (!api) {
+		ast_log(LOG_ERROR, "%s: Could not find api\n", symname);
 		return;
 	}
 
-	real_fn = dlsym(RTLD_DEFAULT, ref->symname);
-	if (real_fn) {
-		if (*ref->function == ref->stub) {
-			ast_verb(4, "Filling stub %s:%s\n", ref->module,
-				ref->symname);
+	api->impl = 0;
+	ao2_callback(api->users, OBJ_NODATA, optional_api_user_relink_cb, impl);
+}
+
+void ast_optional_api_use(const char *symname, ast_optional_fn *optional_ref,
+	ast_optional_fn stub, const char *module)
+{
+	RAII_VAR(struct optional_api_user *, user, NULL, ao2_cleanup);
+	RAII_VAR(struct optional_api *, api, NULL, ao2_cleanup);
+	SCOPED_AO2LOCK(lock, get_apis());
+
+	ast_verb(4, "%s: use by %s\n", symname, module);
+
+	api = ao2_find(get_apis(), symname, OBJ_NOLOCK);
+	if (!api) {
+		api = optional_api_create(symname);
+		if (!api) {
+			ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
+			return;
 		}
-		*ref->function = real_fn;
-	} else {
-		if (*ref->function != ref->stub) {
-			ast_verb(4, "Stubbing %s:%s\n", ref->module,
-				ref->symname);
-		}
-		*ref->function = ref->stub;
-	}
-}
-
-void ast_optional_api_register(ast_optional_fn *function, ast_optional_fn stub,
-	const char *symname, const char *module)
-{
-	RAII_VAR(struct optional_ref *, ref, NULL, ao2_cleanup);
-
-	ast_verb(4, "Registering stub %s:%s\n", module, symname);
-
-	/* Default the function to the stub */
-	*function = stub;
-
-	ref = optional_ref_create(function, stub, symname, module);
-	if (!ref) {
-		ast_log(LOG_ERROR, "Failed to fill in stub for %s:%s\n",
-			ref->module, symname);
+	}
+
+	user = optional_api_user_create(optional_ref, stub, module);
+	if (!user) {
+		ast_log(LOG_ERROR, "%s: Allocation failed\n", symname);
 		return;
 	}
 
-	/* Go ahead and link it, if we can */
-	optional_ref_update(ref);
-
-	AST_LIST_LOCK(&optional_references);
-	AST_LIST_INSERT_HEAD(&optional_references, ao2_bump(ref), list);
-	AST_LIST_UNLOCK(&optional_references);
-}
-
-void ast_optional_api_unregister(ast_optional_fn *function)
-{
-	struct optional_ref *ref;
-
-	ast_verb(4, "unref\n");
-
-	AST_LIST_LOCK(&optional_references);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&optional_references, ref, list) {
-		if (ref->function == function) {
-			ast_verb(5, "Unregistering stub %s:%s\n",
-				ref->module, ref->symname);
-			AST_LIST_REMOVE_CURRENT(list);
-			ao2_cleanup(ref);
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
-	AST_LIST_UNLOCK(&optional_references);
-}
-
-void optional_api_onload(void)
-{
-	struct optional_ref *ref;
-
-	AST_LIST_LOCK(&optional_references);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&optional_references, ref, list) {
-		/* Update any refs that are pointing to their proxy */
-		if (*ref->function == ref->stub) {
-			optional_ref_update(ref);
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
-	AST_LIST_UNLOCK(&optional_references);
-}
-
-void optional_api_onunload(void)
-{
-	struct optional_ref *ref;
-
-	AST_LIST_LOCK(&optional_references);
-	AST_LIST_TRAVERSE_SAFE_BEGIN(&optional_references, ref, list) {
-		/* Update any refs that are pointing to a real impl */
-		if (*ref->function != ref->stub) {
-			optional_ref_update(ref);
-		}
-	}
-	AST_LIST_TRAVERSE_SAFE_END;
-	AST_LIST_UNLOCK(&optional_references);
-}
+	optional_api_user_relink(user, api);
+}
+
+static int optional_api_user_find_and_unuse(void *obj, void *arg, int flags)
+{
+	struct optional_api_user *user = obj;
+	ast_optional_fn *optional_ref = arg;
+
+	if (user->optional_ref != optional_ref) {
+		return 0;
+	}
+
+	ast_verb(4, "   Stubbing %s\n", user->module);
+	*user->optional_ref = user->stub;
+	return CMP_MATCH | CMP_STOP;
+}
+
+void ast_optional_api_unuse(const char *symname, ast_optional_fn *optional_ref,
+	const char *module)
+{
+	RAII_VAR(struct optional_api *, api, NULL, ao2_cleanup);
+	SCOPED_AO2LOCK(lock, get_apis());
+
+	ast_verb(4, "%s: un-use by %s\n", symname, module);
+
+	api = ao2_find(get_apis(), symname, OBJ_NOLOCK);
+	if (!api) {
+		ast_log(LOG_ERROR, "%s: Could not find api\n", symname);
+		return;
+	}
+
+	ao2_callback(api->users, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA,
+		optional_api_user_find_and_unuse, optional_ref);
+}

Modified: team/dlee/ASTERISK-22296/res/ari/ari_websockets.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/ari/ari_websockets.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/ari/ari_websockets.c (original)
+++ team/dlee/ASTERISK-22296/res/ari/ari_websockets.c Mon Aug 26 10:43:11 2013
@@ -20,9 +20,8 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include "asterisk/astobj2.h"
 #include "asterisk/ari.h"
-#include "asterisk/astobj2.h"
-#include "asterisk/http_websocket.h"
 
 /*! \file
  *

Modified: team/dlee/ASTERISK-22296/res/res_ari.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari.c Mon Aug 26 10:43:11 2013
@@ -124,12 +124,11 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/internal.h"
-#include "asterisk/ari.h"
 #include "asterisk/astobj2.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/paths.h"
+#include "asterisk/ari.h"
+#include "ari/internal.h"
 
 #include <string.h>
 #include <sys/stat.h>

Modified: team/dlee/ASTERISK-22296/res/res_ari_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_asterisk.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_asterisk.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_asterisk.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_asterisk.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_asterisk.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_bridges.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_bridges.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_bridges.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_bridges.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_bridges.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_bridges.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_channels.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_channels.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_channels.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_channels.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_channels.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_endpoints.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_endpoints.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_endpoints.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_endpoints.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_endpoints.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_events.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_events.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_events.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_events.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_events.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_events.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_playback.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_playback.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_playback.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_playback.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_playback.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_playback.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_recordings.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_recordings.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_recordings.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_recordings.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_recordings.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_recordings.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/res/res_ari_sounds.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_sounds.c?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_sounds.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_sounds.c Mon Aug 26 10:43:11 2013
@@ -41,11 +41,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_sounds.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_sounds.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif

Modified: team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache?view=diff&rev=397642&r1=397641&r2=397642
==============================================================================
--- team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache (original)
+++ team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache Mon Aug 26 10:43:11 2013
@@ -46,11 +46,10 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
-#include "ari/resource_{{name}}.h"
 #include "asterisk/app.h"
-#include "asterisk/http_websocket.h"
 #include "asterisk/module.h"
 #include "asterisk/stasis_app.h"
+#include "ari/resource_{{name}}.h"
 #if defined(AST_DEVMODE)
 #include "ari/ari_model_validators.h"
 #endif




More information about the asterisk-commits mailing list