Wed Jan 27 20:02:41 2016

Asterisk developer's documentation


loader.c File Reference

Module Loader. More...

#include "asterisk.h"
#include "asterisk/_private.h"
#include "asterisk/paths.h"
#include <dirent.h>
#include "asterisk/linkedlists.h"
#include "asterisk/module.h"
#include "asterisk/config.h"
#include "asterisk/channel.h"
#include "asterisk/term.h"
#include "asterisk/manager.h"
#include "asterisk/cdr.h"
#include "asterisk/enum.h"
#include "asterisk/http.h"
#include "asterisk/lock.h"
#include "asterisk/features.h"
#include "asterisk/dsp.h"
#include "asterisk/udptl.h"
#include "asterisk/heap.h"
#include "asterisk/app.h"
#include "asterisk/test.h"
#include <dlfcn.h>
#include "asterisk/md5.h"
#include "asterisk/utils.h"

Go to the source code of this file.

Data Structures

struct  ast_module
struct  ast_module_user
struct  load_order
struct  load_order_entry
struct  loadupdate
struct  module_list
struct  module_user_list
struct  reload_classes
struct  reload_queue
struct  reload_queue_item
struct  updaters

Defines

#define RTLD_LOCAL   0
#define RTLD_NOW   0

Functions

struct ast_module_user__ast_module_user_add (struct ast_module *mod, struct ast_channel *chan)
void __ast_module_user_hangup_all (struct ast_module *mod)
void __ast_module_user_remove (struct ast_module *mod, struct ast_module_user *u)
static struct load_order_entryadd_to_load_order (const char *resource, struct load_order *load_order, int required)
int ast_load_resource (const char *resource_name)
 Load a module.
int ast_loader_register (int(*v)(void))
 Add a procedure to be run when modules have been updated.
int ast_loader_unregister (int(*v)(void))
 Remove a procedure to be run when modules are updated.
int ast_module_check (const char *name)
 Check if module exists.
char * ast_module_helper (const char *line, const char *word, int pos, int state, int rpos, int needsreload)
 Match modules names for the Asterisk cli.
const char * ast_module_name (const struct ast_module *mod)
 Get the name of a module.
struct ast_moduleast_module_ref (struct ast_module *mod)
void ast_module_register (const struct ast_module_info *info)
int ast_module_reload (const char *name)
 Reload asterisk modules.
void ast_module_shutdown (void)
 Run the unload() callback for all loaded modules.
void ast_module_unref (struct ast_module *mod)
void ast_module_unregister (const struct ast_module_info *info)
void ast_process_pending_reloads (void)
 Process reload requests received during startup.
int ast_unload_resource (const char *resource_name, enum ast_module_unload_mode force)
 Unload a module.
int ast_update_module_list (int(*modentry)(const char *module, const char *description, int usecnt, const char *like), const char *like)
 Ask for a list of modules, descriptions, and use counts.
void ast_update_use_count (void)
 Notify when usecount has been changed.
static void close_lib (const char *name, void *lib)
static struct ast_modulefind_resource (const char *resource, int do_lock)
static unsigned int inspect_module (const struct ast_module *mod)
static int key_matches (const unsigned char *key1, const unsigned char *key2)
static struct ast_moduleload_dynamic_module (const char *resource_in, unsigned int global_symbols_only, struct ast_heap *resource_heap)
int load_modules (unsigned int preload_only)
static enum ast_module_load_result load_resource (const char *resource_name, unsigned int global_symbols_only, struct ast_heap *resource_heap, int required)
static int load_resource_list (struct load_order *load_order, unsigned int global_symbols, int *mod_count)
static int mod_load_cmp (void *a, void *b)
static int printdigest (const unsigned char *d)
static void queue_reload_request (const char *module)
static int resource_name_match (const char *name1_in, const char *name2_in)
static enum ast_module_load_result start_resource (struct ast_module *mod)
static void unload_dynamic_module (struct ast_module *mod)
static int verify_key (const unsigned char *key)

Variables

static char buildopt_sum [33] = AST_BUILDOPT_SUM
static int do_full_reload = 0
static struct module_list embedded_module_list
static unsigned int embedding = 1
static const unsigned char expected_key []
static ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static struct ast_moduleresource_being_loaded

Detailed Description

Module Loader.

Author:
Mark Spencer <markster@digium.com>
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
  • See ModMngMnt

Definition in file loader.c.


Define Documentation

#define RTLD_LOCAL   0

Definition at line 69 of file loader.c.

Referenced by load_dynamic_module().

#define RTLD_NOW   0

Definition at line 65 of file loader.c.

Referenced by load_dynamic_module().


Function Documentation

struct ast_module_user* __ast_module_user_add ( struct ast_module mod,
struct ast_channel chan 
) [read]

Definition at line 209 of file loader.c.

References ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_update_use_count(), ast_module_user::chan, ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

00210 {
00211    struct ast_module_user *u;
00212 
00213    u = ast_calloc(1, sizeof(*u));
00214    if (!u) {
00215       return NULL;
00216    }
00217 
00218    u->chan = chan;
00219 
00220    AST_LIST_LOCK(&mod->users);
00221    AST_LIST_INSERT_HEAD(&mod->users, u, entry);
00222    AST_LIST_UNLOCK(&mod->users);
00223 
00224    ast_atomic_fetchadd_int(&mod->usecount, +1);
00225 
00226    ast_update_use_count();
00227 
00228    return u;
00229 }

void __ast_module_user_hangup_all ( struct ast_module mod  ) 

Definition at line 254 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_update_use_count(), ast_module_user::chan, ast_module::usecount, and ast_module::users.

Referenced by ast_unload_resource().

00255 {
00256    struct ast_module_user *u;
00257 
00258    AST_LIST_LOCK(&mod->users);
00259    while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
00260       if (u->chan) {
00261          ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
00262       }
00263       ast_atomic_fetchadd_int(&mod->usecount, -1);
00264       ast_free(u);
00265    }
00266    AST_LIST_UNLOCK(&mod->users);
00267 
00268    ast_update_use_count();
00269 }

void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 231 of file loader.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_update_use_count(), ast_module::usecount, and ast_module::users.

Referenced by ast_func_read(), ast_func_read2(), ast_func_write(), and pbx_exec().

00232 {
00233    if (!u) {
00234       return;
00235    }
00236 
00237    AST_LIST_LOCK(&mod->users);
00238    u = AST_LIST_REMOVE(&mod->users, u, entry);
00239    AST_LIST_UNLOCK(&mod->users);
00240    if (!u) {
00241       /*
00242        * Was not in the list.  Either a bad pointer or
00243        * __ast_module_user_hangup_all() has been called.
00244        */
00245       return;
00246    }
00247 
00248    ast_atomic_fetchadd_int(&mod->usecount, -1);
00249    ast_free(u);
00250 
00251    ast_update_use_count();
00252 }

static struct load_order_entry* add_to_load_order ( const char *  resource,
struct load_order load_order,
int  required 
) [static, read]

Definition at line 968 of file loader.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, load_order_entry::required, load_order_entry::resource, and resource_name_match().

Referenced by load_modules().

00969 {
00970    struct load_order_entry *order;
00971 
00972    AST_LIST_TRAVERSE(load_order, order, entry) {
00973       if (!resource_name_match(order->resource, resource)) {
00974          /* Make sure we have the proper setting for the required field 
00975             (we might have both load= and required= lines in modules.conf) */
00976          order->required |= required;
00977          return NULL;
00978       }
00979    }
00980 
00981    if (!(order = ast_calloc(1, sizeof(*order))))
00982       return NULL;
00983 
00984    order->resource = ast_strdup(resource);
00985    order->required = required;
00986    AST_LIST_INSERT_TAIL(load_order, order, entry);
00987 
00988    return order;
00989 }

int ast_load_resource ( const char *  resource_name  ) 

Load a module.

Parameters:
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 initialization tasks. Basically, to load a module, just give it the name of the module and it will do the rest.

Returns:
See possible enum values for ast_module_load_result.

Definition at line 947 of file loader.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_test_suite_event_notify, and load_resource().

Referenced by handle_load(), load_module(), and manager_moduleload().

00948 {
00949    int res;
00950    AST_LIST_LOCK(&module_list);
00951    res = load_resource(resource_name, 0, NULL, 0);
00952    if (!res) {
00953       ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);
00954    }
00955    AST_LIST_UNLOCK(&module_list);
00956 
00957    return res;
00958 }

int ast_loader_register ( int(*)(void)  updater  ) 

Add a procedure to be run when modules have been updated.

Parameters:
updater The function to run when modules have been updated.

This function adds the given function to a linked list of functions to be run when the modules are updated.

Return values:
0 on success
-1 on failure.

Definition at line 1268 of file loader.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and loadupdate::updater.

01269 {
01270    struct loadupdate *tmp;
01271 
01272    if (!(tmp = ast_malloc(sizeof(*tmp))))
01273       return -1;
01274 
01275    tmp->updater = v;
01276    AST_LIST_LOCK(&updaters);
01277    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01278    AST_LIST_UNLOCK(&updaters);
01279 
01280    return 0;
01281 }

int ast_loader_unregister ( int(*)(void)  updater  ) 

Remove a procedure to be run when modules are updated.

Parameters:
updater The updater function to unregister.

This removes the given function from the updater list.

Return values:
0 on success
-1 on failure.

Definition at line 1283 of file loader.c.

References AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, and loadupdate::updater.

01284 {
01285    struct loadupdate *cur;
01286 
01287    AST_LIST_LOCK(&updaters);
01288    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01289       if (cur->updater == v)  {
01290          AST_LIST_REMOVE_CURRENT(entry);
01291          break;
01292       }
01293    }
01294    AST_LIST_TRAVERSE_SAFE_END;
01295    AST_LIST_UNLOCK(&updaters);
01296 
01297    return cur ? 0 : -1;
01298 }

int ast_module_check ( const char *  name  ) 

Check if module exists.

Check if module with the name given is loaded.

Definition at line 1255 of file loader.c.

References ast_strlen_zero(), and find_resource().

Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().

01256 {
01257    struct ast_module *cur;
01258 
01259    if (ast_strlen_zero(name))
01260       return 0;       /* FALSE */
01261 
01262    cur = find_resource(name, 1);
01263 
01264    return (cur != NULL);
01265 }

char* ast_module_helper ( const char *  line,
const char *  word,
int  pos,
int  state,
int  rpos,
int  needsreload 
)

Match modules names for the Asterisk cli.

Parameters:
line Unused by this function, but this should be the line we are matching.
word The partial name to match.
pos The position the word we are completing is in.
state The possible match to return.
rpos The position we should be matching. This should be the same as pos.
needsreload This should be 1 if we need to reload this module and 0 otherwise. This function will only return modules that are reloadble if this is 1.
Return values:
A possible completion of the partial match.
NULL if no matches were found.

Definition at line 626 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module::info, name, ast_module_info::reload, and ast_module::resource.

Referenced by conf_run(), handle_modlist(), handle_reload(), handle_unload(), and load_module().

00627 {
00628    struct ast_module *cur;
00629    int i, which=0, l = strlen(word);
00630    char *ret = NULL;
00631 
00632    if (pos != rpos)
00633       return NULL;
00634 
00635    AST_LIST_LOCK(&module_list);
00636    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00637       if (!strncasecmp(word, cur->resource, l) &&
00638           (cur->info->reload || !needsreload) &&
00639           ++which > state) {
00640          ret = ast_strdup(cur->resource);
00641          break;
00642       }
00643    }
00644    AST_LIST_UNLOCK(&module_list);
00645 
00646    if (!ret) {
00647       for (i=0; !ret && reload_classes[i].name; i++) {
00648          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00649             ret = ast_strdup(reload_classes[i].name);
00650       }
00651    }
00652 
00653    return ret;
00654 }

const char* ast_module_name ( const struct ast_module mod  ) 

Get the name of a module.

Parameters:
mod A pointer to the module.
Returns:
the name of the module
Return values:
NULL if mod or mod->info is NULL

Definition at line 104 of file loader.c.

Referenced by acf_retrieve_docs(), ast_register_application2(), and unload_dynamic_module().

00105 {
00106    if (!mod || !mod->info) {
00107       return NULL;
00108    }
00109 
00110    return mod->info->name;
00111 }

struct ast_module* ast_module_ref ( struct ast_module mod  )  [read]
void ast_module_register ( const struct ast_module_info info  ) 

Definition at line 147 of file loader.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedded_module_list, embedding, ast_module::info, ast_module::resource, and ast_module::users.

00148 {
00149    struct ast_module *mod;
00150 
00151    if (embedding) {
00152       if (!(mod = ast_calloc(1, sizeof(*mod) + strlen(info->name) + 1)))
00153          return;
00154       strcpy(mod->resource, info->name);
00155    } else {
00156       mod = resource_being_loaded;
00157    }
00158 
00159    mod->info = info;
00160    AST_LIST_HEAD_INIT(&mod->users);
00161 
00162    /* during startup, before the loader has been initialized,
00163       there are no threads, so there is no need to take the lock
00164       on this list to manipulate it. it is also possible that it
00165       might be unsafe to use the list lock at that point... so
00166       let's avoid it altogether
00167    */
00168    if (embedding) {
00169       AST_LIST_INSERT_TAIL(&embedded_module_list, mod, entry);
00170    } else {
00171       AST_LIST_LOCK(&module_list);
00172       /* it is paramount that the new entry be placed at the tail of
00173          the list, otherwise the code that uses dlopen() to load
00174          dynamic modules won't be able to find out if the module it
00175          just opened was registered or failed to load
00176       */
00177       AST_LIST_INSERT_TAIL(&module_list, mod, entry);
00178       AST_LIST_UNLOCK(&module_list);
00179    }
00180 
00181    /* give the module a copy of its own handle, for later use in registrations and the like */
00182    *((struct ast_module **) &(info->self)) = mod;
00183 }

int ast_module_reload ( const char *  name  ) 

Reload asterisk modules.

Parameters:
name the name of the module to reload

This function reloads the specified module, or if no modules are specified, it will reload all loaded modules.

Note:
Modules are reloaded using their reload() functions, not unloading them and loading them again.
Returns:
0 if the specified module was not found.
Return values:
1 if the module was found but cannot be reloaded.
-1 if a reload operation is already in progress.
2 if the specfied module was found and reloaded.

Definition at line 721 of file loader.c.

References ast_config_AST_CONFIG_DIR, ast_fully_booted, ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_lock_path(), AST_LOCK_SUCCESS, AST_LOCK_TIMEOUT, ast_log(), ast_mutex_trylock, ast_mutex_unlock, ast_opt_lock_confdir, ast_test_suite_event_notify, ast_tvnow(), ast_unlock_path(), ast_verb, ast_verbose, ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, LOG_NOTICE, LOG_WARNING, queue_reload_request(), ast_module_info::reload, ast_module::resource, resource_name_match(), and ast_module::running.

Referenced by action_reload(), action_updateconfig(), ast_process_pending_reloads(), handle_core_reload(), handle_reload(), manager_moduleload(), and monitor_sig_flags().

00722 {
00723    struct ast_module *cur;
00724    int res = 0; /* return value. 0 = not found, others, see below */
00725    int i;
00726 
00727    /* If we aren't fully booted, we just pretend we reloaded but we queue this
00728       up to run once we are booted up. */
00729    if (!ast_fully_booted) {
00730       queue_reload_request(name);
00731       return 0;
00732    }
00733 
00734    if (ast_mutex_trylock(&reloadlock)) {
00735       ast_verbose("The previous reload command didn't finish yet\n");
00736       return -1;  /* reload already in progress */
00737    }
00738    ast_lastreloadtime = ast_tvnow();
00739 
00740    if (ast_opt_lock_confdir) {
00741       int try;
00742       int res;
00743       for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) {
00744          res = ast_lock_path(ast_config_AST_CONFIG_DIR);
00745          if (res == AST_LOCK_TIMEOUT) {
00746             ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
00747          }
00748       }
00749       if (res != AST_LOCK_SUCCESS) {
00750          ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
00751          ast_mutex_unlock(&reloadlock);
00752          return -1;
00753       }
00754    }
00755 
00756    /* Call "predefined" reload here first */
00757    for (i = 0; reload_classes[i].name; i++) {
00758       if (!name || !strcasecmp(name, reload_classes[i].name)) {
00759          if (!reload_classes[i].reload_fn()) {
00760             ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", name);
00761          }
00762          res = 2; /* found and reloaded */
00763       }
00764    }
00765 
00766    if (name && res) {
00767       if (ast_opt_lock_confdir) {
00768          ast_unlock_path(ast_config_AST_CONFIG_DIR);
00769       }
00770       ast_mutex_unlock(&reloadlock);
00771       return res;
00772    }
00773 
00774    AST_LIST_LOCK(&module_list);
00775    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00776       const struct ast_module_info *info = cur->info;
00777 
00778       if (name && resource_name_match(name, cur->resource))
00779          continue;
00780 
00781       if (!cur->flags.running || cur->flags.declined) {
00782          if (!name)
00783             continue;
00784          ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
00785             "Before reloading the module, you must run \"module load %s\" "
00786             "and fix whatever is preventing the module from being initialized.\n",
00787             name, name);
00788          res = 2; /* Don't report that the module was not found */
00789          break;
00790       }
00791 
00792       if (!info->reload) { /* cannot be reloaded */
00793          /* Nothing to reload, so reload is successful */
00794          ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource);
00795          if (res < 1)   /* store result if possible */
00796             res = 1; /* 1 = no reload() method */
00797          continue;
00798       }
00799 
00800       res = 2;
00801       ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
00802       if (!info->reload()) {
00803          ast_test_suite_event_notify("MODULE_RELOAD", "Message: %s", cur->resource);
00804       }
00805    }
00806    AST_LIST_UNLOCK(&module_list);
00807 
00808    if (ast_opt_lock_confdir) {
00809       ast_unlock_path(ast_config_AST_CONFIG_DIR);
00810    }
00811    ast_mutex_unlock(&reloadlock);
00812 
00813    return res;
00814 }

void ast_module_shutdown ( void   ) 

Run the unload() callback for all loaded modules.

This function should be called when Asterisk is shutting down gracefully.

Note:
Some resources, like timers, are started up dynamically, and thus may be still in use, even if all channels are dead. We must therefore check the usecount before asking modules to unload.
If we go through the entire list without changing anything, ignore the usecounts and unload, then exit.

Definition at line 513 of file loader.c.

References AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module::declined, ast_module::flags, free, ast_module::info, ast_module::running, ast_module_info::unload, ast_module::usecount, and ast_module::users.

Referenced by really_quit().

00514 {
00515    struct ast_module *mod;
00516    int somethingchanged = 1, final = 0;
00517 
00518    AST_LIST_LOCK(&module_list);
00519 
00520    /*!\note Some resources, like timers, are started up dynamically, and thus
00521     * may be still in use, even if all channels are dead.  We must therefore
00522     * check the usecount before asking modules to unload. */
00523    do {
00524       if (!somethingchanged) {
00525          /*!\note If we go through the entire list without changing
00526           * anything, ignore the usecounts and unload, then exit. */
00527          final = 1;
00528       }
00529 
00530       /* Reset flag before traversing the list */
00531       somethingchanged = 0;
00532 
00533       AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00534          if (!final && mod->usecount) {
00535             continue;
00536          }
00537          AST_LIST_REMOVE_CURRENT(entry);
00538          if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
00539             mod->info->unload();
00540          }
00541          AST_LIST_HEAD_DESTROY(&mod->users);
00542          free(mod);
00543          somethingchanged = 1;
00544       }
00545       AST_LIST_TRAVERSE_SAFE_END;
00546    } while (somethingchanged && !final);
00547 
00548    AST_LIST_UNLOCK(&module_list);
00549 }

void ast_module_unref ( struct ast_module mod  ) 
void ast_module_unregister ( const struct ast_module_info info  ) 

Definition at line 185 of file loader.c.

References ast_free, AST_LIST_HEAD_DESTROY, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_module::info, and ast_module::users.

00186 {
00187    struct ast_module *mod = NULL;
00188 
00189    /* it is assumed that the users list in the module structure
00190       will already be empty, or we cannot have gotten to this
00191       point
00192    */
00193    AST_LIST_LOCK(&module_list);
00194    AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00195       if (mod->info == info) {
00196          AST_LIST_REMOVE_CURRENT(entry);
00197          break;
00198       }
00199    }
00200    AST_LIST_TRAVERSE_SAFE_END;
00201    AST_LIST_UNLOCK(&module_list);
00202 
00203    if (mod) {
00204       AST_LIST_HEAD_DESTROY(&mod->users);
00205       ast_free(mod);
00206    }
00207 }

void ast_process_pending_reloads ( void   ) 

Process reload requests received during startup.

This function requests that the loader execute the pending reload requests that were queued during server startup.

Note:
This function will do nothing if the server has not completely started up. Once called, the reload queue is emptied, and further invocations will have no affect.

Definition at line 656 of file loader.c.

References ast_free, ast_fully_booted, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), ast_module_reload(), do_full_reload, LOG_NOTICE, and reload_queue_item::module.

Referenced by main().

00657 {
00658    struct reload_queue_item *item;
00659 
00660    if (!ast_fully_booted) {
00661       return;
00662    }
00663 
00664    AST_LIST_LOCK(&reload_queue);
00665 
00666    if (do_full_reload) {
00667       do_full_reload = 0;
00668       AST_LIST_UNLOCK(&reload_queue);
00669       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00670       ast_module_reload(NULL);
00671       return;
00672    }
00673 
00674    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00675       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00676       ast_module_reload(item->module);
00677       ast_free(item);
00678    }
00679 
00680    AST_LIST_UNLOCK(&reload_queue);
00681 }

int ast_unload_resource ( const char *  resource_name,
enum  ast_module_unload_mode 
)

Unload a module.

Parameters:
resource_name The name of the module to unload.
ast_module_unload_mode The force flag. This should be set using one of the AST_FORCE flags.

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).

Return values:
0 on success.
-1 on error.

Definition at line 551 of file loader.c.

References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_test_suite_event_notify, ast_update_use_count(), ast_module::declined, find_resource(), ast_module::flags, ast_module::info, ast_module::lib, LOG_WARNING, ast_module_info::restore_globals, ast_module::running, ast_module_info::unload, unload_dynamic_module(), and ast_module::usecount.

Referenced by handle_unload(), manager_moduleload(), and unload_module().

00552 {
00553    struct ast_module *mod;
00554    int res = -1;
00555    int error = 0;
00556 
00557    AST_LIST_LOCK(&module_list);
00558 
00559    if (!(mod = find_resource(resource_name, 0))) {
00560       AST_LIST_UNLOCK(&module_list);
00561       ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
00562       return -1;
00563    }
00564 
00565    if (!mod->flags.running || mod->flags.declined) {
00566       ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
00567       error = 1;
00568    }
00569 
00570    if (!error && (mod->usecount > 0)) {
00571       if (force)
00572          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00573             resource_name, mod->usecount);
00574       else {
00575          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00576             mod->usecount);
00577          error = 1;
00578       }
00579    }
00580 
00581    if (!error) {
00582       /* Request any channels attached to the module to hangup. */
00583       __ast_module_user_hangup_all(mod);
00584 
00585       res = mod->info->unload();
00586       if (res) {
00587          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00588          if (force <= AST_FORCE_FIRM) {
00589             error = 1;
00590          } else {
00591             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00592          }
00593       }
00594 
00595       if (!error) {
00596          /*
00597           * Request hangup on any channels that managed to get attached
00598           * while we called the module unload function.
00599           */
00600          __ast_module_user_hangup_all(mod);
00601          sched_yield();
00602       }
00603    }
00604 
00605    if (!error)
00606       mod->flags.running = mod->flags.declined = 0;
00607 
00608    AST_LIST_UNLOCK(&module_list);
00609 
00610    if (!error && !mod->lib && mod->info && mod->info->restore_globals)
00611       mod->info->restore_globals();
00612 
00613 #ifdef LOADABLE_MODULES
00614    if (!error) {
00615       unload_dynamic_module(mod);
00616       ast_test_suite_event_notify("MODULE_UNLOAD", "Message: %s", resource_name);
00617    }
00618 #endif
00619 
00620    if (!error)
00621       ast_update_use_count();
00622 
00623    return res;
00624 }

int ast_update_module_list ( int(*)(const char *module, const char *description, int usecnt, const char *like)  modentry,
const char *  like 
)

Ask for a list of modules, descriptions, and use counts.

Parameters:
modentry A callback to an updater function.
like For each of the modules loaded, modentry will be executed with the resource, description, and usecount values of each particular module.
Returns:
the number of modules loaded

Definition at line 1234 of file loader.c.

References AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_module_info::description, ast_module::info, ast_module::resource, and ast_module::usecount.

Referenced by ast_var_Modules(), and handle_modlist().

01236 {
01237    struct ast_module *cur;
01238    int unlock = -1;
01239    int total_mod_loaded = 0;
01240 
01241    if (AST_LIST_TRYLOCK(&module_list))
01242       unlock = 0;
01243  
01244    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01245       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01246    }
01247 
01248    if (unlock)
01249       AST_LIST_UNLOCK(&module_list);
01250 
01251    return total_mod_loaded;
01252 }

void ast_update_use_count ( void   ) 

Notify when usecount has been changed.

This function calulates use counts and notifies anyone trying to keep track of them. It should be called whenever your module's usecount changes.

Note:
The ast_module_user_* functions take care of calling this function for you.

Definition at line 1222 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, and loadupdate::updater.

Referenced by __ast_module_user_add(), __ast_module_user_hangup_all(), __ast_module_user_remove(), ast_module_ref(), ast_module_unref(), ast_unload_resource(), handle_request_do(), oh323_request(), sip_request_call(), start_resource(), and unistim_new().

01223 {
01224    /* Notify any module monitors that the use count for a
01225       resource has changed */
01226    struct loadupdate *m;
01227 
01228    AST_LIST_LOCK(&updaters);
01229    AST_LIST_TRAVERSE(&updaters, m, entry)
01230       m->updater();
01231    AST_LIST_UNLOCK(&updaters);
01232 }

static void close_lib ( const char *  name,
void *  lib 
) [static]

Definition at line 376 of file loader.c.

References ast_log(), AST_LOG_ERROR, and S_OR.

Referenced by load_dynamic_module(), and unload_dynamic_module().

00377 {
00378    char *error;
00379 
00380    if (!lib) {
00381       return;
00382    }
00383 
00384    /* Clear any existing error */
00385    dlerror();
00386    if (dlclose(lib)) {
00387       error = dlerror();
00388       ast_log(AST_LOG_ERROR, "Failure in dlclose for module '%s': %s\n",
00389          S_OR(name, "unknown"), S_OR(error, "Unknown error"));
00390    }
00391 }

static struct ast_module* find_resource ( const char *  resource,
int  do_lock 
) [static, read]

Definition at line 356 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module::resource, and resource_name_match().

Referenced by ast_module_check(), ast_unload_resource(), load_dynamic_module(), load_modules(), and load_resource().

00357 {
00358    struct ast_module *cur;
00359 
00360    if (do_lock)
00361       AST_LIST_LOCK(&module_list);
00362 
00363    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00364       if (!resource_name_match(resource, cur->resource))
00365          break;
00366    }
00367 
00368    if (do_lock)
00369       AST_LIST_UNLOCK(&module_list);
00370 
00371    return cur;
00372 }

static unsigned int inspect_module ( const struct ast_module mod  )  [static]

Definition at line 816 of file loader.c.

References ast_log(), ast_strlen_zero(), buildopt_sum, ast_module_info::buildopt_sum, ast_module_info::description, ast_module::info, ast_module_info::key, LOG_WARNING, ast_module::resource, and verify_key().

Referenced by load_resource().

00817 {
00818    if (!mod->info->description) {
00819       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00820       return 1;
00821    }
00822 
00823    if (!mod->info->key) {
00824       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00825       return 1;
00826    }
00827 
00828    if (verify_key((unsigned char *) mod->info->key)) {
00829       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00830       return 1;
00831    }
00832 
00833    if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00834        strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00835       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00836       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00837       return 1;
00838    }
00839 
00840    return 0;
00841 }

static int key_matches ( const unsigned char *  key1,
const unsigned char *  key2 
) [static]

Definition at line 309 of file loader.c.

Referenced by verify_key().

00310 {
00311    int x;
00312 
00313    for (x = 0; x < 16; x++) {
00314       if (key1[x] != key2[x])
00315          return 0;
00316    }
00317 
00318    return 1;
00319 }

static struct ast_module* load_dynamic_module ( const char *  resource_in,
unsigned int  global_symbols_only,
struct ast_heap resource_heap 
) [static, read]

Definition at line 405 of file loader.c.

References ast_calloc, ast_config_AST_MODULE_DIR, ast_free, AST_LIST_LAST, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, ast_strdupa, ast_strip(), ast_strlen_zero(), ast_test_flag, close_lib(), find_resource(), ast_module::info, ast_module::lib, load_resource(), LOG_WARNING, ast_module_info::nonoptreq, ast_module::resource, resource_being_loaded, RTLD_LOCAL, and RTLD_NOW.

Referenced by load_resource().

00406 {
00407    char fn[PATH_MAX] = "";
00408    void *lib = NULL;
00409    struct ast_module *mod;
00410    unsigned int wants_global;
00411    int space;  /* room needed for the descriptor */
00412    int missing_so = 0;
00413 
00414    space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
00415    if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
00416       missing_so = 1;
00417       space += 3; /* room for the extra ".so" */
00418    }
00419 
00420    snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
00421 
00422    /* make a first load of the module in 'quiet' mode... don't try to resolve
00423       any symbols, and don't export any symbols. this will allow us to peek into
00424       the module's info block (if available) to see what flags it has set */
00425 
00426    resource_being_loaded = ast_calloc(1, space);
00427    if (!resource_being_loaded)
00428       return NULL;
00429    strcpy(resource_being_loaded->resource, resource_in);
00430    if (missing_so)
00431       strcat(resource_being_loaded->resource, ".so");
00432 
00433    if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
00434       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00435       ast_free(resource_being_loaded);
00436       return NULL;
00437    }
00438 
00439    /* the dlopen() succeeded, let's find out if the module
00440       registered itself */
00441    /* note that this will only work properly as long as
00442       ast_module_register() (which is called by the module's
00443       constructor) places the new module at the tail of the
00444       module_list
00445    */
00446    if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
00447       ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
00448       /* no, it did not, so close it and return */
00449       close_lib(resource_in, lib);
00450       /* note that the module's destructor will call ast_module_unregister(),
00451          which will free the structure we allocated in resource_being_loaded */
00452       return NULL;
00453    }
00454 
00455    wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
00456 
00457    /* if we are being asked only to load modules that provide global symbols,
00458       and this one does not, then close it and return */
00459    if (global_symbols_only && !wants_global) {
00460       close_lib(resource_in, lib);
00461       return NULL;
00462    }
00463 
00464    /* This section is a workaround for a gcc 4.1 bug that has already been
00465     * fixed in later versions.  Unfortunately, some distributions, such as
00466     * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal
00467     * with this issue.  This basically ensures that optional_api modules are
00468     * loaded before any module which requires their functionality. */
00469 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref)
00470    if (!ast_strlen_zero(mod->info->nonoptreq)) {
00471       /* Force any required dependencies to load */
00472       char *each, *required_resource = ast_strdupa(mod->info->nonoptreq);
00473       while ((each = strsep(&required_resource, ","))) {
00474          struct ast_module *dependency;
00475          each = ast_strip(each);
00476          dependency = find_resource(each, 0);
00477          /* Is it already loaded? */
00478          if (!dependency) {
00479             load_resource(each, global_symbols_only, resource_heap, 1);
00480          }
00481       }
00482    }
00483 #endif
00484 
00485    close_lib(resource_in, lib);
00486    resource_being_loaded = NULL;
00487 
00488    /* start the load process again */
00489    resource_being_loaded = ast_calloc(1, space);
00490    if (!resource_being_loaded)
00491       return NULL;
00492    strcpy(resource_being_loaded->resource, resource_in);
00493    if (missing_so)
00494       strcat(resource_being_loaded->resource, ".so");
00495 
00496    if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
00497       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00498       ast_free(resource_being_loaded);
00499       return NULL;
00500    }
00501 
00502    /* since the module was successfully opened, and it registered itself
00503       the previous time we did that, we're going to assume it worked this
00504       time too :) */
00505 
00506    AST_LIST_LAST(&module_list)->lib = lib;
00507    resource_being_loaded = NULL;
00508 
00509    return AST_LIST_LAST(&module_list);
00510 }

int load_modules ( unsigned  int  ) 

Provided by loader.c

Definition at line 1072 of file loader.c.

References add_to_load_order(), ast_config_AST_MODULE_DIR, ast_config_destroy(), ast_config_load2(), ast_debug, ast_free, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), AST_MODULE_CONFIG, ast_opt_quiet, ast_true(), ast_variable_browse(), ast_variable_retrieve(), ast_verb, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, embedded_module_list, embedding, EVENT_FLAG_SYSTEM, find_resource(), module_list::first, ast_module::flags, module_list::last, ast_module::lib, load_resource_list(), LOG_NOTICE, LOG_WARNING, manager_event, ast_variable::name, ast_variable::next, load_order_entry::resource, ast_module::resource, resource_name_match(), ast_module::running, and ast_variable::value.

Referenced by main().

01073 {
01074    struct ast_config *cfg;
01075    struct ast_module *mod;
01076    struct load_order_entry *order;
01077    struct ast_variable *v;
01078    unsigned int load_count;
01079    struct load_order load_order;
01080    int res = 0;
01081    struct ast_flags config_flags = { 0 };
01082    int modulecount = 0;
01083 
01084 #ifdef LOADABLE_MODULES
01085    struct dirent *dirent;
01086    DIR *dir;
01087 #endif
01088 
01089    /* all embedded modules have registered themselves by now */
01090    embedding = 0;
01091 
01092    ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
01093 
01094    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
01095 
01096    AST_LIST_LOCK(&module_list);
01097 
01098    if (embedded_module_list.first) {
01099       module_list.first = embedded_module_list.first;
01100       module_list.last = embedded_module_list.last;
01101       embedded_module_list.first = NULL;
01102    }
01103 
01104    cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
01105    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01106       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
01107       goto done;
01108    }
01109 
01110    /* first, find all the modules we have been explicitly requested to load */
01111    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01112       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
01113          add_to_load_order(v->value, &load_order, 0);
01114       }
01115       if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) {
01116          /* Add the module to the list and make sure it's required */
01117          add_to_load_order(v->value, &load_order, 1);
01118          ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
01119       }
01120 
01121    }
01122 
01123    /* check if 'autoload' is on */
01124    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
01125       /* if so, first add all the embedded modules that are not already running to the load order */
01126       AST_LIST_TRAVERSE(&module_list, mod, entry) {
01127          /* if it's not embedded, skip it */
01128          if (mod->lib)
01129             continue;
01130 
01131          if (mod->flags.running)
01132             continue;
01133 
01134          add_to_load_order(mod->resource, &load_order, 0);
01135       }
01136 
01137 #ifdef LOADABLE_MODULES
01138       /* if we are allowed to load dynamic modules, scan the directory for
01139          for all available modules and add them as well */
01140       if ((dir = opendir(ast_config_AST_MODULE_DIR))) {
01141          while ((dirent = readdir(dir))) {
01142             int ld = strlen(dirent->d_name);
01143 
01144             /* Must end in .so to load it.  */
01145 
01146             if (ld < 4)
01147                continue;
01148 
01149             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
01150                continue;
01151 
01152             /* if there is already a module by this name in the module_list,
01153                skip this file */
01154             if (find_resource(dirent->d_name, 0))
01155                continue;
01156 
01157             add_to_load_order(dirent->d_name, &load_order, 0);
01158          }
01159 
01160          closedir(dir);
01161       } else {
01162          if (!ast_opt_quiet)
01163             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
01164                ast_config_AST_MODULE_DIR);
01165       }
01166 #endif
01167    }
01168 
01169    /* now scan the config for any modules we are prohibited from loading and
01170       remove them from the load order */
01171    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01172       if (strcasecmp(v->name, "noload"))
01173          continue;
01174 
01175       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
01176          if (!resource_name_match(order->resource, v->value)) {
01177             AST_LIST_REMOVE_CURRENT(entry);
01178             ast_free(order->resource);
01179             ast_free(order);
01180          }
01181       }
01182       AST_LIST_TRAVERSE_SAFE_END;
01183    }
01184 
01185    /* we are done with the config now, all the information we need is in the
01186       load_order list */
01187    ast_config_destroy(cfg);
01188 
01189    load_count = 0;
01190    AST_LIST_TRAVERSE(&load_order, order, entry)
01191       load_count++;
01192 
01193    if (load_count)
01194       ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);
01195 
01196    /* first, load only modules that provide global symbols */
01197    if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
01198       goto done;
01199    }
01200 
01201    /* now load everything else */
01202    if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
01203       goto done;
01204    }
01205 
01206 done:
01207    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
01208       ast_free(order->resource);
01209       ast_free(order);
01210    }
01211 
01212    AST_LIST_UNLOCK(&module_list);
01213    
01214    /* Tell manager clients that are aggressive at logging in that we're done
01215       loading modules. If there's a DNS problem in chan_sip, we might not
01216       even reach this */
01217    manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
01218    
01219    return res;
01220 }

static enum ast_module_load_result load_resource ( const char *  resource_name,
unsigned int  global_symbols_only,
struct ast_heap resource_heap,
int  required 
) [static]

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 ast_heap is not provided, the module's load function will be executed immediately

Definition at line 893 of file loader.c.

References ast_heap_push(), ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_test_flag, ast_module_info::backup_globals, ast_module::declined, find_resource(), ast_module::flags, ast_module::info, inspect_module(), ast_module::lib, load_dynamic_module(), LOG_WARNING, ast_module::running, start_resource(), and unload_dynamic_module().

Referenced by ast_load_resource(), load_dynamic_module(), and load_resource_list().

00894 {
00895    struct ast_module *mod;
00896    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00897 
00898    if ((mod = find_resource(resource_name, 0))) {
00899       if (mod->flags.running) {
00900          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00901          return AST_MODULE_LOAD_DECLINE;
00902       }
00903       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00904          return AST_MODULE_LOAD_SKIP;
00905    } else {
00906 #ifdef LOADABLE_MODULES
00907       if (!(mod = load_dynamic_module(resource_name, global_symbols_only, resource_heap))) {
00908          /* don't generate a warning message during load_modules() */
00909          if (!global_symbols_only) {
00910             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00911             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00912          } else {
00913             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP;
00914          }
00915       }
00916 #else
00917       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00918       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00919 #endif
00920    }
00921 
00922    if (inspect_module(mod)) {
00923       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00924 #ifdef LOADABLE_MODULES
00925       unload_dynamic_module(mod);
00926 #endif
00927       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00928    }
00929 
00930    if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) {
00931       ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
00932       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00933    }
00934 
00935    mod->flags.declined = 0;
00936 
00937    if (resource_heap) {
00938       ast_heap_push(resource_heap, mod);
00939       res = AST_MODULE_LOAD_PRIORITY;
00940    } else {
00941       res = start_resource(mod);
00942    }
00943 
00944    return res;
00945 }

static int load_resource_list ( struct load_order load_order,
unsigned int  global_symbols,
int *  mod_count 
) [static]

loads modules in order by load_pri, updates mod_count

Returns:
-1 on failure to load module, -2 on failure to load required module, otherwise 0

Definition at line 1010 of file loader.c.

References ast_free, ast_heap_create(), ast_heap_destroy(), ast_heap_pop(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, load_resource(), LOG_ERROR, mod_load_cmp(), load_order_entry::required, load_order_entry::resource, and start_resource().

Referenced by load_modules().

01011 {
01012    struct ast_heap *resource_heap;
01013    struct load_order_entry *order;
01014    struct ast_module *mod;
01015    int count = 0;
01016    int res = 0;
01017 
01018    if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
01019       return -1;
01020    }
01021 
01022    /* first, add find and add modules to heap */
01023    AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
01024       switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) {
01025       case AST_MODULE_LOAD_SUCCESS:
01026       case AST_MODULE_LOAD_DECLINE:
01027          AST_LIST_REMOVE_CURRENT(entry);
01028          ast_free(order->resource);
01029          ast_free(order);
01030          break;
01031       case AST_MODULE_LOAD_FAILURE:
01032          ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
01033          fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
01034          res = order->required ? -2 : -1;
01035          goto done;
01036       case AST_MODULE_LOAD_SKIP:
01037          break;
01038       case AST_MODULE_LOAD_PRIORITY:
01039          AST_LIST_REMOVE_CURRENT(entry);
01040          ast_free(order->resource);
01041          ast_free(order);
01042          break;
01043       }
01044    }
01045    AST_LIST_TRAVERSE_SAFE_END;
01046 
01047    /* second remove modules from heap sorted by priority */
01048    while ((mod = ast_heap_pop(resource_heap))) {
01049       switch (start_resource(mod)) {
01050       case AST_MODULE_LOAD_SUCCESS:
01051          count++;
01052       case AST_MODULE_LOAD_DECLINE:
01053          break;
01054       case AST_MODULE_LOAD_FAILURE:
01055          res = -1;
01056          goto done;
01057       case AST_MODULE_LOAD_SKIP:
01058       case AST_MODULE_LOAD_PRIORITY:
01059          break;
01060       }
01061    }
01062 
01063 done:
01064    if (mod_count) {
01065       *mod_count += count;
01066    }
01067    ast_heap_destroy(resource_heap);
01068 
01069    return res;
01070 }

static int mod_load_cmp ( void *  a,
void *  b 
) [static]

Definition at line 991 of file loader.c.

References AST_MODFLAG_LOAD_ORDER, ast_test_flag, ast_module::info, and ast_module_info::load_pri.

Referenced by load_resource_list().

00992 {
00993    struct ast_module *a_mod = (struct ast_module *) a;
00994    struct ast_module *b_mod = (struct ast_module *) b;
00995    int res = -1;
00996    /* if load_pri is not set, default is 128.  Lower is better*/
00997    unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
00998    unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
00999    if (a_pri == b_pri) {
01000       res = 0;
01001    } else if (a_pri < b_pri) {
01002       res = 1;
01003    }
01004    return res;
01005 }

static int printdigest ( const unsigned char *  d  )  [static]

Definition at line 296 of file loader.c.

References ast_debug.

Referenced by verify_key().

00297 {
00298    int x, pos;
00299    char buf[256]; /* large enough so we don't have to worry */
00300 
00301    for (pos = 0, x = 0; x < 16; x++)
00302       pos += sprintf(buf + pos, " %02x", (unsigned)*d++);
00303 
00304    ast_debug(1, "Unexpected signature:%s\n", buf);
00305 
00306    return 0;
00307 }

static void queue_reload_request ( const char *  module  )  [static]

Definition at line 683 of file loader.c.

References ast_calloc, ast_free, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), do_full_reload, LOG_ERROR, and reload_queue_item::module.

Referenced by ast_module_reload().

00684 {
00685    struct reload_queue_item *item;
00686 
00687    AST_LIST_LOCK(&reload_queue);
00688 
00689    if (do_full_reload) {
00690       AST_LIST_UNLOCK(&reload_queue);
00691       return;
00692    }
00693 
00694    if (ast_strlen_zero(module)) {
00695       /* A full reload request (when module is NULL) wipes out any previous
00696          reload requests and causes the queue to ignore future ones */
00697       while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00698          ast_free(item);
00699       }
00700       do_full_reload = 1;
00701    } else {
00702       /* No reason to add the same module twice */
00703       AST_LIST_TRAVERSE(&reload_queue, item, entry) {
00704          if (!strcasecmp(item->module, module)) {
00705             AST_LIST_UNLOCK(&reload_queue);
00706             return;
00707          }
00708       }
00709       item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
00710       if (!item) {
00711          ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
00712          AST_LIST_UNLOCK(&reload_queue);
00713          return;
00714       }
00715       strcpy(item->module, module);
00716       AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
00717    }
00718    AST_LIST_UNLOCK(&reload_queue);
00719 }

static int resource_name_match ( const char *  name1_in,
const char *  name2_in 
) [static]

Definition at line 338 of file loader.c.

References ast_strdupa.

Referenced by add_to_load_order(), ast_module_reload(), find_resource(), and load_modules().

00339 {
00340    char *name1 = (char *) name1_in;
00341    char *name2 = (char *) name2_in;
00342 
00343    /* trim off any .so extensions */
00344    if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
00345       name1 = ast_strdupa(name1);
00346       name1[strlen(name1) - 3] = '\0';
00347    }
00348    if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
00349       name2 = ast_strdupa(name2);
00350       name2[strlen(name2) - 3] = '\0';
00351    }
00352 
00353    return strcasecmp(name1, name2);
00354 }

static enum ast_module_load_result start_resource ( struct ast_module mod  )  [static]

Definition at line 843 of file loader.c.

References ast_fully_booted, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_PRIORITY, AST_MODULE_LOAD_SKIP, AST_MODULE_LOAD_SUCCESS, ast_opt_console, ast_update_use_count(), ast_verb, ast_verbose, COLOR_BLACK, COLOR_BROWN, ast_module::declined, ast_module_info::description, ast_module::flags, ast_module::info, ast_module_info::load, option_verbose, ast_module::resource, ast_module::running, and term_color().

Referenced by load_resource(), and load_resource_list().

00844 {
00845    char tmp[256];
00846    enum ast_module_load_result res;
00847 
00848    if (mod->flags.running) {
00849       return AST_MODULE_LOAD_SUCCESS;
00850    }
00851 
00852    if (!mod->info->load) {
00853       return AST_MODULE_LOAD_FAILURE;
00854    }
00855 
00856    res = mod->info->load();
00857 
00858    switch (res) {
00859    case AST_MODULE_LOAD_SUCCESS:
00860       if (!ast_fully_booted) {
00861          ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00862          if (ast_opt_console && !option_verbose)
00863             ast_verbose( ".");
00864       } else {
00865          ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
00866       }
00867 
00868       mod->flags.running = 1;
00869 
00870       ast_update_use_count();
00871       break;
00872    case AST_MODULE_LOAD_DECLINE:
00873       mod->flags.declined = 1;
00874       break;
00875    case AST_MODULE_LOAD_FAILURE:
00876    case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
00877    case AST_MODULE_LOAD_PRIORITY:
00878       break;
00879    }
00880 
00881    return res;
00882 }

static void unload_dynamic_module ( struct ast_module mod  )  [static]

Definition at line 393 of file loader.c.

References ast_module_name(), close_lib(), and ast_module::lib.

Referenced by ast_unload_resource(), and load_resource().

00394 {
00395    void *lib = mod->lib;
00396 
00397    /* WARNING: the structure pointed to by mod is going to
00398       disappear when this operation succeeds, so we can't
00399       dereference it */
00400    close_lib(ast_module_name(mod), lib);
00401 }

static int verify_key ( const unsigned char *  key  )  [static]

Definition at line 321 of file loader.c.

References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().

Referenced by inspect_module().

00322 {
00323    struct MD5Context c;
00324    unsigned char digest[16];
00325 
00326    MD5Init(&c);
00327    MD5Update(&c, key, strlen((char *)key));
00328    MD5Final(digest, &c);
00329 
00330    if (key_matches(expected_key, digest))
00331       return 0;
00332 
00333    printdigest(digest);
00334 
00335    return -1;
00336 }


Variable Documentation

char buildopt_sum[33] = AST_BUILDOPT_SUM [static]

Definition at line 83 of file loader.c.

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 135 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

Definition at line 119 of file loader.c.

Referenced by ast_module_register(), and load_modules().

unsigned int embedding = 1 [static]

Definition at line 85 of file loader.c.

Referenced by ast_module_register(), and load_modules().

const unsigned char expected_key[] [static]
Initial value:
{ 0x87, 0x76, 0x79, 0x35, 0x23, 0xea, 0x3a, 0xd3,
  0x25, 0x2a, 0xbb, 0x35, 0x87, 0xe4, 0x22, 0x24 }

Definition at line 79 of file loader.c.

Referenced by verify_key().

ast_mutex_t reloadlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } [static]

Definition at line 128 of file loader.c.

Definition at line 143 of file loader.c.

Referenced by load_dynamic_module().


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1