diff options
Diffstat (limited to 'src/common/HPM.c')
-rw-r--r-- | src/common/HPM.c | 1144 |
1 files changed, 615 insertions, 529 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c index 6e73d1b2a..7d9a0b104 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -3,28 +3,30 @@ #define HERCULES_CORE -#include "../config/core.h" // CONSOLE_INPUT +#include "config/core.h" // CONSOLE_INPUT #include "HPM.h" +#include "common/cbasetypes.h" +#include "common/conf.h" +#include "common/console.h" +#include "common/core.h" +#include "common/db.h" +#include "common/memmgr.h" +#include "common/mapindex.h" +#include "common/mmo.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/sql.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" +#include "common/nullpo.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "../common/cbasetypes.h" -#include "../common/conf.h" -#include "../common/console.h" -#include "../common/core.h" -#include "../common/malloc.h" -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/sql.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" -#include "../common/nullpo.h" - #ifndef WIN32 # include <unistd.h> #endif @@ -32,6 +34,7 @@ struct malloc_interface iMalloc_HPM; struct malloc_interface *HPMiMalloc; struct HPM_interface HPM_s; +struct HPM_interface *HPM; /** * (char*) data name -> (unsigned int) HPMDataCheck[] index @@ -40,28 +43,52 @@ DBMap *datacheck_db; int datacheck_version; const struct s_HPMDataCheck *datacheck_data; -void hplugin_trigger_event(enum hp_event_types type) { - unsigned int i; - for( i = 0; i < HPM->plugin_count; i++ ) { - if( HPM->plugins[i]->hpi->event[type] != NULL ) - (HPM->plugins[i]->hpi->event[type])(); +/** + * Executes an event on all loaded plugins. + * + * @param type The event type to trigger. + */ +void hplugin_trigger_event(enum hp_event_types type) +{ + int i; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + if (plugin->hpi->event[type] != NULL) + plugin->hpi->event[type](); } } -void hplugin_export_symbol(void *var, char *name) { - RECREATE(HPM->symbols, struct hpm_symbol *, ++HPM->symbol_count); - CREATE(HPM->symbols[HPM->symbol_count - 1] ,struct hpm_symbol, 1); - HPM->symbols[HPM->symbol_count - 1]->name = name; - HPM->symbols[HPM->symbol_count - 1]->ptr = var; +/** + * Exports a symbol to the shared symbols list. + * + * @param value The symbol value. + * @param name The symbol name. + */ +void hplugin_export_symbol(void *value, const char *name) +{ + struct hpm_symbol *symbol = NULL; + CREATE(symbol ,struct hpm_symbol, 1); + symbol->name = name; + symbol->ptr = value; + VECTOR_ENSURE(HPM->symbols, 1, 1); + VECTOR_PUSH(HPM->symbols, symbol); } -void *hplugin_import_symbol(char *name, unsigned int pID) { - unsigned int i; +/** + * Imports a shared symbol. + * + * @param name The symbol name. + * @param pID The requesting plugin ID. + * @return The symbol value. + * @retval NULL if the symbol wasn't found. + */ +void *hplugin_import_symbol(char *name, unsigned int pID) +{ + int i; + ARR_FIND(0, VECTOR_LENGTH(HPM->symbols), i, strcmp(VECTOR_INDEX(HPM->symbols, i)->name, name) == 0); - for( i = 0; i < HPM->symbol_count; i++ ) { - if( strcmp(HPM->symbols[i]->name,name) == 0 ) - return HPM->symbols[i]->ptr; - } + if (i != VECTOR_LENGTH(HPM->symbols)) + return VECTOR_INDEX(HPM->symbols, i)->ptr; ShowError("HPM:get_symbol:%s: '"CL_WHITE"%s"CL_RESET"' not found!\n",HPM->pid2name(pID),name); return NULL; @@ -78,62 +105,328 @@ bool hplugin_iscompatible(char* version) { return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false; } -bool hplugin_exists(const char *filename) { - unsigned int i; - for(i = 0; i < HPM->plugin_count; i++) { - if( strcmpi(HPM->plugins[i]->filename,filename) == 0 ) +/** + * Checks whether a plugin is currently loaded + * + * @param filename The plugin filename. + * @retval true if the plugin exists and is currently loaded. + * @retval false otherwise. + */ +bool hplugin_exists(const char *filename) +{ + int i; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + if (strcmpi(VECTOR_INDEX(HPM->plugins, i)->filename,filename) == 0) return true; } return false; } -struct hplugin *hplugin_create(void) { - RECREATE(HPM->plugins, struct hplugin *, ++HPM->plugin_count); - CREATE(HPM->plugins[HPM->plugin_count - 1], struct hplugin, 1); - HPM->plugins[HPM->plugin_count - 1]->idx = HPM->plugin_count - 1; - HPM->plugins[HPM->plugin_count - 1]->filename = NULL; - return HPM->plugins[HPM->plugin_count - 1]; -} -#define HPM_POP(x) { #x , x } -bool hplugin_populate(struct hplugin *plugin, const char *filename) { - struct { - const char* name; - void *Ref; - } ToLink[] = { - HPM_POP(ShowMessage), - HPM_POP(ShowStatus), - HPM_POP(ShowSQL), - HPM_POP(ShowInfo), - HPM_POP(ShowNotice), - HPM_POP(ShowWarning), - HPM_POP(ShowDebug), - HPM_POP(ShowError), - HPM_POP(ShowFatalError), - }; - int i, length = ARRAYLENGTH(ToLink); - for(i = 0; i < length; i++) { - void **Link; - if (!( Link = plugin_import(plugin->dll, ToLink[i].name,void **))) { - ShowWarning("HPM:plugin_load: failed to retrieve '%s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", ToLink[i].name, filename); - HPM->unload(plugin); +/** + * Initializes the data structure for a new plugin and registers it. + * + * @return A (retained) pointer to the initialized data. + */ +struct hplugin *hplugin_create(void) +{ + struct hplugin *plugin = NULL; + CREATE(plugin, struct hplugin, 1); + plugin->idx = (int)VECTOR_LENGTH(HPM->plugins); + plugin->filename = NULL; + VECTOR_ENSURE(HPM->plugins, 1, 1); + VECTOR_PUSH(HPM->plugins, plugin); + return plugin; +} + +bool hplugins_addpacket(unsigned short cmd, unsigned short length, void (*receive) (int fd), unsigned int point, unsigned int pluginID) +{ + struct HPluginPacket *packet; + int i; + + if (point >= hpPHP_MAX) { + ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length); + return false; + } + + for (i = 0; i < VECTOR_LENGTH(HPM->packets[point]); i++) { + if (VECTOR_INDEX(HPM->packets[point], i).cmd == cmd ) { + ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!", + HPM->pid2name(pluginID), cmd, HPM->pid2name(VECTOR_INDEX(HPM->packets[point], i).pluginID)); return false; } - *Link = ToLink[i].Ref; } + VECTOR_ENSURE(HPM->packets[point], 1, 1); + VECTOR_PUSHZEROED(HPM->packets[point]); + packet = &VECTOR_LAST(HPM->packets[point]); + + packet->pluginID = pluginID; + packet->cmd = cmd; + packet->len = length; + packet->receive = receive; + + return true; +} + +/** + * Validates and if necessary initializes a plugin data store. + * + * @param type[in] The data store type. + * @param storeptr[in,out] A pointer to the store. + * @param initialize Whether the store should be initialized in case it isn't. + * @retval false if the store is an invalid or mismatching type. + * @retval true if the store is a valid type. + * + * @remark + * If \c storeptr is a pointer to a NULL pointer (\c storeptr itself can't + * be NULL), two things may happen, depending on the \c initialize value: + * if false, then \c storeptr isn't changed; if true, then \c storeptr is + * initialized through \c HPM->data_store_create() and ownership is passed + * to the caller. + */ +bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data_store **storeptr, bool initialize) +{ + struct hplugin_data_store *store; + nullpo_retr(false, storeptr); + store = *storeptr; + if (!initialize && store == NULL) + return true; + + switch (type) { + /* core-handled */ + case HPDT_SESSION: + break; + default: + if (HPM->data_store_validate_sub == NULL) { + ShowError("HPM:validateHPData failed, type %d needs sub-handler!\n",type); + return false; + } + if (!HPM->data_store_validate_sub(type, storeptr, initialize)) { + ShowError("HPM:HPM:validateHPData failed, unknown type %d!\n",type); + return false; + } + break; + } + if (initialize && (!store || store->type == HPDT_UNKNOWN)) { + HPM->data_store_create(storeptr, type); + store = *storeptr; + } + if (store->type != type) { + ShowError("HPM:HPM:validateHPData failed, store type mismatch %d != %d.\n",store->type, type); + return false; + } return true; } -#undef HPM_POP + +/** + * Adds an entry to a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param storeptr[in,out] A pointer to the store. The store will be initialized if necessary. + * @param data[in] The data entry to add. + * @param classid[in] The entry class identifier. + * @param autofree[in] Whether the entry should be automatically freed when removed. + */ +void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store **storeptr, void *data, uint32 classid, bool autofree) +{ + struct hplugin_data_store *store; + struct hplugin_data_entry *entry; + int i; + nullpo_retv(storeptr); + + if (!HPM->data_store_validate(type, storeptr, true)) { + /* woo it failed! */ + ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); + return; + } + store = *storeptr; + + /* duplicate check */ + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i != VECTOR_LENGTH(store->entries)) { + ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and classid %u\n", HPM->pid2name(pluginID), pluginID, classid); + return; + } + + /* hplugin_data_entry is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */ + CREATE(entry, struct hplugin_data_entry, 1); + + /* input */ + entry->pluginID = pluginID; + entry->classid = classid; + entry->flag.free = autofree ? 1 : 0; + entry->data = data; + + VECTOR_ENSURE(store->entries, 1, 1); + VECTOR_PUSH(store->entries, entry); +} + +/** + * Retrieves an entry from a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param store[in] The store. + * @param classid[in] The entry class identifier. + * + * @return The retrieved entry, or NULL. + */ +void *hplugins_getFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid) +{ + int i; + + if (!HPM->data_store_validate(type, &store, false)) { + /* woo it failed! */ + ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); + return NULL; + } + if (!store) + return NULL; + + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i != VECTOR_LENGTH(store->entries)) + return VECTOR_INDEX(store->entries, i)->data; + + return NULL; +} + +/** + * Removes an entry from a plugin data store. + * + * @param type[in] The store type. + * @param pluginID[in] The plugin identifier. + * @param store[in] The store. + * @param classid[in] The entry class identifier. + */ +void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct hplugin_data_store *store, uint32 classid) +{ + struct hplugin_data_entry *entry; + int i; + + if (!HPM->data_store_validate(type, &store, false)) { + /* woo it failed! */ + ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); + return; + } + if (!store) + return; + + ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); + if (i == VECTOR_LENGTH(store->entries)) + return; + + entry = VECTOR_INDEX(store->entries, i); + VECTOR_ERASE(store->entries, i); // Erase and compact + aFree(entry->data); // when it's removed we delete it regardless of autofree + aFree(entry); +} + +/* TODO: add ability for tracking using pID for the upcoming runtime load/unload support. */ +bool HPM_AddHook(enum HPluginHookType type, const char *target, void *hook, unsigned int pID) +{ + if (!HPM->hooking) { + ShowError("HPM:AddHook Fail! '%s' tried to hook to '%s' but HPMHooking is disabled!\n",HPM->pid2name(pID),target); + return false; + } + /* search if target is a known hook point within 'common' */ + /* if not check if a sub-hooking list is available (from the server) and run it by */ + if (HPM->addhook_sub && HPM->addhook_sub(type,target,hook,pID)) + return true; + + ShowError("HPM:AddHook: unknown Hooking Point '%s'!\n",target); + + return false; +} + +void HPM_HookStop(const char *func, unsigned int pID) +{ + /* track? */ + HPM->force_return = true; +} + +bool HPM_HookStopped (void) +{ + return HPM->force_return; +} + +/** + * Adds a plugin-defined command-line argument. + * + * @param pluginID the current plugin's ID. + * @param name the command line argument's name, including the leading '--'. + * @param has_param whether the command line argument expects to be followed by a value. + * @param func the triggered function. + * @param help the help string to be displayed by '--help', if any. + * @return the success status. + */ +bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help) +{ + int i; + + if (!name || strlen(name) < 3 || name[0] != '-' || name[1] != '-') { + ShowError("HPM:add_arg:%s invalid argument name: arguments must begin with '--' (from %s)\n", name, HPM->pid2name(pluginID)); + return false; + } + + ARR_FIND(0, VECTOR_LENGTH(cmdline->args_data), i, strcmp(VECTOR_INDEX(cmdline->args_data, i).name, name) == 0); + + if (i != VECTOR_LENGTH(cmdline->args_data)) { + ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID)); + return false; + } + + return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL); +} + +/** + * Adds a configuration listener for a plugin. + * + * @param pluginID The plugin identifier. + * @param type The configuration type to listen for. + * @param name The configuration entry name. + * @param func The callback function. + * @retval true if the listener was added successfully. + * @retval false in case of error. + */ +bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) +{ + struct HPConfListenStorage *conf; + int i; + + if (type >= HPCT_MAX) { + ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name); + return false; + } + + ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[type]), i, strcmpi(name, VECTOR_INDEX(HPM->config_listeners[type], i).key) == 0); + if (i != VECTOR_LENGTH(HPM->config_listeners[type])) { + ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!", + HPM->pid2name(pluginID), name, HPM->pid2name(VECTOR_INDEX(HPM->config_listeners[type], i).pluginID)); + return false; + } + + VECTOR_ENSURE(HPM->config_listeners[type], 1, 1); + VECTOR_PUSHZEROED(HPM->config_listeners[type]); + conf = &VECTOR_LAST(HPM->config_listeners[type]); + + conf->pluginID = pluginID; + safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH); + conf->func = func; + + return true; +} + struct hplugin *hplugin_load(const char* filename) { struct hplugin *plugin; struct hplugin_info *info; struct HPMi_interface **HPMi; bool anyEvent = false; void **import_symbol_ref; - Sql **sql_handle; int *HPMDataCheckVer; unsigned int *HPMDataCheckLen; struct s_HPMDataCheck *HPMDataCheck; + const char *(*HPMLoadEvent)(int server_type); if( HPM->exists(filename) ) { ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); @@ -144,15 +437,13 @@ struct hplugin *hplugin_load(const char* filename) { if (!(plugin->dll = plugin_open(filename))) { char buf[1024]; - ShowWarning("HPM:plugin_load: failed to load '"CL_WHITE"%s"CL_RESET"' (error: %s), skipping...\n", filename, plugin_geterror(buf)); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to load '"CL_WHITE"%s"CL_RESET"' (error: %s)!\n", filename, plugin_geterror(buf)); + exit(EXIT_FAILURE); } if( !( info = plugin_import(plugin->dll, "pinfo",struct hplugin_info*) ) ) { - ShowDebug("HPM:plugin_load: failed to retrieve 'plugin_info' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'plugin_info' for '"CL_WHITE"%s"CL_RESET"'!\n", filename); + exit(EXIT_FAILURE); } if( !(info->type & SERVER_TYPE) ) { @@ -161,40 +452,28 @@ struct hplugin *hplugin_load(const char* filename) { } if( !HPM->iscompatible(info->req_version) ) { - ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' incompatible version '%s' -> '%s', skipping...\n", filename, info->req_version, HPM_VERSION); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' incompatible version '%s' -> '%s'!\n", filename, info->req_version, HPM_VERSION); + exit(EXIT_FAILURE); } plugin->info = info; plugin->filename = aStrdup(filename); if( !( import_symbol_ref = plugin_import(plugin->dll, "import_symbol",void **) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'import_symbol' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'import_symbol' for '"CL_WHITE"%s"CL_RESET"'!\n", filename); + exit(EXIT_FAILURE); } *import_symbol_ref = HPM->import_symbol; - if( !( sql_handle = plugin_import(plugin->dll, "mysql_handle",Sql **) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'mysql_handle' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; - } - - *sql_handle = HPM->import_symbol("sql_handle",plugin->idx); - if( !( HPMi = plugin_import(plugin->dll, "HPMi",struct HPMi_interface **) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPMi' for '"CL_WHITE"%s"CL_RESET"'!\n", filename); + exit(EXIT_FAILURE); } if( !( *HPMi = plugin_import(plugin->dll, "HPMi_s",struct HPMi_interface *) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi_s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPMi_s' for '"CL_WHITE"%s"CL_RESET"'!\n", filename); + exit(EXIT_FAILURE); } plugin->hpi = *HPMi; @@ -214,84 +493,86 @@ struct hplugin *hplugin_load(const char* filename) { anyEvent = true; if( !anyEvent ) { - ShowWarning("HPM:plugin_load: no events found for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowWarning("HPM:plugin_load: no events found for '"CL_WHITE"%s"CL_RESET"'!\n", filename); + exit(EXIT_FAILURE); } - if( !HPM->populate(plugin,filename) ) - return NULL; + if (!(HPMLoadEvent = plugin_import(plugin->dll, "HPM_shared_symbols", const char *(*)(int)))) { + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPM_shared_symbols' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h!\n", filename); + exit(EXIT_FAILURE); + } + { + const char *failure = HPMLoadEvent(SERVER_TYPE); + if (failure) { + ShowFatalError("HPM:plugin_load: failed to import symbol '%s' into '"CL_WHITE"%s"CL_RESET"'.\n", failure, filename); + exit(EXIT_FAILURE); + } + } if( !( HPMDataCheckLen = plugin_import(plugin->dll, "HPMDataCheckLen", unsigned int *) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheckLen' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPMDataCheckLen' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h!\n", filename); + exit(EXIT_FAILURE); } if( !( HPMDataCheckVer = plugin_import(plugin->dll, "HPMDataCheckVer", int *) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheckVer' for '"CL_WHITE"%s"CL_RESET"', most likely an outdated plugin, skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPMDataCheckVer' for '"CL_WHITE"%s"CL_RESET"', most likely an outdated plugin!\n", filename); + exit(EXIT_FAILURE); } if( !( HPMDataCheck = plugin_import(plugin->dll, "HPMDataCheck", struct s_HPMDataCheck *) ) ) { - ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheck' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: failed to retrieve 'HPMDataCheck' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h!\n", filename); + exit(EXIT_FAILURE); } // TODO: Remove the HPM->DataCheck != NULL check once login and char support is complete if (HPM->DataCheck != NULL && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,*HPMDataCheckVer,plugin->info->name)) { - ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin), skipping...\n", filename); - HPM->unload(plugin); - return NULL; + ShowFatalError("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin)!\n", filename); + exit(EXIT_FAILURE); } /* id */ plugin->hpi->pid = plugin->idx; /* core */ - plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand",plugin->idx); - plugin->hpi->addPacket = HPM->import_symbol("addPacket",plugin->idx); - plugin->hpi->addToHPData = HPM->import_symbol("addToHPData",plugin->idx); - plugin->hpi->getFromHPData = HPM->import_symbol("getFromHPData",plugin->idx); - plugin->hpi->removeFromHPData = HPM->import_symbol("removeFromHPData",plugin->idx); - plugin->hpi->AddHook = HPM->import_symbol("AddHook",plugin->idx); - plugin->hpi->HookStop = HPM->import_symbol("HookStop",plugin->idx); - plugin->hpi->HookStopped = HPM->import_symbol("HookStopped",plugin->idx); - plugin->hpi->addArg = HPM->import_symbol("addArg",plugin->idx); - plugin->hpi->addConf = HPM->import_symbol("addConf",plugin->idx); +#ifdef CONSOLE_INPUT + plugin->hpi->addCPCommand = console->input->addCommand; +#endif // CONSOLE_INPUT + plugin->hpi->addPacket = hplugins_addpacket; + plugin->hpi->addToHPData = hplugins_addToHPData; + plugin->hpi->getFromHPData = hplugins_getFromHPData; + plugin->hpi->removeFromHPData = hplugins_removeFromHPData; + plugin->hpi->AddHook = HPM_AddHook; + plugin->hpi->HookStop = HPM_HookStop; + plugin->hpi->HookStopped = HPM_HookStopped; + plugin->hpi->addArg = hpm_add_arg; + plugin->hpi->addConf = hplugins_addconf; /* server specific */ if( HPM->load_sub ) HPM->load_sub(plugin); + ShowStatus("HPM: Loaded plugin '"CL_WHITE"%s"CL_RESET"' (%s).\n", plugin->info->name, plugin->info->version); + return plugin; } -void hplugin_unload(struct hplugin* plugin) { - unsigned int i = plugin->idx; - - if( plugin->filename ) +/** + * Unloads and unregisters a plugin. + * + * @param plugin The plugin data. + */ +void hplugin_unload(struct hplugin* plugin) +{ + int i; + if (plugin->filename) aFree(plugin->filename); - if( plugin->dll ) + if (plugin->dll) plugin_close(plugin->dll); /* TODO: for manual packet unload */ /* - Go through known packets and unlink any belonging to the plugin being removed */ - aFree(plugin); - if (!HPM->off) { - int cursor = 0; - HPM->plugins[i] = NULL; - for(i = 0; i < HPM->plugin_count; i++) { - if( HPM->plugins[i] == NULL ) - continue; - if( cursor != i ) - HPM->plugins[cursor] = HPM->plugins[i]; - cursor++; - } - if( !(HPM->plugin_count = cursor) ) { - aFree(HPM->plugins); - HPM->plugins = NULL; - } + ARR_FIND(0, VECTOR_LENGTH(HPM->plugins), i, VECTOR_INDEX(HPM->plugins, i)->idx == plugin->idx); + if (i != VECTOR_LENGTH(HPM->plugins)) { + VECTOR_ERASE(HPM->plugins, i); } + aFree(plugin); } /** @@ -299,8 +580,8 @@ void hplugin_unload(struct hplugin* plugin) { */ CMDLINEARG(loadplugin) { - RECREATE(HPM->cmdline_plugins, char *, ++HPM->cmdline_plugins_count); - HPM->cmdline_plugins[HPM->cmdline_plugins_count-1] = aStrdup(params); + VECTOR_ENSURE(HPM->cmdline_load_plugins, 1, 1); + VECTOR_PUSH(HPM->cmdline_load_plugins, aStrdup(params)); return true; } @@ -323,13 +604,10 @@ void hplugins_config_read(void) { if (libconfig->read_file(&plugins_conf, config_filename)) return; - if( HPM->symbol_defaults_sub ) - HPM->symbol_defaults_sub(); - plist = libconfig->lookup(&plugins_conf, "plugins_list"); - for (i = 0; i < HPM->cmdline_plugins_count; i++) { + for (i = 0; i < VECTOR_LENGTH(HPM->cmdline_load_plugins); i++) { config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING); - config_setting_set_string(entry, HPM->cmdline_plugins[i]); + config_setting_set_string(entry, VECTOR_INDEX(HPM->cmdline_load_plugins, i)); } if (plist != NULL) { @@ -351,11 +629,14 @@ void hplugins_config_read(void) { struct hplugin *plugin; snprintf(filename, 60, "plugins/%s%s", hooking_plugin_name, DLL_EXT); if ((plugin = HPM->load(filename))) { - bool (*func)(bool *fr); + const char * (*func)(bool *fr); bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID); - if ((func = plugin_import(plugin->dll, "Hooked",bool (*)(bool *))) - && (addhook_sub = plugin_import(plugin->dll, "HPM_Plugin_AddHook",bool (*)(enum HPluginHookType, const char *, void *, unsigned int)))) { - if (func(&HPM->force_return)) { + if ((func = plugin_import(plugin->dll, "Hooked",const char * (*)(bool *))) != NULL + && (addhook_sub = plugin_import(plugin->dll, "HPM_Plugin_AddHook",bool (*)(enum HPluginHookType, const char *, void *, unsigned int))) != NULL) { + const char *failed = func(&HPM->force_return); + if (failed) { + ShowError("HPM: failed to retrieve '%s' for '"CL_WHITE"%s"CL_RESET"'!\n", failed, plugin_name); + } else { HPM->hooking = true; HPM->addhook_sub = addhook_sub; } @@ -370,239 +651,120 @@ void hplugins_config_read(void) { snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT); HPM->load(filename); } - libconfig->destroy(&plugins_conf); - } - - if( HPM->plugin_count ) - ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count); -} -CPCMD(plugins) { - if( HPM->plugin_count == 0 ) { - ShowInfo("HPC: there are no plugins loaded\n"); - } else { - unsigned int i; - - ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count); - - for(i = 0; i < HPM->plugin_count; i++) { - ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename); - } - } -} -void hplugins_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) { - /* record address */ - switch( type ) { - /* core-handled */ - case HPDT_SESSION: - ret->HPDataSRCPtr = (void**)(&((struct socket_data *)ptr)->hdata); - ret->hdatac = &((struct socket_data *)ptr)->hdatac; - break; - /* goes to sub */ - default: - if( HPM->grabHPDataSub ) { - if( HPM->grabHPDataSub(ret,type,ptr) ) - return; - else { - ShowError("HPM:HPM:grabHPData failed, unknown type %d!\n",type); - } - } else - ShowError("HPM:grabHPData failed, type %d needs sub-handler!\n",type); - ret->HPDataSRCPtr = NULL; - ret->hdatac = NULL; - return; - } -} -void hplugins_addToHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, void *data, unsigned int index, bool autofree) { - struct HPluginData *HPData, **HPDataSRC; - struct HPDataOperationStorage action; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); - - if( action.hdatac == NULL ) { /* woo it failed! */ - ShowError("HPM:addToHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); - return; - } - - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); - - /* duplicate check */ - for(i = 0; i < max; i++) { - if( HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index ) { - ShowError("HPM:addToHPData:%s: error! attempting to insert duplicate struct of id %u and index %u\n",HPM->pid2name(pluginID),pluginID,index); - return; - } - } - - /* HPluginData is always same size, probably better to use the ERS (with reasonable chunk size e.g. 10/25/50) */ - CREATE(HPData, struct HPluginData, 1); - - /* input */ - HPData->pluginID = pluginID; - HPData->type = index; - HPData->flag.free = autofree ? 1 : 0; - HPData->data = data; - - /* resize */ - *(action.hdatac) += 1; - RECREATE(*(action.HPDataSRCPtr),struct HPluginData *,*(action.hdatac)); - - /* RECREATE modified the address */ - HPDataSRC = *(action.HPDataSRCPtr); - HPDataSRC[*(action.hdatac) - 1] = HPData; -} - -void *hplugins_getFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index) { - struct HPDataOperationStorage action; - struct HPluginData **HPDataSRC; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); - - if( action.hdatac == NULL ) { /* woo it failed! */ - ShowError("HPM:getFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); - return NULL; - } - - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); - - for(i = 0; i < max; i++) { - if( HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index ) - return HPDataSRC[i]->data; } + libconfig->destroy(&plugins_conf); - return NULL; + if (VECTOR_LENGTH(HPM->plugins)) + ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", VECTOR_LENGTH(HPM->plugins)); } -void hplugins_removeFromHPData(enum HPluginDataTypes type, unsigned int pluginID, void *ptr, unsigned int index) { - struct HPDataOperationStorage action; - struct HPluginData **HPDataSRC; - unsigned int i, max; - - HPM->grabHPData(&action,type,ptr); +/** + * Console command: plugins + * + * Shows a list of loaded plugins. + * + * @see CPCMD() + */ +CPCMD(plugins) +{ + int i; - if( action.hdatac == NULL ) { /* woo it failed! */ - ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index); + if (VECTOR_LENGTH(HPM->plugins) == 0) { + ShowInfo("HPC: there are no plugins loaded\n"); return; } - /* flag */ - HPDataSRC = *(action.HPDataSRCPtr); - max = *(action.hdatac); + ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n", VECTOR_LENGTH(HPM->plugins)); - for(i = 0; i < max; i++) { - if( HPDataSRC[i]->pluginID == pluginID && HPDataSRC[i]->type == index ) - break; - } - - if( i != max ) { - unsigned int cursor; - - aFree(HPDataSRC[i]->data);/* when its removed we delete it regardless of autofree */ - aFree(HPDataSRC[i]); - HPDataSRC[i] = NULL; - - for(i = 0, cursor = 0; i < max; i++) { - if( HPDataSRC[i] == NULL ) - continue; - if( i != cursor ) - HPDataSRC[cursor] = HPDataSRC[i]; - cursor++; - } - *(action.hdatac) = cursor; + for(i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n", plugin->info->name, plugin->filename); } } -bool hplugins_addpacket(unsigned short cmd, short length,void (*receive) (int fd),unsigned int point,unsigned int pluginID) { - struct HPluginPacket *packet; - unsigned int i; - - if( point >= hpPHP_MAX ) { - ShowError("HPM->addPacket:%s: unknown point '%u' specified for packet 0x%04x (len %d)\n",HPM->pid2name(pluginID),point,cmd,length); - return false; - } - - for(i = 0; i < HPM->packetsc[point]; i++) { - if( HPM->packets[point][i].cmd == cmd ) { - ShowError("HPM->addPacket:%s: can't add packet 0x%04x, already in use by '%s'!",HPM->pid2name(pluginID),cmd,HPM->pid2name(HPM->packets[point][i].pluginID)); - return false; - } - } - - RECREATE(HPM->packets[point], struct HPluginPacket, ++HPM->packetsc[point]); - packet = &HPM->packets[point][HPM->packetsc[point] - 1]; - - packet->pluginID = pluginID; - packet->cmd = cmd; - packet->len = length; - packet->receive = receive; - - return true; -} -/* - 0 = unknown - 1 = OK - 2 = incomplete +/** + * Parses a packet through the registered plugin. + * + * @param fd The connection fd. + * @param point The packet hooking point. + * @retval 0 unknown packet + * @retval 1 OK + * @retval 2 incomplete packet */ -unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) { - unsigned int i; +unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) +{ + struct HPluginPacket *packet = NULL; + int i; + int16 length; - for(i = 0; i < HPM->packetsc[point]; i++) { - if( HPM->packets[point][i].cmd == RFIFOW(fd,0) ) - break; - } + ARR_FIND(0, VECTOR_LENGTH(HPM->packets[point]), i, VECTOR_INDEX(HPM->packets[point], i).cmd == RFIFOW(fd,0)); - if( i != HPM->packetsc[point] ) { - struct HPluginPacket *packet = &HPM->packets[point][i]; - short length; + if (i == VECTOR_LENGTH(HPM->packets[point])) + return 0; - if( (length = packet->len) == -1 ) { - if( (length = RFIFOW(fd, 2)) > (int)RFIFOREST(fd) ) - return 2; - } + packet = &VECTOR_INDEX(HPM->packets[point], i); + length = packet->len; + if (length == -1) + length = RFIFOW(fd, 2); - packet->receive(fd); - RFIFOSKIP(fd, length); - return 1; - } + if (length > (int)RFIFOREST(fd)) + return 2; - return 0; + packet->receive(fd); + RFIFOSKIP(fd, length); + return 1; } -char *hplugins_id2name (unsigned int pid) { - unsigned int i; +/** + * Retrieves a plugin name by ID. + * + * @param pid The plugin identifier. + * @return The plugin name. + * @retval "core" if the plugin ID belongs to the Hercules core. + * @retval "UnknownPlugin" if the plugin wasn't found. + */ +char *hplugins_id2name(unsigned int pid) +{ + int i; if (pid == HPM_PID_CORE) return "core"; - for( i = 0; i < HPM->plugin_count; i++ ) { - if( HPM->plugins[i]->idx == pid ) - return HPM->plugins[i]->info->name; + for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { + struct hplugin *plugin = VECTOR_INDEX(HPM->plugins, i); + if (plugin->idx == pid) + return plugin->info->name; } return "UnknownPlugin"; } -char* HPM_file2ptr(const char *file) { - unsigned int i; - for(i = 0; i < HPM->fnamec; i++) { - if( HPM->fnames[i].addr == file ) - return HPM->fnames[i].name; - } +/** + * Returns a retained permanent pointer to a source filename, for memory-manager reporting use. + * + * The returned pointer is safe to be used as filename in the memory manager + * functions, and it will be available during and after the memory manager + * shutdown (for memory leak reporting purposes). + * + * @param file The string/filename to retain + * @return A retained copy of the source string. + */ +const char *HPM_file2ptr(const char *file) +{ + int i; - i = HPM->fnamec; + ARR_FIND(0, HPM->filenames.count, i, HPM->filenames.data[i].addr == file); + if (i != HPM->filenames.count) { + return HPM->filenames.data[i].name; + } /* we handle this memory outside of the server's memory manager because we need it to exist after the memory manager goes down */ - HPM->fnames = realloc(HPM->fnames,(++HPM->fnamec)*sizeof(struct HPMFileNameCache)); + HPM->filenames.data = realloc(HPM->filenames.data, (++HPM->filenames.count)*sizeof(struct HPMFileNameCache)); - HPM->fnames[i].addr = file; - HPM->fnames[i].name = strdup(file); + HPM->filenames.data[i].addr = file; + HPM->filenames.data[i].name = strdup(file); - return HPM->fnames[i].name; + return HPM->filenames.data[i].name; } void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) { return iMalloc->malloc(size,HPM_file2ptr(file),line,func); @@ -619,96 +781,75 @@ void* HPM_reallocz(void *p, size_t size, const char *file, int line, const char char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { return iMalloc->astrdup(p,HPM_file2ptr(file),line,func); } -/* TODO: add ability for tracking using pID for the upcoming runtime load/unload support. */ -bool HPM_AddHook(enum HPluginHookType type, const char *target, void *hook, unsigned int pID) { - if( !HPM->hooking ) { - ShowError("HPM:AddHook Fail! '%s' tried to hook to '%s' but HPMHooking is disabled!\n",HPM->pid2name(pID),target); - return false; - } - /* search if target is a known hook point within 'common' */ - /* if not check if a sub-hooking list is available (from the server) and run it by */ - if( HPM->addhook_sub && HPM->addhook_sub(type,target,hook,pID) ) - return true; - - ShowError("HPM:AddHook: unknown Hooking Point '%s'!\n",target); - return false; -} -void HPM_HookStop (const char *func, unsigned int pID) { - /* track? */ - HPM->force_return = true; -} -bool HPM_HookStopped (void) { - return HPM->force_return; -} /** - * Adds a plugin-defined command-line argument. + * Parses a configuration entry through the registered plugins. * - * @param pluginID the current plugin's ID. - * @param name the command line argument's name, including the leading '--'. - * @param has_param whether the command line argument expects to be followed by a value. - * @param func the triggered function. - * @param help the help string to be displayed by '--help', if any. - * @return the success status. + * @param w1 The configuration entry name. + * @param w2 The configuration entry value. + * @param point The type of configuration file. + * @retval true if a registered plugin was found to handle the entry. + * @retval false if no registered plugins could be found. */ -bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecFunc func, const char *help) { +bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) +{ int i; - - if (!name || strlen(name) < 3 || name[0] != '-' || name[1] != '-') { - ShowError("HPM:add_arg:%s invalid argument name: arguments must begin with '--' (from %s)\n", name, HPM->pid2name(pluginID)); + ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[point]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[point], i).key) == 0); + if (i == VECTOR_LENGTH(HPM->config_listeners[point])) return false; - } - - ARR_FIND(0, cmdline->args_data_count, i, strcmp(cmdline->args_data[i].name, name) == 0); - if (i < cmdline->args_data_count) { - ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID)); - return false; - } - - return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL); + VECTOR_INDEX(HPM->config_listeners[point], i).func(w2); + return true; } -bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*func) (const char *val)) { - struct HPConfListenStorage *conf; - unsigned int i; - if( type >= HPCT_MAX ) { - ShowError("HPM->addConf:%s: unknown point '%u' specified for config '%s'\n",HPM->pid2name(pluginID),type,name); - return false; - } +/** + * Helper to destroy an interface's hplugin_data store and release any owned memory. + * + * The pointer will be cleared. + * + * @param storeptr[in,out] A pointer to the plugin data store. + */ +void hplugin_data_store_destroy(struct hplugin_data_store **storeptr) +{ + struct hplugin_data_store *store; + nullpo_retv(storeptr); + store = *storeptr; + if (store == NULL) + return; - for(i = 0; i < HPM->confsc[type]; i++) { - if( !strcmpi(name,HPM->confs[type][i].key) ) { - ShowError("HPM->addConf:%s: duplicate '%s', already in use by '%s'!",HPM->pid2name(pluginID),name,HPM->pid2name(HPM->confs[type][i].pluginID)); - return false; + while (VECTOR_LENGTH(store->entries) > 0) { + struct hplugin_data_entry *entry = VECTOR_POP(store->entries); + if (entry->flag.free) { + aFree(entry->data); } + aFree(entry); } - - RECREATE(HPM->confs[type], struct HPConfListenStorage, ++HPM->confsc[type]); - conf = &HPM->confs[type][HPM->confsc[type] - 1]; - - conf->pluginID = pluginID; - safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH); - conf->func = func; - - return true; + VECTOR_CLEAR(store->entries); + aFree(store); + *storeptr = NULL; } -bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) { - unsigned int i; - /* exists? */ - for(i = 0; i < HPM->confsc[point]; i++) { - if( !strcmpi(w1,HPM->confs[point][i].key) ) - break; - } +/** + * Helper to create and initialize an interface's hplugin_data store. + * + * The store is owned by the caller, and it should be eventually destroyed by + * \c hdata_destroy. + * + * @param storeptr[in,out] A pointer to the data store to initialize. + * @param type[in] The store type. + */ +void hplugin_data_store_create(struct hplugin_data_store **storeptr, enum HPluginDataTypes type) +{ + struct hplugin_data_store *store; + nullpo_retv(storeptr); - /* trigger and we're set! */ - if( i != HPM->confsc[point] ) { - HPM->confs[point][i].func(w2); - return true; + if (*storeptr == NULL) { + CREATE(*storeptr, struct hplugin_data_store, 1); } + store = *storeptr; - return false; + store->type = type; + VECTOR_INIT(store->entries); } /** @@ -723,7 +864,7 @@ bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, c } for (i = 0; i < size; i++) { - if (!(src[i].type|SERVER_TYPE)) + if (!(src[i].type&SERVER_TYPE)) continue; if (!strdb_exists(datacheck_db, src[i].name)) { @@ -761,55 +902,15 @@ void HPM_datacheck_final(void) { db_destroy(datacheck_db); } -void hplugins_share_defaults(void) { - /* console */ -#ifdef CONSOLE_INPUT - HPM->share(console->input->addCommand,"addCPCommand"); -#endif - /* our own */ - HPM->share(hplugins_addpacket,"addPacket"); - HPM->share(hplugins_addToHPData,"addToHPData"); - HPM->share(hplugins_getFromHPData,"getFromHPData"); - HPM->share(hplugins_removeFromHPData,"removeFromHPData"); - HPM->share(HPM_AddHook,"AddHook"); - HPM->share(HPM_HookStop,"HookStop"); - HPM->share(HPM_HookStopped,"HookStopped"); - HPM->share(hpm_add_arg,"addArg"); - HPM->share(hplugins_addconf,"addConf"); - /* core */ - HPM->share(&runflag,"runflag"); - HPM->share(arg_v,"arg_v"); - HPM->share(&arg_c,"arg_c"); - HPM->share(SERVER_NAME,"SERVER_NAME"); - HPM->share(&SERVER_TYPE,"SERVER_TYPE"); - HPM->share(DB, "DB"); - HPM->share(HPMiMalloc, "iMalloc"); - HPM->share(nullpo,"nullpo"); - /* socket */ - HPM->share(sockt,"sockt"); - /* strlib */ - HPM->share(strlib,"strlib"); - HPM->share(sv,"sv"); - HPM->share(StrBuf,"StrBuf"); - /* sql */ - HPM->share(SQL,"SQL"); - /* timer */ - HPM->share(timer,"timer"); - /* libconfig */ - HPM->share(libconfig,"libconfig"); - /* sysinfo */ - HPM->share(sysinfo,"sysinfo"); -} - void hpm_init(void) { - unsigned int i; + int i; datacheck_db = NULL; datacheck_data = NULL; datacheck_version = 0; - HPM->symbols = NULL; - HPM->plugins = NULL; - HPM->plugin_count = HPM->symbol_count = 0; + VECTOR_INIT(HPM->plugins); + VECTOR_INIT(HPM->symbols); + HPM->off = false; memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface)); @@ -827,96 +928,81 @@ void hpm_init(void) { return; } - for(i = 0; i < hpPHP_MAX; i++) { - HPM->packets[i] = NULL; - HPM->packetsc[i] = 0; + for (i = 0; i < hpPHP_MAX; i++) { + VECTOR_INIT(HPM->packets[i]); } - HPM->symbol_defaults(); + for (i = 0; i < HPCT_MAX; i++) { + VECTOR_INIT(HPM->config_listeners[i]); + } #ifdef CONSOLE_INPUT console->input->addCommand("plugins",CPCMD_A(plugins)); #endif return; } + +/** + * Releases the retained filenames cache. + */ void hpm_memdown(void) { - /* this memory is handled outside of the server's memory manager and thus cleared after memory manager goes down */ - - if (HPM->fnames) { - unsigned int i; - for (i = 0; i < HPM->fnamec; i++) { - free(HPM->fnames[i].name); + /* this memory is handled outside of the server's memory manager and + * thus cleared after memory manager goes down */ + if (HPM->filenames.count) { + int i; + for (i = 0; i < HPM->filenames.count; i++) { + free(HPM->filenames.data[i].name); } - free(HPM->fnames); + free(HPM->filenames.data); + HPM->filenames.data = NULL; + HPM->filenames.count = 0; } } -void hpm_final(void) { - unsigned int i; + +void hpm_final(void) +{ + int i; HPM->off = true; - if( HPM->plugins ) - { - for( i = 0; i < HPM->plugin_count; i++ ) { - HPM->unload(HPM->plugins[i]); - } - aFree(HPM->plugins); + while (VECTOR_LENGTH(HPM->plugins)) { + HPM->unload(VECTOR_LAST(HPM->plugins)); } + VECTOR_CLEAR(HPM->plugins); - if( HPM->symbols ) - { - for( i = 0; i < HPM->symbol_count; i++ ) { - aFree(HPM->symbols[i]); - } - aFree(HPM->symbols); + while (VECTOR_LENGTH(HPM->symbols)) { + aFree(VECTOR_POP(HPM->symbols)); } + VECTOR_CLEAR(HPM->symbols); - for( i = 0; i < hpPHP_MAX; i++ ) { - if( HPM->packets[i] ) - aFree(HPM->packets[i]); + for (i = 0; i < hpPHP_MAX; i++) { + VECTOR_CLEAR(HPM->packets[i]); } - for( i = 0; i < HPCT_MAX; i++ ) { - if( HPM->confsc[i] ) - aFree(HPM->confs[i]); + for (i = 0; i < HPCT_MAX; i++) { + VECTOR_CLEAR(HPM->config_listeners[i]); } - if (HPM->cmdline_plugins) { - int j; - for (j = 0; j < HPM->cmdline_plugins_count; j++) - aFree(HPM->cmdline_plugins[j]); - aFree(HPM->cmdline_plugins); - HPM->cmdline_plugins = NULL; - HPM->cmdline_plugins_count = 0; + + while (VECTOR_LENGTH(HPM->cmdline_load_plugins)) { + aFree(VECTOR_POP(HPM->cmdline_load_plugins)); } + VECTOR_CLEAR(HPM->cmdline_load_plugins); /* HPM->fnames is cleared after the memory manager goes down */ iMalloc->post_shutdown = hpm_memdown; return; } -void hpm_defaults(void) { - unsigned int i; +void hpm_defaults(void) +{ HPM = &HPM_s; - HPM->fnames = NULL; - HPM->fnamec = 0; + memset(&HPM->filenames, 0, sizeof(HPM->filenames)); + VECTOR_INIT(HPM->cmdline_load_plugins); HPM->force_return = false; HPM->hooking = false; /* */ - HPM->fnames = NULL; - HPM->fnamec = 0; - for(i = 0; i < hpPHP_MAX; i++) { - HPM->packets[i] = NULL; - HPM->packetsc[i] = 0; - } - for(i = 0; i < HPCT_MAX; i++) { - HPM->confs[i] = NULL; - HPM->confsc[i] = 0; - } - HPM->cmdline_plugins = NULL; - HPM->cmdline_plugins_count = 0; - /* */ HPM->init = hpm_init; HPM->final = hpm_final; @@ -928,18 +1014,18 @@ void hpm_defaults(void) { HPM->iscompatible = hplugin_iscompatible; HPM->import_symbol = hplugin_import_symbol; HPM->share = hplugin_export_symbol; - HPM->symbol_defaults = hplugins_share_defaults; HPM->config_read = hplugins_config_read; - HPM->populate = hplugin_populate; - HPM->symbol_defaults_sub = NULL; HPM->pid2name = hplugins_id2name; HPM->parse_packets = hplugins_parse_packets; HPM->load_sub = NULL; HPM->addhook_sub = NULL; - HPM->grabHPData = hplugins_grabHPData; - HPM->grabHPDataSub = NULL; HPM->parseConf = hplugins_parse_conf; HPM->DataCheck = HPM_DataCheck; HPM->datacheck_init = HPM_datacheck_init; HPM->datacheck_final = HPM_datacheck_final; + + HPM->data_store_destroy = hplugin_data_store_destroy; + HPM->data_store_create = hplugin_data_store_create; + HPM->data_store_validate = hplugin_data_store_validate; + HPM->data_store_validate_sub = NULL; } |