📄 loader.c
字号:
/* * Asterisk -- An open source telephony toolkit. * * Copyright (C) 1999 - 2005, Digium, Inc. * * Mark Spencer <markster@digium.com> * * See http://www.asterisk.org for more information about * the Asterisk project. Please do not directly contact * any of the maintainers of this project for assistance; * the project provides a web site, mailing lists and IRC * channels for your use. * * This program is free software, distributed under the terms of * the GNU General Public License Version 2. See the LICENSE file * at the top of the source tree. *//*! \file * * \brief Module Loader * */#include <stdio.h>#include <dirent.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include "asterisk.h"ASTERISK_FILE_VERSION(__FILE__, "$Revision: 8162 $")#include "asterisk/module.h"#include "asterisk/options.h"#include "asterisk/config.h"#include "asterisk/logger.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/lock.h"#ifdef DLFCNCOMPAT#include "asterisk/dlfcn-compat.h"#else#include <dlfcn.h>#endif#include "asterisk/md5.h"#ifndef RTLD_NOW#define RTLD_NOW 0#endifAST_MUTEX_DEFINE_STATIC(modlock);AST_MUTEX_DEFINE_STATIC(reloadlock);static struct module *module_list=NULL;static int modlistver = 0;static unsigned char expected_key[] ={ 0x8e, 0x93, 0x22, 0x83, 0xf5, 0xc3, 0xc0, 0x75, 0xff, 0x8b, 0xa9, 0xbe, 0x7c, 0x43, 0x74, 0x63 };struct module { int (*load_module)(void); int (*unload_module)(void); int (*usecount)(void); char *(*description)(void); char *(*key)(void); int (*reload)(void); void *lib; char resource[256]; struct module *next;};static struct loadupdate { int (*updater)(void); struct loadupdate *next;} *updaters = NULL;static int printdigest(unsigned char *d){ int x; char buf[256]; char buf2[16]; snprintf(buf, sizeof(buf), "Unexpected signature:"); for (x=0; x<16; x++) { snprintf(buf2, sizeof(buf2), " %02x", *(d++)); strcat(buf, buf2); } strcat(buf, "\n"); ast_log(LOG_DEBUG, "%s", buf); return 0;}static int key_matches(unsigned char *key1, unsigned char *key2){ int match = 1; int x; for (x=0; x<16; x++) { match &= (key1[x] == key2[x]); } return match;}static int verify_key(unsigned char *key){ struct MD5Context c; unsigned char digest[16]; MD5Init(&c); MD5Update(&c, key, strlen((char *)key)); MD5Final(digest, &c); if (key_matches(expected_key, digest)) return 0; printdigest(digest); return -1;}int ast_unload_resource(const char *resource_name, int force){ struct module *m, *ml = NULL; int res = -1; if (ast_mutex_lock(&modlock)) ast_log(LOG_WARNING, "Failed to lock\n"); m = module_list; while(m) { if (!strcasecmp(m->resource, resource_name)) { if ((res = m->usecount()) > 0) { if (force) ast_log(LOG_WARNING, "Warning: Forcing removal of module %s with use count %d\n", resource_name, res); else { ast_log(LOG_WARNING, "Soft unload failed, '%s' has use count %d\n", resource_name, res); ast_mutex_unlock(&modlock); return -1; } } res = m->unload_module(); if (res) { ast_log(LOG_WARNING, "Firm unload failed for %s\n", resource_name); if (force <= AST_FORCE_FIRM) { ast_mutex_unlock(&modlock); return -1; } else ast_log(LOG_WARNING, "** Dangerous **: Unloading resource anyway, at user request\n"); } if (ml) ml->next = m->next; else module_list = m->next; dlclose(m->lib); free(m); break; } ml = m; m = m->next; } modlistver = rand(); ast_mutex_unlock(&modlock); ast_update_use_count(); return res;}char *ast_module_helper(char *line, char *word, int pos, int state, int rpos, int needsreload){ struct module *m; int which=0; char *ret; if (pos != rpos) return NULL; ast_mutex_lock(&modlock); m = module_list; while(m) { if (!strncasecmp(word, m->resource, strlen(word)) && (m->reload || !needsreload)) { if (++which > state) break; } m = m->next; } if (m) { ret = strdup(m->resource); } else { ret = NULL; if (!strncasecmp(word, "extconfig", strlen(word))) { if (++which > state) ret = strdup("extconfig"); } else if (!strncasecmp(word, "manager", strlen(word))) { if (++which > state) ret = strdup("manager"); } else if (!strncasecmp(word, "enum", strlen(word))) { if (++which > state) ret = strdup("enum"); } else if (!strncasecmp(word, "rtp", strlen(word))) { if (++which > state) ret = strdup("rtp"); } } ast_mutex_unlock(&modlock); return ret;}int ast_module_reload(const char *name){ struct module *m; int reloaded = 0; int oldversion; int (*reload)(void); /* We'll do the logger and manager the favor of calling its reload here first */ if (ast_mutex_trylock(&reloadlock)) { ast_verbose("The previous reload command didn't finish yet\n"); return -1; } if (!name || !strcasecmp(name, "extconfig")) { read_config_maps(); reloaded = 2; } if (!name || !strcasecmp(name, "manager")) { reload_manager(); reloaded = 2; } if (!name || !strcasecmp(name, "cdr")) { ast_cdr_engine_reload(); reloaded = 2; } if (!name || !strcasecmp(name, "enum")) { ast_enum_reload(); reloaded = 2; } if (!name || !strcasecmp(name, "rtp")) { ast_rtp_reload(); reloaded = 2; } if (!name || !strcasecmp(name, "dnsmgr")) { dnsmgr_reload(); reloaded = 2; } //***************************************************** //**** add by wangqiang***************** if(!name||!strcasecmp(name,"dbfile")){ dbfile_reload(); reload=2; } time(&ast_lastreloadtime); ast_mutex_lock(&modlock); oldversion = modlistver; m = module_list; while(m) { if (!name || !strcasecmp(name, m->resource)) { if (reloaded < 1) reloaded = 1; reload = m->reload; ast_mutex_unlock(&modlock); if (reload) { reloaded = 2; if (option_verbose > 2) ast_verbose(VERBOSE_PREFIX_3 "Reloading module '%s' (%s)\n", m->resource, m->description()); reload(); } ast_mutex_lock(&modlock); if (oldversion != modlistver) break; } m = m->next; } ast_mutex_unlock(&modlock); ast_mutex_unlock(&reloadlock); return reloaded;}static int __load_resource(const char *resource_name, const struct ast_config *cfg){ static char fn[256]; int errors=0; int res; struct module *m; int flags=RTLD_NOW;#ifdef RTLD_GLOBAL char *val;#endif unsigned char *key; char tmp[80]; if (strncasecmp(resource_name, "res_", 4)) {#ifdef RTLD_GLOBAL if (cfg) { if ((val = ast_variable_retrieve(cfg, "global", resource_name)) && ast_true(val)) flags |= RTLD_GLOBAL; }#endif } else { /* Resource modules are always loaded global and lazy */#ifdef RTLD_GLOBAL flags = (RTLD_GLOBAL | RTLD_LAZY);#else flags = RTLD_LAZY;#endif } if (ast_mutex_lock(&modlock)) ast_log(LOG_WARNING, "Failed to lock\n"); m = module_list; while(m) { if (!strcasecmp(m->resource, resource_name)) { ast_log(LOG_WARNING, "Module '%s' already exists\n", resource_name); ast_mutex_unlock(&modlock); return -1; } m = m->next; } m = malloc(sizeof(struct module)); if (!m) { ast_log(LOG_WARNING, "Out of memory\n"); ast_mutex_unlock(&modlock); return -1; } strncpy(m->resource, resource_name, sizeof(m->resource)-1); if (resource_name[0] == '/') { strncpy(fn, resource_name, sizeof(fn)-1); } else { snprintf(fn, sizeof(fn), "%s/%s", (char *)ast_config_AST_MODULE_DIR, resource_name);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -