summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--apps/app_transfer.c2
-rw-r--r--channels/chan_sip.c1
-rw-r--r--include/asterisk/module.h2
-rw-r--r--main/cdr.c17
-rw-r--r--main/loader.c374
6 files changed, 232 insertions, 169 deletions
diff --git a/CHANGES b/CHANGES
index 8a7fb3198..7cfdedeac 100644
--- a/CHANGES
+++ b/CHANGES
@@ -21,6 +21,11 @@ Core
Asterisk is compiled with the LOW_MEMORY compile time option enabled because
the cache code does not exist.
+chan_sip
+------------------
+ * Calls to invalid extensions are now reported as an ACL failure security event
+ "no_extension_match".
+
res_rtp_asterisk
------------------
* The X.509 certificate used for DTLS negotation can now be automatically
diff --git a/apps/app_transfer.c b/apps/app_transfer.c
index 7bc67e154..1d7c87920 100644
--- a/apps/app_transfer.c
+++ b/apps/app_transfer.c
@@ -51,7 +51,7 @@
</syntax>
<description>
<para>Requests the remote caller be transferred
- to a given destination. If TECH (SIP, IAX2, LOCAL etc) is used, only
+ to a given destination. If TECH (SIP, IAX2, etc) is used, only
an incoming call with the same channel technology will be transferred.
Note that for SIP, if you transfer before call is setup, a 302 redirect
SIP message will be returned to the caller.</para>
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index 4bae39da0..b0573002b 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -26460,6 +26460,7 @@ static int handle_request_invite(struct sip_pvt *p, struct sip_request *req, str
ast_log(LOG_NOTICE, "Call from '%s' (%s) to extension"
" '%s' rejected because extension not found in context '%s'.\n",
S_OR(p->username, p->peername), ast_sockaddr_stringify(&p->recv), decoded_exten, p->context);
+ sip_report_failed_acl(p, "no_extension_match");
}
break;
case SIP_GET_DEST_REFUSED:
diff --git a/include/asterisk/module.h b/include/asterisk/module.h
index 6c60429c9..3df924c59 100644
--- a/include/asterisk/module.h
+++ b/include/asterisk/module.h
@@ -69,7 +69,7 @@ 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 (For loader.c use only. Should never be returned by modules)*/
- AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to prioity heap */
+ AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to priority list */
AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */
};
diff --git a/main/cdr.c b/main/cdr.c
index 3681cdc6b..0e0366836 100644
--- a/main/cdr.c
+++ b/main/cdr.c
@@ -2457,12 +2457,12 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
* \param cand_cdr The \ref cdr_object that is a candidate
*
*/
-static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
+static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *base_cand_cdr)
{
struct cdr_object_snapshot *party_a;
struct cdr_object *cand_cdr;
- SCOPED_AO2LOCK(lock, base_cand_cdr);
+ ao2_lock(base_cand_cdr);
for (cand_cdr = base_cand_cdr; cand_cdr; cand_cdr = cand_cdr->next) {
/* Skip any records that are not in this bridge */
@@ -2474,7 +2474,7 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)
|| (cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name))) {
- return 0;
+ break;
}
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
@@ -2482,7 +2482,7 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
* Party B */
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
- return 0;
+ break;
}
/* We're Party B. Check if we can add ourselves immediately or if we need
@@ -2502,9 +2502,11 @@ static int bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *b
*/
memset(&cand_cdr->end, 0, sizeof(cand_cdr->end));
}
- return 0;
+
+ break;
}
- return 0;
+
+ ao2_unlock(base_cand_cdr);
}
/*!
@@ -2587,6 +2589,7 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
ao2_lock(cdr);
+try_again:
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
if (it_cdr->fn_table->process_party_a) {
CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
@@ -2639,7 +2642,7 @@ static void handle_standard_bridge_enter_message(struct cdr_object *cdr,
/* This is guaranteed to succeed: the new CDR is created in the single state
* and will be able to handle the bridge enter message
*/
- handle_standard_bridge_enter_message(cdr, bridge, channel);
+ goto try_again;
}
}
ao2_unlock(cdr);
diff --git a/main/loader.c b/main/loader.c
index 23a29d994..2a203c6a7 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -52,7 +52,7 @@
#include "asterisk/features_config.h"
#include "asterisk/dsp.h"
#include "asterisk/udptl.h"
-#include "asterisk/heap.h"
+#include "asterisk/vector.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include "asterisk/sounds_index.h"
@@ -110,6 +110,8 @@ static const unsigned char expected_key[] =
static char buildopt_sum[33] = AST_BUILDOPT_SUM;
+AST_VECTOR(module_vector, struct ast_module *);
+
/*!
* \brief Internal flag to indicate all modules have been initially loaded.
*/
@@ -133,13 +135,34 @@ struct ast_module {
/*! This module is being held open until it's time to shutdown. */
unsigned int keepuntilshutdown:1;
} flags;
- AST_LIST_ENTRY(ast_module) list_entry;
AST_DLLIST_ENTRY(ast_module) entry;
char resource[0];
};
static AST_DLLIST_HEAD_STATIC(module_list, ast_module);
+static int module_vector_strcasecmp(struct ast_module *a, struct ast_module *b)
+{
+ return strcasecmp(a->resource, b->resource);
+}
+
+static int module_vector_cmp(struct ast_module *a, struct ast_module *b)
+{
+ /* if load_pri is not set, default is 128. Lower is better */
+ int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER)
+ ? a->info->load_pri : AST_MODPRI_DEFAULT;
+ int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER)
+ ? b->info->load_pri : AST_MODPRI_DEFAULT;
+
+ /*
+ * Returns comparison values for a vector sorted by priority.
+ * <0 a_pri < b_pri
+ * =0 a_pri == b_pri
+ * >0 a_pri > b_pri
+ */
+ return a_pri - b_pri;
+}
+
const char *ast_module_name(const struct ast_module *mod)
{
if (!mod || !mod->info) {
@@ -167,38 +190,51 @@ static int do_full_reload = 0;
static AST_DLLIST_HEAD_STATIC(reload_queue, reload_queue_item);
-/* when dynamic modules are being loaded, ast_module_register() will
- need to know what filename the module was loaded from while it
- is being registered
-*/
+/*!
+ * \internal
+ *
+ * This variable is set by load_dynamic_module so ast_module_register
+ * can know what pointer is being registered.
+ *
+ * This is protected by the module_list lock.
+ */
static struct ast_module *resource_being_loaded;
-/* XXX: should we check for duplicate resource names here? */
-
+/*!
+ * \internal
+ * \brief Used by AST_MODULE_INFO to register with the module loader.
+ *
+ * This function is automatically called when each module is opened.
+ * It must never be used from outside AST_MODULE_INFO.
+ */
void ast_module_register(const struct ast_module_info *info)
{
- struct ast_module *mod = resource_being_loaded;
+ struct ast_module *mod;
+
+ /*
+ * This lock protects resource_being_loaded as well as the module
+ * list. Normally we already have a lock on module_list when we
+ * begin the load but locking again from here prevents corruption
+ * if an asterisk module is dlopen'ed from outside the module loader.
+ */
+ AST_DLLIST_LOCK(&module_list);
+ mod = resource_being_loaded;
+ if (!mod) {
+ AST_DLLIST_UNLOCK(&module_list);
+ return;
+ }
ast_debug(5, "Registering module %s\n", info->name);
+ /* This tells load_dynamic_module that we're registered. */
+ resource_being_loaded = NULL;
+
mod->info = info;
if (ast_opt_ref_debug) {
mod->ref_debug = ao2_t_alloc(0, NULL, info->name);
}
AST_LIST_HEAD_INIT(&mod->users);
- /* during startup, before the loader has been initialized,
- there are no threads, so there is no need to take the lock
- on this list to manipulate it. it is also possible that it
- might be unsafe to use the list lock at that point... so
- let's avoid it altogether
- */
- AST_DLLIST_LOCK(&module_list);
- /* it is paramount that the new entry be placed at the tail of
- the list, otherwise the code that uses dlopen() to load
- dynamic modules won't be able to find out if the module it
- just opened was registered or failed to load
- */
AST_DLLIST_INSERT_TAIL(&module_list, mod, entry);
AST_DLLIST_UNLOCK(&module_list);
@@ -206,6 +242,13 @@ void ast_module_register(const struct ast_module_info *info)
*((struct ast_module **) &(info->self)) = mod;
}
+static void module_destroy(struct ast_module *mod)
+{
+ AST_LIST_HEAD_DESTROY(&mod->users);
+ ao2_cleanup(mod->ref_debug);
+ ast_free(mod);
+}
+
void ast_module_unregister(const struct ast_module_info *info)
{
struct ast_module *mod = NULL;
@@ -226,9 +269,7 @@ void ast_module_unregister(const struct ast_module_info *info)
if (mod) {
ast_debug(5, "Unregistering module %s\n", info->name);
- AST_LIST_HEAD_DESTROY(&mod->users);
- ao2_cleanup(mod->ref_debug);
- ast_free(mod);
+ module_destroy(mod);
}
}
@@ -498,96 +539,93 @@ static void unload_dynamic_module(struct ast_module *mod)
#endif
}
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required);
-
#define MODULE_LOCAL_ONLY (void *)-1
-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap)
+/*!
+ * \internal
+ * \brief Attempt to dlopen a module.
+ *
+ * \param resource_in The module name to load.
+ * \param so_ext ".so" or blank if ".so" is already part of resource_in.
+ * \param filename Passed directly to dlopen.
+ * \param flags Passed directly to dlopen.
+ * \param suppress_logging Do not log any error from dlopen.
+ *
+ * \return Pointer to opened module, NULL on error.
+ *
+ * \warning module_list must be locked before calling this function.
+ */
+static struct ast_module *load_dlopen(const char *resource_in, const char *so_ext,
+ const char *filename, int flags, unsigned int suppress_logging)
{
- char fn[PATH_MAX] = "";
- void *lib = NULL;
struct ast_module *mod;
- unsigned int wants_global;
- int space; /* room needed for the descriptor */
- int missing_so = 0;
-
- space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
- if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
- missing_so = 1;
- space += 3; /* room for the extra ".so" */
- }
-
- snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
- /* make a first load of the module in 'quiet' mode... don't try to resolve
- any symbols, and don't export any symbols. this will allow us to peek into
- the module's info block (if available) to see what flags it has set */
+ ast_assert(!resource_being_loaded);
- resource_being_loaded = ast_calloc(1, space);
- if (!resource_being_loaded)
+ mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);
+ if (!mod) {
return NULL;
- strcpy(resource_being_loaded->resource, resource_in);
- if (missing_so)
- strcat(resource_being_loaded->resource, ".so");
+ }
- if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL))) {
- if (!suppress_logging) {
+ sprintf(mod->resource, "%s%s", resource_in, so_ext); /* safe */
+
+ resource_being_loaded = mod;
+ mod->lib = dlopen(filename, flags);
+ if (resource_being_loaded) {
+ resource_being_loaded = NULL;
+ if (mod->lib) {
+ ast_log(LOG_ERROR, "Module '%s' did not register itself during load\n", resource_in);
+ logged_dlclose(resource_in, mod->lib);
+ } else if (!suppress_logging) {
ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
}
- ast_free(resource_being_loaded);
- return NULL;
- }
+ ast_free(mod);
- /* the dlopen() succeeded, let's find out if the module
- registered itself */
- /* note that this will only work properly as long as
- ast_module_register() (which is called by the module's
- constructor) places the new module at the tail of the
- module_list
- */
- if (resource_being_loaded != (mod = AST_DLLIST_LAST(&module_list))) {
- ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
- /* no, it did not, so close it and return */
- logged_dlclose(resource_in, lib);
- /* note that the module's destructor will call ast_module_unregister(),
- which will free the structure we allocated in resource_being_loaded */
return NULL;
}
- wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ return mod;
+}
- /* 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) {
- logged_dlclose(resource_in, lib);
- return MODULE_LOCAL_ONLY;
+static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging)
+{
+ char fn[PATH_MAX];
+ struct ast_module *mod;
+ size_t resource_in_len = strlen(resource_in);
+ int exports_globals;
+ const char *so_ext = "";
+
+ if (resource_in_len < 4 || strcasecmp(resource_in + resource_in_len - 3, ".so")) {
+ so_ext = ".so";
}
- logged_dlclose(resource_in, lib);
- resource_being_loaded = NULL;
+ snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);
- /* start the load process again */
- resource_being_loaded = ast_calloc(1, space);
- if (!resource_being_loaded)
- return NULL;
- strcpy(resource_being_loaded->resource, resource_in);
- if (missing_so)
- strcat(resource_being_loaded->resource, ".so");
+ /* Try loading in quiet mode first with flags to export global symbols.
+ * If the module does not want to export globals we will close and reopen. */
+ mod = load_dlopen(resource_in, so_ext, fn,
+ global_symbols_only ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL,
+ suppress_logging);
- 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);
+ if (!mod) {
return NULL;
}
- /* since the module was successfully opened, and it registered itself
- the previous time we did that, we're going to assume it worked this
- time too :) */
+ exports_globals = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
+ if ((global_symbols_only && exports_globals) || (!global_symbols_only && !exports_globals)) {
+ /* The first dlopen had the correct flags. */
+ return mod;
+ }
- AST_DLLIST_LAST(&module_list)->lib = lib;
- resource_being_loaded = NULL;
+ /* Close the module so we can reopen with correct flags. */
+ logged_dlclose(resource_in, mod->lib);
+ if (global_symbols_only) {
+ return MODULE_LOCAL_ONLY;
+ }
- return AST_DLLIST_LAST(&module_list);
+ return load_dlopen(resource_in, so_ext, fn,
+ exports_globals ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL,
+ 0);
}
int modules_shutdown(void)
@@ -621,9 +659,7 @@ int modules_shutdown(void)
ast_verb(1, "Unloading %s\n", mod->resource);
mod->info->unload();
}
- AST_LIST_HEAD_DESTROY(&mod->users);
- ao2_cleanup(mod->ref_debug);
- ast_free(mod);
+ module_destroy(mod);
somethingchanged = 1;
}
AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
@@ -1120,13 +1156,13 @@ static enum ast_module_load_result start_resource(struct ast_module *mod)
/*! loads a resource based upon resource_name. If global_symbols_only is set
* only modules with global symbols will be loaded.
*
- * If the ast_heap is provided (not NULL) the module is found and added to the
- * heap without running the module's load() function. By doing this, modules
- * added to the resource_heap can be initialized later in order by priority.
+ * If the module_vector is provided (not NULL) the module is found and added to the
+ * vector without running the module's load() function. By doing this, modules
+ * can be initialized later in order by priority and dependencies.
*
- * If the ast_heap is not provided, the module's load function will be executed
+ * If the module_vector is not provided, the module's load function will be executed
* immediately */
-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required)
+static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct module_vector *resource_heap, int required)
{
struct ast_module *mod;
enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
@@ -1139,7 +1175,7 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
return AST_MODULE_LOAD_SKIP;
} else {
- mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging, resource_heap);
+ mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging);
if (mod == MODULE_LOCAL_ONLY) {
return AST_MODULE_LOAD_SKIP;
}
@@ -1152,21 +1188,26 @@ static enum ast_module_load_result load_resource(const char *resource_name, unsi
}
if (inspect_module(mod)) {
- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
- unload_dynamic_module(mod);
- return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
+ goto prestart_error;
}
mod->flags.declined = 0;
if (resource_heap) {
- ast_heap_push(resource_heap, mod);
+ if (AST_VECTOR_ADD_SORTED(resource_heap, mod, module_vector_cmp)) {
+ goto prestart_error;
+ }
res = AST_MODULE_LOAD_PRIORITY;
} else {
res = start_resource(mod);
}
return res;
+
+prestart_error:
+ ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
+ unload_dynamic_module(mod);
+ return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
}
int ast_load_resource(const char *resource_name)
@@ -1214,23 +1255,6 @@ static struct load_order_entry *add_to_load_order(const char *resource, struct l
return order;
}
-static int mod_load_cmp(void *a, void *b)
-{
- struct ast_module *a_mod = (struct ast_module *) a;
- struct ast_module *b_mod = (struct ast_module *) b;
- /* if load_pri is not set, default is 128. Lower is better */
- int a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
- int b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
-
- /*
- * Returns comparison values for a min-heap
- * <0 a_pri > b_pri
- * =0 a_pri == b_pri
- * >0 a_pri < b_pri
- */
- return b_pri - a_pri;
-}
-
AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);
/*! loads modules in order by load_pri, updates mod_count
@@ -1238,9 +1262,8 @@ AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);
*/
static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)
{
- struct ast_heap *resource_heap;
+ struct module_vector resource_heap;
struct load_order_entry *order;
- struct ast_module *mod;
struct load_retries load_retries;
int count = 0;
int res = 0;
@@ -1249,7 +1272,9 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
AST_LIST_HEAD_INIT_NOLOCK(&load_retries);
- if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
+ if (AST_VECTOR_INIT(&resource_heap, 500)) {
+ ast_log(LOG_ERROR, "Failed to initialize module loader.\n");
+
return -1;
}
@@ -1258,7 +1283,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
enum ast_module_load_result lres;
/* Suppress log messages unless this is the last pass */
- lres = load_resource(order->resource, global_symbols, 1, resource_heap, order->required);
+ lres = load_resource(order->resource, global_symbols, 1, &resource_heap, order->required);
ast_debug(3, "PASS 0: %-46s %d %d\n", order->resource, lres, global_symbols);
switch (lres) {
case AST_MODULE_LOAD_SUCCESS:
@@ -1282,7 +1307,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
*/
break;
case AST_MODULE_LOAD_PRIORITY:
- /* load_resource worked and the module was added to the priority heap */
+ /* load_resource worked and the module was added to the priority vector */
AST_LIST_REMOVE_CURRENT(entry);
ast_free(order->resource);
ast_free(order);
@@ -1297,7 +1322,7 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
enum ast_module_load_result lres;
/* Suppress log messages unless this is the last pass */
- lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), resource_heap, order->required);
+ lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), &resource_heap, order->required);
ast_debug(3, "PASS %d %-46s %d %d\n", i + 1, order->resource, lres, global_symbols);
switch (lres) {
/* These are all retryable. */
@@ -1335,7 +1360,8 @@ static int load_resource_list(struct load_order *load_order, unsigned int global
}
/* second remove modules from heap sorted by priority */
- while ((mod = ast_heap_pop(resource_heap))) {
+ for (i = 0; i < AST_VECTOR_SIZE(&resource_heap); i++) {
+ struct ast_module *mod = AST_VECTOR_GET(&resource_heap, i);
enum ast_module_load_result lres;
lres = start_resource(mod);
@@ -1365,7 +1391,7 @@ done:
if (mod_count) {
*mod_count += count;
}
- ast_heap_destroy(resource_heap);
+ AST_VECTOR_FREE(&resource_heap);
return res;
}
@@ -1503,33 +1529,57 @@ void ast_update_use_count(void)
AST_LIST_UNLOCK(&updaters);
}
+/*!
+ * \internal
+ * \brief Build an alpha sorted list of modules.
+ *
+ * \param alpha_module_list Pointer to uninitialized module_vector.
+ *
+ * This function always initializes alpha_module_list.
+ *
+ * \pre module_list must be locked.
+ */
+static int alpha_module_list_create(struct module_vector *alpha_module_list)
+{
+ struct ast_module *cur;
+
+ if (AST_VECTOR_INIT(alpha_module_list, 32)) {
+ return -1;
+ }
+
+ AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
+ if (AST_VECTOR_ADD_SORTED(alpha_module_list, cur, module_vector_strcasecmp)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
int ast_update_module_list(int (*modentry)(const char *module, const char *description,
int usecnt, const char *status, const char *like,
enum ast_module_support_level support_level),
const char *like)
{
- struct ast_module *cur;
- int unlock = -1;
int total_mod_loaded = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
- if (AST_DLLIST_TRYLOCK(&module_list)) {
- unlock = 0;
- }
+ AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
- }
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- if (unlock) {
- AST_DLLIST_UNLOCK(&module_list);
+ total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running ? "Running" : "Not Running", like, cur->info->support_level);
+ }
}
+ AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
+
return total_mod_loaded;
}
@@ -1539,22 +1589,24 @@ int ast_update_module_list_data(int (*modentry)(const char *module, const char *
void *data),
const char *like, void *data)
{
- struct ast_module *cur;
int total_mod_loaded = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
+ total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data);
+ }
}
AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
return total_mod_loaded;
}
@@ -1566,23 +1618,25 @@ int ast_update_module_list_condition(int (*modentry)(const char *module, const c
void *data, const char *condition),
const char *like, void *data, const char *condition)
{
- struct ast_module *cur;
int conditions_met = 0;
- AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
+ struct module_vector alpha_module_list;
AST_DLLIST_LOCK(&module_list);
- AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource);
- }
+ if (!alpha_module_list_create(&alpha_module_list)) {
+ int idx;
+
+ for (idx = 0; idx < AST_VECTOR_SIZE(&alpha_module_list); idx++) {
+ struct ast_module *cur = AST_VECTOR_GET(&alpha_module_list, idx);
- while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) {
- conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
- cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
- condition);
+ conditions_met += modentry(cur->resource, cur->info->description, cur->usecount,
+ cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data,
+ condition);
+ }
}
AST_DLLIST_UNLOCK(&module_list);
+ AST_VECTOR_FREE(&alpha_module_list);
return conditions_met;
}