aboutsummaryrefslogtreecommitdiffstats
path: root/include/asterisk/module.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/asterisk/module.h')
-rw-r--r--include/asterisk/module.h309
1 files changed, 113 insertions, 196 deletions
diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index 2b94bae26..4ce6e9460 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -4,6 +4,8 @@
* Copyright (C) 1999 - 2006, Digium, Inc.
*
* Mark Spencer <markster@digium.com>
+ * Kevin P. Fleming <kpfleming@digium.com>
+ * Luigi Rizzo <rizzo@icir.org>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
@@ -26,19 +28,12 @@
#ifndef _ASTERISK_MODULE_H
#define _ASTERISK_MODULE_H
-#ifdef STATIC_MODULE
-#error STATIC_MODULE should not be defined
-#endif
-#define STATIC_MODULE --- this is an error
-#define LOCAL_USER_DECL /* --- this is an error --- */
-
#include "asterisk/utils.h"
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
-
/*! \brief The text the key() function should return. */
#define ASTERISK_GPL_KEY \
"This paragraph is copyright (c) 2006 by Digium, Inc. \
@@ -55,24 +50,31 @@ express written permission of Digium, Inc. is prohibited.\n"
#define AST_MODULE_CONFIG "modules.conf" /*!< \brief Module configuration file */
-enum unload_mode {
- AST_FORCE_SOFT = 0, /*! Softly unload a module, only if not in use */
- AST_FORCE_FIRM = 1, /*! Firmly unload a module, even if in use */
- AST_FORCE_HARD = 2, /*! as FIRM, plus dlclose() on the module. Not recommended
+enum ast_module_unload_mode {
+ AST_FORCE_SOFT = 0, /*!< Softly unload a module, only if not in use */
+ AST_FORCE_FIRM = 1, /*!< Firmly unload a module, even if in use */
+ AST_FORCE_HARD = 2, /*!< as FIRM, plus dlclose() on the module. Not recommended
as it may cause crashes */
};
+enum ast_module_load_result {
+ AST_MODULE_LOAD_SUCCESS = 0, /*!< Module loaded and configured */
+ AST_MODULE_LOAD_DECLINE = 1, /*!< Module is not configured */
+ AST_MODULE_LOAD_SKIP = 2, /*!< Module was skipped for some reason */
+ AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */
+};
+
/*!
* \brief Load a module.
- * \param resource_name The filename of the module to load.
+ * \param resource_name The name of the module to load.
*
* This function is run by the PBX to load the modules. It performs
* all loading and initilization tasks. Basically, to load a module, just
* give it the name of the module and it will do the rest.
*
- * \return Zero on success, -1 on error.
+ * \return See possible enum values for ast_module_load_result.
*/
-int ast_load_resource(const char *resource_name);
+enum ast_module_load_result ast_load_resource(const char *resource_name);
/*!
* \brief Unloads a module.
@@ -82,11 +84,11 @@ int ast_load_resource(const char *resource_name);
* This function unloads a module. It will only unload modules that are not in
* use (usecount not zero), unless #AST_FORCE_FIRM or #AST_FORCE_HARD is
* specified. Setting #AST_FORCE_FIRM or #AST_FORCE_HARD will unload the
- * module regardless of consequences (NOT_RECOMMENDED).
+ * module regardless of consequences (NOT RECOMMENDED).
*
* \return Zero on success, -1 on error.
*/
-int ast_unload_resource(const char *resource_name, enum unload_mode);
+int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode);
/*!
* \brief Notify when usecount has been changed.
@@ -150,208 +152,123 @@ int ast_loader_unregister(int (*updater)(void));
*/
char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload);
-/* Local user routines keep track of which channels are using a given module
- resource. They can help make removing modules safer, particularly if
- they're in use at the time they have been requested to be removed */
+/* Opaque type for module handles generated by the loader */
-struct localuser {
- struct localuser *next;
- struct ast_channel *chan;
-};
+struct ast_module;
-struct module_symbols; /* forward declaration */
-struct localuser *ast_localuser_add(struct module_symbols *, struct ast_channel *);
-void ast_localuser_remove(struct module_symbols *, struct localuser *);
-void ast_hangup_localusers(struct module_symbols *);
+/* User count routines keep track of which channels are using a given module
+ resource. They can help make removing modules safer, particularly if
+ they're in use at the time they have been requested to be removed */
-/* XXX deprecated macros, only for backward compatibility */
-#define LOCAL_USER_ADD(u) do { u = ast_localuser_add(__mod_desc, chan); } while (0)
-#define LOCAL_USER_REMOVE(u) ast_localuser_remove(__mod_desc, u)
-#define STANDARD_HANGUP_LOCALUSERS ast_hangup_localusers(__mod_desc)
+struct ast_module_user;
+struct ast_module_user_list;
/*! \page ModMngmnt The Asterisk Module management interface
- * \par The following is part of the new module management code.
*
* All modules must implement the module API (load, unload...)
* whose functions are exported through fields of a "struct module_symbol";
- *
- * Modules exporting extra symbols (data or functions), should list
- * them into an array of struct symbol_entry:
- * struct symbol_entry exported_symbols[]
- * of symbols, with a NULL name on the last entry
- *
- * Functions should be added with MOD_FUNC(name),
- * data structures with MOD_DATA(_name).
- * The array in turn is referenced by struct module_symbols.
- * (Typically, a module will export only a single symbol, which points
- * to a record containing all the methods. This is the API of the module,
- * and should be known to the module's clients as well.
- *
- * \par Connections to symbols in other modules
- * Modules that require symbols supplied by other modules should
- * provide an array
- * struct symbol_entry required_symbols[]
- * of symbols, with a NULL name on the last entry, containing the
- * name of the desired symbol.
- * For good measure, we also provide the size in both caller and calle
- * to figure out if there is a mismatch (not terribly useful because most
- * objects are a single word, but still... )
- * The symbol can be added to the array with MOD_WANT(symbol) macro.
- * required_symbols is also pointed by through struct module_symbols.
- *
- * Typically, the whole interface exported by a module should be
- * in a single structure named after the module, as follows.
- * Say the module high level name is 'foo', then we should have
- * - in include/asterisk/foo.h
- * struct foo_interface {
- * int (*f)(int, char *); -- first function exported
- * const char (*g)(int); -- second function exported
- * char *buf;
- * ... -- other fields
- * }
- * - in the module exporting the interface, e.g. res/res_foo.c
- * static int f(int, char *);
- * static const char *g(int);
- * const char buf[BUFSZ];
- * struct foo_interface foo = {
- * .f = f,
- * .g = g,
- * .buf = buf,
- * }
- *
- * \note NOTE: symbol names are 'global' in this module namespace, so it
- * will be wiser to name exported symbols with a prefix indicating the module
- * supplying it, e.g. foo_f, foo_g, foo_buf. Internally to the module,
- * symbols are still static so they can keep short and meaningful names.
- * The macros MOD_FIELD and METHOD_BASE() below help setting these entries.
- *
- * MOD_FIELD(f1), -- field and function name are the same
- * METHOD_BASE(foo_, f1), -- field and function name differ by a prefix
- * .f1 = function_name, -- generic case
- * }
- *
- * Note that the loader requires that no fields of exported_symbols
- * are NULL, because that is used as an indication of the end of the array.
- *
- * \par Module states
- * Modules can be in a number of different states, as below:
- * - \b MS_FAILED attempt to load failed. This is final.
- * - \b MS_NEW just added to the list, symbols unresolved.
- * - \b MS_RESOLVED all symbols resolved, but supplier modules not active yet.
- * - \b MS_CANLOAD all symbols resolved and suppliers are all active
- * (or we are in a cyclic dependency and we are breaking a loop)
- * - \b MS_ACTIVE load() returned successfully.
- *
- *
- * \par Module Types
- * For backward compatibility, we have 3 types of loadable modules:
- *
- * - \b MOD_0 these are the 'old style' modules, which export a number
- * of callbacks, and their full interface, as globally visible
- * symbols. The module needs to be loaded with RTLD_LAZY and
- * RTLD_GLOBAL to make symbols visible to other modules, and
- * to avoid load failures due to cross dependencies.
- *
- * - \b MOD_1 almost as above, but the generic callbacks are all into a
- * a structure, mod_data. Same load requirements as above.
- *
- * - \b MOD_2 this is the 'new style' format for modules. The module must
- * explictly declare which simbols are exported and which
- * symbols from other modules are used, and the code in this
- * loader will implement appropriate checks to load the modules
- * in the correct order. Also this allows to load modules
- * with RTLD_NOW and RTLD_LOCAL so there is no chance of run-time
- * bugs due to unresolved symbols or name conflicts.
*/
-struct symbol_entry {
- const char *name;
- void *value;
- int size;
- struct module *src; /* module sourcing it, filled by loader */
+enum ast_module_flags {
+ AST_MODFLAG_DEFAULT = 0,
+ AST_MODFLAG_GLOBAL_SYMBOLS = (1 << 0),
};
-/*
- * Constructors for symbol_entry values
- */
-#define MOD_FUNC(f) { .name = #f, .value = f, .size = sizeof(f) }
-#define MOD_DATA(d) { .name = #d, .value = &d, .size = sizeof(_name) }
-#define MOD_WANT(s) { .name = #s, .value = &s, 0 } /* required symbols */
+struct ast_module_info {
-/*
- * Constructors for fields of foo_interface
- */
-#define MOD_FIELD(f) . ## f = f
-#define METHOD_BASE(_base, _name) . ## _name = _base ## _name
+ /* The 'self' pointer for a module; it will be set by the loader before
+ it calls the module's load_module() entrypoint, and used by various
+ other macros that need to identify the module.
+ */
-/*
- * Each 'registerable' entity has a pointer in the
- * struct ast_registry, which points to an array of objects of
- * the same type. The ast_*_register() function will be able to
- * derive the size of these entries.
- */
-struct ast_registry {
- struct ast_cli_entry *clis;
-};
+ struct ast_module *self;
+ enum ast_module_load_result (*load)(void); /* register stuff etc. Optional. */
+ int (*reload)(void); /* config etc. Optional. */
+ int (*unload)(void); /* unload. called with the module locked */
+ const char *name; /* name of the module for loader reference and CLI commands */
+ const char *description; /* user friendly description of the module. */
-struct module_symbols {
- /* load, reload and unload receive as argument a pointer to a module descriptor
- * to be stored locally and used for local calls and so on.
- * They all return 0 on success, non zero (-1) on failure.
+ /*!
+ * This holds the ASTERISK_GPL_KEY, signifiying that you agree to the terms of
+ * the Asterisk license as stated in the ASTERISK_GPL_KEY. Your module will not
+ * load if it does not return the EXACT key string.
*/
- int (*load_module)(void *); /* register stuff etc. Optional. */
+ const char *key;
+ unsigned int flags;
+};
- int (*reload)(void *); /* reload config etc. Optional. */
+void ast_module_register(const struct ast_module_info *);
+void ast_module_unregister(const struct ast_module_info *);
- int (*unload_module)(void *); /* unload. called with the module locked */
+struct ast_module_user *__ast_module_user_add(struct ast_module *, struct ast_channel *);
+void __ast_module_user_remove(struct ast_module *, struct ast_module_user *);
+void __ast_module_user_hangup_all(struct ast_module *);
- const char *(*description)(void); /* textual id of the module. */
+#define ast_module_user_add(chan) __ast_module_user_add(ast_module_info->self, chan)
+#define ast_module_user_remove(user) __ast_module_user_remove(ast_module_info->self, user)
+#define ast_module_user_hangup_all() __ast_module_user_hangup_all(ast_module_info->self)
- /*!
- * This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of
- * the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does
- * not return the EXACT message:
- */
- const char *(*key)(void); /*! the asterisk key */
-
- enum module_flags {
- MOD_0 = 0x0, /* old module style */
- MOD_1 = 0x1, /* old style, but symbols here */
- MOD_2 = 0x2, /* new style, exported symbols */
- MOD_MASK = 0xf, /* mask for module types */
- NO_USECOUNT = 0x10, /* do not track usecount */
- NO_UNLOAD = 0x20, /* only forced unload allowed */
- DO_LOCALUSERS = 0x40, /* track localusers */
- } flags;
- /* the following two fields should go in the astobj. */
- ast_mutex_t lock;
- int usecnt; /* number of active clients */
-
- /* list of clients */
- struct localuser *lu_head;
- struct ast_registry *reg; /* list of things to register. */
- struct symbol_entry *exported_symbols;
- struct symbol_entry *required_symbols;
-};
-
-#ifndef MOD_LOADER /* the loader does not use these */
-struct module_symbols mod_data; /* forward declaration */
-static struct module_symbols *__mod_desc __attribute__ ((__unused__)) = &mod_data; /* used by localuser */
-
-#define STD_MOD(t, reload_fn, exp, req) \
-struct module_symbols mod_data = { \
- .load_module = load_module, \
- .unload_module = unload_module, \
- .description = description, \
- .key = key, \
- .reload = reload_fn, \
- .flags = t, \
- .exported_symbols = exp, \
- .required_symbols = req \
-};
+struct ast_module *ast_module_ref(struct ast_module *);
+void ast_module_unref(struct ast_module *);
-#define STD_MOD1 STD_MOD(MOD_1, NULL, NULL, NULL)
+#if defined(__cplusplus) || defined(c_plusplus)
+#define AST_MODULE_INFO(keystr, flags_to_set, desc, load_func, unload_func, reload_func) \
+ static struct ast_module_info __mod_info = { \
+ NULL, \
+ load_func, \
+ unload_func, \
+ reload_func, \
+ AST_MODULE, \
+ desc, \
+ keystr, \
+ flags_to_set \
+ }; \
+ static void __attribute__ ((constructor)) __reg_module(void) \
+ { \
+ ast_module_register(&__mod_info); \
+ } \
+ static void __attribute__ ((destructor)) __unreg_module(void) \
+ { \
+ ast_module_unregister(&__mod_info); \
+ } \
+ const static __attribute__((unused)) struct ast_module_info *ast_module_info = &__mod_info
+
+#define AST_MODULE_INFO_STANDARD(keystr, desc) \
+ AST_MODULE_INFO(keystr, AST_MODFLAG_DEFAULT, desc, \
+ load_module, \
+ unload_module, \
+ NULL \
+ )
+#else
+/* forward declare this pointer in modules, so that macro/function
+ calls that need it can get it, since it will actually be declared
+ and populated at the end of the module's source file... */
+const static __attribute__((unused)) struct ast_module_info *ast_module_info;
+
+#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...) \
+ static struct ast_module_info __mod_info = { \
+ .name = AST_MODULE, \
+ .flags = flags_to_set, \
+ .description = desc, \
+ .key = keystr, \
+ fields \
+ }; \
+ static void __attribute__ ((constructor)) __reg_module(void) \
+ { \
+ ast_module_register(&__mod_info); \
+ } \
+ static void __attribute__ ((destructor)) __unreg_module(void) \
+ { \
+ ast_module_unregister(&__mod_info); \
+ } \
+ const static struct ast_module_info *ast_module_info = &__mod_info
+
+#define AST_MODULE_INFO_STANDARD(keystr, desc) \
+ AST_MODULE_INFO(keystr, AST_MODFLAG_DEFAULT, desc, \
+ .load = load_module, \
+ .unload = unload_module, \
+ )
#endif
#if defined(__cplusplus) || defined(c_plusplus)