summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-10-04 16:12:09 -0300
committershennetsind <ind@henn.et>2013-10-04 16:12:09 -0300
commita49787ff1589d86efa87263676761ddcbecd64ce (patch)
tree3f4c4f003f261d51995f0e3ff7092bbf82bbab68 /src/common
parent2f2afbd3b63a75695f8f96e3bcb4db9fff5a7dc6 (diff)
downloadhercules-a49787ff1589d86efa87263676761ddcbecd64ce.tar.gz
hercules-a49787ff1589d86efa87263676761ddcbecd64ce.tar.bz2
hercules-a49787ff1589d86efa87263676761ddcbecd64ce.tar.xz
hercules-a49787ff1589d86efa87263676761ddcbecd64ce.zip
HPM: Hooking!
http://hercules.ws/board/topic/2399-hpm-hooking-now-available/ Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/common')
-rw-r--r--src/common/HPM.c110
-rw-r--r--src/common/HPM.h8
-rw-r--r--src/common/HPMi.h23
3 files changed, 106 insertions, 35 deletions
diff --git a/src/common/HPM.c b/src/common/HPM.c
index 9895ae95d..8be9298f9 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -40,7 +40,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++ ) {
@@ -48,7 +48,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;
}
@@ -59,7 +59,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;
}
@@ -108,7 +108,7 @@ bool hplugin_populate(struct hplugin *plugin, const char *filename) {
return true;
}
-void hplugin_load(const char* filename) {
+struct hplugin *hplugin_load(const char* filename) {
struct hplugin *plugin;
struct hplugin_info *info;
struct HPMi_interface **HPMi;
@@ -118,7 +118,7 @@ void hplugin_load(const char* filename) {
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();
@@ -126,30 +126,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;
@@ -157,21 +160,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;
@@ -184,30 +187,34 @@ 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( !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;
+
/* id */
plugin->hpi->pid = plugin->idx;
/* core */
- plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand");
- plugin->hpi->addPacket = HPM->import_symbol("addPacket");
- plugin->hpi->addToSession = HPM->import_symbol("addToSession");
- plugin->hpi->getFromSession = HPM->import_symbol("getFromSession");
- plugin->hpi->removeFromSession = HPM->import_symbol("removeFromSession");
+ plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand",plugin->idx);
+ plugin->hpi->addPacket = HPM->import_symbol("addPacket",plugin->idx);
+ plugin->hpi->addToSession = HPM->import_symbol("addToSession",plugin->idx);
+ plugin->hpi->getFromSession = HPM->import_symbol("getFromSession",plugin->idx);
+ plugin->hpi->removeFromSession = HPM->import_symbol("removeFromSession",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);
/* server specific */
if( HPM->load_sub )
HPM->load_sub(plugin);
-
- plugin->info = info;
- plugin->filename = aStrdup(filename);
-
- return;
+
+ return plugin;
}
void hplugin_unload(struct hplugin* plugin) {
@@ -253,8 +260,26 @@ void hplugins_config_read(void) {
int length = config_setting_length(plist), i;
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(config_setting_get_string_elem(plist,i),"HPMHooking") ) {//must load it first
+ struct hplugin *plugin;
+ snprintf(filename, 60, "plugins/%s%s", config_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(config_setting_get_string_elem(plist,i),"HPMHooking") ) {//now all others
+ snprintf(filename, 60, "plugins/%s%s", config_setting_get_string_elem(plist,i), DLL_EXT);
+ HPM->load(filename);
+ }
}
config_destroy(&plugins_conf);
}
@@ -436,6 +461,25 @@ void* HPM_realloc(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;
+ return false;
+}
+void HPM_HookStop (const char *func, unsigned int pID) {
+ /* track? */
+ HPM->force_return = true;
+}
+bool HPM_HookStopped (void) {
+ return HPM->force_return;
+}
void hplugins_share_defaults(void) {
/* console */
@@ -447,6 +491,9 @@ void hplugins_share_defaults(void) {
HPM->share(hplugins_addToSession,"addToSession");
HPM->share(hplugins_getFromSession,"getFromSession");
HPM->share(hplugins_removeFromSession,"removeFromSession");
+ HPM->share(HPM_AddHook,"AddHook");
+ HPM->share(HPM_HookStop,"HookStop");
+ HPM->share(HPM_HookStopped,"HookStopped");
/* core */
HPM->share(&runflag,"runflag");
HPM->share(arg_v,"arg_v");
@@ -489,7 +536,7 @@ void hpm_init(void) {
HPMiMalloc->realloc = HPM_realloc;
HPMiMalloc->astrdup = HPM_astrdup;
- sscanf(HPM_VERSION, "%d.%d", &HPM->version[0], &HPM->version[1]);
+ 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");
@@ -554,6 +601,8 @@ void hpm_defaults(void) {
HPM->fnames = NULL;
HPM->fnamec = 0;
+ HPM->force_return = false;
+ HPM->hooking = false;
HPM->init = hpm_init;
HPM->final = hpm_final;
@@ -573,4 +622,5 @@ void hpm_defaults(void) {
HPM->pid2name = hplugins_id2name;
HPM->parse_packets = hplugins_parse_packets;
HPM->load_sub = NULL;
+ HPM->addhook_sub = NULL;
}
diff --git a/src/common/HPM.h b/src/common/HPM.h
index 614498fd3..395555948 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -79,6 +79,9 @@ struct HPM_interface {
/* vars */
unsigned int version[2];
bool off;
+ bool hooking;
+ /* hooking */
+ bool force_return;
/* data */
struct hplugin **plugins;
unsigned int plugin_count;
@@ -94,12 +97,12 @@ struct HPM_interface {
void (*init) (void);
void (*final) (void);
struct hplugin * (*create) (void);
- void (*load) (const char* filename);
+ struct hplugin * (*load) (const char* filename);
void (*unload) (struct hplugin* plugin);
bool (*exists) (const char *filename);
bool (*iscompatible) (char* version);
void (*event) (enum hp_event_types type);
- void *(*import_symbol) (char *);
+ void *(*import_symbol) (char *name, unsigned int pID);
void (*share) (void *, char *);
void (*symbol_defaults) (void);
void (*config_read) (void);
@@ -108,6 +111,7 @@ struct HPM_interface {
char *(*pid2name) (unsigned int pid);
unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point);
void (*load_sub) (struct hplugin *plugin);
+ bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
} HPM_s;
struct HPM_interface *HPM;
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index c8bce8ee8..9c2a6184e 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -35,7 +35,7 @@ struct map_session_data;
/* after */
#include "../common/showmsg.h"
-#define HPM_VERSION "0.2"
+#define HPM_VERSION "1.0"
struct hplugin_info {
char* name;
@@ -44,10 +44,10 @@ struct hplugin_info {
char* req_version;
};
-HPExport void *(*import_symbol) (char *name);
+HPExport void *(*import_symbol) (char *name, unsigned int pID);
HPExport Sql *mysql_handle;
-#define GET_SYMBOL(n) import_symbol(n)
+#define GET_SYMBOL(n) import_symbol(n,HPMi->pid)
#define SERVER_TYPE_ALL SERVER_TYPE_LOGIN|SERVER_TYPE_CHAR|SERVER_TYPE_MAP
@@ -55,6 +55,7 @@ enum hp_event_types {
HPET_INIT,/* server starts */
HPET_FINAL,/* server is shutting down */
HPET_READY,/* server is ready (online) */
+ HPET_POST_FINAL,/* server is done shutting down */
HPET_MAX,
};
@@ -70,6 +71,18 @@ enum HPluginPacketHookingPoints {
hpPHP_MAX,
};
+enum HPluginHookType {
+ HOOK_TYPE_PRE,
+ HOOK_TYPE_POST,
+};
+
+#define addHookPre(tname,hook) HPMi->AddHook(HOOK_TYPE_PRE,tname,hook,HPMi->pid)
+#define addHookPost(tname,hook) HPMi->AddHook(HOOK_TYPE_POST,tname,hook,HPMi->pid)
+/* need better names ;/ */
+/* will not run the original function after pre-hook processing is complete (other hooks will run) */
+#define hookStop() HPMi->HookStop(__func__,HPMi->pid)
+#define hookStopped() HPMi->HookStopped()
+
/* Hercules Plugin Mananger Include Interface */
HPExport struct HPMi_interface {
/* */
@@ -89,6 +102,10 @@ HPExport struct HPMi_interface {
void (*removeFromSession) (struct socket_data *sess, unsigned int id, unsigned int type);
/* packet */
bool (*addPacket) (unsigned short cmd, unsigned short length, void (*receive)(int fd), unsigned int point, unsigned int pluginID);
+ /* Hooking */
+ bool (*AddHook) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
+ void (*HookStop) (const char *func, unsigned int pID);
+ bool (*HookStopped) (void);
} HPMi_s;
#ifndef _HPM_H_
HPExport struct HPMi_interface *HPMi;