[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