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