[asterisk-commits] dlee: branch dlee/ASTERISK-22296 r397592 - /team/dlee/ASTERISK-22296/main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Fri Aug 23 15:53:04 CDT 2013
Author: dlee
Date: Fri Aug 23 15:53:01 2013
New Revision: 397592
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397592
Log:
MOAR HACKING
Added:
team/dlee/ASTERISK-22296/main/optional_api.c (with props)
Added: team/dlee/ASTERISK-22296/main/optional_api.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/optional_api.c?view=auto&rev=397592
==============================================================================
--- team/dlee/ASTERISK-22296/main/optional_api.c (added)
+++ team/dlee/ASTERISK-22296/main/optional_api.c Fri Aug 23 15:53:01 2013
@@ -1,0 +1,163 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * David M. Lee, II <dlee at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#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;
+ ast_optional_fn stub;
+ const char *module;
+ 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) {
+ 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);
+ }
+ *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);
+ 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);
+}
Propchange: team/dlee/ASTERISK-22296/main/optional_api.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/dlee/ASTERISK-22296/main/optional_api.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/dlee/ASTERISK-22296/main/optional_api.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list