diff options
Diffstat (limited to 'src/common/HPM.c')
-rw-r--r-- | src/common/HPM.c | 232 |
1 files changed, 185 insertions, 47 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c index d9c3262d7..c84b447e8 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2013-2015 Hercules Dev Team + * Copyright (C) 2013-2016 Hercules Dev Team * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,6 +38,7 @@ #include "common/timer.h" #include "common/utils.h" #include "common/nullpo.h" +#include "plugins/HPMHooking.h" #include <stdio.h> #include <stdlib.h> @@ -51,11 +52,12 @@ struct malloc_interface iMalloc_HPM; struct malloc_interface *HPMiMalloc; struct HPM_interface HPM_s; struct HPM_interface *HPM; +struct HPMHooking_core_interface HPMHooking_core_s; /** * (char*) data name -> (unsigned int) HPMDataCheck[] index **/ -DBMap *datacheck_db; +struct DBMap *datacheck_db; int datacheck_version; const struct s_HPMDataCheck *datacheck_data; @@ -101,6 +103,7 @@ void hplugin_export_symbol(void *value, const char *name) void *hplugin_import_symbol(char *name, unsigned int pID) { int i; + nullpo_retr(NULL, name); ARR_FIND(0, VECTOR_LENGTH(HPM->symbols), i, strcmp(VECTOR_INDEX(HPM->symbols, i)->name, name) == 0); if (i != VECTOR_LENGTH(HPM->symbols)) @@ -131,6 +134,7 @@ bool hplugin_iscompatible(char* version) { bool hplugin_exists(const char *filename) { int i; + nullpo_retr(false, filename); for (i = 0; i < VECTOR_LENGTH(HPM->plugins); i++) { if (strcmpi(VECTOR_INDEX(HPM->plugins, i)->filename,filename) == 0) return true; @@ -214,11 +218,11 @@ bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data break; default: if (HPM->data_store_validate_sub == NULL) { - ShowError("HPM:validateHPData failed, type %d needs sub-handler!\n",type); + ShowError("HPM:validateHPData failed, type %u 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); + ShowError("HPM:HPM:validateHPData failed, unknown type %u!\n", type); return false; } break; @@ -228,7 +232,7 @@ bool hplugin_data_store_validate(enum HPluginDataTypes type, struct hplugin_data store = *storeptr; } if (store->type != type) { - ShowError("HPM:HPM:validateHPData failed, store type mismatch %d != %d.\n",store->type, type); + ShowError("HPM:HPM:validateHPData failed, store type mismatch %u != %u.\n", store->type, type); return false; } return true; @@ -253,10 +257,11 @@ void hplugins_addToHPData(enum HPluginDataTypes type, uint32 pluginID, struct hp 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); + ShowError("HPM:addToHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return; } store = *storeptr; + nullpo_retv(store); /* duplicate check */ ARR_FIND(0, VECTOR_LENGTH(store->entries), i, VECTOR_INDEX(store->entries, i)->pluginID == pluginID && VECTOR_INDEX(store->entries, i)->classid == classid); @@ -294,7 +299,7 @@ void *hplugins_getFromHPData(enum HPluginDataTypes type, uint32 pluginID, struct 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); + ShowError("HPM:getFromHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return NULL; } if (!store) @@ -322,7 +327,7 @@ void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, stru 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); + ShowError("HPM:removeFromHPData:%s: failed, type %u (%u|%u)\n", HPM->pid2name(pluginID), type, pluginID, classid); return; } if (!store) @@ -341,13 +346,13 @@ void hplugins_removeFromHPData(enum HPluginDataTypes type, uint32 pluginID, stru /* 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) { + if (!HPM->hooking->enabled) { 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)) + if (HPM->hooking->addhook_sub != NULL && HPM->hooking->addhook_sub(type,target,hook,pID)) return true; ShowError("HPM:AddHook: unknown Hooking Point '%s'!\n",target); @@ -358,12 +363,12 @@ bool HPM_AddHook(enum HPluginHookType type, const char *target, void *hook, unsi void HPM_HookStop(const char *func, unsigned int pID) { /* track? */ - HPM->force_return = true; + HPM->hooking->force_return = true; } -bool HPM_HookStopped (void) +bool HPM_HookStopped(void) { - return HPM->force_return; + return HPM->hooking->force_return; } /** @@ -387,12 +392,12 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF 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; - } + 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); + return cmdline->arg_add(pluginID, name, '\0', func, help, has_param ? CMDLINE_OPT_PARAM : CMDLINE_OPT_NORMAL); } /** @@ -405,7 +410,7 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, CmdlineExecF * @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 (*parse_func) (const char *key, const char *val), int (*return_func) (const char *key)) +bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *name, void (*parse_func) (const char *key, const char *val), int (*return_func) (const char *key), bool required) { struct HPConfListenStorage *conf; int i; @@ -440,11 +445,13 @@ bool hplugins_addconf(unsigned int pluginID, enum HPluginConfType type, char *na safestrncpy(conf->key, name, HPM_ADDCONF_LENGTH); conf->parse_func = parse_func; conf->return_func = return_func; + conf->required = required; return true; } -struct hplugin *hplugin_load(const char* filename) { +struct hplugin *hplugin_load(const char* filename) +{ struct hplugin *plugin; struct hplugin_info *info; struct HPMi_interface **HPMi; @@ -560,6 +567,7 @@ struct hplugin *hplugin_load(const char* filename) { /* id */ plugin->hpi->pid = plugin->idx; /* core */ + plugin->hpi->memmgr = HPMiMalloc; #ifdef CONSOLE_INPUT plugin->hpi->addCPCommand = console->input->addCommand; #endif // CONSOLE_INPUT @@ -567,16 +575,20 @@ struct hplugin *hplugin_load(const char* filename) { 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; + if ((plugin->hpi->hooking = plugin_import(plugin->dll, "HPMHooking_s", struct HPMHooking_interface *)) != NULL) { + plugin->hpi->hooking->AddHook = HPM_AddHook; + plugin->hpi->hooking->HookStop = HPM_HookStop; + plugin->hpi->hooking->HookStopped = HPM_HookStopped; + } /* 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); + ShowStatus("HPM: Loaded plugin '"CL_WHITE"%s"CL_RESET"' (%s)%s.\n", + plugin->info->name, plugin->info->version, + plugin->hpi->hooking != NULL ? " built with HPMHooking support" : ""); return plugin; } @@ -589,6 +601,7 @@ struct hplugin *hplugin_load(const char* filename) { void hplugin_unload(struct hplugin* plugin) { int i; + nullpo_retv(plugin); if (plugin->filename) aFree(plugin->filename); if (plugin->dll) @@ -615,9 +628,10 @@ CMDLINEARG(loadplugin) /** * Reads the plugin configuration and loads the plugins as necessary. */ -void hplugins_config_read(void) { - config_t plugins_conf; - config_setting_t *plist = NULL; +void hplugins_config_read(void) +{ + struct config_t plugins_conf; + struct config_setting_t *plist = NULL; const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name FILE *fp; int i; @@ -628,12 +642,12 @@ void hplugins_config_read(void) { fclose(fp); } - if (libconfig->read_file(&plugins_conf, config_filename)) + if (!libconfig->load_file(&plugins_conf, config_filename)) return; plist = libconfig->lookup(&plugins_conf, "plugins_list"); for (i = 0; i < VECTOR_LENGTH(HPM->cmdline_load_plugins); i++) { - config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING); + struct config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING); config_setting_set_string(entry, VECTOR_INDEX(HPM->cmdline_load_plugins, i)); } @@ -660,12 +674,13 @@ void hplugins_config_read(void) { bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID); 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); + const char *failed = func(&HPM->hooking->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; + HPM->hooking->enabled = true; + HPM->hooking->addhook_sub = addhook_sub; + HPM->hooking->Hooked = func; // The purpose of this is type-checking 'func' at compile time. } } } @@ -780,6 +795,7 @@ const char *HPM_file2ptr(const char *file) { int i; + nullpo_retr(NULL, file); ARR_FIND(0, HPM->filenames.count, i, HPM->filenames.data[i].addr == file); if (i != HPM->filenames.count) { return HPM->filenames.data[i].name; @@ -793,19 +809,29 @@ const char *HPM_file2ptr(const char *file) return HPM->filenames.data[i].name; } -void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) { + +void* HPM_mmalloc(size_t size, const char *file, int line, const char *func) +{ return iMalloc->malloc(size,HPM_file2ptr(file),line,func); } -void* HPM_calloc(size_t num, size_t size, const char *file, int line, const char *func) { + +void* HPM_calloc(size_t num, size_t size, const char *file, int line, const char *func) +{ return iMalloc->calloc(num,size,HPM_file2ptr(file),line,func); } -void* HPM_realloc(void *p, size_t size, const char *file, int line, const char *func) { + +void* HPM_realloc(void *p, size_t size, const char *file, int line, const char *func) +{ return iMalloc->realloc(p,size,HPM_file2ptr(file),line,func); } -void* HPM_reallocz(void *p, size_t size, const char *file, int line, const char *func) { + +void* HPM_reallocz(void *p, size_t size, const char *file, int line, const char *func) +{ return iMalloc->reallocz(p,size,HPM_file2ptr(file),line,func); } -char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { + +char* HPM_astrdup(const char *p, const char *file, int line, const char *func) +{ return iMalloc->astrdup(p,HPM_file2ptr(file),line,func); } @@ -818,7 +844,7 @@ char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { * @retval true if a registered plugin was found to handle the entry. * @retval false if no registered plugins could be found. */ -bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType point) +bool hplugins_parse_conf_entry(const char *w1, const char *w2, enum HPluginConfType point) { int i; ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[point]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[point], i).key) == 0); @@ -841,6 +867,7 @@ bool hplugins_get_battle_conf(const char *w1, int *value) { int i; + nullpo_retr(false, w1); nullpo_retr(false, value); ARR_FIND(0, VECTOR_LENGTH(HPM->config_listeners[HPCT_BATTLE]), i, strcmpi(w1, VECTOR_INDEX(HPM->config_listeners[HPCT_BATTLE], i).key) == 0); @@ -852,6 +879,106 @@ bool hplugins_get_battle_conf(const char *w1, int *value) } /** + * Parses configuration entries registered by plugins. + * + * @param config The configuration file to parse. + * @param filename Path to configuration file. + * @param point The type of configuration file. + * @param imported Whether the current config is imported from another file. + * @retval false in case of error. + */ +bool hplugins_parse_conf(const struct config_t *config, const char *filename, enum HPluginConfType point, bool imported) +{ + const struct config_setting_t *setting = NULL; + int i, val, type; + char buf[1024]; + bool retval = true; + + nullpo_retr(false, config); + + for (i = 0; i < VECTOR_LENGTH(HPM->config_listeners[point]); i++) { + const struct HPConfListenStorage *entry = &VECTOR_INDEX(HPM->config_listeners[point], i); + const char *config_name = entry->key; + const char *str = NULL; + if ((setting = libconfig->lookup(config, config_name)) == NULL) { + if (!imported && entry->required) { + ShowWarning("Missing configuration '%s' in file %s!\n", config_name, filename); + retval = false; + } + continue; + } + + switch ((type = config_setting_type(setting))) { + case CONFIG_TYPE_INT: + val = libconfig->setting_get_int(setting); + sprintf(buf, "%d", val); // FIXME: Remove this when support to int's as value is added + str = buf; + break; + case CONFIG_TYPE_BOOL: + val = libconfig->setting_get_bool(setting); + sprintf(buf, "%d", val); // FIXME: Remove this when support to int's as value is added + str = buf; + break; + case CONFIG_TYPE_STRING: + str = libconfig->setting_get_string(setting); + break; + default: // Unsupported type + ShowWarning("Setting %s has unsupported type %d, ignoring...\n", config_name, type); + retval = false; + continue; + } + entry->parse_func(config_name, str); + } + return retval; +} + +/** + * parses battle config entries registered by plugins. + * + * @param config the configuration file to parse. + * @param filename path to configuration file. + * @param imported whether the current config is imported from another file. + * @retval false in case of error. + */ +bool hplugins_parse_battle_conf(const struct config_t *config, const char *filename, bool imported) +{ + const struct config_setting_t *setting = NULL; + int i, val, type; + char str[1024]; + bool retval = true; + + nullpo_retr(false, config); + + for (i = 0; i < VECTOR_LENGTH(HPM->config_listeners[HPCT_BATTLE]); i++) { + const struct HPConfListenStorage *entry = &VECTOR_INDEX(HPM->config_listeners[HPCT_BATTLE], i); + const char *config_name = entry->key; + if ((setting = libconfig->lookup(config, config_name)) == NULL) { + if (!imported && entry->required) { + ShowWarning("Missing configuration '%s' in file %s!\n", config_name, filename); + retval = false; + } + continue; + } + + switch ((type = config_setting_type(setting))) { + case CONFIG_TYPE_INT: + val = libconfig->setting_get_int(setting); + break; + case CONFIG_TYPE_BOOL: + val = libconfig->setting_get_bool(setting); + break; + default: // Unsupported type + ShowWarning("Setting %s has unsupported type %d, ignoring...\n", config_name, type); + retval = false; + continue; + } + sprintf(str, "%d", val); // FIXME: Remove this when support to int's as value is added + entry->parse_func(config_name, str); + } + return retval; +} + +/** * Helper to destroy an interface's hplugin_data store and release any owned memory. * * The pointer will be cleared. @@ -904,9 +1031,11 @@ void hplugin_data_store_create(struct hplugin_data_store **storeptr, enum HPlugi /** * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching! **/ -bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, char *name) { +bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, char *name) +{ unsigned int i, j; + nullpo_retr(false, src); if (version != datacheck_version) { ShowError("HPMDataCheck:%s: DataCheck API version mismatch %d != %d\n", name, datacheck_version, version); return false; @@ -931,7 +1060,8 @@ bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, c return true; } -void HPM_datacheck_init(const struct s_HPMDataCheck *src, unsigned int length, int version) { +void HPM_datacheck_init(const struct s_HPMDataCheck *src, unsigned int length, int version) +{ unsigned int i; datacheck_version = version; @@ -947,11 +1077,13 @@ void HPM_datacheck_init(const struct s_HPMDataCheck *src, unsigned int length, i } } -void HPM_datacheck_final(void) { +void HPM_datacheck_final(void) +{ db_destroy(datacheck_db); } -void hpm_init(void) { +void hpm_init(void) +{ int i; datacheck_db = NULL; datacheck_data = NULL; @@ -962,8 +1094,8 @@ void hpm_init(void) { HPM->off = false; - memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface)); HPMiMalloc = &iMalloc_HPM; + *HPMiMalloc = *iMalloc; HPMiMalloc->malloc = HPM_mmalloc; HPMiMalloc->calloc = HPM_calloc; HPMiMalloc->realloc = HPM_realloc; @@ -1043,14 +1175,14 @@ void hpm_final(void) return; } + void hpm_defaults(void) { HPM = &HPM_s; + HPM->hooking = &HPMHooking_core_s; memset(&HPM->filenames, 0, sizeof(HPM->filenames)); VECTOR_INIT(HPM->cmdline_load_plugins); - HPM->force_return = false; - HPM->hooking = false; /* */ HPM->init = hpm_init; HPM->final = hpm_final; @@ -1067,8 +1199,9 @@ void hpm_defaults(void) HPM->pid2name = hplugins_id2name; HPM->parse_packets = hplugins_parse_packets; HPM->load_sub = NULL; - HPM->addhook_sub = NULL; - HPM->parseConf = hplugins_parse_conf; + HPM->parse_conf_entry = hplugins_parse_conf_entry; + HPM->parse_conf = hplugins_parse_conf; + HPM->parse_battle_conf = hplugins_parse_battle_conf; HPM->getBattleConf = hplugins_get_battle_conf; HPM->DataCheck = HPM_DataCheck; HPM->datacheck_init = HPM_datacheck_init; @@ -1078,4 +1211,9 @@ void hpm_defaults(void) HPM->data_store_create = hplugin_data_store_create; HPM->data_store_validate = hplugin_data_store_validate; HPM->data_store_validate_sub = NULL; + + HPM->hooking->enabled = false; + HPM->hooking->force_return = false; + HPM->hooking->addhook_sub = NULL; + HPM->hooking->Hooked = NULL; } |