diff options
-rw-r--r-- | include/asterisk.h | 7 | ||||
-rw-r--r-- | main/asterisk.c | 19 | ||||
-rw-r--r-- | main/loader.c | 112 |
3 files changed, 138 insertions, 0 deletions
diff --git a/include/asterisk.h b/include/asterisk.h index 71cb4d454..9d5c1ae8a 100644 --- a/include/asterisk.h +++ b/include/asterisk.h @@ -88,6 +88,13 @@ void ast_register_file_version(const char *file, const char *version); */ void ast_unregister_file_version(const char *file); +/*! \brief Find version for given module name + * \param file Module name (i.e. chan_sip.so) + * \return version string or NULL if the module is not found + */ +const char *ast_file_version_find(const char *file); + + /*! * \brief Register/unregister a source code file with the core. * \param file the source file name diff --git a/main/asterisk.c b/main/asterisk.c index 1a9e366a7..e2ac68328 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -288,6 +288,25 @@ void ast_unregister_file_version(const char *file) ast_free(find); } +/*! \brief Find version for given module name */ +const char *ast_file_version_find(const char *file) +{ + struct file_version *iterator; + + AST_RWLIST_WRLOCK(&file_versions); + AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, iterator, list) { + if (!strcasecmp(iterator->file, file)) + break; + } + AST_RWLIST_TRAVERSE_SAFE_END; + AST_RWLIST_UNLOCK(&file_versions); + if (iterator) + return iterator->version; + return NULL; +} + + + struct thread_list_t { AST_RWLIST_ENTRY(thread_list_t) list; char *name; diff --git a/main/loader.c b/main/loader.c index 0d042675a..02fb8a905 100644 --- a/main/loader.c +++ b/main/loader.c @@ -80,6 +80,11 @@ static char buildopt_sum[33] = AST_BUILDOPT_SUM; static unsigned int embedding = 1; /* we always start out by registering embedded modules, since they are here before we dlopen() any */ +/* Forward declaration */ +static int manager_moduleload(struct mansession *s, const struct message *m); +static char mandescr_moduleload[]; +static int manager_modulecheck(struct mansession *s, const struct message *m); +static char mandescr_modulecheck[]; struct ast_module { const struct ast_module_info *info; @@ -748,6 +753,7 @@ int load_modules(unsigned int preload_only) struct load_order load_order; int res = 0; struct ast_flags config_flags = { 0 }; + int modulecount = 0; #ifdef LOADABLE_MODULES struct dirent *dirent; DIR *dir; @@ -856,6 +862,7 @@ int load_modules(unsigned int preload_only) AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { switch (load_resource(order->resource, 1)) { case AST_MODULE_LOAD_SUCCESS: + modulecount++; case AST_MODULE_LOAD_DECLINE: AST_LIST_REMOVE_CURRENT(entry); ast_free(order->resource); @@ -875,6 +882,7 @@ int load_modules(unsigned int preload_only) AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) { switch (load_resource(order->resource, 0)) { case AST_MODULE_LOAD_SUCCESS: + modulecount++; case AST_MODULE_LOAD_DECLINE: AST_LIST_REMOVE_CURRENT(entry); ast_free(order->resource); @@ -898,6 +906,13 @@ done: AST_LIST_UNLOCK(&module_list); + ast_manager_register2("ModuleLoad", EVENT_FLAG_SYSTEM, manager_moduleload, "Module management", mandescr_moduleload); + ast_manager_register2("ModuleCheck", EVENT_FLAG_SYSTEM, manager_modulecheck, "Check if module is loaded", mandescr_modulecheck); + + /* Tell manager clients that are aggressive at logging in that we're done + loading modules. If there's a DNS problem in chan_sip, we might not + even reach this */ + manager_event(EVENT_FLAG_SYSTEM, "ModuleLoadReport", "ModuleLoadStatus: Done\r\nModuleSelection: %s\r\nModuleCount: %d\r\n", preload_only ? "Preload" : "All", modulecount); return res; } @@ -992,3 +1007,100 @@ void ast_module_unref(struct ast_module *mod) ast_atomic_fetchadd_int(&mod->usecount, -1); ast_update_use_count(); } + +static char mandescr_modulecheck[] = +"Description: Checks if Asterisk module is loaded\n" +"Variables: \n" +" ActionID: <id> Action ID for this transaction. Will be returned.\n" +" Module: <name> Asterisk module name (not including extension)\n" +"\n" +"Will return Success/Failure\n" +"For success returns, the module revision number is included.\n"; + +/* Manager function to check if module is loaded */ +static int manager_modulecheck(struct mansession *s, const struct message *m) +{ + int res; + const char *module = astman_get_header(m, "Module"); + const char *id = astman_get_header(m,"ActionID"); + char idText[BUFSIZ]; + const char *version; + char filename[BUFSIZ/2]; + char *cut; + + snprintf(filename, sizeof(filename), module); + if ((cut = strchr(filename, '.'))) { + *cut = '\0'; + } else { + cut = filename + strlen(filename); + } + sprintf(cut, ".so"); + ast_log(LOG_DEBUG, "**** ModuleCheck .so file %s\n", filename); + res = ast_module_check(filename); + if (!res) { + astman_send_error(s, m, "Module not loaded"); + return 0; + } + sprintf(cut, ".c"); + ast_log(LOG_DEBUG, "**** ModuleCheck .c file %s\n", filename); + version = ast_file_version_find(filename); + + if (!ast_strlen_zero(id)) + snprintf(idText, sizeof(idText), "ActionID: %s\r\n", id); + astman_append(s, "Response: Success\r\n%s", idText); + astman_append(s, "Version: %s\r\n\r\n", version ? version : ""); + return 0; +} + + +static char mandescr_moduleload[] = +"Description: Loads, unloads or reloads an Asterisk module in a running system.\n" +"Variables: \n" +" ActionID: <id> Action ID for this transaction. Will be returned.\n" +" Module: <name> Asterisk module name (including .so extension)\n" +" or subsystem identifier:\n" +" cdr, enum, dnsmgr, extconfig, manager, rtp, http\n" +" LoadType: load | unload | reload\n" +" The operation to be done on module\n" +" If no module is specified for a reload loadtype, all modules are reloaded"; + +static int manager_moduleload(struct mansession *s, const struct message *m) +{ + int res; + const char *module = astman_get_header(m, "Module"); + const char *loadtype = astman_get_header(m, "LoadType"); + + if (!loadtype || strlen(loadtype) == 0) + astman_send_error(s, m, "Incomplete ModuleLoad action."); + if ((!module || strlen(module) == 0) && strcasecmp(loadtype, "reload") != 0) + astman_send_error(s, m, "Need module name"); + + if (!strcasecmp(loadtype, "load")) { + res = ast_load_resource(module); + if (res) + astman_send_error(s, m, "Could not load module."); + else + astman_send_ack(s, m, "Module loaded."); + } else if (!strcasecmp(loadtype, "unload")) { + res = ast_unload_resource(module, AST_FORCE_SOFT); + if (res) + astman_send_error(s, m, "Could not unload module."); + else + astman_send_ack(s, m, "Module unloaded."); + } else if (!strcasecmp(loadtype, "reload")) { + if (module != NULL) { + res = ast_module_reload(module); + if (res == 0) + astman_send_error(s, m, "No such module."); + else if (res == 1) + astman_send_error(s, m, "Module does not support reload action."); + else + astman_send_ack(s, m, "Module reloaded."); + } else { + ast_module_reload(NULL); /* Reload all modules */ + astman_send_ack(s, m, "All modules reloaded"); + } + } else + astman_send_error(s, m, "Incomplete ModuleLoad action."); + return 0; +} |