<p>Corey Farrell has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/6987">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">RFC: Rewrite module loader ordering.<br><br>* Add "requires" field to module info.<br>* Reimplement load_dynamic_module to reduce the number of times we run<br> dlopen.<br>* Remove global symbols only startup stage.<br>* Implement automatic references for dependent modules.<br><br>New startup order:<br>On startup we read modules.conf, build a list of module names we will<br>load. We then iterate the list attempting to dlopen all modules. We<br>repeat this process suppressing all errors until we cannot dlopen any<br>further modules. If we were unable to dlopen anything modules.conf<br>declared as required we abort. All modules that were successfully<br>opened are added to a vector ordered by load priority. We start modules<br>in priority order except when we find an unmet dependency. This forces<br>the unmet dependency to start earlier. Unloading modules is restricted<br>by dependencies references.<br><br>TODO:<br>* The dependency checking is currently unforgiving and does a poor job<br> logging the reason.<br>* Telling modules.conf to require a module is only half effective. It<br> only enforces that the module successfully load, but by the time we<br> start the module our knowledge of the require directive is lost. This<br> is an existing bug found while working on this.<br>* Perform all startup dlopen's during preload so preload vs regular will<br> only change when the modules are started. This way when a module is<br> set to preload but depends on a module that is only set to regular<br> load, we will be able to load the other module early. Currently the<br> preload phase would fail to find the non-preload file as it wouldn't<br> be registered yet.<br>* Testing: so far this has only passed the smoke test - it starts and<br> stops without error when autoload is enabled.<br>* Investigate better ways to set the "requires" field. Can it be<br> generated from MODULEINFO or can the build process which extracts<br> MODULEINFO also find the "requires" field and generate the depends<br> nodes?<br>* Investigate dependencies among modules I cannot compile.<br>* Investigate how this affects realtime / sorcery backends. Improved or<br> made worse? Same for other types of modules like codecs and formats.<br>* Make this thread safe. Not entirely sure it was before.<br>* Review new symbol names.<br>* Remove redundent checks for dependent modules.<br>* Remove redundent module self references, for example in res_pjsip<br> registration functions.<br>* Audit module load priorities.<br><br>Change-Id: I979ffb7caecc696ce0afa939193dfa76b19248e7<br>---<br>M apps/app_speech_utils.c<br>M apps/app_stasis.c<br>M channels/chan_motif.c<br>M channels/chan_pjsip.c<br>M channels/chan_rtp.c<br>M funcs/func_pjsip_aor.c<br>M funcs/func_pjsip_contact.c<br>M funcs/func_pjsip_endpoint.c<br>M include/asterisk/module.h<br>M main/loader.c<br>M pbx/pbx_ael.c<br>M res/ari/resource_asterisk.c<br>M res/res_agi.c<br>M res/res_ari.c<br>M res/res_ari_applications.c<br>M res/res_ari_asterisk.c<br>M res/res_ari_bridges.c<br>M res/res_ari_channels.c<br>M res/res_ari_device_states.c<br>M res/res_ari_endpoints.c<br>M res/res_ari_events.c<br>M res/res_ari_mailboxes.c<br>M res/res_ari_playbacks.c<br>M res/res_ari_recordings.c<br>M res/res_ari_sounds.c<br>M res/res_fax_spandsp.c<br>M res/res_hep_rtcp.c<br>M res/res_mwi_external_ami.c<br>M res/res_pjsip.c<br>M res/res_pjsip_acl.c<br>M res/res_pjsip_authenticator_digest.c<br>M res/res_pjsip_caller_id.c<br>M res/res_pjsip_config_wizard.c<br>M res/res_pjsip_dialog_info_body_generator.c<br>M res/res_pjsip_diversion.c<br>M res/res_pjsip_dlg_options.c<br>M res/res_pjsip_dtmf_info.c<br>M res/res_pjsip_empty_info.c<br>M res/res_pjsip_endpoint_identifier_anonymous.c<br>M res/res_pjsip_endpoint_identifier_ip.c<br>M res/res_pjsip_endpoint_identifier_user.c<br>M res/res_pjsip_exten_state.c<br>M res/res_pjsip_header_funcs.c<br>M res/res_pjsip_history.c<br>M res/res_pjsip_logger.c<br>M res/res_pjsip_messaging.c<br>M res/res_pjsip_mwi.c<br>M res/res_pjsip_mwi_body_generator.c<br>M res/res_pjsip_nat.c<br>M res/res_pjsip_notify.c<br>M res/res_pjsip_one_touch_record_info.c<br>M res/res_pjsip_outbound_authenticator_digest.c<br>M res/res_pjsip_outbound_publish.c<br>M res/res_pjsip_outbound_registration.c<br>M res/res_pjsip_path.c<br>M res/res_pjsip_phoneprov_provider.c<br>M res/res_pjsip_pidf_body_generator.c<br>M res/res_pjsip_pidf_digium_body_supplement.c<br>M res/res_pjsip_pidf_eyebeam_body_supplement.c<br>M res/res_pjsip_publish_asterisk.c<br>M res/res_pjsip_pubsub.c<br>M res/res_pjsip_refer.c<br>M res/res_pjsip_registrar.c<br>M res/res_pjsip_registrar_expire.c<br>M res/res_pjsip_rfc3326.c<br>M res/res_pjsip_sdp_rtp.c<br>M res/res_pjsip_send_to_voicemail.c<br>M res/res_pjsip_session.c<br>M res/res_pjsip_sips_contact.c<br>M res/res_pjsip_t38.c<br>M res/res_pjsip_transport_management.c<br>M res/res_pjsip_transport_websocket.c<br>M res/res_pjsip_xpidf_body_generator.c<br>M res/res_stasis_answer.c<br>M res/res_stasis_device_state.c<br>M res/res_stasis_mailbox.c<br>M res/res_stasis_playback.c<br>M res/res_stasis_recording.c<br>M res/res_stasis_snoop.c<br>M rest-api-templates/res_ari_resource.c.mustache<br>M tests/test_ari.c<br>M tests/test_ari_model.c<br>M tests/test_res_pjsip_scheduler.c<br>M tests/test_res_stasis.c<br>M tests/test_stasis_endpoints.c<br>85 files changed, 487 insertions(+), 241 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/87/6987/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/apps/app_speech_utils.c b/apps/app_speech_utils.c<br>index 3a6a191..11c57c8 100644<br>--- a/apps/app_speech_utils.c<br>+++ b/apps/app_speech_utils.c<br>@@ -1003,5 +1003,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_speech",<br>+ .requires = "res_speech",<br> );<br>diff --git a/apps/app_stasis.c b/apps/app_stasis.c<br>index 81c58e8..8d09349 100644<br>--- a/apps/app_stasis.c<br>+++ b/apps/app_stasis.c<br>@@ -144,5 +144,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis",<br>+ .requires = "res_stasis",<br> );<br>diff --git a/channels/chan_motif.c b/channels/chan_motif.c<br>index 210cf36..8cdea5a 100644<br>--- a/channels/chan_motif.c<br>+++ b/channels/chan_motif.c<br>@@ -2821,4 +2821,5 @@<br> .unload = unload_module,<br> .reload = reload,<br> .load_pri = AST_MODPRI_CHANNEL_DRIVER,<br>+ .requires = "res_xmpp",<br> );<br>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c<br>index 7520c2b..7f1d058 100644<br>--- a/channels/chan_pjsip.c<br>+++ b/channels/chan_pjsip.c<br>@@ -3060,4 +3060,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DRIVER,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/channels/chan_rtp.c b/channels/chan_rtp.c<br>index e1c29a2..5758d7c 100644<br>--- a/channels/chan_rtp.c<br>+++ b/channels/chan_rtp.c<br>@@ -431,4 +431,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DRIVER,<br>+ .requires = "res_rtp_multicast",<br> );<br>diff --git a/funcs/func_pjsip_aor.c b/funcs/func_pjsip_aor.c<br>index 799e9e4..589f667 100644<br>--- a/funcs/func_pjsip_aor.c<br>+++ b/funcs/func_pjsip_aor.c<br>@@ -181,4 +181,9 @@<br> return ast_custom_function_register(&pjsip_aor_function);<br> }<br> <br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get information about a PJSIP AOR");<br>+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Get information about a PJSIP AOR",<br>+ .support_level = AST_MODULE_SUPPORT_CORE,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .requires = "res_pjsip",<br>+);<br>diff --git a/funcs/func_pjsip_contact.c b/funcs/func_pjsip_contact.c<br>index c840365..fac4cb6 100644<br>--- a/funcs/func_pjsip_contact.c<br>+++ b/funcs/func_pjsip_contact.c<br>@@ -198,4 +198,9 @@<br> return ast_custom_function_register(&pjsip_contact_function);<br> }<br> <br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get information about a PJSIP contact");<br>+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Get information about a PJSIP contact",<br>+ .support_level = AST_MODULE_SUPPORT_CORE,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .requires = "res_pjsip",<br>+);<br>diff --git a/funcs/func_pjsip_endpoint.c b/funcs/func_pjsip_endpoint.c<br>index a64d93b..e4a6aba 100644<br>--- a/funcs/func_pjsip_endpoint.c<br>+++ b/funcs/func_pjsip_endpoint.c<br>@@ -156,4 +156,9 @@<br> return ast_custom_function_register(&pjsip_endpoint_function);<br> }<br> <br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Get information about a PJSIP endpoint");<br>+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Get information about a PJSIP endpoint",<br>+ .support_level = AST_MODULE_SUPPORT_CORE,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .requires = "res_pjsip",<br>+);<br>diff --git a/include/asterisk/module.h b/include/asterisk/module.h<br>index 69ebb26..22d18ce 100644<br>--- a/include/asterisk/module.h<br>+++ b/include/asterisk/module.h<br>@@ -68,8 +68,7 @@<br> enum ast_module_load_result {<br> AST_MODULE_LOAD_SUCCESS = 0, /*!< Module loaded and configured */<br> AST_MODULE_LOAD_DECLINE = 1, /*!< Module is not configured */<br>- AST_MODULE_LOAD_SKIP = 2, /*!< Module was skipped for some reason (For loader.c use only. Should never be returned by modules)*/<br>- AST_MODULE_LOAD_PRIORITY = 3, /*!< Module is not loaded yet, but is added to prioity heap */<br>+ AST_MODULE_LOAD_PRIORITY = 2, /*!< Module is not loaded yet, but is added to priority list */<br> AST_MODULE_LOAD_FAILURE = -1, /*!< Module could not be loaded properly */<br> };<br> <br>@@ -338,9 +337,12 @@<br> unsigned char load_pri;<br> <br> /*! Modules which should be loaded first, in comma-separated string format.<br>- * These are only required for loading, when the optional_api header file<br>- * detects that the compiler does not support the optional API featureset. */<br>+ * These are only required if OPTIONAL_API is disabled. */<br> const char *nonoptreq;<br>+<br>+ /*! Modules which must be started first, in comma-separated string format. */<br>+ const char *requires;<br>+<br> /*! The support level for the given module */<br> enum ast_module_support_level support_level;<br> };<br>diff --git a/main/loader.c b/main/loader.c<br>index add6a42..bb3e9d3 100644<br>--- a/main/loader.c<br>+++ b/main/loader.c<br>@@ -56,6 +56,7 @@<br> #include "asterisk/app.h"<br> #include "asterisk/test.h"<br> #include "asterisk/sounds_index.h"<br>+#include "asterisk/vector.h"<br> <br> #include <dlfcn.h><br> <br>@@ -115,6 +116,8 @@<br> */<br> static int modules_loaded;<br> <br>+AST_VECTOR(module_vector, struct ast_module *);<br>+<br> struct ast_module {<br> const struct ast_module_info *info;<br> /* Used to get module references into refs log */<br>@@ -166,6 +169,20 @@<br> is being registered<br> */<br> static struct ast_module *resource_being_loaded;<br>+<br>+static int module_requires_check(struct ast_module *mod, struct module_vector *deps, int all);<br>+<br>+#define CALLBACK_REF(dep_mod, mod) \<br>+ do { \<br>+ ast_debug(1, "Load of %s referencing %s\n", mod->resource, dep_mod->resource); \<br>+ __ast_module_ref(dep_mod, mod->resource, __LINE__, __PRETTY_FUNCTION__); \<br>+ } while (0)<br>+<br>+#define CALLBACK_UNREF(dep_mod, mod) \<br>+ do { \<br>+ ast_debug(1, "Unload of %s releasing %s\n", mod->resource, dep_mod->resource); \<br>+ __ast_module_unref(dep_mod, mod->resource, __LINE__, __PRETTY_FUNCTION__); \<br>+ } while (0)<br> <br> /* XXX: should we check for duplicate resource names here? */<br> <br>@@ -488,43 +505,42 @@<br> #endif<br> }<br> <br>-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required);<br>-<br>-#define MODULE_LOCAL_ONLY (void *)-1<br>-<br>-static struct ast_module *load_dynamic_module(const char *resource_in, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap)<br>+/*!<br>+ * \internal<br>+ * \brief Perform actual calls to dlopen for a module.<br>+ *<br>+ * \param resource_in The module name to load.<br>+ * \param so_ext ".so" or blank if ".so" is already part of resource_in.<br>+ * \param flags Passed directly to dlopen.<br>+ * \param suppress_logging Do not log any error from dlopen.<br>+ *<br>+ * \return Pointer to opened module, NULL on error.<br>+ */<br>+static struct ast_module *load_dlopen(const char *resource_in, const char *so_ext,<br>+ int flags, unsigned int suppress_logging)<br> {<br>- char fn[PATH_MAX] = "";<br>- void *lib = NULL;<br> struct ast_module *mod;<br>- unsigned int wants_global;<br>- int space; /* room needed for the descriptor */<br>- int missing_so = 0;<br>+ void *lib;<br>+ char fn[PATH_MAX];<br> <br>- space = sizeof(*resource_being_loaded) + strlen(resource_in) + 1;<br>- if (strcasecmp(resource_in + strlen(resource_in) - 3, ".so")) {<br>- missing_so = 1;<br>- space += 3; /* room for the extra ".so" */<br>+ mod = ast_calloc(1, sizeof(*mod) + strlen(resource_in) + strlen(so_ext) + 1);<br>+ if (!mod) {<br>+ return NULL;<br> }<br> <br>- snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, missing_so ? ".so" : "");<br>+ sprintf(mod->resource, "%s%s", resource_in, so_ext);<br>+ snprintf(fn, sizeof(fn), "%s/%s%s", ast_config_AST_MODULE_DIR, resource_in, so_ext);<br> <br>- /* make a first load of the module in 'quiet' mode... don't try to resolve<br>- any symbols, and don't export any symbols. this will allow us to peek into<br>- the module's info block (if available) to see what flags it has set */<br>+ resource_being_loaded = mod;<br>+ lib = dlopen(fn, flags);<br>+ resource_being_loaded = NULL;<br> <br>- resource_being_loaded = ast_calloc(1, space);<br>- if (!resource_being_loaded)<br>- return NULL;<br>- strcpy(resource_being_loaded->resource, resource_in);<br>- if (missing_so)<br>- strcat(resource_being_loaded->resource, ".so");<br>-<br>- if (!(lib = dlopen(fn, RTLD_LAZY | RTLD_GLOBAL))) {<br>+ if (!lib) {<br> if (!suppress_logging) {<br> ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());<br> }<br>- ast_free(resource_being_loaded);<br>+ ast_free(mod);<br>+<br> return NULL;<br> }<br> <br>@@ -535,7 +551,7 @@<br> constructor) places the new module at the tail of the<br> module_list<br> */<br>- if (resource_being_loaded != (mod = AST_DLLIST_LAST(&module_list))) {<br>+ if (mod != AST_DLLIST_LAST(&module_list)) {<br> ast_log(LOG_WARNING, "Module '%s' did not register itself during load\n", resource_in);<br> /* no, it did not, so close it and return */<br> logged_dlclose(resource_in, lib);<br>@@ -544,40 +560,39 @@<br> return NULL;<br> }<br> <br>- wants_global = ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS);<br>+ mod->lib = lib;<br> <br>- /* if we are being asked only to load modules that provide global symbols,<br>- and this one does not, then close it and return */<br>- if (global_symbols_only && !wants_global) {<br>- logged_dlclose(resource_in, lib);<br>- return MODULE_LOCAL_ONLY;<br>+ return mod;<br>+}<br>+<br>+static struct ast_module *load_dynamic_module(const char *name, unsigned int suppress_logging)<br>+{<br>+ struct ast_module *mod;<br>+ size_t name_len = strlen(name);<br>+ const char *so_ext = "";<br>+<br>+ if (name_len < 4 || strcasecmp(name + name_len - 3, ".so")) {<br>+ so_ext = ".so";<br> }<br> <br>- logged_dlclose(resource_in, lib);<br>- resource_being_loaded = NULL;<br>-<br>- /* start the load process again */<br>- resource_being_loaded = ast_calloc(1, space);<br>- if (!resource_being_loaded)<br>- return NULL;<br>- strcpy(resource_being_loaded->resource, resource_in);<br>- if (missing_so)<br>- strcat(resource_being_loaded->resource, ".so");<br>-<br>- if (!(lib = dlopen(fn, wants_global ? RTLD_LAZY | RTLD_GLOBAL : RTLD_NOW | RTLD_LOCAL))) {<br>- ast_log(LOG_WARNING, "Error loading module '%s': %s\n", resource_in, dlerror());<br>- ast_free(resource_being_loaded);<br>+ /* Most modules do not export symbols, start with that. */<br>+ mod = load_dlopen(name, so_ext, RTLD_NOW | RTLD_LOCAL, suppress_logging);<br>+ if (!mod) {<br> return NULL;<br> }<br> <br>- /* since the module was successfully opened, and it registered itself<br>- the previous time we did that, we're going to assume it worked this<br>- time too :) */<br>+ if (!ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS)) {<br>+ return mod;<br>+ }<br> <br>- AST_DLLIST_LAST(&module_list)->lib = lib;<br>- resource_being_loaded = NULL;<br>+ logged_dlclose(name, mod->lib);<br> <br>- return AST_DLLIST_LAST(&module_list);<br>+ mod = load_dlopen(name, so_ext, RTLD_NOW | RTLD_GLOBAL, 0);<br>+ if (!mod) {<br>+ return NULL;<br>+ }<br>+<br>+ return mod;<br> }<br> <br> int modules_shutdown(void)<br>@@ -601,6 +616,8 @@<br> somethingchanged = 0;<br> <br> AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&module_list, mod, entry) {<br>+ struct module_vector deps;<br>+<br> if (!final && mod->usecount) {<br> ast_debug(1, "Passing on %s: its use count is %d\n",<br> mod->resource, mod->usecount);<br>@@ -610,7 +627,16 @@<br> if (mod->flags.running && !mod->flags.declined && mod->info->unload) {<br> ast_verb(1, "Unloading %s\n", mod->resource);<br> mod->info->unload();<br>+<br> }<br>+<br>+ if (mod->flags.running && !mod->flags.declined) {<br>+ AST_VECTOR_INIT(&deps, 4);<br>+ module_requires_check(mod, &deps, 1);<br>+ AST_VECTOR_CALLBACK_VOID(&deps, CALLBACK_UNREF, mod);<br>+ AST_VECTOR_FREE(&deps);<br>+ }<br>+<br> AST_LIST_HEAD_DESTROY(&mod->users);<br> ao2_cleanup(mod->ref_debug);<br> ast_free(mod);<br>@@ -639,6 +665,7 @@<br> struct ast_module *mod;<br> int res = -1;<br> int error = 0;<br>+ struct module_vector deps;<br> <br> AST_DLLIST_LOCK(&module_list);<br> <br>@@ -689,8 +716,14 @@<br> }<br> }<br> <br>- if (!error)<br>+ if (!error) {<br> mod->flags.running = mod->flags.declined = 0;<br>+ }<br>+<br>+ AST_VECTOR_INIT(&deps, 4);<br>+ module_requires_check(mod, &deps, 1);<br>+ AST_VECTOR_CALLBACK_VOID(&deps, CALLBACK_UNREF, mod);<br>+ AST_VECTOR_FREE(&deps);<br> <br> AST_DLLIST_UNLOCK(&module_list);<br> <br>@@ -1056,10 +1089,89 @@<br> return 0;<br> }<br> <br>+static int module_vector_cmp(struct ast_module *a, struct ast_module *b)<br>+{<br>+ /* if load_pri is not set, default is 128. Lower is better */<br>+ int a_pri = ast_test_flag(a->info, AST_MODFLAG_LOAD_ORDER) ? a->info->load_pri : 128;<br>+ int b_pri = ast_test_flag(b->info, AST_MODFLAG_LOAD_ORDER) ? b->info->load_pri : 128;<br>+<br>+ /*<br>+ * Returns comparison values for a min-heap<br>+ * <0 a_pri > b_pri<br>+ * =0 a_pri == b_pri<br>+ * >0 a_pri < b_pri<br>+ */<br>+ return a_pri - b_pri;<br>+}<br>+<br>+static int requires_string_check(const char *input, struct module_vector *deps,<br>+ int getrunning, int optional_api)<br>+{<br>+ char *list = ast_strdupa(input);<br>+ char *tmp;<br>+<br>+ if (!list) {<br>+ return -1;<br>+ }<br>+<br>+ while ((tmp = strsep(&list, ","))) {<br>+ struct ast_module *dep;<br>+<br>+ dep = find_resource(tmp, 0);<br>+ if (!dep) {<br>+ ast_debug(1, "dep %s not found, optional_api=%d\n", tmp, optional_api);<br>+<br>+ return optional_api ? 0 : -1;<br>+ }<br>+<br>+ if (getrunning && !dep->flags.running) {<br>+ /* getrunning means all deps need to be running. */<br>+ ast_debug(1, "We need %s running but didn't get it.\n", dep->resource);<br>+ return -1;<br>+ }<br>+<br>+ if (!dep->flags.running || getrunning) {<br>+ if (!deps) {<br>+ ast_debug(1, "no 'deps' list and dep is not running: %s.", dep->resource);<br>+ return -1;<br>+ }<br>+<br>+ /* Ignore duplicates */<br>+ if (!AST_VECTOR_GET_CMP(deps, dep, AST_VECTOR_ELEM_DEFAULT_CMP)) {<br>+ AST_VECTOR_APPEND(deps, dep);<br>+ }<br>+ }<br>+ };<br>+<br>+ return 0;<br>+}<br>+<br>+#ifdef OPTIONAL_API<br>+#define NONOPT_IS_OPTIONAL 1<br>+#else<br>+#define NONOPT_IS_OPTIONAL 0<br>+#endif<br>+<br>+static int module_requires_check(struct ast_module *mod, struct module_vector *deps, int all)<br>+{<br>+ if (mod->info->requires && requires_string_check(mod->info->requires, deps, all, 0)) {<br>+ ast_debug(1, "%s is missing requires: %s\n", mod->resource, mod->info->requires);<br>+ return -1;<br>+ }<br>+<br>+ if (mod->info->nonoptreq && requires_string_check(mod->info->nonoptreq, deps, all, NONOPT_IS_OPTIONAL)) {<br>+ ast_debug(1, "%s is missing nonoptreq: %s\n", mod->resource, mod->info->nonoptreq);<br>+ return -1;<br>+ }<br>+<br>+ return 0;<br>+}<br>+<br> static enum ast_module_load_result start_resource(struct ast_module *mod)<br> {<br> char tmp[256];<br> enum ast_module_load_result res;<br>+ struct module_vector deps;<br> <br> if (mod->flags.running) {<br> return AST_MODULE_LOAD_SUCCESS;<br>@@ -1068,6 +1180,18 @@<br> if (!mod->info->load) {<br> return AST_MODULE_LOAD_FAILURE;<br> }<br>+<br>+ AST_VECTOR_INIT(&deps, 4);<br>+ /* This returns an error if any required dep isn't running, otherwise returns full list. */<br>+ if (module_requires_check(mod, &deps, 1)) {<br>+ mod->flags.declined = 1;<br>+ AST_VECTOR_FREE(&deps);<br>+<br>+ return -1;<br>+ }<br>+<br>+ /* This grabs a reference to all the required modules. */<br>+ AST_VECTOR_CALLBACK_VOID(&deps, CALLBACK_REF, mod);<br> <br> if (!ast_fully_booted) {<br> ast_verb(1, "Loading %s.\n", mod->resource);<br>@@ -1088,12 +1212,16 @@<br> break;<br> case AST_MODULE_LOAD_DECLINE:<br> mod->flags.declined = 1;<br>- break;<br>+ /* fall-through */<br> case AST_MODULE_LOAD_FAILURE:<br>- case AST_MODULE_LOAD_SKIP: /* modules should never return this value */<br>+ /* We're not running so release the references. */<br>+ AST_VECTOR_CALLBACK_VOID(&deps, CALLBACK_UNREF, mod);<br>+ break;<br> case AST_MODULE_LOAD_PRIORITY:<br> break;<br> }<br>+<br>+ AST_VECTOR_FREE(&deps);<br> <br> /* Make sure the newly started module is at the end of the list */<br> AST_DLLIST_LOCK(&module_list);<br>@@ -1104,36 +1232,27 @@<br> return res;<br> }<br> <br>-/*! loads a resource based upon resource_name. If global_symbols_only is set<br>- * only modules with global symbols will be loaded.<br>+/*! loads a resource based upon resource_name.<br> *<br>- * If the ast_heap is provided (not NULL) the module is found and added to the<br>- * heap without running the module's load() function. By doing this, modules<br>- * added to the resource_heap can be initialized later in order by priority.<br>+ * If the module_vector is provided (not NULL) the module is found and added to the<br>+ * vector without running the module's load() function. By doing this, modules<br>+ * can be initialized later in order by priority and dependencies.<br> *<br>- * If the ast_heap is not provided, the module's load function will be executed<br>+ * If the module_vector is not provided, the module's load function will be executed<br> * immediately */<br>-static enum ast_module_load_result load_resource(const char *resource_name, unsigned int global_symbols_only, unsigned int suppress_logging, struct ast_heap *resource_heap, int required)<br>+static enum ast_module_load_result load_resource(const char *resource_name, unsigned int suppress_logging, struct module_vector *module_vector, int required)<br> {<br> struct ast_module *mod;<br>- enum ast_module_load_result res = AST_MODULE_LOAD_SUCCESS;<br>+ enum ast_module_load_result res;<br> <br> if ((mod = find_resource(resource_name, 0))) {<br> if (mod->flags.running) {<br> ast_log(LOG_WARNING, "Module '%s' already exists.\n", resource_name);<br> return AST_MODULE_LOAD_DECLINE;<br> }<br>- if (global_symbols_only && !ast_test_flag(mod->info, AST_MODFLAG_GLOBAL_SYMBOLS))<br>- return AST_MODULE_LOAD_SKIP;<br> } else {<br>- mod = load_dynamic_module(resource_name, global_symbols_only, suppress_logging, resource_heap);<br>- if (mod == MODULE_LOCAL_ONLY) {<br>- return AST_MODULE_LOAD_SKIP;<br>- }<br>+ mod = load_dynamic_module(resource_name, suppress_logging);<br> if (!mod) {<br>- if (!global_symbols_only) {<br>- ast_log(LOG_WARNING, "Module '%s' could not be loaded.\n", resource_name);<br>- }<br> return required ? AST_MODULE_LOAD_FAILURE : AST_MODULE_LOAD_DECLINE;<br> }<br> }<br>@@ -1146,8 +1265,8 @@<br> <br> mod->flags.declined = 0;<br> <br>- if (resource_heap) {<br>- ast_heap_push(resource_heap, mod);<br>+ if (module_vector) {<br>+ AST_VECTOR_ADD_SORTED(module_vector, mod, module_vector_cmp);<br> res = AST_MODULE_LOAD_PRIORITY;<br> } else {<br> res = start_resource(mod);<br>@@ -1160,7 +1279,7 @@<br> {<br> int res;<br> AST_DLLIST_LOCK(&module_list);<br>- res = load_resource(resource_name, 0, 0, NULL, 0);<br>+ res = load_resource(resource_name, 0, NULL, 0);<br> if (!res) {<br> ast_test_suite_event_notify("MODULE_LOAD", "Message: %s", resource_name);<br> }<br>@@ -1200,91 +1319,192 @@<br> return order;<br> }<br> <br>-static int mod_load_cmp(void *a, void *b)<br>+/*!<br>+ * \brief Recursively check dependencies, optionally populating a vector.<br>+ *<br>+ * \retval 0 All dependencies resolved.<br>+ * \retval -1 Failed to resolve some dependencies.<br>+ *<br>+ * An error from this function usually means a required module is not even loaded.<br>+ *<br>+ * This function is safe from infinate recursion, but dependency loops are not<br>+ * reported as an error from here.<br>+ */<br>+static int find_missingdeps(struct ast_module *mod, struct module_vector *missingdeps)<br> {<br>- struct ast_module *a_mod = (struct ast_module *) a;<br>- struct ast_module *b_mod = (struct ast_module *) b;<br>- /* if load_pri is not set, default is 128. Lower is better */<br>- int a_pri = ast_test_flag(a_mod->info, AST_MODFLAG_LOAD_ORDER) ? a_mod->info->load_pri : 128;<br>- int b_pri = ast_test_flag(b_mod->info, AST_MODFLAG_LOAD_ORDER) ? b_mod->info->load_pri : 128;<br>+ int i = 0;<br>+ int res;<br>+ struct module_vector localdeps;<br>+ struct ast_module *tmp;<br> <br>- /*<br>- * Returns comparison values for a min-heap<br>- * <0 a_pri > b_pri<br>- * =0 a_pri == b_pri<br>- * >0 a_pri < b_pri<br>- */<br>- return b_pri - a_pri;<br>+ AST_VECTOR_INIT(&localdeps, 4);<br>+ if (module_requires_check(mod, &localdeps, 0)) {<br>+ AST_VECTOR_FREE(&localdeps);<br>+<br>+ return -1;<br>+ }<br>+<br>+ while (i < AST_VECTOR_SIZE(&localdeps)) {<br>+ tmp = AST_VECTOR_GET(&localdeps, i);<br>+<br>+ if (AST_VECTOR_GET_CMP(missingdeps, tmp, AST_VECTOR_ELEM_DEFAULT_CMP)) {<br>+ AST_VECTOR_REMOVE(&localdeps, i, 0);<br>+ } else {<br>+ /* missingdeps is the real list so keep it sorted. */<br>+ AST_VECTOR_ADD_SORTED(missingdeps, tmp, module_vector_cmp);<br>+ i++;<br>+ }<br>+ }<br>+<br>+ res = 0;<br>+ while (!res && AST_VECTOR_SIZE(&localdeps)) {<br>+ tmp = AST_VECTOR_GET(&localdeps, 0);<br>+ AST_VECTOR_REMOVE(&localdeps, 0, 1);<br>+ res = find_missingdeps(tmp, missingdeps);<br>+ if (res) {<br>+ break;<br>+ }<br>+ }<br>+<br>+ AST_VECTOR_FREE(&localdeps);<br>+<br>+ return res;<br> }<br> <br>-AST_LIST_HEAD_NOLOCK(load_retries, load_order_entry);<br>+static int try_module_start(struct ast_module *mod, int *count)<br>+{<br>+ static enum ast_module_load_result lres;<br>+<br>+ /* Quick non-recursive check. */<br>+ if (module_requires_check(mod, NULL, 0)) {<br>+ ast_debug(1, "Module %s is missing dependencies\n", mod->resource);<br>+ return -1;<br>+ }<br>+<br>+ lres = start_resource(mod);<br>+ ast_debug(3, "START: %-46s[%d] %d\n",<br>+ mod->resource,<br>+ ast_test_flag(mod->info, AST_MODFLAG_LOAD_ORDER) ? mod->info->load_pri : AST_MODPRI_DEFAULT,<br>+ lres);<br>+ if (lres == AST_MODULE_LOAD_FAILURE) {<br>+ ast_log(LOG_ERROR, "*** Failed to load module %s\n", mod->resource);<br>+<br>+ return -1;<br>+ }<br>+<br>+ if (lres == AST_MODULE_LOAD_SUCCESS) {<br>+ (*count)++;<br>+ }<br>+<br>+ return 0;<br>+}<br>+<br>+static int start_module_vector(struct module_vector *resources, int *mod_count)<br>+{<br>+ struct module_vector missingdeps;<br>+ int res = 0;<br>+<br>+ AST_VECTOR_INIT(&missingdeps, 0);<br>+ while (AST_VECTOR_SIZE(resources)) {<br>+ struct ast_module *mod = AST_VECTOR_REMOVE(resources, 0, 1);<br>+<br>+ if (!try_module_start(mod, mod_count)) {<br>+ /* No missing dependencies, successful. */<br>+ continue;<br>+ }<br>+<br>+ res = find_missingdeps(mod, &missingdeps);<br>+ if (res) {<br>+ ast_debug(1, "Error from find_missingdeps for %s\n", mod->resource);<br>+ /* This module likely requires something that isn't loaded. */<br>+ break;<br>+ }<br>+<br>+ if (!AST_VECTOR_SIZE(&missingdeps)) {<br>+ ast_log(LOG_WARNING, "%s isn't missing any dependencies but still didn't start\n", mod->resource);<br>+ /* Dependencies were met but the module failed to start. */<br>+ res = -1;<br>+ break;<br>+ }<br>+<br>+ ast_debug(1, "%s has %d dependencies\n", mod->resource, (int)AST_VECTOR_SIZE(&missingdeps));<br>+ while (AST_VECTOR_SIZE(&missingdeps)) {<br>+ int didwork = 0;<br>+ int i = 0;<br>+<br>+ while (i < AST_VECTOR_SIZE(&missingdeps)) {<br>+ struct ast_module *tmp = AST_VECTOR_GET(&missingdeps, i);<br>+<br>+ ast_debug(1, "%s trying to start %s\n", mod->resource, tmp->resource);<br>+ if (!try_module_start(tmp, mod_count)) {<br>+ ast_debug(1, "%s started %s\n", mod->resource, tmp->resource);<br>+ AST_VECTOR_REMOVE(&missingdeps, i, 1);<br>+ AST_VECTOR_REMOVE_CMP_ORDERED(resources, tmp,<br>+ AST_VECTOR_ELEM_DEFAULT_CMP, AST_VECTOR_ELEM_CLEANUP_NOOP);<br>+ didwork++;<br>+ continue;<br>+ }<br>+ ast_debug(1, "%s failed to start %s\n", mod->resource, tmp->resource);<br>+ i++;<br>+ }<br>+<br>+ if (!didwork) {<br>+ break;<br>+ }<br>+ }<br>+<br>+ if (AST_VECTOR_SIZE(&missingdeps)) {<br>+ ast_log(LOG_ERROR, "Failed to load %s due to unfilled dependencies.\n", mod->resource);<br>+ /* We've failed to mod and it's load deps. Really abort? */<br>+ res = -1;<br>+ break;<br>+ } else {<br>+ res = try_module_start(mod, mod_count);<br>+ if (res) {<br>+ ast_log(LOG_ERROR, "Failed to load %s: %d\n", mod->resource, res);<br>+ break;<br>+ }<br>+ }<br>+ }<br>+<br>+ AST_VECTOR_FREE(&missingdeps);<br>+<br>+ return res;<br>+}<br> <br> /*! loads modules in order by load_pri, updates mod_count<br> \return -1 on failure to load module, -2 on failure to load required module, otherwise 0<br> */<br>-static int load_resource_list(struct load_order *load_order, unsigned int global_symbols, int *mod_count)<br>+static int load_resource_list(struct load_order *load_order, int *mod_count)<br> {<br>- struct ast_heap *resource_heap;<br>- struct load_order_entry *order;<br>- struct ast_module *mod;<br>- struct load_retries load_retries;<br>- int count = 0;<br>+ struct module_vector resources;<br> int res = 0;<br> int i = 0;<br>-#define LOAD_RETRIES 4<br>+ int try_again = 1;<br>+ int action_taken = 0;<br> <br>- AST_LIST_HEAD_INIT_NOLOCK(&load_retries);<br>+ AST_VECTOR_INIT(&resources, 10);<br> <br>- if(!(resource_heap = ast_heap_create(8, mod_load_cmp, -1))) {<br>- return -1;<br>- }<br>+ /*<br>+ * This loops until one iteration after nothing is done. Once we iterate the<br>+ * full load_order list without loading anything it's impossible to make further<br>+ * progress. We run the loop again so we can log messages for any required<br>+ * modules that failed.<br>+ */<br>+ do {<br>+ struct load_order_entry *order;<br> <br>- /* first, add find and add modules to heap */<br>- AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {<br>- enum ast_module_load_result lres;<br>-<br>- /* Suppress log messages unless this is the last pass */<br>- lres = load_resource(order->resource, global_symbols, 1, resource_heap, order->required);<br>- ast_debug(3, "PASS 0: %-46s %d %d\n", order->resource, lres, global_symbols);<br>- switch (lres) {<br>- case AST_MODULE_LOAD_SUCCESS:<br>- /* We're supplying a heap so SUCCESS isn't possible but we still have to test for it. */<br>- break;<br>- case AST_MODULE_LOAD_FAILURE:<br>- case AST_MODULE_LOAD_DECLINE:<br>- /*<br>- * DECLINE or FAILURE means there was an issue with dlopen or module_register<br>- * which might be retryable. LOAD_FAILURE only happens for required modules<br>- * but we're still going to retry. We need to remove the entry from the<br>- * load_order list and add it to the load_retries list.<br>- */<br>- AST_LIST_REMOVE_CURRENT(entry);<br>- AST_LIST_INSERT_TAIL(&load_retries, order, entry);<br>- break;<br>- case AST_MODULE_LOAD_SKIP:<br>- /*<br>- * SKIP means that dlopen worked but global_symbols was set and this module doesn't qualify.<br>- * Leave it in load_order for the next call of load_resource_list.<br>- */<br>- break;<br>- case AST_MODULE_LOAD_PRIORITY:<br>- /* load_resource worked and the module was added to the priority heap */<br>- AST_LIST_REMOVE_CURRENT(entry);<br>- ast_free(order->resource);<br>- ast_free(order);<br>- break;<br>+ if (!action_taken && i) {<br>+ try_again = 0;<br> }<br>- }<br>- AST_LIST_TRAVERSE_SAFE_END;<br>+ action_taken = 0;<br> <br>- /* Retry the failures until the list is empty or we reach LOAD_RETRIES */<br>- for (i = 0; !AST_LIST_EMPTY(&load_retries) && i < LOAD_RETRIES; i++) {<br>- AST_LIST_TRAVERSE_SAFE_BEGIN(&load_retries, order, entry) {<br>+ AST_LIST_TRAVERSE_SAFE_BEGIN(load_order, order, entry) {<br> enum ast_module_load_result lres;<br> <br> /* Suppress log messages unless this is the last pass */<br>- lres = load_resource(order->resource, global_symbols, (i < LOAD_RETRIES - 1), resource_heap, order->required);<br>- ast_debug(3, "PASS %d %-46s %d %d\n", i + 1, order->resource, lres, global_symbols);<br>+ lres = load_resource(order->resource, try_again, &resources, order->required);<br>+ ast_debug(3, "PASS %d %-46s %d\n", i, order->resource, lres);<br> switch (lres) {<br> /* These are all retryable. */<br> case AST_MODULE_LOAD_SUCCESS:<br>@@ -1292,66 +1512,33 @@<br> break;<br> case AST_MODULE_LOAD_FAILURE:<br> /* LOAD_FAILURE only happens for required modules */<br>- if (i == LOAD_RETRIES - 1) {<br>- /* This was the last chance to load a required module*/<br>+ if (!try_again) {<br> ast_log(LOG_ERROR, "*** Failed to load module %s - Required\n", order->resource);<br> fprintf(stderr, "*** Failed to load module %s - Required\n", order->resource);<br> res = -2;<br>- goto done;<br> }<br>- break;;<br>- case AST_MODULE_LOAD_SKIP:<br>- /*<br>- * SKIP means that dlopen worked but global_symbols was set and this module<br>- * doesn't qualify. Put it back in load_order for the next call of<br>- * load_resource_list.<br>- */<br>- AST_LIST_REMOVE_CURRENT(entry);<br>- AST_LIST_INSERT_TAIL(load_order, order, entry);<br> break;<br> case AST_MODULE_LOAD_PRIORITY:<br>- /* load_resource worked and the module was added to the priority heap */<br>+ /* load_resource worked and the module was added to the priority vector */<br> AST_LIST_REMOVE_CURRENT(entry);<br> ast_free(order->resource);<br> ast_free(order);<br>+ action_taken++;<br> break;<br> }<br> }<br> AST_LIST_TRAVERSE_SAFE_END;<br>- }<br> <br>- /* second remove modules from heap sorted by priority */<br>- while ((mod = ast_heap_pop(resource_heap))) {<br>- enum ast_module_load_result lres;<br>-<br>- lres = start_resource(mod);<br>- ast_debug(3, "START: %-46s %d %d\n", mod->resource, lres, global_symbols);<br>- switch (lres) {<br>- case AST_MODULE_LOAD_SUCCESS:<br>- count++;<br>- case AST_MODULE_LOAD_DECLINE:<br>- break;<br>- case AST_MODULE_LOAD_FAILURE:<br>- ast_log(LOG_ERROR, "*** Failed to load module %s\n", mod->resource);<br>- res = -1;<br>+ if (res == -2) {<br> goto done;<br>- case AST_MODULE_LOAD_SKIP:<br>- case AST_MODULE_LOAD_PRIORITY:<br>- break;<br> }<br>- }<br> <br>+ i++;<br>+ } while (try_again);<br>+<br>+ res = start_module_vector(&resources, mod_count);<br> done:<br>-<br>- while ((order = AST_LIST_REMOVE_HEAD(&load_retries, entry))) {<br>- ast_free(order->resource);<br>- ast_free(order);<br>- }<br>-<br>- if (mod_count) {<br>- *mod_count += count;<br>- }<br>- ast_heap_destroy(resource_heap);<br>+ AST_VECTOR_FREE(&resources);<br> <br> return res;<br> }<br>@@ -1453,15 +1640,7 @@<br> if (load_count)<br> ast_log(LOG_NOTICE, "%u modules will be loaded.\n", load_count);<br> <br>- /* first, load only modules that provide global symbols */<br>- if ((res = load_resource_list(&load_order, 1, &modulecount)) < 0) {<br>- goto done;<br>- }<br>-<br>- /* now load everything else */<br>- if ((res = load_resource_list(&load_order, 0, &modulecount)) < 0) {<br>- goto done;<br>- }<br>+ res = load_resource_list(&load_order, &modulecount);<br> <br> done:<br> while ((order = AST_LIST_REMOVE_HEAD(&load_order, entry))) {<br>diff --git a/pbx/pbx_ael.c b/pbx/pbx_ael.c<br>index 8ad4914..71cec1d 100644<br>--- a/pbx/pbx_ael.c<br>+++ b/pbx/pbx_ael.c<br>@@ -292,6 +292,7 @@<br> .load = load_module,<br> .unload = unload_module,<br> .reload = reload,<br>+ .requires = "res_ael_share",<br> );<br> <br> #ifdef AAL_ARGCHECK<br>diff --git a/res/ari/resource_asterisk.c b/res/ari/resource_asterisk.c<br>index e76eb02..d357093 100644<br>--- a/res/ari/resource_asterisk.c<br>+++ b/res/ari/resource_asterisk.c<br>@@ -533,11 +533,6 @@<br> response, 409, "Conflict",<br> "Module load declined");<br> return;<br>- } else if (load_result == AST_MODULE_LOAD_SKIP) {<br>- ast_ari_response_error(<br>- response, 409, "Conflict",<br>- "Module was skipped");<br>- return;<br> } else if (load_result == AST_MODULE_LOAD_FAILURE) {<br> ast_ari_response_error(<br> response, 409, "Conflict",<br>diff --git a/res/res_agi.c b/res/res_agi.c<br>index 4660635..1be8685 100644<br>--- a/res/res_agi.c<br>+++ b/res/res_agi.c<br>@@ -4721,4 +4721,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_speech",<br> );<br>diff --git a/res/res_ari.c b/res/res_ari.c<br>index 5145499..362f5d5 100644<br>--- a/res/res_ari.c<br>+++ b/res/res_ari.c<br>@@ -1195,5 +1195,6 @@<br> .unload = unload_module,<br> .reload = reload_module,<br> .nonoptreq = "res_http_websocket",<br>+ .requires = "res_stasis",<br> .load_pri = AST_MODPRI_APP_DEPEND,<br> );<br>diff --git a/res/res_ari_applications.c b/res/res_ari_applications.c<br>index cf700c4..323bdb3 100644<br>--- a/res/res_ari_applications.c<br>+++ b/res/res_ari_applications.c<br>@@ -518,5 +518,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_asterisk.c b/res/res_ari_asterisk.c<br>index eb0617b..9f76f93 100644<br>--- a/res/res_ari_asterisk.c<br>+++ b/res/res_ari_asterisk.c<br>@@ -1239,5 +1239,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c<br>index 35fd3bd..34b9d89 100644<br>--- a/res/res_ari_bridges.c<br>+++ b/res/res_ari_bridges.c<br>@@ -1579,5 +1579,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_channels.c b/res/res_ari_channels.c<br>index f6befcc..7862c10 100644<br>--- a/res/res_ari_channels.c<br>+++ b/res/res_ari_channels.c<br>@@ -2869,5 +2869,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_device_states.c b/res/res_ari_device_states.c<br>index f393935..ec8890b 100644<br>--- a/res/res_ari_device_states.c<br>+++ b/res/res_ari_device_states.c<br>@@ -349,5 +349,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_endpoints.c b/res/res_ari_endpoints.c<br>index d1242c0..07197ca 100644<br>--- a/res/res_ari_endpoints.c<br>+++ b/res/res_ari_endpoints.c<br>@@ -473,5 +473,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_events.c b/res/res_ari_events.c<br>index f916d0e..f750a54 100644<br>--- a/res/res_ari_events.c<br>+++ b/res/res_ari_events.c<br>@@ -473,5 +473,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_mailboxes.c b/res/res_ari_mailboxes.c<br>index 1f6d2cc..6469f93 100644<br>--- a/res/res_ari_mailboxes.c<br>+++ b/res/res_ari_mailboxes.c<br>@@ -355,5 +355,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_playbacks.c b/res/res_ari_playbacks.c<br>index 40099cf..0148a74 100644<br>--- a/res/res_ari_playbacks.c<br>+++ b/res/res_ari_playbacks.c<br>@@ -307,5 +307,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_recordings.c b/res/res_ari_recordings.c<br>index fe3d343..531ff65 100644<br>--- a/res/res_ari_recordings.c<br>+++ b/res/res_ari_recordings.c<br>@@ -891,5 +891,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_ari_sounds.c b/res/res_ari_sounds.c<br>index 8d5928a..5c27ebd 100644<br>--- a/res/res_ari_sounds.c<br>+++ b/res/res_ari_sounds.c<br>@@ -237,5 +237,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br>diff --git a/res/res_fax_spandsp.c b/res/res_fax_spandsp.c<br>index 540a902..93c699b 100644<br>--- a/res/res_fax_spandsp.c<br>+++ b/res/res_fax_spandsp.c<br>@@ -1266,4 +1266,5 @@<br> .support_level = AST_MODULE_SUPPORT_EXTENDED,<br> .load = load_module,<br> .unload = unload_module,<br>+ .requires = "res_fax",<br> );<br>diff --git a/res/res_hep_rtcp.c b/res/res_hep_rtcp.c<br>index 31b9c48..380c7de 100644<br>--- a/res/res_hep_rtcp.c<br>+++ b/res/res_hep_rtcp.c<br>@@ -185,4 +185,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_DEFAULT,<br>+ .requires = "res_hep",<br> );<br>diff --git a/res/res_mwi_external_ami.c b/res/res_mwi_external_ami.c<br>index 516969b..5516475 100644<br>--- a/res/res_mwi_external_ami.c<br>+++ b/res/res_mwi_external_ami.c<br>@@ -370,5 +370,7 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>+ .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,<br>+ .requires = "res_mwi_external",<br> );<br> <br>diff --git a/res/res_pjsip.c b/res/res_pjsip.c<br>index 7499ded..8e89820 100644<br>--- a/res/res_pjsip.c<br>+++ b/res/res_pjsip.c<br>@@ -4960,4 +4960,5 @@<br> .unload = unload_module,<br> .reload = reload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,<br>+ .requires = "res_pjproject",<br> );<br>diff --git a/res/res_pjsip_acl.c b/res/res_pjsip_acl.c<br>index 5c10e57..9269864 100644<br>--- a/res/res_pjsip_acl.c<br>+++ b/res/res_pjsip_acl.c<br>@@ -321,4 +321,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_authenticator_digest.c b/res/res_pjsip_authenticator_digest.c<br>index ef57e37..b6f2b74 100644<br>--- a/res/res_pjsip_authenticator_digest.c<br>+++ b/res/res_pjsip_authenticator_digest.c<br>@@ -554,4 +554,5 @@<br> .unload = unload_module,<br> .reload = reload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 5,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_caller_id.c b/res/res_pjsip_caller_id.c<br>index 64191a7..1673147 100644<br>--- a/res/res_pjsip_caller_id.c<br>+++ b/res/res_pjsip_caller_id.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -764,4 +763,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_config_wizard.c b/res/res_pjsip_config_wizard.c<br>index 1526dc2..f85ff5b 100644<br>--- a/res/res_pjsip_config_wizard.c<br>+++ b/res/res_pjsip_config_wizard.c<br>@@ -1336,4 +1336,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_REALTIME_DRIVER,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_dialog_info_body_generator.c b/res/res_pjsip_dialog_info_body_generator.c<br>index 7c386e3..866ea9d 100644<br>--- a/res/res_pjsip_dialog_info_body_generator.c<br>+++ b/res/res_pjsip_dialog_info_body_generator.c<br>@@ -20,7 +20,6 @@<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br> <depend>res_pjsip_pubsub</depend><br>- <depend>res_pjsip_exten_state</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -219,4 +218,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_diversion.c b/res/res_pjsip_diversion.c<br>index efb5489..84c42dc 100644<br>--- a/res/res_pjsip_diversion.c<br>+++ b/res/res_pjsip_diversion.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -429,4 +428,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_dlg_options.c b/res/res_pjsip_dlg_options.c<br>index e2ed29a..ac230af 100644<br>--- a/res/res_pjsip_dlg_options.c<br>+++ b/res/res_pjsip_dlg_options.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -102,4 +101,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_dtmf_info.c b/res/res_pjsip_dtmf_info.c<br>index e534f3e..68df617 100644<br>--- a/res/res_pjsip_dtmf_info.c<br>+++ b/res/res_pjsip_dtmf_info.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -178,4 +177,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_empty_info.c b/res/res_pjsip_empty_info.c<br>index 774f9de..c67835c 100644<br>--- a/res/res_pjsip_empty_info.c<br>+++ b/res/res_pjsip_empty_info.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -84,4 +83,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_endpoint_identifier_anonymous.c b/res/res_pjsip_endpoint_identifier_anonymous.c<br>index a529466..207d2cf 100644<br>--- a/res/res_pjsip_endpoint_identifier_anonymous.c<br>+++ b/res/res_pjsip_endpoint_identifier_anonymous.c<br>@@ -129,4 +129,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_DEFAULT,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c<br>index 8b92cef..2b59663 100644<br>--- a/res/res_pjsip_endpoint_identifier_ip.c<br>+++ b/res/res_pjsip_endpoint_identifier_ip.c<br>@@ -728,4 +728,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c<br>index 369cb62..7f22a7f 100644<br>--- a/res/res_pjsip_endpoint_identifier_user.c<br>+++ b/res/res_pjsip_endpoint_identifier_user.c<br>@@ -210,4 +210,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_exten_state.c b/res/res_pjsip_exten_state.c<br>index 95a4082..14f086d 100644<br>--- a/res/res_pjsip_exten_state.c<br>+++ b/res/res_pjsip_exten_state.c<br>@@ -1012,4 +1012,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,<br>+ .requires = "res_pjsip,res_pjsip_pubsub,res_pjsip_outbound_publish",<br> );<br>diff --git a/res/res_pjsip_header_funcs.c b/res/res_pjsip_header_funcs.c<br>index 648f1c8..06fba06 100644<br>--- a/res/res_pjsip_header_funcs.c<br>+++ b/res/res_pjsip_header_funcs.c<br>@@ -629,4 +629,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/res/res_pjsip_history.c b/res/res_pjsip_history.c<br>index 4e7dbd0..91eb559 100644<br>--- a/res/res_pjsip_history.c<br>+++ b/res/res_pjsip_history.c<br>@@ -1387,4 +1387,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_logger.c b/res/res_pjsip_logger.c<br>index d29a6e2..460b6a3 100644<br>--- a/res/res_pjsip_logger.c<br>+++ b/res/res_pjsip_logger.c<br>@@ -262,4 +262,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c<br>index b6e7a64..3739bcf 100644<br>--- a/res/res_pjsip_messaging.c<br>+++ b/res/res_pjsip_messaging.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -850,4 +849,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_mwi.c b/res/res_pjsip_mwi.c<br>index 5423038..92dc7dc 100644<br>--- a/res/res_pjsip_mwi.c<br>+++ b/res/res_pjsip_mwi.c<br>@@ -1397,4 +1397,5 @@<br> .unload = unload_module,<br> .reload = reload,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_mwi_body_generator.c b/res/res_pjsip_mwi_body_generator.c<br>index e827910..65ac600 100644<br>--- a/res/res_pjsip_mwi_body_generator.c<br>+++ b/res/res_pjsip_mwi_body_generator.c<br>@@ -116,4 +116,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_nat.c b/res/res_pjsip_nat.c<br>index e1d56e6..4231a1e 100644<br>--- a/res/res_pjsip_nat.c<br>+++ b/res/res_pjsip_nat.c<br>@@ -378,4 +378,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_notify.c b/res/res_pjsip_notify.c<br>index 8de88c7..5b18148 100644<br>--- a/res/res_pjsip_notify.c<br>+++ b/res/res_pjsip_notify.c<br>@@ -1032,4 +1032,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_one_touch_record_info.c b/res/res_pjsip_one_touch_record_info.c<br>index ec5f9be..ef59fca 100644<br>--- a/res/res_pjsip_one_touch_record_info.c<br>+++ b/res/res_pjsip_one_touch_record_info.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -129,4 +128,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_outbound_authenticator_digest.c b/res/res_pjsip_outbound_authenticator_digest.c<br>index 7e2d711..54bba08 100644<br>--- a/res/res_pjsip_outbound_authenticator_digest.c<br>+++ b/res/res_pjsip_outbound_authenticator_digest.c<br>@@ -224,4 +224,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c<br>index 0fac8ad..1f4f9ab 100644<br>--- a/res/res_pjsip_outbound_publish.c<br>+++ b/res/res_pjsip_outbound_publish.c<br>@@ -1700,4 +1700,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjproject,res_pjsip",<br> );<br>diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c<br>index 4697e5c..01d35d3 100644<br>--- a/res/res_pjsip_outbound_registration.c<br>+++ b/res/res_pjsip_outbound_registration.c<br>@@ -2288,4 +2288,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_path.c b/res/res_pjsip_path.c<br>index e170a75..b245f15 100644<br>--- a/res/res_pjsip_path.c<br>+++ b/res/res_pjsip_path.c<br>@@ -264,4 +264,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_phoneprov_provider.c b/res/res_pjsip_phoneprov_provider.c<br>index eef3a08..642d71d 100644<br>--- a/res/res_pjsip_phoneprov_provider.c<br>+++ b/res/res_pjsip_phoneprov_provider.c<br>@@ -417,4 +417,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip,res_phoneprov",<br> );<br>diff --git a/res/res_pjsip_pidf_body_generator.c b/res/res_pjsip_pidf_body_generator.c<br>index 29c9e6b..6426dfa 100644<br>--- a/res/res_pjsip_pidf_body_generator.c<br>+++ b/res/res_pjsip_pidf_body_generator.c<br>@@ -135,4 +135,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_pidf_digium_body_supplement.c b/res/res_pjsip_pidf_digium_body_supplement.c<br>index 93e4982..f855e21 100644<br>--- a/res/res_pjsip_pidf_digium_body_supplement.c<br>+++ b/res/res_pjsip_pidf_digium_body_supplement.c<br>@@ -114,4 +114,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_pidf_eyebeam_body_supplement.c b/res/res_pjsip_pidf_eyebeam_body_supplement.c<br>index 4047084..6629aa3 100644<br>--- a/res/res_pjsip_pidf_eyebeam_body_supplement.c<br>+++ b/res/res_pjsip_pidf_eyebeam_body_supplement.c<br>@@ -111,4 +111,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_publish_asterisk.c b/res/res_pjsip_publish_asterisk.c<br>index fa5e4ce..5bb5cee 100644<br>--- a/res/res_pjsip_publish_asterisk.c<br>+++ b/res/res_pjsip_publish_asterisk.c<br>@@ -932,4 +932,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND + 5,<br>+ .requires = "res_pjsip,res_pjsip_outbound_publish,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_pjsip_pubsub.c b/res/res_pjsip_pubsub.c<br>index 62b1879..773b1ef 100644<br>--- a/res/res_pjsip_pubsub.c<br>+++ b/res/res_pjsip_pubsub.c<br>@@ -5491,4 +5491,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c<br>index 62f8b67..f823385 100644<br>--- a/res/res_pjsip_refer.c<br>+++ b/res/res_pjsip_refer.c<br>@@ -1229,4 +1229,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c<br>index 3290601..6551917 100644<br>--- a/res/res_pjsip_registrar.c<br>+++ b/res/res_pjsip_registrar.c<br>@@ -1116,4 +1116,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 3,<br>+ .requires = "res_pjproject,res_pjsip",<br> );<br>diff --git a/res/res_pjsip_registrar_expire.c b/res/res_pjsip_registrar_expire.c<br>index fe4a60d..85e3fb8 100644<br>--- a/res/res_pjsip_registrar_expire.c<br>+++ b/res/res_pjsip_registrar_expire.c<br>@@ -150,4 +150,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_rfc3326.c b/res/res_pjsip_rfc3326.c<br>index d49a170..8b8035e 100644<br>--- a/res/res_pjsip_rfc3326.c<br>+++ b/res/res_pjsip_rfc3326.c<br>@@ -19,7 +19,6 @@<br> /*** MODULEINFO<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br>- <depend>res_pjsip_session</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -156,4 +155,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c<br>index a877582..7bff88f 100644<br>--- a/res/res_pjsip_sdp_rtp.c<br>+++ b/res/res_pjsip_sdp_rtp.c<br>@@ -1969,4 +1969,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DRIVER,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/res/res_pjsip_send_to_voicemail.c b/res/res_pjsip_send_to_voicemail.c<br>index 1cd28ce..06c3edc 100644<br>--- a/res/res_pjsip_send_to_voicemail.c<br>+++ b/res/res_pjsip_send_to_voicemail.c<br>@@ -236,4 +236,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c<br>index 4724d46..455e889 100644<br>--- a/res/res_pjsip_session.c<br>+++ b/res/res_pjsip_session.c<br>@@ -4152,4 +4152,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_sips_contact.c b/res/res_pjsip_sips_contact.c<br>index 7579be6..41b26df 100644<br>--- a/res/res_pjsip_sips_contact.c<br>+++ b/res/res_pjsip_sips_contact.c<br>@@ -104,4 +104,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c<br>index 48cbab3..203f043 100644<br>--- a/res/res_pjsip_t38.c<br>+++ b/res/res_pjsip_t38.c<br>@@ -1044,4 +1044,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DRIVER,<br>+ .requires = "res_pjsip,res_pjsip_session",<br> );<br>diff --git a/res/res_pjsip_transport_management.c b/res/res_pjsip_transport_management.c<br>index eb92eb7..acffb86 100644<br>--- a/res/res_pjsip_transport_management.c<br>+++ b/res/res_pjsip_transport_management.c<br>@@ -397,4 +397,5 @@<br> .reload = reload_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND - 4,<br>+ .requires = "res_pjsip",<br> );<br>diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c<br>index 22ec195..7c8ec08 100644<br>--- a/res/res_pjsip_transport_websocket.c<br>+++ b/res/res_pjsip_transport_websocket.c<br>@@ -520,4 +520,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_APP_DEPEND,<br>+ .requires = "res_pjsip,res_http_websocket",<br> );<br>diff --git a/res/res_pjsip_xpidf_body_generator.c b/res/res_pjsip_xpidf_body_generator.c<br>index 41f6224..f7c84db 100644<br>--- a/res/res_pjsip_xpidf_body_generator.c<br>+++ b/res/res_pjsip_xpidf_body_generator.c<br>@@ -20,7 +20,6 @@<br> <depend>pjproject</depend><br> <depend>res_pjsip</depend><br> <depend>res_pjsip_pubsub</depend><br>- <depend>res_pjsip_exten_state</depend><br> <support_level>core</support_level><br> ***/<br> <br>@@ -177,4 +176,5 @@<br> .load = load_module,<br> .unload = unload_module,<br> .load_pri = AST_MODPRI_CHANNEL_DEPEND,<br>+ .requires = "res_pjsip,res_pjsip_pubsub",<br> );<br>diff --git a/res/res_stasis_answer.c b/res/res_stasis_answer.c<br>index 407a631..6ec50c8 100644<br>--- a/res/res_stasis_answer.c<br>+++ b/res/res_stasis_answer.c<br>@@ -73,5 +73,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis"<br>+ .requires = "res_stasis",<br> );<br>diff --git a/res/res_stasis_device_state.c b/res/res_stasis_device_state.c<br>index 276a98b..1c209e8 100644<br>--- a/res/res_stasis_device_state.c<br>+++ b/res/res_stasis_device_state.c<br>@@ -482,5 +482,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis"<br>+ .requires = "res_stasis",<br> );<br>diff --git a/res/res_stasis_mailbox.c b/res/res_stasis_mailbox.c<br>index 4522adc..eb618cb 100644<br>--- a/res/res_stasis_mailbox.c<br>+++ b/res/res_stasis_mailbox.c<br>@@ -160,5 +160,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis,res_mwi_external"<br>+ .requires = "res_stasis,res_mwi_external"<br> );<br>diff --git a/res/res_stasis_playback.c b/res/res_stasis_playback.c<br>index c6f2136..aeb6d0e 100644<br>--- a/res/res_stasis_playback.c<br>+++ b/res/res_stasis_playback.c<br>@@ -755,5 +755,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis,res_stasis_recording"<br>+ .requires = "res_stasis,res_stasis_recording"<br> );<br>diff --git a/res/res_stasis_recording.c b/res/res_stasis_recording.c<br>index 56984cb..17213aa 100644<br>--- a/res/res_stasis_recording.c<br>+++ b/res/res_stasis_recording.c<br>@@ -655,6 +655,6 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis",<br>+ .requires = "res_stasis",<br> .load_pri = AST_MODPRI_APP_DEPEND<br> );<br>diff --git a/res/res_stasis_snoop.c b/res/res_stasis_snoop.c<br>index f797a9b..b234de1 100644<br>--- a/res/res_stasis_snoop.c<br>+++ b/res/res_stasis_snoop.c<br>@@ -445,5 +445,5 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis"<br>+ .requires = "res_stasis",<br> );<br>diff --git a/rest-api-templates/res_ari_resource.c.mustache b/rest-api-templates/res_ari_resource.c.mustache<br>index d4ccda9..c1f680f 100644<br>--- a/rest-api-templates/res_ari_resource.c.mustache<br>+++ b/rest-api-templates/res_ari_resource.c.mustache<br>@@ -324,6 +324,6 @@<br> .support_level = AST_MODULE_SUPPORT_CORE,<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari,res_stasis",<br>+ .requires = "res_ari,res_ari_model,res_stasis",<br> );<br> {{/api_declaration}}<br>diff --git a/tests/test_ari.c b/tests/test_ari.c<br>index bce5f95..a5db228 100644<br>--- a/tests/test_ari.c<br>+++ b/tests/test_ari.c<br>@@ -573,5 +573,5 @@<br> AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ARI testing",<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_ari",<br>+ .requires = "res_ari",<br> );<br>diff --git a/tests/test_ari_model.c b/tests/test_ari_model.c<br>index caf4118..e5a96cd 100644<br>--- a/tests/test_ari_model.c<br>+++ b/tests/test_ari_model.c<br>@@ -452,4 +452,9 @@<br> return AST_MODULE_LOAD_SUCCESS;<br> }<br> <br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Skeleton (sample) Test");<br>+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Skeleton (sample) Test",<br>+ .support_level = AST_MODULE_SUPPORT_CORE,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .requires = "res_ari_model",<br>+);<br>diff --git a/tests/test_res_pjsip_scheduler.c b/tests/test_res_pjsip_scheduler.c<br>index da51d43..47a7034 100644<br>--- a/tests/test_res_pjsip_scheduler.c<br>+++ b/tests/test_res_pjsip_scheduler.c<br>@@ -396,4 +396,9 @@<br> return 0;<br> }<br> <br>-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "res_pjsip scheduler test module");<br>+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "res_pjsip scheduler test module",<br>+ .support_level = AST_MODULE_SUPPORT_CORE,<br>+ .load = load_module,<br>+ .unload = unload_module,<br>+ .requires = "res_pjsip",<br>+);<br>diff --git a/tests/test_res_stasis.c b/tests/test_res_stasis.c<br>index cb79fa6..077cc4c 100644<br>--- a/tests/test_res_stasis.c<br>+++ b/tests/test_res_stasis.c<br>@@ -195,5 +195,5 @@<br> AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Stasis Core testing",<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis",<br>+ .requires = "res_stasis",<br> );<br>diff --git a/tests/test_stasis_endpoints.c b/tests/test_stasis_endpoints.c<br>index 134738f..42c7532 100644<br>--- a/tests/test_stasis_endpoints.c<br>+++ b/tests/test_stasis_endpoints.c<br>@@ -306,5 +306,5 @@<br> AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Endpoint stasis-related testing",<br> .load = load_module,<br> .unload = unload_module,<br>- .nonoptreq = "res_stasis_test",<br>+ .requires = "res_stasis_test",<br> );<br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/6987">change 6987</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/6987"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I979ffb7caecc696ce0afa939193dfa76b19248e7 </div>
<div style="display:none"> Gerrit-Change-Number: 6987 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>