static int _module_load(module_handler_t* hMod) { int idx; // Check if module loaded idx = module_find(hMod->name); if ( idx>=0 ) return idx; // Find empty slot for ( idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++ ); if ( idx == MAX_NUM_LOADED_MODULES ) { moduleload_error("%d already loaded",MAX_NUM_LOADED_MODULES); return -1; } if (module_preload(hMod->name, hMod->version) != 0) { // Module is valid. Finalize binding modules[idx].hdr = flat_buf; // store runtime params flat_module_name_make(modules[idx].modulename, module_filename); modules[idx].hMod = hMod; int bind_err = bind_module( hMod, flat_buf->_module_info->lib ); if ( flat_buf->_module_info->lib->loader ) { uint32_t x = flat_buf->_module_info->lib->loader(); bind_err = bind_err || x; } if ( bind_err ) { module_unload(module_filename); moduleload_error("chdk mismatch",0); return -1; } return idx; } return -1; }
// Load a module referenced by a 'module_handler_t' structure // Returns index into modules array if successful (or module already loaded) // otherwise returns -1 static int _module_load(module_handler_t* hMod) { int idx; // Get full path to module file, and hash of path char path[60]; unsigned int hash = get_module_path(path, hMod->name); // Check if module already loaded idx = module_find(hash); if (idx >= 0) return idx; // Reset lib (should not be needed, loader should only be called from 'default' lib) *hMod->lib = hMod->default_lib; // Simple lock to prevent multiple attempts to load modules simultaneously (in different tasks) // Not perfect; but should be sufficient static int isLoading = 0; while (isLoading != 0) msleep(10); isLoading = 1; // Find empty slot for (idx=0; idx<MAX_NUM_LOADED_MODULES && modules[idx].hdr; idx++) ; // If no slot found return error if (idx == MAX_NUM_LOADED_MODULES) { moduleload_error(hMod->name, "too many modules loaded"); idx = -1; } else { // Load and relocate module (returns 0 if error) flat_hdr* mod = module_preload(path, hMod->name, hMod->version); if (mod != 0) { // Module is valid. Finalize binding modules[idx].hdr = mod; modules[idx].hName = hash; modules[idx].hMod = hMod; int bind_err = bind_module(hMod, mod->_module_info->lib); // Call module loader if required if (!bind_err && mod->_module_info->lib->loader) { bind_err = mod->_module_info->lib->loader(); } // If any errors, unload module and display error message if (bind_err) { module_unload_idx(idx); moduleload_error(hMod->name, "loader error"); idx = -1; } } else { // module did not load, return invalid index idx = -1; } } // Release lock isLoading = 0; return idx; }
int main(int argc, char *argv[]) { bool prefer_ipv6 = false, run_daemon = false, test = false; const char *ua_eprm = NULL; const char *exec = NULL; const char *modv[16]; size_t modc = 0; int err; (void)re_fprintf(stderr, "baresip v%s" " Copyright (C) 2010 - 2015" " Alfred E. Heggestad et al.\n", BARESIP_VERSION); (void)sys_coredump_set(true); err = libre_init(); if (err) goto out; #ifdef HAVE_GETOPT for (;;) { const int c = getopt(argc, argv, "6de:f:p:hu:vtm:"); if (0 > c) break; switch (c) { case '?': case 'h': usage(); return -2; #if HAVE_INET6 case '6': prefer_ipv6 = true; break; #endif case 'd': run_daemon = true; break; case 'e': exec = optarg; break; case 'f': conf_path_set(optarg); break; case 'm': if (modc >= ARRAY_SIZE(modv)) { warning("max %zu modules\n", ARRAY_SIZE(modv)); err = EINVAL; goto out; } modv[modc++] = optarg; break; case 'p': play_set_path(optarg); break; case 't': test = true; break; case 'u': ua_eprm = optarg; break; case 'v': log_enable_debug(true); break; default: break; } } #else (void)argc; (void)argv; #endif err = conf_configure(); if (err) { warning("main: configure failed: %m\n", err); goto out; } /* NOTE: must be done after all arguments are processed */ if (modc) { size_t i; info("pre-loading modules: %zu\n", modc); for (i=0; i<modc; i++) { err = module_preload(modv[i]); if (err) { re_fprintf(stderr, "could not pre-load module" " '%s' (%m)\n", modv[i], err); } } } /* Initialise User Agents */ err = ua_init("baresip v" BARESIP_VERSION " (" ARCH "/" OS ")", true, true, true, prefer_ipv6); if (err) goto out; if (ua_eprm) { err = uag_set_extra_params(ua_eprm); if (err) goto out; } if (test) goto out; /* Load modules */ err = conf_modules(); if (err) goto out; if (run_daemon) { err = sys_daemon(); if (err) goto out; log_enable_stderr(false); } info("baresip is ready.\n"); if (exec) ui_input_str(exec); /* Main loop */ err = re_main(signal_handler); out: if (err) ua_stop_all(true); ua_close(); conf_close(); libre_close(); /* Check for memory leaks */ tmr_debug(); mem_debug(); return err; }
int main(int argc, char *argv[]) { bool prefer_ipv6 = false, run_daemon = false, test = false; const char *exec = NULL; int err; (void)re_fprintf(stderr, "baresip v%s" " Copyright (C) 2010 - 2015" " Alfred E. Heggestad et al.\n", BARESIP_VERSION); (void)sys_coredump_set(true); err = libre_init(); if (err) goto out; #ifdef HAVE_GETOPT for (;;) { const int c = getopt(argc, argv, "6de:f:p:hvtm:"); if (0 > c) break; switch (c) { case '?': case 'h': usage(); return -2; #if HAVE_INET6 case '6': prefer_ipv6 = true; break; #endif case 'd': run_daemon = true; break; case 'e': exec = optarg; break; case 'f': conf_path_set(optarg); break; case 'm': err = module_preload(optarg); if (err) { re_fprintf(stderr, "could not pre-load module" " '%s' (%m)\n", optarg, err); } break; case 'p': play_set_path(optarg); break; case 't': test = true; break; case 'v': log_enable_debug(true); break; default: break; } } #else (void)argc; (void)argv; #endif err = conf_configure(); if (err) { warning("main: configure failed: %m\n", err); goto out; } /* Initialise User Agents */ err = ua_init("baresip v" BARESIP_VERSION " (" ARCH "/" OS ")", true, true, true, prefer_ipv6); if (err) goto out; if (test) goto out; /* Load modules */ err = conf_modules(); if (err) goto out; if (run_daemon) { err = sys_daemon(); if (err) goto out; log_enable_stderr(false); } info("baresip is ready.\n"); if (exec) ui_input_str(exec); /* Main loop */ err = re_main(signal_handler); out: if (err) ua_stop_all(true); ua_close(); mod_close(); libre_close(); /* Check for memory leaks */ tmr_debug(); mem_debug(); return err; }