#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/rtp.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 <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_entry * | add_to_load_order (const char *resource, struct load_order *load_order) |
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_module * | ast_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_module * | find_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_module * | load_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) |
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 unsigned char | expected_key [] |
static ast_mutex_t | reloadlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) |
ast_module * | resource_being_loaded |
Kevin P. Fleming <kpfleming@digium.com>
Luigi Rizzo <rizzo@icir.org>
Definition in file loader.c.
#define RTLD_LOCAL 0 |
#define RTLD_NOW 0 |
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_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_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 | |||
) | [static] |
Definition at line 853 of file loader.c.
References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_strdup, ast_module_user::entry, load_order_entry::resource, and resource_name_match().
Referenced by load_modules().
00854 { 00855 struct load_order_entry *order; 00856 00857 AST_LIST_TRAVERSE(load_order, order, entry) { 00858 if (!resource_name_match(order->resource, resource)) 00859 return NULL; 00860 } 00861 00862 if (!(order = ast_calloc(1, sizeof(*order)))) 00863 return NULL; 00864 00865 order->resource = ast_strdup(resource); 00866 AST_LIST_INSERT_TAIL(load_order, order, entry); 00867 00868 return order; 00869 }
int ast_load_resource | ( | const char * | resource_name | ) |
Load a module.
resource_name | The name of the module to load. |
Definition at line 836 of file loader.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, and load_resource().
Referenced by file_ok_sel(), handle_load(), load_module(), manager_moduleload(), and reload().
00837 { 00838 int res; 00839 AST_LIST_LOCK(&module_list); 00840 res = load_resource(resource_name, 0, NULL); 00841 AST_LIST_UNLOCK(&module_list); 00842 00843 return res; 00844 }
int ast_loader_register | ( | int(*)(void) | updater | ) |
Add a procedure to be run when modules have been updated.
updater | The function to run when modules have been updated. |
0 | on success | |
-1 | on failure. |
Definition at line 1135 of file loader.c.
References AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_malloc, and ast_module_user::entry.
Referenced by show_console().
01136 { 01137 struct loadupdate *tmp; 01138 01139 if (!(tmp = ast_malloc(sizeof(*tmp)))) 01140 return -1; 01141 01142 tmp->updater = v; 01143 AST_LIST_LOCK(&updaters); 01144 AST_LIST_INSERT_HEAD(&updaters, tmp, entry); 01145 AST_LIST_UNLOCK(&updaters); 01146 01147 return 0; 01148 }
int ast_loader_unregister | ( | int(*)(void) | updater | ) |
Remove a procedure to be run when modules are updated.
updater | The updater function to unregister. |
0 | on success | |
-1 | on failure. |
Definition at line 1150 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.
Referenced by exit_now().
01151 { 01152 struct loadupdate *cur; 01153 01154 AST_LIST_LOCK(&updaters); 01155 AST_LIST_TRAVERSE_SAFE_BEGIN(&updaters, cur, entry) { 01156 if (cur->updater == v) { 01157 AST_LIST_REMOVE_CURRENT(entry); 01158 break; 01159 } 01160 } 01161 AST_LIST_TRAVERSE_SAFE_END; 01162 AST_LIST_UNLOCK(&updaters); 01163 01164 return cur ? 0 : -1; 01165 }
int ast_module_check | ( | const char * | name | ) |
Check if module with the name given is loaded.
name | Module name, like "chan_sip.so" |
1 | if true | |
0 | if false |
Definition at line 1122 of file loader.c.
References ast_strlen_zero(), and find_resource().
Referenced by ifmodule_read(), load_module(), manager_modulecheck(), and unload_module().
01123 { 01124 struct ast_module *cur; 01125 01126 if (ast_strlen_zero(name)) 01127 return 0; /* FALSE */ 01128 01129 cur = find_resource(name, 1); 01130 01131 return (cur != NULL); 01132 }
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.
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. |
A | possible completion of the partial match. | |
NULL | if no matches were found. |
Definition at line 547 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 handle_modlist(), handle_reload(), handle_unload(), and load_module().
00548 { 00549 struct ast_module *cur; 00550 int i, which=0, l = strlen(word); 00551 char *ret = NULL; 00552 00553 if (pos != rpos) 00554 return NULL; 00555 00556 AST_LIST_LOCK(&module_list); 00557 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00558 if (!strncasecmp(word, cur->resource, l) && 00559 (cur->info->reload || !needsreload) && 00560 ++which > state) { 00561 ret = ast_strdup(cur->resource); 00562 break; 00563 } 00564 } 00565 AST_LIST_UNLOCK(&module_list); 00566 00567 if (!ret) { 00568 for (i=0; !ret && reload_classes[i].name; i++) { 00569 if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) 00570 ret = ast_strdup(reload_classes[i].name); 00571 } 00572 } 00573 00574 return ret; 00575 }
struct ast_module* ast_module_ref | ( | struct ast_module * | mod | ) |
Definition at line 1167 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_iax2_new(), ast_timer_open(), dahdi_new(), fn_wrapper(), gtalk_new(), handle_cli_file_convert(), handle_orig(), mgcp_new(), moh_alloc(), moh_files_alloc(), newpvt(), oss_new(), phone_check_exception(), phone_new(), sip_new(), skinny_new(), and usbradio_new().
01168 { 01169 ast_atomic_fetchadd_int(&mod->usecount, +1); 01170 ast_update_use_count(); 01171 01172 return mod; 01173 }
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, resource_being_loaded, 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.
name | the name of the module to reload |
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 642 of file loader.c.
References ast_fully_booted, ast_lastreloadtime, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_trylock(), ast_mutex_unlock(), ast_tvnow(), ast_verb, ast_verbose, ast_module::declined, ast_module_info::description, ast_module_user::entry, ast_module::flags, ast_module::info, LOG_NOTICE, 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_reload(), manager_moduleload(), and monitor_sig_flags().
00643 { 00644 struct ast_module *cur; 00645 int res = 0; /* return value. 0 = not found, others, see below */ 00646 int i; 00647 00648 /* If we aren't fully booted, we just pretend we reloaded but we queue this 00649 up to run once we are booted up. */ 00650 if (!ast_fully_booted) { 00651 queue_reload_request(name); 00652 return 0; 00653 } 00654 00655 if (ast_mutex_trylock(&reloadlock)) { 00656 ast_verbose("The previous reload command didn't finish yet\n"); 00657 return -1; /* reload already in progress */ 00658 } 00659 ast_lastreloadtime = ast_tvnow(); 00660 00661 /* Call "predefined" reload here first */ 00662 for (i = 0; reload_classes[i].name; i++) { 00663 if (!name || !strcasecmp(name, reload_classes[i].name)) { 00664 reload_classes[i].reload_fn(); /* XXX should check error ? */ 00665 res = 2; /* found and reloaded */ 00666 } 00667 } 00668 00669 if (name && res) { 00670 ast_mutex_unlock(&reloadlock); 00671 return res; 00672 } 00673 00674 AST_LIST_LOCK(&module_list); 00675 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00676 const struct ast_module_info *info = cur->info; 00677 00678 if (name && resource_name_match(name, cur->resource)) 00679 continue; 00680 00681 if (!cur->flags.running || cur->flags.declined) { 00682 if (!name) 00683 continue; 00684 ast_log(LOG_NOTICE, "The module '%s' was not properly initialized. " 00685 "Before reloading the module, you must run \"module load %s\" " 00686 "and fix whatever is preventing the module from being initialized.\n", 00687 name, name); 00688 res = 2; /* Don't report that the module was not found */ 00689 break; 00690 } 00691 00692 if (!info->reload) { /* cannot be reloaded */ 00693 if (res < 1) /* store result if possible */ 00694 res = 1; /* 1 = no reload() method */ 00695 continue; 00696 } 00697 00698 res = 2; 00699 ast_verb(3, "Reloading module '%s' (%s)\n", cur->resource, info->description); 00700 info->reload(); 00701 } 00702 AST_LIST_UNLOCK(&module_list); 00703 00704 ast_mutex_unlock(&reloadlock); 00705 00706 return res; 00707 }
void ast_module_shutdown | ( | void | ) |
Run the unload() callback for all loaded modules.
This function should be called when Asterisk is shutting down gracefully.
If we go through the entire list without changing anything, ignore the usecounts and unload, then exit.
Definition at line 449 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_user::entry, free, ast_module::info, ast_module_info::unload, ast_module::usecount, and ast_module::users.
Referenced by quit_handler().
00450 { 00451 struct ast_module *mod; 00452 int somethingchanged = 1, final = 0; 00453 00454 AST_LIST_LOCK(&module_list); 00455 00456 /*!\note Some resources, like timers, are started up dynamically, and thus 00457 * may be still in use, even if all channels are dead. We must therefore 00458 * check the usecount before asking modules to unload. */ 00459 do { 00460 if (!somethingchanged) { 00461 /*!\note If we go through the entire list without changing 00462 * anything, ignore the usecounts and unload, then exit. */ 00463 final = 1; 00464 } 00465 00466 /* Reset flag before traversing the list */ 00467 somethingchanged = 0; 00468 00469 AST_LIST_TRAVERSE_SAFE_BEGIN(&module_list, mod, entry) { 00470 if (!final && mod->usecount) { 00471 continue; 00472 } 00473 AST_LIST_REMOVE_CURRENT(entry); 00474 if (mod->info->unload) { 00475 mod->info->unload(); 00476 } 00477 AST_LIST_HEAD_DESTROY(&mod->users); 00478 free(mod); 00479 somethingchanged = 1; 00480 } 00481 AST_LIST_TRAVERSE_SAFE_END; 00482 } while (somethingchanged && !final); 00483 00484 AST_LIST_UNLOCK(&module_list); 00485 }
void ast_module_unref | ( | struct ast_module * | mod | ) |
Definition at line 1175 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_smdi_interface_destroy(), ast_timer_close(), dahdi_destroy_channel_bynum(), dahdi_hangup(), destroy(), filestream_destructor(), gtalk_hangup(), handle_cli_file_convert(), handle_orig(), iax2_predestroy(), local_ast_moh_cleanup(), mgcp_hangup(), oh323_hangup(), oss_hangup(), phone_check_exception(), phone_hangup(), sip_hangup(), and usbradio_hangup().
01176 { 01177 ast_atomic_fetchadd_int(&mod->usecount, -1); 01178 ast_update_use_count(); 01179 }
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.
Definition at line 577 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().
00578 { 00579 struct reload_queue_item *item; 00580 00581 if (!ast_fully_booted) { 00582 return; 00583 } 00584 00585 AST_LIST_LOCK(&reload_queue); 00586 00587 if (do_full_reload) { 00588 do_full_reload = 0; 00589 AST_LIST_UNLOCK(&reload_queue); 00590 ast_log(LOG_NOTICE, "Executing deferred reload request.\n"); 00591 ast_module_reload(NULL); 00592 return; 00593 } 00594 00595 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00596 ast_log(LOG_NOTICE, "Executing deferred reload request for module '%s'.\n", item->module); 00597 ast_module_reload(item->module); 00598 ast_free(item); 00599 } 00600 00601 AST_LIST_UNLOCK(&reload_queue); 00602 }
int ast_unload_resource | ( | const char * | resource_name, | |
enum | ast_module_unload_mode | |||
) |
Unload a module.
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. |
0 | on success. | |
-1 | on error. |
Definition at line 487 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 exit_now(), handle_unload(), manager_moduleload(), reload(), and remove_module().
00488 { 00489 struct ast_module *mod; 00490 int res = -1; 00491 int error = 0; 00492 00493 AST_LIST_LOCK(&module_list); 00494 00495 if (!(mod = find_resource(resource_name, 0))) { 00496 AST_LIST_UNLOCK(&module_list); 00497 ast_log(LOG_WARNING, "Unload failed, '%s' could not be found\n", resource_name); 00498 return -1; 00499 } 00500 00501 if (!(mod->flags.running || mod->flags.declined)) 00502 error = 1; 00503 00504 if (!error && (mod->usecount > 0)) { 00505 if (force) 00506 ast_log(LOG_WARNING, "Warning: Forcing removal of module '%s' with use count %d\n", 00507 resource_name, mod->usecount); 00508 else { 00509 ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, 00510 mod->usecount); 00511 error = 1; 00512 } 00513 } 00514 00515 if (!error) { 00516 __ast_module_user_hangup_all(mod); 00517 res = mod->info->unload(); 00518 00519 if (res) { 00520 ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); 00521 if (force <= AST_FORCE_FIRM) 00522 error = 1; 00523 else 00524 ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); 00525 } 00526 } 00527 00528 if (!error) 00529 mod->flags.running = mod->flags.declined = 0; 00530 00531 AST_LIST_UNLOCK(&module_list); 00532 00533 if (!error && !mod->lib && mod->info && mod->info->restore_globals) 00534 mod->info->restore_globals(); 00535 00536 #ifdef LOADABLE_MODULES 00537 if (!error) 00538 unload_dynamic_module(mod); 00539 #endif 00540 00541 if (!error) 00542 ast_update_use_count(); 00543 00544 return res; 00545 }
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.
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. |
Definition at line 1101 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 handle_modlist(), and mod_update().
01103 { 01104 struct ast_module *cur; 01105 int unlock = -1; 01106 int total_mod_loaded = 0; 01107 01108 if (AST_LIST_TRYLOCK(&module_list)) 01109 unlock = 0; 01110 01111 AST_LIST_TRAVERSE(&module_list, cur, entry) { 01112 total_mod_loaded += modentry(cur->resource, cur->info->description, cur->usecount, like); 01113 } 01114 01115 if (unlock) 01116 AST_LIST_UNLOCK(&module_list); 01117 01118 return total_mod_loaded; 01119 }
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.
Definition at line 1089 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(), exit_now(), handle_request_do(), load_module(), oh323_request(), sip_request_call(), start_resource(), and unistim_new().
01090 { 01091 /* Notify any module monitors that the use count for a 01092 resource has changed */ 01093 struct loadupdate *m; 01094 01095 AST_LIST_LOCK(&updaters); 01096 AST_LIST_TRAVERSE(&updaters, m, entry) 01097 m->updater(); 01098 AST_LIST_UNLOCK(&updaters); 01099 }
static struct ast_module* find_resource | ( | const char * | resource, | |
int | do_lock | |||
) | [static] |
Definition at line 325 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(), and load_resource().
00326 { 00327 struct ast_module *cur; 00328 00329 if (do_lock) 00330 AST_LIST_LOCK(&module_list); 00331 00332 AST_LIST_TRAVERSE(&module_list, cur, entry) { 00333 if (!resource_name_match(resource, cur->resource)) 00334 break; 00335 } 00336 00337 if (do_lock) 00338 AST_LIST_UNLOCK(&module_list); 00339 00340 return cur; 00341 }
static unsigned int inspect_module | ( | const struct ast_module * | mod | ) | [static] |
Definition at line 709 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().
00710 { 00711 if (!mod->info->description) { 00712 ast_log(LOG_WARNING, "Module '%s' does not provide a description.\n", mod->resource); 00713 return 1; 00714 } 00715 00716 if (!mod->info->key) { 00717 ast_log(LOG_WARNING, "Module '%s' does not provide a license key.\n", mod->resource); 00718 return 1; 00719 } 00720 00721 if (verify_key((unsigned char *) mod->info->key)) { 00722 ast_log(LOG_WARNING, "Module '%s' did not provide a valid license key.\n", mod->resource); 00723 return 1; 00724 } 00725 00726 if (!ast_strlen_zero(mod->info->buildopt_sum) && 00727 strcmp(buildopt_sum, mod->info->buildopt_sum)) { 00728 ast_log(LOG_WARNING, "Module '%s' was not compiled with the same compile-time options as this version of Asterisk.\n", mod->resource); 00729 ast_log(LOG_WARNING, "Module '%s' will not be initialized as it may cause instability.\n", mod->resource); 00730 return 1; 00731 } 00732 00733 return 0; 00734 }
static int key_matches | ( | const unsigned char * | key1, | |
const unsigned char * | key2 | |||
) | [static] |
Definition at line 278 of file loader.c.
Referenced by verify_key().
00279 { 00280 int x; 00281 00282 for (x = 0; x < 16; x++) { 00283 if (key1[x] != key2[x]) 00284 return 0; 00285 } 00286 00287 return 1; 00288 }
static struct ast_module* load_dynamic_module | ( | const char * | resource_in, | |
unsigned int | global_symbols_only | |||
) | [static] |
Definition at line 356 of file loader.c.
References ast_calloc, ast_config_AST_MODULE_DIR, ast_free, AST_LIST_LAST, ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, ast_test_flag, ast_module::info, ast_module::lib, LOG_WARNING, ast_module::resource, resource_being_loaded, RTLD_LOCAL, and RTLD_NOW.
Referenced by load_resource().
00357 { 00358 char fn[PATH_MAX] = ""; 00359 void *lib = NULL; 00360 struct ast_module *mod; 00361 unsigned int wants_global; 00362 int space; /* room needed for the descriptor */ 00363 int missing_so = 0; 00364 00365 space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1; 00366 if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) { 00367 missing_so = 1; 00368 space += 3; /* room for the extra ".so" */ 00369 } 00370 00371 snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : ""); 00372 00373 /* make a first load of the module in 'quiet' mode... don't try to resolve 00374 any symbols, and don't export any symbols. this will allow us to peek into 00375 the module's info block (if available) to see what flags it has set */ 00376 00377 resource_being_loaded = ast_calloc(1, space); 00378 if (!resource_being_loaded) 00379 return NULL; 00380 strcpy(resource_being_loaded->resource, resource_in); 00381 if (missing_so) 00382 strcat(resource_being_loaded->resource, ".so"); 00383 00384 /* libopenh323 is buggy and segfaults on dlclose() when opened with 00385 * RTLD_LAZY. Workaround this until it gets fixed */ 00386 if (!strcasecmp(resource_being_loaded->resource, "chan_h323.so") || 00387 !strcasecmp(resource_being_loaded->resource, "chan_oh323.so")) 00388 lib = dlopen(fn, RTLD_NOW | RTLD_LOCAL); 00389 00390 if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_LOCAL))) { 00391 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00392 ast_free(resource_being_loaded); 00393 return NULL; 00394 } 00395 00396 /* the dlopen() succeeded, let's find out if the module 00397 registered itself */ 00398 /* note that this will only work properly as long as 00399 ast_module_register() (which is called by the module's 00400 constructor) places the new module at the tail of the 00401 module_list 00402 */ 00403 if (resource_being_loaded != (mod = AST_LIST_LAST(&module_list))) { 00404 ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in); 00405 /* no, it did not, so close it and return */ 00406 while (!dlclose(lib)); 00407 /* note that the module's destructor will call ast_module_unregister(), 00408 which will free the structure we allocated in resource_being_loaded */ 00409 return NULL; 00410 } 00411 00412 wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS); 00413 00414 /* if we are being asked only to load modules that provide global symbols, 00415 and this one does not, then close it and return */ 00416 if (global_symbols_only && !wants_global) { 00417 while (!dlclose(lib)); 00418 return NULL; 00419 } 00420 00421 while (!dlclose(lib)); 00422 resource_being_loaded = NULL; 00423 00424 /* start the load process again */ 00425 resource_being_loaded = ast_calloc(1, space); 00426 if (!resource_being_loaded) 00427 return NULL; 00428 strcpy(resource_being_loaded->resource, resource_in); 00429 if (missing_so) 00430 strcat(resource_being_loaded->resource, ".so"); 00431 00432 if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) { 00433 ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror()); 00434 ast_free(resource_being_loaded); 00435 return NULL; 00436 } 00437 00438 /* since the module was successfully opened, and it registered itself 00439 the previous time we did that, we're going to assume it worked this 00440 time too :) */ 00441 00442 AST_LIST_LAST(&module_list)->lib = lib; 00443 resource_being_loaded = NULL; 00444 00445 return AST_LIST_LAST(&module_list); 00446 }
int load_modules | ( | unsigned | int | ) |
Provided by loader.c
Definition at line 946 of file loader.c.
References add_to_load_order(), ast_config_load2(), AST_LIST_HEAD_INIT_NOLOCK, AST_LIST_LOCK, ast_log(), AST_MODULE_CONFIG, ast_variable_browse(), ast_verb, config_flags, dir, embedding, LOG_WARNING, ast_variable::name, ast_variable::next, and ast_variable::value.
Referenced by main().
00947 { 00948 struct ast_config *cfg; 00949 struct ast_module *mod; 00950 struct load_order_entry *order; 00951 struct ast_variable *v; 00952 unsigned int load_count; 00953 struct load_order load_order; 00954 int res = 0; 00955 struct ast_flags config_flags = { 0 }; 00956 int modulecount = 0; 00957 00958 #ifdef LOADABLE_MODULES 00959 struct dirent *dirent; 00960 DIR *dir; 00961 #endif 00962 00963 /* all embedded modules have registered themselves by now */ 00964 embedding = 0; 00965 00966 ast_verb(1, "Asterisk Dynamic Loader Starting:\n"); 00967 00968 AST_LIST_HEAD_INIT_NOLOCK(&load_order); 00969 00970 AST_LIST_LOCK(&module_list); 00971 00972 if (embedded_module_list.first) { 00973 module_list.first = embedded_module_list.first; 00974 module_list.last = embedded_module_list.last; 00975 embedded_module_list.first = NULL; 00976 } 00977 00978 if (!(cfg = ast_config_load2(AST_MODULE_CONFIG, "" /* core, can't reload */, config_flags))) { 00979 ast_log(LOG_WARNING, "No '%s' found, no modules will be loaded.\n", AST_MODULE_CONFIG); 00980 goto done; 00981 } 00982 00983 /* first, find all the modules we have been explicitly requested to load */ 00984 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 00985 if (!strcasecmp(v->name, preload_only ? "preload" : "load")) { 00986 add_to_load_order(v->value, &load_order); 00987 } 00988 } 00989 00990 /* check if 'autoload' is on */ 00991 if (!preload_only && ast_true(ast_variable_retrieve(cfg, "modules", "autoload"))) { 00992 /* if so, first add all the embedded modules that are not already running to the load order */ 00993 AST_LIST_TRAVERSE(&module_list, mod, entry) { 00994 /* if it's not embedded, skip it */ 00995 if (mod->lib) 00996 continue; 00997 00998 if (mod->flags.running) 00999 continue; 01000 01001 order = add_to_load_order(mod->resource, &load_order); 01002 } 01003 01004 #ifdef LOADABLE_MODULES 01005 /* if we are allowed to load dynamic modules, scan the directory for 01006 for all available modules and add them as well */ 01007 if ((dir = opendir(ast_config_AST_MODULE_DIR))) { 01008 while ((dirent = readdir(dir))) { 01009 int ld = strlen(dirent->d_name); 01010 01011 /* Must end in .so to load it. */ 01012 01013 if (ld < 4) 01014 continue; 01015 01016 if (strcasecmp(dirent->d_name + ld - 3, ".so")) 01017 continue; 01018 01019 /* if there is already a module by this name in the module_list, 01020 skip this file */ 01021 if (find_resource(dirent->d_name, 0)) 01022 continue; 01023 01024 add_to_load_order(dirent->d_name, &load_order); 01025 } 01026 01027 closedir(dir); 01028 } else { 01029 if (!ast_opt_quiet) 01030 ast_log(LOG_WARNING, "Unable to open modules directory '%s'.\n", 01031 ast_config_AST_MODULE_DIR); 01032 } 01033 #endif 01034 } 01035 01036 /* now scan the config for any modules we are prohibited from loading and 01037 remove them from the load order */ 01038 for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) { 01039 if (strcasecmp(v->name, "noload")) 01040 continue; 01041 01042 AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { 01043 if (!resource_name_match(order->resource, v->value)) { 01044 AST_LIST_REMOVE_CURRENT(entry); 01045 ast_free(order->resource); 01046 ast_free(order); 01047 } 01048 } 01049 AST_LIST_TRAVERSE_SAFE_END; 01050 } 01051 01052 /* we are done with the config now, all the information we need is in the 01053 load_order list */ 01054 ast_config_destroy(cfg); 01055 01056 load_count = 0; 01057 AST_LIST_TRAVERSE(&load_order, order, entry) 01058 load_count++; 01059 01060 if (load_count) 01061 ast_log(LOG_NOTICE, "%d modules will be loaded.\n", load_count); 01062 01063 /* first, load only modules that provide global symbols */ 01064 if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) { 01065 goto done; 01066 } 01067 01068 /* now load everything else */ 01069 if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) { 01070 goto done; 01071 } 01072 01073 done: 01074 while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) { 01075 ast_free(order->resource); 01076 ast_free(order); 01077 } 01078 01079 AST_LIST_UNLOCK(&module_list); 01080 01081 /* Tell manager clients that are aggressive at logging in that we're done 01082 loading modules. If there's a DNS problem in chan_sip, we might not 01083 even reach this */ 01084 manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount); 01085 01086 return res; 01087 }
static enum ast_module_load_result load_resource | ( | const char * | resource_name, | |
unsigned int | global_symbols_only, | |||
struct ast_heap * | resource_heap | |||
) | [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 782 of file loader.c.
References ast_heap_push(), ast_log(), AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODULE_LOAD_DECLINE, 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().
00783 { 00784 struct ast_module *mod; 00785 enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS; 00786 00787 if ((mod = find_resource(resource_name, 0))) { 00788 if (mod->flags.running) { 00789 ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name); 00790 return AST_MODULE_LOAD_DECLINE; 00791 } 00792 if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) 00793 return AST_MODULE_LOAD_SKIP; 00794 } else { 00795 #ifdef LOADABLE_MODULES 00796 if (!(mod = load_dynamic_module(resource_name, global_symbols_only))) { 00797 /* don't generate a warning message during load_modules() */ 00798 if (!global_symbols_only) { 00799 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00800 return AST_MODULE_LOAD_DECLINE; 00801 } else { 00802 return AST_MODULE_LOAD_SKIP; 00803 } 00804 } 00805 #else 00806 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00807 return AST_MODULE_LOAD_DECLINE; 00808 #endif 00809 } 00810 00811 if (inspect_module(mod)) { 00812 ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name); 00813 #ifdef LOADABLE_MODULES 00814 unload_dynamic_module(mod); 00815 #endif 00816 return AST_MODULE_LOAD_DECLINE; 00817 } 00818 00819 if (!mod->lib && mod->info->backup_globals()) { 00820 ast_log(LOG_WARNING, "Module '%s' was unable to backup its global data.\n", resource_name); 00821 return AST_MODULE_LOAD_DECLINE; 00822 } 00823 00824 mod->flags.declined = 0; 00825 00826 if (resource_heap) { 00827 ast_heap_push(resource_heap, mod); 00828 res = AST_MODULE_LOAD_PRIORITY; 00829 } else { 00830 res = start_resource(mod); 00831 } 00832 00833 return res; 00834 }
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
Definition at line 888 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_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(), mod_load_cmp(), load_order_entry::resource, and start_resource().
00889 { 00890 struct ast_heap *resource_heap; 00891 struct load_order_entry *order; 00892 struct ast_module *mod; 00893 int count = 0; 00894 int res = 0; 00895 00896 if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) { 00897 return -1; 00898 } 00899 00900 /* first, add find and add modules to heap */ 00901 AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) { 00902 switch (load_resource(order->resource, global_symbols, resource_heap)) { 00903 case AST_MODULE_LOAD_SUCCESS: 00904 case AST_MODULE_LOAD_DECLINE: 00905 AST_LIST_REMOVE_CURRENT(entry); 00906 ast_free(order->resource); 00907 ast_free(order); 00908 break; 00909 case AST_MODULE_LOAD_FAILURE: 00910 res = -1; 00911 goto done; 00912 case AST_MODULE_LOAD_SKIP: 00913 break; 00914 case AST_MODULE_LOAD_PRIORITY: 00915 AST_LIST_REMOVE_CURRENT(entry); 00916 break; 00917 } 00918 } 00919 AST_LIST_TRAVERSE_SAFE_END; 00920 00921 /* second remove modules from heap sorted by priority */ 00922 while ((mod = ast_heap_pop(resource_heap))) { 00923 switch (start_resource(mod)) { 00924 case AST_MODULE_LOAD_SUCCESS: 00925 count++; 00926 case AST_MODULE_LOAD_DECLINE: 00927 break; 00928 case AST_MODULE_LOAD_FAILURE: 00929 res = -1; 00930 goto done; 00931 case AST_MODULE_LOAD_SKIP: 00932 case AST_MODULE_LOAD_PRIORITY: 00933 break; 00934 } 00935 } 00936 00937 done: 00938 if (mod_count) { 00939 *mod_count += count; 00940 } 00941 ast_heap_destroy(resource_heap); 00942 00943 return res; 00944 }
static int mod_load_cmp | ( | void * | a, | |
void * | b | |||
) | [static] |
Definition at line 871 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().
00872 { 00873 struct ast_module *a_mod = (struct ast_module *) a; 00874 struct ast_module *b_mod = (struct ast_module *) b; 00875 int res = -1; 00876 /* if load_pri is not set, default is 255. Lower is better*/ 00877 unsigned char a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 255; 00878 unsigned char b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 255; 00879 if (a_pri == b_pri) { 00880 res = 0; 00881 } else if (a_pri < b_pri) { 00882 res = 1; 00883 } 00884 return res; 00885 }
static int printdigest | ( | const unsigned char * | d | ) | [static] |
Definition at line 265 of file loader.c.
References ast_debug, and buf.
Referenced by verify_key().
00266 { 00267 int x, pos; 00268 char buf[256]; /* large enough so we don't have to worry */ 00269 00270 for (pos = 0, x = 0; x < 16; x++) 00271 pos += sprintf(buf + pos, " %02x", *d++); 00272 00273 ast_debug(1, "Unexpected signature:%s\n", buf); 00274 00275 return 0; 00276 }
static void queue_reload_request | ( | const char * | module | ) | [static] |
Definition at line 604 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().
00605 { 00606 struct reload_queue_item *item; 00607 00608 AST_LIST_LOCK(&reload_queue); 00609 00610 if (do_full_reload) { 00611 AST_LIST_UNLOCK(&reload_queue); 00612 return; 00613 } 00614 00615 if (ast_strlen_zero(module)) { 00616 /* A full reload request (when module is NULL) wipes out any previous 00617 reload requests and causes the queue to ignore future ones */ 00618 while ((item = AST_LIST_REMOVE_HEAD(&reload_queue, entry))) { 00619 ast_free(item); 00620 } 00621 do_full_reload = 1; 00622 } else { 00623 /* No reason to add the same module twice */ 00624 AST_LIST_TRAVERSE(&reload_queue, item, entry) { 00625 if (!strcasecmp(item->module, module)) { 00626 AST_LIST_UNLOCK(&reload_queue); 00627 return; 00628 } 00629 } 00630 item = ast_calloc(1, sizeof(*item) + strlen(module) + 1); 00631 if (!item) { 00632 ast_log(LOG_ERROR, "Failed to allocate reload queue item.\n"); 00633 AST_LIST_UNLOCK(&reload_queue); 00634 return; 00635 } 00636 strcpy(item->module, module); 00637 AST_LIST_INSERT_TAIL(&reload_queue, item, entry); 00638 } 00639 AST_LIST_UNLOCK(&reload_queue); 00640 }
static int resource_name_match | ( | const char * | name1_in, | |
const char * | name2_in | |||
) | [static] |
Definition at line 307 of file loader.c.
References ast_strdupa.
Referenced by add_to_load_order(), ast_module_reload(), and find_resource().
00308 { 00309 char *name1 = (char *) name1_in; 00310 char *name2 = (char *) name2_in; 00311 00312 /* trim off any .so extensions */ 00313 if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) { 00314 name1 = ast_strdupa(name1); 00315 name1[strlen(name1) - 3] = '\0'; 00316 } 00317 if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) { 00318 name2 = ast_strdupa(name2); 00319 name2[strlen(name2) - 3] = '\0'; 00320 } 00321 00322 return strcasecmp(name1, name2); 00323 }
static enum ast_module_load_result start_resource | ( | struct ast_module * | mod | ) | [static] |
Definition at line 736 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().
00737 { 00738 char tmp[256]; 00739 enum ast_module_load_result res; 00740 00741 if (!mod->info->load) { 00742 return AST_MODULE_LOAD_FAILURE; 00743 } 00744 00745 res = mod->info->load(); 00746 00747 switch (res) { 00748 case AST_MODULE_LOAD_SUCCESS: 00749 if (!ast_fully_booted) { 00750 ast_verb(1, "%s => (%s)\n", mod->resource, term_color(tmp, mod->info->description, COLOR_BROWN, COLOR_BLACK, sizeof(tmp))); 00751 if (ast_opt_console && !option_verbose) 00752 ast_verbose( "."); 00753 } else { 00754 ast_verb(1, "Loaded %s => (%s)\n", mod->resource, mod->info->description); 00755 } 00756 00757 mod->flags.running = 1; 00758 00759 ast_update_use_count(); 00760 break; 00761 case AST_MODULE_LOAD_DECLINE: 00762 mod->flags.declined = 1; 00763 break; 00764 case AST_MODULE_LOAD_FAILURE: 00765 case AST_MODULE_LOAD_SKIP: /* modules should never return this value */ 00766 case AST_MODULE_LOAD_PRIORITY: 00767 break; 00768 } 00769 00770 return res; 00771 }
static void unload_dynamic_module | ( | struct ast_module * | mod | ) | [static] |
Definition at line 344 of file loader.c.
References ast_module::lib.
Referenced by ast_unload_resource(), and load_resource().
00345 { 00346 void *lib = mod->lib; 00347 00348 /* WARNING: the structure pointed to by mod is going to 00349 disappear when this operation succeeds, so we can't 00350 dereference it */ 00351 00352 if (lib) 00353 while (!dlclose(lib)); 00354 }
static int verify_key | ( | const unsigned char * | key | ) | [static] |
Definition at line 290 of file loader.c.
References expected_key, key_matches(), MD5Final(), MD5Init(), MD5Update(), and printdigest().
Referenced by inspect_module().
00291 { 00292 struct MD5Context c; 00293 unsigned char digest[16]; 00294 00295 MD5Init(&c); 00296 MD5Update(&c, key, strlen((char *)key)); 00297 MD5Final(digest, &c); 00298 00299 if (key_matches(expected_key, digest)) 00300 return 0; 00301 00302 printdigest(digest); 00303 00304 return -1; 00305 }
char buildopt_sum[33] = AST_BUILDOPT_SUM [static] |
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] |
unsigned int embedding = 1 [static] |
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 = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP ) [static] |
struct ast_module* resource_being_loaded |
Definition at line 129 of file loader.c.
Referenced by ast_module_register(), and load_dynamic_module().