diff --git a/main/loader.c b/main/loader.c index 033693e8b0..f06016c9fa 100644 --- a/main/loader.c +++ b/main/loader.c @@ -153,37 +153,7 @@ static unsigned int loader_ready; static struct ast_vector_string startup_errors; static struct ast_str *startup_error_builder; -#if defined(HAVE_PERMANENT_DLOPEN) -#define FIRST_DLOPEN 999 - -struct ao2_container *info_list = NULL; - -struct info_list_obj { - const struct ast_module_info *info; - int dlopened; - char name[0]; -}; - -static struct info_list_obj *info_list_obj_alloc(const char *name, - const struct ast_module_info *info) -{ - struct info_list_obj *new_entry; - - new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL); - - if (!new_entry) { - return NULL; - } - - strcpy(new_entry->name, name); /* SAFE */ - new_entry->info = info; - new_entry->dlopened = FIRST_DLOPEN; - - return new_entry; -} - -AO2_STRING_FIELD_CMP_FN(info_list_obj, name) - +#if defined(HAVE_PERMANENT_DLOPEN) || defined(AST_XML_DOCS) static char *get_name_from_resource(const char *resource) { int len; @@ -219,6 +189,38 @@ static char *get_name_from_resource(const char *resource) /* Unable to allocate memory. */ return NULL; } +#endif + +#if defined(HAVE_PERMANENT_DLOPEN) +#define FIRST_DLOPEN 999 + +struct ao2_container *info_list = NULL; + +struct info_list_obj { + const struct ast_module_info *info; + int dlopened; + char name[0]; +}; + +static struct info_list_obj *info_list_obj_alloc(const char *name, + const struct ast_module_info *info) +{ + struct info_list_obj *new_entry; + + new_entry = ao2_alloc(sizeof(*new_entry) + strlen(name) + 1, NULL); + + if (!new_entry) { + return NULL; + } + + strcpy(new_entry->name, name); /* SAFE */ + new_entry->info = info; + new_entry->dlopened = FIRST_DLOPEN; + + return new_entry; +} + +AO2_STRING_FIELD_CMP_FN(info_list_obj, name) static void manual_mod_reg(const void *lib, const char *resource) { @@ -2341,6 +2343,16 @@ int load_modules(void) int res = 0; int modulecount = 0; int i; + struct ast_module *cur; +#ifdef AST_XML_DOCS + struct ast_str *warning_msg; + char deprecated_in[33]; + char removed_in[33]; + char replacement[129]; +#endif + struct timeval start_time = ast_tvnow(); + struct timeval end_time; + int64_t usElapsed; ast_verb(1, "Asterisk Dynamic Loader Starting:\n"); @@ -2388,8 +2400,103 @@ done: ast_free(order); } +#ifdef AST_XML_DOCS + warning_msg = ast_str_create(512); +#endif + + AST_DLLIST_TRAVERSE(&module_list, cur, entry) { +#ifdef AST_XML_DOCS + char *mod_name = NULL; + struct ast_xml_xpath_results *results; +#endif + + if (!cur->flags.running || cur->flags.declined) { + continue; + } + +#ifdef AST_XML_DOCS + mod_name = get_name_from_resource(cur->resource); + if (!warning_msg || !mod_name) { + /* If we can't allocate memory, we have bigger issues */ + ast_free(mod_name); + continue; + } + + results = ast_xmldoc_query("/docs/module[@name='%s']/deprecated_in", mod_name); + deprecated_in[0] = '\0'; + if (results) { + const char *result_tmp = ast_xml_get_text(ast_xml_xpath_get_first_result(results)); + if (!ast_strlen_zero(result_tmp)) { + ast_copy_string(deprecated_in, result_tmp, sizeof(deprecated_in)); + } + ast_xml_xpath_results_free(results); + } + + results = ast_xmldoc_query("/docs/module[@name='%s']/removed_in", mod_name); + removed_in[0] = '\0'; + if (results) { + const char *result_tmp = ast_xml_get_text(ast_xml_xpath_get_first_result(results)); + if (!ast_strlen_zero(result_tmp)) { + ast_copy_string(removed_in, result_tmp, sizeof(removed_in)); + } + ast_xml_xpath_results_free(results); + } + + results = ast_xmldoc_query("/docs/module[@name='%s']/replacement", mod_name); + replacement[0] = '\0'; + if (results) { + const char *result_tmp = ast_xml_get_text(ast_xml_xpath_get_first_result(results)); + if (!ast_strlen_zero(result_tmp)) { + ast_copy_string(replacement, result_tmp, sizeof(replacement)); + } + ast_xml_xpath_results_free(results); + } + + ast_str_reset(warning_msg); + + if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED || !ast_strlen_zero(deprecated_in) + || !ast_strlen_zero(removed_in) || !ast_strlen_zero(replacement)) { + int already_butted = 0; + + ast_str_append(&warning_msg, -1, "Module '%s' has been loaded", mod_name); + if (!ast_strlen_zero(deprecated_in)) { + ast_str_append(&warning_msg, -1, " but %s deprecated in Asterisk version %s", + cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED ? "was" : "will be", deprecated_in); + already_butted = 1; + } + + if (!ast_strlen_zero(removed_in)) { + ast_str_append(&warning_msg, -1, " %s will be removed in Asterisk version %s", already_butted ? "and" : "but", removed_in); + } else { + ast_str_append(&warning_msg, -1, " %s may be removed in a future release", already_butted ? "and" : "but"); + } + + ast_str_append(&warning_msg, -1, "."); + + if (!ast_strlen_zero(replacement)) { + ast_str_append(&warning_msg, -1, " Its replacement is '%s'.", replacement); + } + } + + if (ast_str_strlen(warning_msg)) { + ast_log(LOG_WARNING, "%s\n", ast_str_buffer(warning_msg)); + } + + ast_free(mod_name); +#else + if (cur->info->support_level == AST_MODULE_SUPPORT_DEPRECATED) { + ast_log(LOG_WARNING, "The deprecated module '%s' has been loaded and is running, it may be removed in a future version\n", cur->resource); + } +#endif + } + +#ifdef AST_XML_DOCS + ast_free(warning_msg); +#endif + AST_DLLIST_UNLOCK(&module_list); + for (i = 0; i < AST_VECTOR_SIZE(&startup_errors); i++) { char *str = AST_VECTOR_GET(&startup_errors, i); @@ -2401,6 +2508,15 @@ done: ast_free(startup_error_builder); startup_error_builder = NULL; + end_time = ast_tvnow(); + usElapsed = ast_tvdiff_us(end_time, start_time); + +#ifdef AST_XML_DOCS + ast_debug(1, "Loader time with AST_XML_DOCS: %ld.%06ld\n", usElapsed / 1000000, usElapsed % 1000000); +#else + ast_debug(1, "Loader time without AST_XML_DOCS: %ld.%06ld\n", usElapsed / 1000000, usElapsed % 1000000); +#endif + return res; }