summaryrefslogtreecommitdiff
path: root/src/common/HPM.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/HPM.c')
-rw-r--r--src/common/HPM.c660
1 files changed, 586 insertions, 74 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 9283360dc..f39954175 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -1,27 +1,36 @@
// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
// See the LICENSE file
+#define HERCULES_CORE
+
+#include "../config/core.h" // CONSOLE_INPUT
+#include "HPM.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
#include "../common/cbasetypes.h"
-#include "../common/mmo.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/conf.h"
#include "../common/utils.h"
-#include "../common/console.h"
-#include "../common/strlib.h"
-#include "../common/sql.h"
-#include "HPM.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
#ifndef WIN32
-#include <unistd.h>
+# include <unistd.h>
#endif
+struct malloc_interface iMalloc_HPM;
+struct malloc_interface *HPMiMalloc;
+
void hplugin_trigger_event(enum hp_event_types type) {
unsigned int i;
for( i = 0; i < HPM->plugin_count; i++ ) {
@@ -37,7 +46,7 @@ void hplugin_export_symbol(void *var, char *name) {
HPM->symbols[HPM->symbol_count - 1]->ptr = var;
}
-void *hplugin_import_symbol(char *name) {
+void *hplugin_import_symbol(char *name, unsigned int pID) {
unsigned int i;
for( i = 0; i < HPM->symbol_count; i++ ) {
@@ -45,7 +54,7 @@ void *hplugin_import_symbol(char *name) {
return HPM->symbols[i]->ptr;
}
- ShowError("HPM:get_symbol: '"CL_WHITE"%s"CL_RESET"' not found!\n",name);
+ ShowError("HPM:get_symbol:%s: '"CL_WHITE"%s"CL_RESET"' not found!\n",HPM->pid2name(pID),name);
return NULL;
}
@@ -56,7 +65,7 @@ bool hplugin_iscompatible(char* version) {
return false;
sscanf(version, "%u.%u", &req_major, &req_minor);
-
+
return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false;
}
@@ -105,17 +114,20 @@ bool hplugin_populate(struct hplugin *plugin, const char *filename) {
return true;
}
-void hplugin_load(const char* filename) {
+#undef HPM_POP
+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;
+ unsigned int *HPMDataCheckLen;
+ struct s_HPMDataCheck *HPMDataCheck;
if( HPM->exists(filename) ) {
ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
- return;
+ return NULL;
}
plugin = HPM->create();
@@ -123,30 +135,33 @@ void hplugin_load(const char* filename) {
if( !( plugin->dll = plugin_open(filename) ) ){
ShowWarning("HPM:plugin_load: failed to load '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
HPM->unload(plugin);
- return;
+ return NULL;
}
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;
+ return NULL;
}
if( !(info->type & SERVER_TYPE) ) {
HPM->unload(plugin);
- return;
+ return NULL;
}
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;
+ return NULL;
}
-
+
+ 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;
+ return NULL;
}
*import_symbol_ref = HPM->import_symbol;
@@ -154,21 +169,21 @@ void hplugin_load(const char* filename) {
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;
+ return NULL;
}
- *sql_handle = HPM->import_symbol("sql_handle");
+ *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;
+ return NULL;
}
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;
+ return NULL;
}
plugin->hpi = *HPMi;
@@ -181,25 +196,57 @@ void hplugin_load(const char* filename) {
if( ( plugin->hpi->event[HPET_READY] = plugin_import(plugin->dll, "server_online",void (*)(void)) ) )
anyEvent = true;
+ if( ( plugin->hpi->event[HPET_POST_FINAL] = plugin_import(plugin->dll, "server_post_final",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( ( plugin->hpi->event[HPET_PRE_INIT] = plugin_import(plugin->dll, "server_preinit",void (*)(void)) ) )
+ anyEvent = true;
+
if( !anyEvent ) {
ShowWarning("HPM:plugin_load: no events found for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
HPM->unload(plugin);
- return;
+ return NULL;
}
if( !HPM->populate(plugin,filename) )
- return;
+ return NULL;
- if( SERVER_TYPE == SERVER_TYPE_MAP ) {
- plugin->hpi->addCommand = HPM->import_symbol("addCommand");
- plugin->hpi->addScript = HPM->import_symbol("addScript");
- plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand");
+ 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;
}
- plugin->info = info;
- plugin->filename = aStrdup(filename);
-
- return;
+ 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;
+ }
+
+ if( HPM->DataCheck && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,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;
+ }
+
+ /* 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);
+ /* server specific */
+ if( HPM->load_sub )
+ HPM->load_sub(plugin);
+
+ return plugin;
}
void hplugin_unload(struct hplugin* plugin) {
@@ -209,7 +256,8 @@ void hplugin_unload(struct hplugin* plugin) {
aFree(plugin->filename);
if( plugin->dll )
plugin_close(plugin->dll);
-
+ /* TODO: for manual packet unload */
+ /* - Go thru known packets and unlink any belonging to the plugin being removed */
aFree(plugin);
if( !HPM->off ) {
HPM->plugins[i] = NULL;
@@ -227,53 +275,444 @@ void hplugin_unload(struct hplugin* plugin) {
}
}
-void hplugins_config_read(void) {
+void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_count) {
config_t plugins_conf;
config_setting_t *plist = NULL;
const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
+ FILE *fp;
+ int i;
+
+// uncomment once login/char support is wrapped up
+// if( !HPM->DataCheck ) {
+// ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n");
+// return;
+// }
+
+ /* yes its ugly, its temporary and will be gone as soon as the new inter-server.conf is set */
+ if( (fp = fopen("conf/import/plugins.conf","r")) ) {
+ config_filename = "conf/import/plugins.conf";
+ fclose(fp);
+ }
- if (conf_read_file(&plugins_conf, config_filename))
+ if (libconfig->read_file(&plugins_conf, config_filename))
return;
if( HPM->symbol_defaults_sub )
HPM->symbol_defaults_sub();
- plist = config_lookup(&plugins_conf, "plugins_list");
+ plist = libconfig->lookup(&plugins_conf, "plugins_list");
+ for (i = 0; i < extra_plugins_count; i++) {
+ config_setting_t *entry = libconfig->setting_add(plist, NULL, CONFIG_TYPE_STRING);
+ config_setting_set_string(entry, extra_plugins[i]);
+ }
if (plist != NULL) {
- int length = config_setting_length(plist), i;
+ int length = libconfig->setting_length(plist);
char filename[60];
for(i = 0; i < length; i++) {
- snprintf(filename, 60, "plugins/%s%s", config_setting_get_string_elem(plist,i), DLL_EXT);
- HPM->load(filename);
+ if( !strcmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking") ) {//must load it first
+ struct hplugin *plugin;
+ snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT);
+ if( ( plugin = HPM->load(filename) ) ) {
+ bool (*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) ) {
+ HPM->hooking = true;
+ HPM->addhook_sub = addhook_sub;
+ }
+ }
+ }
+ }
+ }
+ for(i = 0; i < length; i++) {
+ if( strcmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking") ) {//now all others
+ snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT);
+ HPM->load(filename);
+ }
}
- config_destroy(&plugins_conf);
+ 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;
+ }
+
+ return NULL;
+}
+
+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);
+
+ if( action.hdatac == NULL ) { /* woo it failed! */
+ ShowError("HPM:removeFromHPData:%s: failed, type %d (%u|%u)\n",HPM->pid2name(pluginID),type,pluginID,index);
+ return;
+ }
+
+ /* flag */
+ HPDataSRC = *(action.HPDataSRCPtr);
+ max = *(action.hdatac);
+
+ 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;
+ }
+
+}
+
+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
+ */
+unsigned char hplugins_parse_packets(int fd, enum HPluginPacketHookingPoints point) {
+ unsigned int i;
+
+ for(i = 0; i < HPM->packetsc[point]; i++) {
+ if( HPM->packets[point][i].cmd == RFIFOW(fd,0) )
+ break;
+ }
+
+ if( i != HPM->packetsc[point] ) {
+ struct HPluginPacket *packet = &HPM->packets[point][i];
+ short length;
+
+ if( (length = packet->len) == -1 ) {
+ if( (length = RFIFOW(fd, 2)) > (int)RFIFOREST(fd) )
+ return 2;
+ }
+
+ packet->receive(fd);
+ RFIFOSKIP(fd, length);
+ return 1;
+ }
+
+ return 0;
+}
+
+char *hplugins_id2name (unsigned int pid) {
+ unsigned int i;
+
+ for( i = 0; i < HPM->plugin_count; i++ ) {
+ if( HPM->plugins[i]->idx == pid )
+ return HPM->plugins[i]->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;
+ }
+
+ i = HPM->fnamec;
+
+ /* 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->fnames[i].addr = file;
+ HPM->fnames[i].name = strdup(file);
+
+ return HPM->fnames[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);
+}
+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) {
+ 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) {
+ return iMalloc->reallocz(p,size,HPM_file2ptr(file),line,func);
+}
+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;
+}
+/* command-line args */
+bool hpm_parse_arg(const char *arg, int *index, char *argv[], bool param) {
+ struct HPMArgData *data;
+
+ if( (data = strdb_get(HPM->arg_db,arg)) ) {
+ data->func((data->has_param && param)?argv[(*index)+1]:NULL);
+ if( data->has_param && param ) *index += 1;
+ return true;
+ }
+
+ return false;
+}
+void hpm_arg_help(void) {
+ DBIterator *iter = db_iterator(HPM->arg_db);
+ struct HPMArgData *data = NULL;
+
+ for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) ) {
+ if( data->help != NULL )
+ data->help();
+ else
+ ShowInfo(" %s (%s)\t\t<no description provided>\n",data->name,HPM->pid2name(data->pluginID));
+ }
+
+ dbi_destroy(iter);
+}
+bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, void (*func) (char *param),void (*help) (void)) {
+ struct HPMArgData *data = NULL;
+
+ if( strdb_exists(HPM->arg_db, name) ) {
+ ShowError("HPM:add_arg:%s duplicate! (from %s)\n",name,HPM->pid2name(pluginID));
+ return false;
+ }
+
+ CREATE(data, struct HPMArgData, 1);
+
+ data->pluginID = pluginID;
+ data->name = aStrdup(name);
+ data->func = func;
+ data->help = help;
+ data->has_param = has_param;
+
+ strdb_put(HPM->arg_db, data->name, data);
+
+ 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;
+ }
+
+ 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;
+ }
+ }
+
+ 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;
+}
+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;
+ }
+
+ /* trigger and we're set! */
+ if( i != HPM->confsc[point] ) {
+ HPM->confs[point][i].func(w2);
+ return true;
+ }
+
+ return false;
+}
+
void hplugins_share_defaults(void) {
/* console */
- HPM->share(console->addCommand,"addCPCommand");
+#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((void*)get_svn_revision,"get_svn_revision");
- HPM->share((void*)get_git_hash,"get_git_hash");
HPM->share(DB, "DB");
- HPM->share(iMalloc, "iMalloc");
+ HPM->share(HPMiMalloc, "iMalloc");
/* socket */
- HPM->share(RFIFOSKIP,"RFIFOSKIP");
- HPM->share(WFIFOSET,"WFIFOSET");
- HPM->share(do_close,"do_close");
- HPM->share(make_connection,"make_connection");
- HPM->share(session,"session");
- HPM->share(&fd_max,"fd_max");
- HPM->share(addr_,"addr");
+ HPM->share(sockt,"sockt");
/* strlib */
HPM->share(strlib,"strlib");
HPM->share(sv,"sv");
@@ -281,41 +720,70 @@ void hplugins_share_defaults(void) {
/* sql */
HPM->share(SQL,"SQL");
/* timer */
- HPM->share(iTimer,"iTimer");
-
-}
-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);
- }
- }
+ HPM->share(timer,"timer");
+ /* libconfig */
+ HPM->share(libconfig,"libconfig");
+ /* sysinfo */
+ HPM->share(sysinfo,"sysinfo");
}
+
void hpm_init(void) {
+ unsigned int i;
+
HPM->symbols = NULL;
HPM->plugins = NULL;
HPM->plugin_count = HPM->symbol_count = 0;
HPM->off = false;
- sscanf(HPM_VERSION, "%d.%d", &HPM->version[0], &HPM->version[1]);
+ memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface));
+ HPMiMalloc = &iMalloc_HPM;
+ HPMiMalloc->malloc = HPM_mmalloc;
+ HPMiMalloc->calloc = HPM_calloc;
+ HPMiMalloc->realloc = HPM_realloc;
+ HPMiMalloc->reallocz = HPM_reallocz;
+ HPMiMalloc->astrdup = HPM_astrdup;
+
+ sscanf(HPM_VERSION, "%u.%u", &HPM->version[0], &HPM->version[1]);
if( HPM->version[0] == 0 && HPM->version[1] == 0 ) {
ShowError("HPM:init:failed to retrieve HPM version!!\n");
return;
}
+
+ for(i = 0; i < hpPHP_MAX; i++) {
+ HPM->packets[i] = NULL;
+ HPM->packetsc[i] = 0;
+ }
+
+ HPM->arg_db = strdb_alloc(DB_OPT_RELEASE_DATA, 0);
+
HPM->symbol_defaults();
- console->addCommand("plugins",CPCMD_A(plugins));
-
+#ifdef CONSOLE_INPUT
+ console->input->addCommand("plugins",CPCMD_A(plugins));
+#endif
return;
}
-
+void hpm_memdown(void) {
+ unsigned int i;
+
+ /* this memory is handled outside of the server's memory manager and thus cleared after memory manager goes down */
+
+ for( i = 0; i < HPM->fnamec; i++ ) {
+ free(HPM->fnames[i].name);
+ }
+
+ if( HPM->fnames )
+ free(HPM->fnames);
+
+}
+int hpm_arg_db_clear_sub(DBKey key, DBData *data, va_list args) {
+ struct HPMArgData *a = DB->data2ptr(data);
+
+ aFree(a->name);
+
+ return 0;
+}
void hpm_final(void) {
unsigned int i;
@@ -334,12 +802,45 @@ void hpm_final(void) {
if( HPM->symbols )
aFree(HPM->symbols);
-
+
+ for( i = 0; i < hpPHP_MAX; i++ ) {
+ if( HPM->packets[i] )
+ aFree(HPM->packets[i]);
+ }
+
+ for( i = 0; i < HPCT_MAX; i++ ) {
+ if( HPM->confsc[i] )
+ aFree(HPM->confs[i]);
+ }
+
+ HPM->arg_db->destroy(HPM->arg_db,HPM->arg_db_clear_sub);
+
+ /* HPM->fnames is cleared after the memory manager goes down */
+ iMalloc->post_shutdown = hpm_memdown;
+
return;
}
void hpm_defaults(void) {
+ unsigned int i;
HPM = &HPM_s;
+ HPM->fnames = NULL;
+ HPM->fnamec = 0;
+ 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->arg_db = NULL;
+ /* */
HPM->init = hpm_init;
HPM->final = hpm_final;
@@ -355,4 +856,15 @@ void hpm_defaults(void) {
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->arg_db_clear_sub = hpm_arg_db_clear_sub;
+ HPM->parse_arg = hpm_parse_arg;
+ HPM->arg_help = hpm_arg_help;
+ HPM->grabHPData = hplugins_grabHPData;
+ HPM->grabHPDataSub = NULL;
+ HPM->parseConf = hplugins_parse_conf;
+ HPM->DataCheck = NULL;
}