Mon Jun 27 16:51:15 2011

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

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 with the name given is loaded.
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.
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 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)
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>

Definition in file loader.c.


Define Documentation

#define RTLD_LOCAL   0

Definition at line 64 of file loader.c.

Referenced by load_dynamic_module().

#define RTLD_NOW   0

Definition at line 60 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 
)

Definition at line 195 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_user::entry, ast_module::usecount, and ast_module::users.

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

00197 {
00198    struct ast_module_user *u = ast_calloc(1, sizeof(*u));
00199 
00200    if (!u)
00201       return NULL;
00202 
00203    u->chan = chan;
00204 
00205    AST_LIST_LOCK(&mod->users);
00206    AST_LIST_INSERT_HEAD(&mod->users, u, entry);
00207    AST_LIST_UNLOCK(&mod->users);
00208 
00209    ast_atomic_fetchadd_int(&mod->usecount, +1);
00210 
00211    ast_update_use_count();
00212 
00213    return u;
00214 }

void __ast_module_user_hangup_all ( struct ast_module mod  ) 

Definition at line 227 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_user::entry, ast_module::usecount, and ast_module::users.

Referenced by ast_unload_resource().

00228 {
00229    struct ast_module_user *u;
00230 
00231    AST_LIST_LOCK(&mod->users);
00232    while ((u = AST_LIST_REMOVE_HEAD(&mod->users, entry))) {
00233       ast_softhangup(u->chan, AST_SOFTHANGUP_APPUNLOAD);
00234       ast_atomic_fetchadd_int(&mod->usecount, -1);
00235       ast_free(u);
00236    }
00237    AST_LIST_UNLOCK(&mod->users);
00238 
00239    ast_update_use_count();
00240 }

void __ast_module_user_remove ( struct ast_module mod,
struct ast_module_user u 
)

Definition at line 216 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_user::entry, ast_module::usecount, and ast_module::users.

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

00217 {
00218    AST_LIST_LOCK(&mod->users);
00219    AST_LIST_REMOVE(&mod->users, u, entry);
00220    AST_LIST_UNLOCK(&mod->users);
00221    ast_atomic_fetchadd_int(&mod->usecount, -1);
00222    ast_free(u);
00223 
00224    ast_update_use_count();
00225 }

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

Definition at line 894 of file loader.c.

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

Referenced by load_modules().

00895 {
00896    struct load_order_entry *order;
00897 
00898    AST_LIST_TRAVERSE(load_order, order, entry) {
00899       if (!resource_name_match(order->resource, resource)) {
00900          /* Make sure we have the proper setting for the required field 
00901             (we might have both load= and required= lines in modules.conf) */
00902          order->required |= required;
00903          return NULL;
00904       }
00905    }
00906 
00907    if (!(order = ast_calloc(1, sizeof(*order))))
00908       return NULL;
00909 
00910    order->resource = ast_strdup(resource);
00911    order->required = required;
00912    AST_LIST_INSERT_TAIL(load_order, order, entry);
00913 
00914    return order;
00915 }

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 876 of file loader.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().

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

00877 {
00878    int res;
00879    AST_LIST_LOCK(&module_list);
00880    res = load_resource(resource_name, 0, NULL, 0);
00881    AST_LIST_UNLOCK(&module_list);
00882 
00883    return res;
00884 }

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 1192 of file loader.c.

References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and ast_module_user::entry.

01193 {
01194    struct loadupdate *tmp;
01195 
01196    if (!(tmp = ast_malloc(sizeof(*tmp))))
01197       return -1;
01198 
01199    tmp->updater = v;
01200    AST_LIST_LOCK(&updaters);
01201    AST_LIST_INSERT_HEAD(&updaters, tmp, entry);
01202    AST_LIST_UNLOCK(&updaters);
01203 
01204    return 0;
01205 }

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 1207 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, ast_module_user::entry, and loadupdate::updater.

01208 {
01209    struct loadupdate *cur;
01210 
01211    AST_LIST_LOCK(&updaters);
01212    AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) {
01213       if (cur->updater == v)  {
01214          AST_LIST_REMOVE_CURRENT(entry);
01215          break;
01216       }
01217    }
01218    AST_LIST_TRAVERSE_SAFE_END;
01219    AST_LIST_UNLOCK(&updaters);
01220 
01221    return cur ? 0 : -1;
01222 }

int ast_module_check ( const char *  name  ) 

Check if module with the name given is loaded.

Parameters:
name Module name, like "chan_sip.so"
Return values:
1 if true
0 if false

Definition at line 1179 of file loader.c.

References ast_strlen_zero(), and find_resource().

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

01180 {
01181    struct ast_module *cur;
01182 
01183    if (ast_strlen_zero(name))
01184       return 0;       /* FALSE */
01185 
01186    cur = find_resource(name, 1);
01187 
01188    return (cur != NULL);
01189 }

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 565 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strdup, ast_module_user::entry, 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().

00566 {
00567    struct ast_module *cur;
00568    int i, which=0, l = strlen(word);
00569    char *ret = NULL;
00570 
00571    if (pos != rpos)
00572       return NULL;
00573 
00574    AST_LIST_LOCK(&module_list);
00575    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00576       if (!strncasecmp(word, cur->resource, l) &&
00577           (cur->info->reload || !needsreload) &&
00578           ++which > state) {
00579          ret = ast_strdup(cur->resource);
00580          break;
00581       }
00582    }
00583    AST_LIST_UNLOCK(&module_list);
00584 
00585    if (!ret) {
00586       for (i=0; !ret && reload_classes[i].name; i++) {
00587          if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state)
00588             ret = ast_strdup(reload_classes[i].name);
00589       }
00590    }
00591 
00592    return ret;
00593 }

struct ast_module* ast_module_ref ( struct ast_module mod  ) 

Definition at line 1224 of file loader.c.

References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.

Referenced by __oh323_new(), agi_handle_command(), alsa_new(), ast_agi_register(), ast_fax_tech_register(), ast_iax2_new(), ast_rtp_instance_new(), ast_srtp_create(), ast_timer_open(), dahdi_new(), data_result_generate_node(), fax_session_new(), fax_session_reserve(), find_best_technology(), fn_wrapper(), gtalk_new(), handle_cli_file_convert(), handle_orig(), load_module(), mgcp_new(), moh_alloc(), moh_files_alloc(), mute_add_audiohook(), my_module_ref(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_handle_cc(), sip_new(), skinny_new(), and usbradio_new().

01225 {
01226    if (!mod) {
01227       return NULL;
01228    }
01229 
01230    ast_atomic_fetchadd_int(&mod->usecount, +1);
01231    ast_update_use_count();
01232 
01233    return mod;
01234 }

void ast_module_register ( const struct ast_module_info info  ) 

Definition at line 133 of file loader.c.

References ast_calloc, AST_LIST_HEAD_INIT, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, embedding, ast_module_user::entry, ast_module::info, and ast_module::users.

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

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 660 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_tvnow(), ast_unlock_path(), ast_verb, ast_verbose, ast_module::declined, ast_module_info::description, ast_module_user::entry, 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().

00661 {
00662    struct ast_module *cur;
00663    int res = 0; /* return value. 0 = not found, others, see below */
00664    int i;
00665 
00666    /* If we aren't fully booted, we just pretend we reloaded but we queue this
00667       up to run once we are booted up. */
00668    if (!ast_fully_booted) {
00669       queue_reload_request(name);
00670       return 0;
00671    }
00672 
00673    if (ast_mutex_trylock(&reloadlock)) {
00674       ast_verbose("The previous reload command didn't finish yet\n");
00675       return -1;  /* reload already in progress */
00676    }
00677    ast_lastreloadtime = ast_tvnow();
00678 
00679    if (ast_opt_lock_confdir) {
00680       int try;
00681       int res;
00682       for (try = 1, res = AST_LOCK_TIMEOUT; try < 6 && (res == AST_LOCK_TIMEOUT); try++) {
00683          res = ast_lock_path(ast_config_AST_CONFIG_DIR);
00684          if (res == AST_LOCK_TIMEOUT) {
00685             ast_log(LOG_WARNING, "Failed to grab lock on %s, try %d\n", ast_config_AST_CONFIG_DIR, try);
00686          }
00687       }
00688       if (res != AST_LOCK_SUCCESS) {
00689          ast_verbose("Cannot grab lock on %s\n", ast_config_AST_CONFIG_DIR);
00690          ast_mutex_unlock(&reloadlock);
00691          return -1;
00692       }
00693    }
00694 
00695    /* Call "predefined" reload here first */
00696    for (i = 0; reload_classes[i].name; i++) {
00697       if (!name || !strcasecmp(name, reload_classes[i].name)) {
00698          reload_classes[i].reload_fn();   /* XXX should check error ? */
00699          res = 2; /* found and reloaded */
00700       }
00701    }
00702 
00703    if (name && res) {
00704       if (ast_opt_lock_confdir) {
00705          ast_unlock_path(ast_config_AST_CONFIG_DIR);
00706       }
00707       ast_mutex_unlock(&reloadlock);
00708       return res;
00709    }
00710 
00711    AST_LIST_LOCK(&module_list);
00712    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00713       const struct ast_module_info *info = cur->info;
00714 
00715       if (name && resource_name_match(name, cur->resource))
00716          continue;
00717 
00718       if (!cur->flags.running || cur->flags.declined) {
00719          if (!name)
00720             continue;
00721          ast_log(LOG_NOTICE, "The module '%s' was not properly initialized.  "
00722             "Before reloading the module, you must run \"module load %s\" "
00723             "and fix whatever is preventing the module from being initialized.\n",
00724             name, name);
00725          res = 2; /* Don't report that the module was not found */
00726          break;
00727       }
00728 
00729       if (!info->reload) { /* cannot be reloaded */
00730          if (res < 1)   /* store result if possible */
00731             res = 1; /* 1 = no reload() method */
00732          continue;
00733       }
00734 
00735       res = 2;
00736       ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description);
00737       info->reload();
00738    }
00739    AST_LIST_UNLOCK(&module_list);
00740 
00741    if (ast_opt_lock_confdir) {
00742       ast_unlock_path(ast_config_AST_CONFIG_DIR);
00743    }
00744    ast_mutex_unlock(&reloadlock);
00745 
00746    return res;
00747 }

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 465 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_user::entry, ast_module::flags, free, ast_module::info, ast_module::running, ast_module_info::unload, ast_module::usecount, and ast_module::users.

Referenced by quit_handler().

00466 {
00467    struct ast_module *mod;
00468    int somethingchanged = 1, final = 0;
00469 
00470    AST_LIST_LOCK(&module_list);
00471 
00472    /*!\note Some resources, like timers, are started up dynamically, and thus
00473     * may be still in use, even if all channels are dead.  We must therefore
00474     * check the usecount before asking modules to unload. */
00475    do {
00476       if (!somethingchanged) {
00477          /*!\note If we go through the entire list without changing
00478           * anything, ignore the usecounts and unload, then exit. */
00479          final = 1;
00480       }
00481 
00482       /* Reset flag before traversing the list */
00483       somethingchanged = 0;
00484 
00485       AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00486          if (!final && mod->usecount) {
00487             continue;
00488          }
00489          AST_LIST_REMOVE_CURRENT(entry);
00490          if (mod->flags.running && !mod->flags.declined && mod->info->unload) {
00491             mod->info->unload();
00492          }
00493          AST_LIST_HEAD_DESTROY(&mod->users);
00494          free(mod);
00495          somethingchanged = 1;
00496       }
00497       AST_LIST_TRAVERSE_SAFE_END;
00498    } while (somethingchanged && !final);
00499 
00500    AST_LIST_UNLOCK(&module_list);
00501 }

void ast_module_unref ( struct ast_module mod  ) 

Definition at line 1236 of file loader.c.

References ast_atomic_fetchadd_int(), ast_update_use_count(), and ast_module::usecount.

Referenced by agi_handle_command(), alsa_hangup(), ast_agi_unregister(), ast_bridge_check(), ast_fax_tech_unregister(), ast_rtp_instance_new(), ast_smdi_interface_destroy(), ast_srtp_destroy(), ast_timer_close(), dahdi_destroy_channel_bynum(), dahdi_hangup(), data_result_generate_node(), destroy(), destroy_bridge(), destroy_callback(), destroy_session(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), instance_destructor(), local_ast_moh_cleanup(), mgcp_hangup(), my_module_unref(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_cc_monitor_destructor(), sip_hangup(), skinny_hangup(), smart_bridge_operation(), and usbradio_hangup().

01237 {
01238    if (!mod) {
01239       return;
01240    }
01241 
01242    ast_atomic_fetchadd_int(&mod->usecount, -1);
01243    ast_update_use_count();
01244 }

void ast_module_unregister ( const struct ast_module_info info  ) 

Definition at line 171 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_user::entry, ast_module::info, and ast_module::users.

00172 {
00173    struct ast_module *mod = NULL;
00174 
00175    /* it is assumed that the users list in the module structure
00176       will already be empty, or we cannot have gotten to this
00177       point
00178    */
00179    AST_LIST_LOCK(&module_list);
00180    AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) {
00181       if (mod->info == info) {
00182          AST_LIST_REMOVE_CURRENT(entry);
00183          break;
00184       }
00185    }
00186    AST_LIST_TRAVERSE_SAFE_END;
00187    AST_LIST_UNLOCK(&module_list);
00188 
00189    if (mod) {
00190       AST_LIST_HEAD_DESTROY(&mod->users);
00191       ast_free(mod);
00192    }
00193 }

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 595 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, ast_module_user::entry, LOG_NOTICE, and reload_queue_item::module.

Referenced by main().

00596 {
00597    struct reload_queue_item *item;
00598 
00599    if (!ast_fully_booted) {
00600       return;
00601    }
00602 
00603    AST_LIST_LOCK(&reload_queue);
00604 
00605    if (do_full_reload) {
00606       do_full_reload = 0;
00607       AST_LIST_UNLOCK(&reload_queue);
00608       ast_log(LOG_NOTICE, "Executing deferred reload request.\n");
00609       ast_module_reload(NULL);
00610       return;
00611    }
00612 
00613    while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00614       ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module);
00615       ast_module_reload(item->module);
00616       ast_free(item);
00617    }
00618 
00619    AST_LIST_UNLOCK(&reload_queue);
00620 }

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 503 of file loader.c.

References __ast_module_user_hangup_all(), AST_FORCE_FIRM, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, unload_dynamic_module(), and ast_module::usecount.

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

00504 {
00505    struct ast_module *mod;
00506    int res = -1;
00507    int error = 0;
00508 
00509    AST_LIST_LOCK(&module_list);
00510 
00511    if (!(mod = find_resource(resource_name, 0))) {
00512       AST_LIST_UNLOCK(&module_list);
00513       ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name);
00514       return -1;
00515    }
00516 
00517    if (!mod->flags.running || mod->flags.declined) {
00518       ast_log(LOG_WARNING, "Unload failed, '%s' is not loaded.\n", resource_name);
00519       error = 1;
00520    }
00521 
00522    if (!error && (mod->usecount > 0)) {
00523       if (force)
00524          ast_log(LOG_WARNING, "Warning:  Forcing removal of module '%s' with use count %d\n",
00525             resource_name, mod->usecount);
00526       else {
00527          ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name,
00528             mod->usecount);
00529          error = 1;
00530       }
00531    }
00532 
00533    if (!error) {
00534       __ast_module_user_hangup_all(mod);
00535       res = mod->info->unload();
00536 
00537       if (res) {
00538          ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name);
00539          if (force <= AST_FORCE_FIRM)
00540             error = 1;
00541          else
00542             ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n");
00543       }
00544    }
00545 
00546    if (!error)
00547       mod->flags.running = mod->flags.declined = 0;
00548 
00549    AST_LIST_UNLOCK(&module_list);
00550 
00551    if (!error && !mod->lib && mod->info && mod->info->restore_globals)
00552       mod->info->restore_globals();
00553 
00554 #ifdef LOADABLE_MODULES
00555    if (!error)
00556       unload_dynamic_module(mod);
00557 #endif
00558 
00559    if (!error)
00560       ast_update_use_count();
00561 
00562    return res;
00563 }

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 1158 of file loader.c.

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

Referenced by ast_var_Modules(), and handle_modlist().

01160 {
01161    struct ast_module *cur;
01162    int unlock = -1;
01163    int total_mod_loaded = 0;
01164 
01165    if (AST_LIST_TRYLOCK(&module_list))
01166       unlock = 0;
01167  
01168    AST_LIST_TRAVERSE(&module_list, cur, entry) {
01169       total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like);
01170    }
01171 
01172    if (unlock)
01173       AST_LIST_UNLOCK(&module_list);
01174 
01175    return total_mod_loaded;
01176 }

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 1146 of file loader.c.

References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_module_user::entry, 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().

01147 {
01148    /* Notify any module monitors that the use count for a
01149       resource has changed */
01150    struct loadupdate *m;
01151 
01152    AST_LIST_LOCK(&updaters);
01153    AST_LIST_TRAVERSE(&updaters, m, entry)
01154       m->updater();
01155    AST_LIST_UNLOCK(&updaters);
01156 }

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

Definition at line 327 of file loader.c.

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

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

00328 {
00329    struct ast_module *cur;
00330 
00331    if (do_lock)
00332       AST_LIST_LOCK(&module_list);
00333 
00334    AST_LIST_TRAVERSE(&module_list, cur, entry) {
00335       if (!resource_name_match(resource, cur->resource))
00336          break;
00337    }
00338 
00339    if (do_lock)
00340       AST_LIST_UNLOCK(&module_list);
00341 
00342    return cur;
00343 }

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

Definition at line 749 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().

00750 {
00751    if (!mod->info->description) {
00752       ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource);
00753       return 1;
00754    }
00755 
00756    if (!mod->info->key) {
00757       ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource);
00758       return 1;
00759    }
00760 
00761    if (verify_key((unsigned char *) mod->info->key)) {
00762       ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource);
00763       return 1;
00764    }
00765 
00766    if (!ast_strlen_zero(mod->info->buildopt_sum) &&
00767        strcmp(buildopt_sum, mod->info->buildopt_sum)) {
00768       ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource);
00769       ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource);
00770       return 1;
00771    }
00772 
00773    return 0;
00774 }

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

Definition at line 280 of file loader.c.

Referenced by verify_key().

00281 {
00282    int x;
00283 
00284    for (x = 0; x < 16; x++) {
00285       if (key1[x] != key2[x])
00286          return 0;
00287    }
00288 
00289    return 1;
00290 }

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

Definition at line 358 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, find_resource(), ast_module::info, ast_module::lib, LOG_WARNING, ast_module_info::nonoptreq, ast_module::resource, resource_being_loaded, RTLD_LOCAL, RTLD_NOW, and strsep().

Referenced by load_resource().

00359 {
00360    char fn[PATH_MAX] = "";
00361    void *lib = NULL;
00362    struct ast_module *mod;
00363    unsigned int wants_global;
00364    int space;  /* room needed for the descriptor */
00365    int missing_so = 0;
00366 
00367    space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;
00368    if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {
00369       missing_so = 1;
00370       space += 3; /* room for the extra ".so" */
00371    }
00372 
00373    snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");
00374 
00375    /* make a first load of the module in 'quiet' mode... don't try to resolve
00376       any symbols, and don't export any symbols. this will allow us to peek into
00377       the module's info block (if available) to see what flags it has set */
00378 
00379    resource_being_loaded = ast_calloc(1, space);
00380    if (!resource_being_loaded)
00381       return NULL;
00382    strcpy(resource_being_loaded->resource, resource_in);
00383    if (missing_so)
00384       strcat(resource_being_loaded->resource, ".so");
00385 
00386    if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) {
00387       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00388       ast_free(resource_being_loaded);
00389       return NULL;
00390    }
00391 
00392    /* the dlopen() succeeded, let's find out if the module
00393       registered itself */
00394    /* note that this will only work properly as long as
00395       ast_module_register() (which is called by the module's
00396       constructor) places the new module at the tail of the
00397       module_list
00398    */
00399    if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) {
00400       ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);
00401       /* no, it did not, so close it and return */
00402       while (!dlclose(lib));
00403       /* note that the module's destructor will call ast_module_unregister(),
00404          which will free the structure we allocated in resource_being_loaded */
00405       return NULL;
00406    }
00407 
00408    wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);
00409 
00410    /* if we are being asked only to load modules that provide global symbols,
00411       and this one does not, then close it and return */
00412    if (global_symbols_only && !wants_global) {
00413       while (!dlclose(lib));
00414       return NULL;
00415    }
00416 
00417    /* This section is a workaround for a gcc 4.1 bug that has already been
00418     * fixed in later versions.  Unfortunately, some distributions, such as
00419     * RHEL/CentOS 5, distribute gcc 4.1, so we're stuck with having to deal
00420     * with this issue.  This basically ensures that optional_api modules are
00421     * loaded before any module which requires their functionality. */
00422 #if !defined(HAVE_ATTRIBUTE_weak_import) && !defined(HAVE_ATTRIBUTE_weakref)
00423    if (!ast_strlen_zero(mod->info->nonoptreq)) {
00424       /* Force any required dependencies to load */
00425       char *each, *required_resource = ast_strdupa(mod->info->nonoptreq);
00426       while ((each = strsep(&required_resource, ","))) {
00427          each = ast_strip(each);
00428 
00429          /* Is it already loaded? */
00430          if (!find_resource(each, 0)) {
00431             load_dynamic_module(each, global_symbols_only);
00432          }
00433       }
00434    }
00435 #endif
00436 
00437    while (!dlclose(lib));
00438    resource_being_loaded = NULL;
00439 
00440    /* start the load process again */
00441    resource_being_loaded = ast_calloc(1, space);
00442    if (!resource_being_loaded)
00443       return NULL;
00444    strcpy(resource_being_loaded->resource, resource_in);
00445    if (missing_so)
00446       strcat(resource_being_loaded->resource, ".so");
00447 
00448    if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {
00449       ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());
00450       ast_free(resource_being_loaded);
00451       return NULL;
00452    }
00453 
00454    /* since the module was successfully opened, and it registered itself
00455       the previous time we did that, we're going to assume it worked this
00456       time too :) */
00457 
00458    AST_LIST_LAST(&module_list)->lib = lib;
00459    resource_being_loaded = NULL;
00460 
00461    return AST_LIST_LAST(&module_list);
00462 }

int load_modules ( unsigned  int  ) 

Provided by loader.c

Definition at line 996 of file loader.c.

References add_to_load_order(), ast_config_load2(), ast_debug, AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verb, config_flags, CONFIG_STATUS_FILEINVALID, CONFIG_STATUS_FILEMISSING, embedding, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.

Referenced by main().

00997 {
00998    struct ast_config *cfg;
00999    struct ast_module *mod;
01000    struct load_order_entry *order;
01001    struct ast_variable *v;
01002    unsigned int load_count;
01003    struct load_order load_order;
01004    int res = 0;
01005    struct ast_flags config_flags = { 0 };
01006    int modulecount = 0;
01007 
01008 #ifdef LOADABLE_MODULES
01009    struct dirent *dirent;
01010    DIR *dir;
01011 #endif
01012 
01013    /* all embedded modules have registered themselves by now */
01014    embedding = 0;
01015 
01016    ast_verb(1, "Asterisk Dynamic Loader Starting:\n");
01017 
01018    AST_LIST_HEAD_INIT_NOLOCK(&load_order);
01019 
01020    AST_LIST_LOCK(&module_list);
01021 
01022    if (embedded_module_list.first) {
01023       module_list.first = embedded_module_list.first;
01024       module_list.last = embedded_module_list.last;
01025       embedded_module_list.first = NULL;
01026    }
01027 
01028    cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags);
01029    if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
01030       ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG);
01031       goto done;
01032    }
01033 
01034    /* first, find all the modules we have been explicitly requested to load */
01035    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01036       if (!strcasecmp(v->name, preload_only ? "preload" : "load")) {
01037          add_to_load_order(v->value, &load_order, 0);
01038       }
01039       if (!strcasecmp(v->name, preload_only ? "preload-require" : "require")) {
01040          /* Add the module to the list and make sure it's required */
01041          add_to_load_order(v->value, &load_order, 1);
01042          ast_debug(2, "Adding module to required list: %s (%s)\n", v->value, v->name);
01043       }
01044 
01045    }
01046 
01047    /* check if 'autoload' is on */
01048    if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) {
01049       /* if so, first add all the embedded modules that are not already running to the load order */
01050       AST_LIST_TRAVERSE(&module_list, mod, entry) {
01051          /* if it's not embedded, skip it */
01052          if (mod->lib)
01053             continue;
01054 
01055          if (mod->flags.running)
01056             continue;
01057 
01058          order = add_to_load_order(mod->resource, &load_order, 0);
01059       }
01060 
01061 #ifdef LOADABLE_MODULES
01062       /* if we are allowed to load dynamic modules, scan the directory for
01063          for all available modules and add them as well */
01064       if ((dir  = opendir(ast_config_AST_MODULE_DIR))) {
01065          while ((dirent = readdir(dir))) {
01066             int ld = strlen(dirent->d_name);
01067 
01068             /* Must end in .so to load it.  */
01069 
01070             if (ld < 4)
01071                continue;
01072 
01073             if (strcasecmp(dirent->d_name + ld - 3, ".so"))
01074                continue;
01075 
01076             /* if there is already a module by this name in the module_list,
01077                skip this file */
01078             if (find_resource(dirent->d_name, 0))
01079                continue;
01080 
01081             add_to_load_order(dirent->d_name, &load_order, 0);
01082          }
01083 
01084          closedir(dir);
01085       } else {
01086          if (!ast_opt_quiet)
01087             ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n",
01088                ast_config_AST_MODULE_DIR);
01089       }
01090 #endif
01091    }
01092 
01093    /* now scan the config for any modules we are prohibited from loading and
01094       remove them from the load order */
01095    for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
01096       if (strcasecmp(v->name, "noload"))
01097          continue;
01098 
01099       AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
01100          if (!resource_name_match(order->resource, v->value)) {
01101             AST_LIST_REMOVE_CURRENT(entry);
01102             ast_free(order->resource);
01103             ast_free(order);
01104          }
01105       }
01106       AST_LIST_TRAVERSE_SAFE_END;
01107    }
01108 
01109    /* we are done with the config now, all the information we need is in the
01110       load_order list */
01111    ast_config_destroy(cfg);
01112 
01113    load_count = 0;
01114    AST_LIST_TRAVERSE(&load_order, order, entry)
01115       load_count++;
01116 
01117    if (load_count)
01118       ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count);
01119 
01120    /* first, load only modules that provide global symbols */
01121    if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {
01122       goto done;
01123    }
01124 
01125    /* now load everything else */
01126    if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {
01127       goto done;
01128    }
01129 
01130 done:
01131    while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {
01132       ast_free(order->resource);
01133       ast_free(order);
01134    }
01135 
01136    AST_LIST_UNLOCK(&module_list);
01137    
01138    /* Tell manager clients that are aggressive at logging in that we're done
01139       loading modules. If there's a DNS problem in chan_sip, we might not
01140       even reach this */
01141    manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount);
01142    
01143    return res;
01144 }

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 822 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(), and load_resource_list().

00823 {
00824    struct ast_module *mod;
00825    enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;
00826 
00827    if ((mod = find_resource(resource_name, 0))) {
00828       if (mod->flags.running) {
00829          ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);
00830          return AST_MODULE_LOAD_DECLINE;
00831       }
00832       if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))
00833          return AST_MODULE_LOAD_SKIP;
00834    } else {
00835 #ifdef LOADABLE_MODULES
00836       if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) {
00837          /* don't generate a warning message during load_modules() */
00838          if (!global_symbols_only) {
00839             ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00840             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00841          } else {
00842             return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_SKIP;
00843          }
00844       }
00845 #else
00846       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00847       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00848 #endif
00849    }
00850 
00851    if (inspect_module(mod)) {
00852       ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);
00853 #ifdef LOADABLE_MODULES
00854       unload_dynamic_module(mod);
00855 #endif
00856       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00857    }
00858 
00859    if (!mod->lib && mod->info->backup_globals && mod->info->backup_globals()) {
00860       ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name);
00861       return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;
00862    }
00863 
00864    mod->flags.declined = 0;
00865 
00866    if (resource_heap) {
00867       ast_heap_push(resource_heap, mod);
00868       res = AST_MODULE_LOAD_PRIORITY;
00869    } else {
00870       res = start_resource(mod);
00871    }
00872 
00873    return res;
00874 }

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 936 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, ast_module_user::entry, load_resource(), LOG_ERROR, mod_load_cmp(), load_order_entry::required, load_order_entry::resource, and start_resource().

00937 {
00938    struct ast_heap *resource_heap;
00939    struct load_order_entry *order;
00940    struct ast_module *mod;
00941    int count = 0;
00942    int res = 0;
00943 
00944    if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {
00945       return -1;
00946    }
00947 
00948    /* first, add find and add modules to heap */
00949    AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {
00950       switch (load_resource(order->resource, global_symbols, resource_heap, order->required)) {
00951       case AST_MODULE_LOAD_SUCCESS:
00952       case AST_MODULE_LOAD_DECLINE:
00953          AST_LIST_REMOVE_CURRENT(entry);
00954          ast_free(order->resource);
00955          ast_free(order);
00956          break;
00957       case AST_MODULE_LOAD_FAILURE:
00958          ast_log(LOG_ERROR, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
00959          fprintf(stderr, "*** Failed to load module %s - %s\n", order->resource, order->required ? "Required" : "Not required");
00960          res = order->required ? -2 : -1;
00961          goto done;
00962       case AST_MODULE_LOAD_SKIP:
00963          break;
00964       case AST_MODULE_LOAD_PRIORITY:
00965          AST_LIST_REMOVE_CURRENT(entry);
00966          break;
00967       }
00968    }
00969    AST_LIST_TRAVERSE_SAFE_END;
00970 
00971    /* second remove modules from heap sorted by priority */
00972    while ((mod = ast_heap_pop(resource_heap))) {
00973       switch (start_resource(mod)) {
00974       case AST_MODULE_LOAD_SUCCESS:
00975          count++;
00976       case AST_MODULE_LOAD_DECLINE:
00977          break;
00978       case AST_MODULE_LOAD_FAILURE:
00979          res = -1;
00980          goto done;
00981       case AST_MODULE_LOAD_SKIP:
00982       case AST_MODULE_LOAD_PRIORITY:
00983          break;
00984       }
00985    }
00986 
00987 done:
00988    if (mod_count) {
00989       *mod_count += count;
00990    }
00991    ast_heap_destroy(resource_heap);
00992 
00993    return res;
00994 }

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

Definition at line 917 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().

00918 {
00919    struct ast_module *a_mod = (struct ast_module *) a;
00920    struct ast_module *b_mod = (struct ast_module *) b;
00921    int res = -1;
00922    /* if load_pri is not set, default is 128.  Lower is better*/
00923    unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;
00924    unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;
00925    if (a_pri == b_pri) {
00926       res = 0;
00927    } else if (a_pri < b_pri) {
00928       res = 1;
00929    }
00930    return res;
00931 }

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

Definition at line 267 of file loader.c.

References ast_debug.

Referenced by verify_key().

00268 {
00269    int x, pos;
00270    char buf[256]; /* large enough so we don't have to worry */
00271 
00272    for (pos = 0, x = 0; x < 16; x++)
00273       pos += sprintf(buf + pos, " %02x", *d++);
00274 
00275    ast_debug(1, "Unexpected signature:%s\n", buf);
00276 
00277    return 0;
00278 }

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

Definition at line 622 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, ast_module_user::entry, LOG_ERROR, and reload_queue_item::module.

Referenced by ast_module_reload().

00623 {
00624    struct reload_queue_item *item;
00625 
00626    AST_LIST_LOCK(&reload_queue);
00627 
00628    if (do_full_reload) {
00629       AST_LIST_UNLOCK(&reload_queue);
00630       return;
00631    }
00632 
00633    if (ast_strlen_zero(module)) {
00634       /* A full reload request (when module is NULL) wipes out any previous
00635          reload requests and causes the queue to ignore future ones */
00636       while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) {
00637          ast_free(item);
00638       }
00639       do_full_reload = 1;
00640    } else {
00641       /* No reason to add the same module twice */
00642       AST_LIST_TRAVERSE(&reload_queue, item, entry) {
00643          if (!strcasecmp(item->module, module)) {
00644             AST_LIST_UNLOCK(&reload_queue);
00645             return;
00646          }
00647       }
00648       item = ast_calloc(1, sizeof(*item) + strlen(module) + 1);
00649       if (!item) {
00650          ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n");
00651          AST_LIST_UNLOCK(&reload_queue);
00652          return;
00653       }
00654       strcpy(item->module, module);
00655       AST_LIST_INSERT_TAIL(&reload_queue, item, entry);
00656    }
00657    AST_LIST_UNLOCK(&reload_queue);
00658 }

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

Definition at line 309 of file loader.c.

References ast_strdupa.

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

00310 {
00311    char *name1 = (char *) name1_in;
00312    char *name2 = (char *) name2_in;
00313 
00314    /* trim off any .so extensions */
00315    if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
00316       name1 = ast_strdupa(name1);
00317       name1[strlen(name1) - 3] = '\0';
00318    }
00319    if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
00320       name2 = ast_strdupa(name2);
00321       name2[strlen(name2) - 3] = '\0';
00322    }
00323 
00324    return strcasecmp(name1, name2);
00325 }

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

Definition at line 776 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().

00777 {
00778    char tmp[256];
00779    enum ast_module_load_result res;
00780 
00781    if (!mod->info->load) {
00782       return AST_MODULE_LOAD_FAILURE;
00783    }
00784 
00785    res = mod->info->load();
00786 
00787    switch (res) {
00788    case AST_MODULE_LOAD_SUCCESS:
00789       if (!ast_fully_booted) {
00790          ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp)));
00791          if (ast_opt_console && !option_verbose)
00792             ast_verbose( ".");
00793       } else {
00794          ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description);
00795       }
00796 
00797       mod->flags.running = 1;
00798 
00799       ast_update_use_count();
00800       break;
00801    case AST_MODULE_LOAD_DECLINE:
00802       mod->flags.declined = 1;
00803       break;
00804    case AST_MODULE_LOAD_FAILURE:
00805    case AST_MODULE_LOAD_SKIP: /* modules should never return this value */
00806    case AST_MODULE_LOAD_PRIORITY:
00807       break;
00808    }
00809 
00810    return res;
00811 }

static void unload_dynamic_module ( struct ast_module mod  )  [static]

Definition at line 346 of file loader.c.

References ast_module::lib.

Referenced by ast_unload_resource(), and load_resource().

00347 {
00348    void *lib = mod->lib;
00349 
00350    /* WARNING: the structure pointed to by mod is going to
00351       disappear when this operation succeeds, so we can't
00352       dereference it */
00353 
00354    if (lib)
00355       while (!dlclose(lib));
00356 }

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

Definition at line 292 of file loader.c.

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

Referenced by inspect_module().

00293 {
00294    struct MD5Context c;
00295    unsigned char digest[16];
00296 
00297    MD5Init(&c);
00298    MD5Update(&c, key, strlen((char *)key));
00299    MD5Final(digest, &c);
00300 
00301    if (key_matches(expected_key, digest))
00302       return 0;
00303 
00304    printdigest(digest);
00305 
00306    return -1;
00307 }


Variable Documentation

char buildopt_sum[33] = AST_BUILDOPT_SUM [static]

Definition at line 78 of file loader.c.

Referenced by inspect_module().

int do_full_reload = 0 [static]

Definition at line 121 of file loader.c.

Referenced by ast_process_pending_reloads(), and queue_reload_request().

struct module_list embedded_module_list [static]

Definition at line 105 of file loader.c.

unsigned int embedding = 1 [static]

Definition at line 80 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 74 of file loader.c.

Referenced by verify_key().

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

Definition at line 114 of file loader.c.

Referenced by load_module(), and reload().

struct ast_module* resource_being_loaded [static]

Definition at line 129 of file loader.c.

Referenced by load_dynamic_module().


Generated on Mon Jun 27 16:51:15 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7