summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorshennetsind <ind@henn.et>2013-05-02 17:14:01 -0300
committershennetsind <ind@henn.et>2013-05-02 17:14:01 -0300
commita2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d (patch)
tree710a44f94cceff2f0198211d21ddfbe99b66f02c /src/common
parent219a4f5267b33349649f952266532a132a48c2a3 (diff)
downloadhercules-a2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d.tar.gz
hercules-a2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d.tar.bz2
hercules-a2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d.tar.xz
hercules-a2c45a8db6d724b98ab41fe9e75e1f7ea7523d5d.zip
Introducing Hercules Plugin Mananger
http://hercules.ws/board/topic/549-introducing-hercules-plugin-manager/ Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/common')
-rw-r--r--src/common/CMakeLists.txt3
-rw-r--r--src/common/HPM.c348
-rw-r--r--src/common/HPM.h83
-rw-r--r--src/common/HPMi.h67
-rw-r--r--src/common/Makefile.in2
-rw-r--r--src/common/console.c223
-rw-r--r--src/common/console.h24
-rw-r--r--src/common/core.c16
-rw-r--r--src/common/core.h17
-rw-r--r--src/common/db.c20
-rw-r--r--src/common/ers.c9
-rw-r--r--src/common/netbuffer.c8
-rw-r--r--src/common/showmsg.c17
-rw-r--r--src/common/showmsg.h32
14 files changed, 811 insertions, 58 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 508154c00..dbc30734c 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -68,6 +68,8 @@ set( COMMON_BASE_HEADERS
"${COMMON_SOURCE_DIR}/des.h"
"${COMMON_SOURCE_DIR}/ers.h"
"${COMMON_SOURCE_DIR}/grfio.h"
+ "${COMMON_SOURCE_DIR}/HPM.h"
+ "${COMMON_SOURCE_DIR}/HPMi.h"
"${COMMON_SOURCE_DIR}/malloc.h"
"${COMMON_SOURCE_DIR}/mapindex.h"
"${COMMON_SOURCE_DIR}/md5calc.h"
@@ -94,6 +96,7 @@ set( COMMON_BASE_SOURCES
"${COMMON_SOURCE_DIR}/des.c"
"${COMMON_SOURCE_DIR}/ers.c"
"${COMMON_SOURCE_DIR}/grfio.c"
+ "${COMMON_SOURCE_DIR}/HPM.c"
"${COMMON_SOURCE_DIR}/malloc.c"
"${COMMON_SOURCE_DIR}/mapindex.c"
"${COMMON_SOURCE_DIR}/md5calc.c"
diff --git a/src/common/HPM.c b/src/common/HPM.c
new file mode 100644
index 000000000..ec5ba888e
--- /dev/null
+++ b/src/common/HPM.c
@@ -0,0 +1,348 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#include "../common/cbasetypes.h"
+#include "../common/mmo.h"
+#include "../common/core.h"
+#include "../common/malloc.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/timer.h"
+#include "../common/conf.h"
+#include "../common/utils.h"
+#include "../common/console.h"
+#include "HPM.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+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])();
+ }
+}
+
+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;
+}
+
+void *hplugin_import_symbol(char *name) {
+ unsigned int i;
+
+ for( i = 0; i < HPM->symbol_count; i++ ) {
+ if( strcmp(HPM->symbols[i]->name,name) == 0 )
+ return HPM->symbols[i]->ptr;
+ }
+
+ ShowError("HPM:get_symbol: '"CL_WHITE"%s"CL_RESET"' not found!\n",name);
+ return NULL;
+}
+
+bool hplugin_iscompatible(char* version) {
+ unsigned int req_major = 0, req_minor = 0;
+
+ if( version == NULL )
+ return false;
+
+ sscanf(version, "%d.%d", &req_major, &req_minor);
+
+ 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 )
+ 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];
+}
+bool hplugin_showmsg_populate(struct hplugin *plugin, const char *filename) {
+ void **ShowSub;
+ const char* ShowSubNames[9] = {
+ "ShowMessage",
+ "ShowStatus",
+ "ShowSQL",
+ "ShowInfo",
+ "ShowNotice",
+ "ShowWarning",
+ "ShowDebug",
+ "ShowError",
+ "ShowFatalError",
+ };
+ void* ShowSubRef[9] = {
+ ShowMessage,
+ ShowStatus,
+ ShowSQL,
+ ShowInfo,
+ ShowNotice,
+ ShowWarning,
+ ShowDebug,
+ ShowError,
+ ShowFatalError,
+ };
+ int i;
+ for(i = 0; i < 9; i++) {
+ if( !( ShowSub = plugin_import(plugin->dll, ShowSubNames[i],void **) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve '%s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", ShowSubNames[i], filename);
+ HPM->unload(plugin);
+ return false;
+ }
+ *ShowSub = ShowSubRef[i];
+ }
+ return true;
+}
+void hplugin_load(const char* filename) {
+ struct hplugin *plugin;
+ struct hplugin_info *info;
+ struct HPMi_interface **HPMi;
+ bool anyEvent = false;
+ void **import_symbol_ref;
+
+ if( HPM->exists(filename) ) {
+ ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename);
+ return;
+ }
+
+ plugin = HPM->create();
+
+ 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;
+ }
+
+ 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;
+ }
+
+ if( !(info->type & SERVER_TYPE) ) {
+ HPM->unload(plugin);
+ return;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ *import_symbol_ref = HPM->import_symbol;
+
+ 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;
+ }
+
+ 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;
+ }
+ plugin->hpi = *HPMi;
+
+ if( ( plugin->hpi->event[HPET_INIT] = plugin_import(plugin->dll, "plugin_init",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( ( plugin->hpi->event[HPET_FINAL] = plugin_import(plugin->dll, "plugin_final",void (*)(void)) ) )
+ anyEvent = true;
+
+ if( ( plugin->hpi->event[HPET_READY] = plugin_import(plugin->dll, "server_online",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;
+ }
+
+ if( !HPM->showmsg_pop(plugin,filename) )
+ return;
+
+ 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");
+ }
+
+ plugin->info = info;
+ plugin->filename = aStrdup(filename);
+
+ return;
+}
+
+void hplugin_unload(struct hplugin* plugin) {
+ unsigned int i = plugin->idx, cursor = 0;
+
+ if( plugin->filename )
+ aFree(plugin->filename);
+ if( plugin->dll )
+ plugin_close(plugin->dll);
+
+ aFree(plugin);
+ if( !HPM->off ) {
+ 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;
+ }
+ }
+}
+
+void hplugins_config_read(void) {
+ config_t plugins_conf;
+ config_setting_t *plist = NULL;
+ const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name
+
+ if (conf_read_file(&plugins_conf, config_filename))
+ return;
+
+ if( HPM->symbol_defaults_sub )
+ HPM->symbol_defaults_sub();
+
+ plist = config_lookup(&plugins_conf, "plugins_list");
+
+ if (plist != NULL) {
+ 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);
+ }
+ config_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);
+}
+void hplugins_share_defaults(void) {
+ /* console */
+ HPM->share(console->addCommand,"addCPCommand");
+ /* 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");
+ /* 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");
+ /* timer */
+ HPM->share(gettick,"gettick");
+ HPM->share(add_timer,"add_timer");
+ HPM->share(add_timer_interval,"add_timer_interval");
+ HPM->share(add_timer_func_list,"add_timer_func_list");
+ HPM->share(delete_timer,"delete_timer");
+ HPM->share(get_uptime,"get_uptime");
+}
+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 hpm_init(void) {
+ 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]);
+
+ if( HPM->version[0] == 0 && HPM->version[1] == 0 ) {
+ ShowError("HPM:init:failed to retrieve HPM version!!\n");
+ return;
+ }
+ HPM->symbol_defaults();
+
+ console->addCommand("plugins",CPCMD_A(plugins));
+
+ return;
+}
+
+void hpm_final(void) {
+ unsigned int i;
+
+ HPM->off = true;
+
+ for( i = 0; i < HPM->plugin_count; i++ ) {
+ HPM->unload(HPM->plugins[i]);
+ }
+
+ if( HPM->plugins )
+ aFree(HPM->plugins);
+
+ for( i = 0; i < HPM->symbol_count; i++ ) {
+ aFree(HPM->symbols[i]);
+ }
+
+ if( HPM->symbols )
+ aFree(HPM->symbols);
+
+ return;
+}
+void hpm_defaults(void) {
+ HPM = &HPM_s;
+
+ HPM->init = hpm_init;
+ HPM->final = hpm_final;
+
+ HPM->create = hplugin_create;
+ HPM->load = hplugin_load;
+ HPM->unload = hplugin_unload;
+ HPM->event = hplugin_trigger_event;
+ HPM->exists = hplugin_exists;
+ 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->showmsg_pop = hplugin_showmsg_populate;
+ HPM->symbol_defaults_sub = NULL;
+} \ No newline at end of file
diff --git a/src/common/HPM.h b/src/common/HPM.h
new file mode 100644
index 000000000..ac2c4050f
--- /dev/null
+++ b/src/common/HPM.h
@@ -0,0 +1,83 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef _HPM_H_
+#define _HPM_H_
+
+#include "../common/cbasetypes.h"
+#include "../common/HPMi.h"
+
+#ifdef WIN32
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #endif
+ #include <windows.h>
+ #define plugin_open(x) LoadLibraryA(x)
+ #define plugin_import(x,y,z) (z)GetProcAddress(x,y)
+ #define plugin_close(x) FreeLibrary(x)
+
+ #define DLL_EXT ".dll"
+ #define DLL HINSTANCE
+#else
+ #include <dlfcn.h>
+ #define plugin_open(x) dlopen(x,RTLD_NOW)
+ #define plugin_import(x,y,z) (z)dlsym(x,y)
+ #define plugin_close(x) dlclose(x)
+
+ #ifdef CYGWIN
+ #define DLL_EXT ".dll"
+ #else
+ #define DLL_EXT ".so"
+ #endif
+
+ #define DLL void *
+
+ #include <string.h> // size_t
+
+#endif
+
+struct hplugin {
+ DLL dll;
+ unsigned int idx;
+ char *filename;
+ struct hplugin_info *info;
+ struct HPMi_interface *hpi;
+};
+
+struct hpm_symbol {
+ char *name;
+ void *ptr;
+};
+
+/* Hercules Plugin Manager Interface */
+struct HPM_interface {
+ /* vars */
+ unsigned int version[2];
+ bool off;
+ /* data */
+ struct hplugin **plugins;
+ unsigned int plugin_count;
+ struct hpm_symbol **symbols;
+ unsigned int symbol_count;
+ /* funcs */
+ void (*init) (void);
+ void (*final) (void);
+ struct hplugin * (*create) (void);
+ void (*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 (*share) (void *, char *);
+ void (*symbol_defaults) (void);
+ void (*config_read) (void);
+ bool (*showmsg_pop) (struct hplugin *plugin,const char *filename);
+ void (*symbol_defaults_sub) (void);
+} HPM_s;
+
+struct HPM_interface *HPM;
+
+void hpm_defaults(void);
+
+#endif /* _HPM_H_ */ \ No newline at end of file
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
new file mode 100644
index 000000000..517d9125d
--- /dev/null
+++ b/src/common/HPMi.h
@@ -0,0 +1,67 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef _HPMi_H_
+#define _HPMi_H_
+
+#include "../common/cbasetypes.h"
+#include "../common/core.h"
+#include "../common/console.h"
+
+struct script_state;
+struct AtCommandInfo;
+
+#ifdef WIN32
+ #define HPExport __declspec(dllexport)
+#else
+ #define HPExport
+#endif
+
+#ifndef _SHOWMSG_H_
+ HPExport void (*ShowMessage) (const char *, ...);
+ HPExport void (*ShowStatus) (const char *, ...);
+ HPExport void (*ShowSQL) (const char *, ...);
+ HPExport void (*ShowInfo) (const char *, ...);
+ HPExport void (*ShowNotice) (const char *, ...);
+ HPExport void (*ShowWarning) (const char *, ...);
+ HPExport void (*ShowDebug) (const char *, ...);
+ HPExport void (*ShowError) (const char *, ...);
+ HPExport void (*ShowFatalError) (const char *, ...);
+#endif
+
+/* after */
+#include "../common/showmsg.h"
+
+#define HPM_VERSION "0.1"
+
+struct hplugin_info {
+ char* name;
+ enum server_types type;
+ char* version;
+ char* req_version;
+};
+
+HPExport void *(*import_symbol) (char *name);
+#define GET_SYMBOL(n) import_symbol(n)
+
+#define SERVER_TYPE_ALL SERVER_TYPE_LOGIN|SERVER_TYPE_CHAR|SERVER_TYPE_MAP
+
+enum hp_event_types {
+ HPET_INIT,/* server starts */
+ HPET_FINAL,/* server is shutting down */
+ HPET_READY,/* server is ready (online) */
+ HPET_MAX,
+};
+
+/* Hercules Plugin Mananger Include Interface */
+struct HPMi_interface {
+ void (*event[HPET_MAX]) (void);
+ bool (*addCommand) (char *name, bool (*func)(const int fd, struct map_session_data* sd, const char* command, const char* message,struct AtCommandInfo *info));
+ bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st));
+ void (*addCPCommand) (char *name, CParseFunc func);
+} HPMi_s;
+#ifndef _HPM_H_
+ struct HPMi_interface *HPMi;
+#endif
+
+#endif /* _HPMi_H_ */ \ No newline at end of file
diff --git a/src/common/Makefile.in b/src/common/Makefile.in
index 26cae3e51..279f82e5f 100644
--- a/src/common/Makefile.in
+++ b/src/common/Makefile.in
@@ -1,5 +1,5 @@
-COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o \
+COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/HPM.o \
obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \
obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \
obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \
diff --git a/src/common/console.c b/src/common/console.c
index 67897ee81..db914db98 100644
--- a/src/common/console.c
+++ b/src/common/console.c
@@ -8,6 +8,8 @@
#include "console.h"
#ifndef MINICORE
+ #include "../common/ers.h"
+ #include "../common/malloc.h"
#include "../common/atomic.h"
#include "../common/spinlock.h"
#include "../common/thread.h"
@@ -77,7 +79,212 @@ int console_parse_key_pressed(void) {
return FD_ISSET(STDIN_FILENO, &fds);
}
#endif /* _WIN32 */
+CPCMD(exit) {
+ runflag = 0;
+}
+CPCMD(ers_report) {
+ ers_report();
+}
+CPCMD(help) {
+ unsigned int i = 0;
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( console->cmd_list[i]->next_count ) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->cmd_list[i]->cmd);
+ console->parse_list_subs(console->cmd_list[i],2);
+ } else {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->cmd_list[i]->cmd);
+ }
+ }
+}
+/* [Ind/Hercules] */
+CPCMD(malloc_usage) {
+ unsigned int val = (unsigned int)malloc_usage();
+ ShowInfo("malloc_usage: %.2f MB\n",(double)(val)/1024);
+}
+#define CP_DEF_C(x) { #x , NULL , NULL, NULL }
+#define CP_DEF_C2(x,y) { #x , NULL , #y, NULL }
+#define CP_DEF_S(x,y) { #x , console_parse_ ## x , #y, NULL }
+#define CP_DEF(x) { #x , console_parse_ ## x , NULL, NULL }
+void console_load_defaults(void) {
+ struct {
+ char *name;
+ CParseFunc func;
+ char *connect;
+ struct CParseEntry *self;
+ } default_list[] = {
+ CP_DEF(help),
+ CP_DEF_C(server),
+ CP_DEF_S(ers_report,server),
+ CP_DEF_S(malloc_usage,server),
+ CP_DEF_S(exit,server),
+ };
+ unsigned int i, len = ARRAYLENGTH(default_list);
+ struct CParseEntry *cmd;
+
+ RECREATE(console->cmds,struct CParseEntry *, len);
+
+ for(i = 0; i < len; i++) {
+ CREATE(cmd, struct CParseEntry, 1);
+
+ safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH);
+
+ if( default_list[i].func )
+ cmd->u.func = default_list[i].func;
+ else
+ cmd->u.next = NULL;
+
+ cmd->next_count = 0;
+
+ console->cmd_count++;
+ console->cmds[i] = cmd;
+ default_list[i].self = cmd;
+ if( !default_list[i].connect ) {
+ RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count);
+ console->cmd_list[console->cmd_list_count - 1] = cmd;
+ }
+ }
+
+ for(i = 0; i < len; i++) {
+ unsigned int k;
+ if( !default_list[i].connect )
+ continue;
+ for(k = 0; k < console->cmd_count; k++) {
+ if( strcmpi(default_list[i].connect,console->cmds[k]->cmd) == 0 ) {
+ cmd = default_list[i].self;
+ RECREATE(console->cmds[k]->u.next, struct CParseEntry *, ++console->cmds[k]->next_count);
+ console->cmds[k]->u.next[console->cmds[k]->next_count - 1] = cmd;
+ break;
+ }
+ }
+ }
+}
+void console_parse_create(char *name, CParseFunc func) {
+ unsigned int i;
+ char *tok;
+ char sublist[CP_CMD_LENGTH * 5];
+ struct CParseEntry *cmd;
+
+ safestrncpy(sublist, name, CP_CMD_LENGTH * 5);
+ tok = strtok(sublist,":");
+
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
+ break;
+ }
+ if( i == console->cmd_list_count ) {
+ RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count);
+ CREATE(cmd, struct CParseEntry, 1);
+ safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH);
+ cmd->next_count = 0;
+ console->cmds[console->cmd_count - 1] = cmd;
+ RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count);
+ console->cmd_list[console->cmd_list_count - 1] = cmd;
+ i = console->cmd_list_count - 1;
+ }
+
+ cmd = console->cmd_list[i];
+ while( ( tok = strtok(NULL, ":") ) != NULL ) {
+
+ for(i = 0; i < cmd->next_count; i++) {
+ if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
+ break;
+ }
+
+ if ( i == cmd->next_count ) {
+ RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count);
+ CREATE(console->cmds[console->cmd_count-1], struct CParseEntry, 1);
+ safestrncpy(console->cmds[console->cmd_count-1]->cmd, tok, CP_CMD_LENGTH);
+ console->cmds[console->cmd_count-1]->next_count = 0;
+ RECREATE(cmd->u.next, struct CParseEntry *, ++cmd->next_count);
+ cmd->u.next[cmd->next_count - 1] = console->cmds[console->cmd_count-1];
+ cmd = console->cmds[console->cmd_count-1];
+ continue;
+ }
+
+ }
+ cmd->u.func = func;
+}
+void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) {
+ unsigned int i;
+ char msg[CP_CMD_LENGTH * 2];
+ for( i = 0; i < cmd->next_count; i++ ) {
+ if( cmd->u.next[i]->next_count ) {
+ memset(msg, '-', depth);
+ snprintf(msg + depth,CP_CMD_LENGTH * 2, " '"CL_WHITE"%s"CL_RESET"'",cmd->u.next[i]->cmd);
+ ShowInfo("%s subs\n",msg);
+ console->parse_list_subs(cmd->u.next[i],depth + 1);
+ } else {
+ memset(msg, '-', depth);
+ snprintf(msg + depth,CP_CMD_LENGTH * 2, " %s",cmd->u.next[i]->cmd);
+ ShowInfo("%s\n",msg);
+ }
+ }
+}
+void console_parse_sub(char *line) {
+ struct CParseEntry *cmd;
+ char bline[200];
+ char *tok;
+ char sublist[CP_CMD_LENGTH * 5];
+ unsigned int i, len = 0;
+ memcpy(bline, line, 200);
+ tok = strtok(line, " ");
+ for ( i = 0; i < console->cmd_list_count; i++ ) {
+ if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 )
+ break;
+ }
+
+ if( i == console->cmd_list_count ) {
+ ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line);
+ return;
+ }
+
+ cmd = console->cmd_list[i];
+
+ len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd) + 1;
+
+ if( cmd->next_count == 0 && console->cmd_list[i]->u.func ) {
+ char *r = NULL;
+ if( (tok = strtok(NULL, " ")) ) {
+ r = bline;
+ r += len + 1;
+ }
+ cmd->u.func(r);
+ } else {
+ while( ( tok = strtok(NULL, " ") ) != NULL ) {
+ for( i = 0; i < cmd->next_count; i++ ) {
+ if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 )
+ break;
+ }
+ if( i == cmd->next_count ) {
+ if( strcmpi("help",tok) == 0 ) {
+ if( cmd->next_count ) {
+ ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist);
+ console->parse_list_subs(cmd,2);
+ } else {
+ ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist);
+ }
+ return;
+ }
+ ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd);
+ ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+ return;
+ }
+ if( cmd->u.next[i]->next_count == 0 && cmd->u.next[i]->u.func ) {
+ char *r = NULL;
+ if( (tok = strtok(NULL, " ")) ) {
+ r = bline;
+ r += len + strlen(cmd->u.next[i]->cmd) + 1;
+ }
+ cmd->u.next[i]->u.func(r);
+ return;
+ } else
+ cmd = cmd->u.next[i];
+ len += snprintf(sublist + len,CP_CMD_LENGTH * 5,":%s", cmd->cmd);
+ }
+ ShowError("it is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist);
+ }
+}
void console_parse(char* line) {
int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */
@@ -122,7 +329,7 @@ int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) {
int i;
EnterSpinLock(&console->ptlock);
for(i = 0; i < cinput.count; i++) {
- parse_console(cinput.queue[i]);
+ console->parse_sub(cinput.queue[i]);
}
cinput.count = 0;
LeaveSpinLock(&console->ptlock);
@@ -163,12 +370,22 @@ void console_parse_init(void) {
void console_init (void) {
#ifdef CONSOLE_INPUT
+ console->cmd_count = console->cmd_list_count = 0;
+ console->load_defaults();
console->parse_init();
#endif
}
void console_final(void) {
#ifdef CONSOLE_INPUT
+ int i;
console->parse_final();
+ for( i = 0; i < console->cmd_count; i++ ) {
+ if( console->cmds[i]->next_count )
+ aFree(console->cmds[i]->u.next);
+ aFree(console->cmds[i]);
+ }
+ aFree(console->cmds);
+ aFree(console->cmd_list);
#endif
}
void console_defaults(void) {
@@ -182,6 +399,10 @@ void console_defaults(void) {
console->parse_timer = console_parse_timer;
console->pthread_main = cThread_main;
console->parse = console_parse;
+ console->parse_sub = console_parse_sub;
console->key_pressed = console_parse_key_pressed;
+ console->load_defaults = console_load_defaults;
+ console->parse_list_subs = console_parse_list_subs;
+ console->addCommand = console_parse_create;
#endif
}
diff --git a/src/common/console.h b/src/common/console.h
index 7f1490084..ebce013f7 100644
--- a/src/common/console.h
+++ b/src/common/console.h
@@ -14,6 +14,21 @@
* why is there a limit, why not make it dynamic? - I'm playing it safe, I'd rather not play with memory management between threads
**/
#define CONSOLE_PARSE_SIZE 10
+
+typedef void (*CParseFunc)(char *line);
+#define CPCMD(x) void console_parse_ ##x (char *line)
+#define CPCMD_A(x) console_parse_ ##x
+
+#define CP_CMD_LENGTH 20
+struct CParseEntry {
+ char cmd[CP_CMD_LENGTH];
+ union {
+ CParseFunc func;
+ struct CParseEntry **next;
+ } u;
+ unsigned short next_count;
+};
+
struct {
char queue[CONSOLE_PARSE_SIZE][MAX_CONSOLE_INPUT];
unsigned short count;
@@ -31,12 +46,21 @@ struct console_interface {
ramutex ptmutex;/* parse thread mutex */
racond ptcond;/* parse thread cond */
/* */
+ struct CParseEntry **cmd_list;
+ struct CParseEntry **cmds;
+ unsigned int cmd_count;
+ unsigned int cmd_list_count;
+ /* */
void (*parse_init) (void);
void (*parse_final) (void);
int (*parse_timer) (int tid, unsigned int tick, int id, intptr_t data);
void *(*pthread_main) (void *x);
void (*parse) (char* line);
+ void (*parse_sub) (char* line);
int (*key_pressed) (void);
+ void (*load_defaults) (void);
+ void (*parse_list_subs) (struct CParseEntry *cmd, unsigned char depth);
+ void (*addCommand) (char *name, CParseFunc func);
#endif
};
diff --git a/src/common/core.c b/src/common/core.c
index da4e4ccf9..9fd9747aa 100644
--- a/src/common/core.c
+++ b/src/common/core.c
@@ -17,6 +17,7 @@
#include "../common/sql.h"
#include "../config/core.h"
#include "../common/strlib.h"
+ #include "../common/HPM.h"
#endif
#include <stdio.h>
@@ -37,7 +38,6 @@ int arg_c = 0;
char **arg_v = NULL;
char *SERVER_NAME = NULL;
-char SERVER_TYPE = ATHENA_SERVER_NONE;
#ifndef MINICORE // minimalist Core
// Added by Gabuzomeu
@@ -295,6 +295,9 @@ int main (int argc, char **argv)
arg_c = argc;
arg_v = argv;
}
+#ifndef MINICORE
+ hpm_defaults();
+#endif
console_defaults();
malloc_init();// needed for Show* in display_title() [FlavioJS]
@@ -320,13 +323,16 @@ int main (int argc, char **argv)
#endif
timer_init();
-
+
console->init();
+
+#ifndef MINICORE
+ HPM->init();
+#endif
socket_init();
do_init(argc,argv);
-
{// Main runtime cycle
int next;
while (runflag != CORE_ST_STOP) {
@@ -338,7 +344,9 @@ int main (int argc, char **argv)
console->final();
do_final();
-
+#ifndef MINICORE
+ HPM->final();
+#endif
timer_final();
socket_final();
db_final();
diff --git a/src/common/core.h b/src/common/core.h
index 21da18938..8fdcdcfc3 100644
--- a/src/common/core.h
+++ b/src/common/core.h
@@ -23,17 +23,15 @@ extern char **arg_v;
extern int runflag;
extern char *SERVER_NAME;
-enum {
- ATHENA_SERVER_NONE = 0, // not defined
- ATHENA_SERVER_LOGIN = 1, // login server
- ATHENA_SERVER_CHAR = 2, // char server
- ATHENA_SERVER_INTER = 4, // inter server
- ATHENA_SERVER_MAP = 8, // map server
+enum server_types {
+ SERVER_TYPE_UNKNOWN = 0x0,
+ SERVER_TYPE_LOGIN = 0x1,
+ SERVER_TYPE_CHAR = 0x2,
+ SERVER_TYPE_MAP = 0x4,
};
-extern char SERVER_TYPE;
+enum server_types SERVER_TYPE;
-extern int parse_console(const char* buf);
const char *get_svn_revision(void);
const char *get_git_hash (void);
extern int do_init(int,char**);
@@ -42,8 +40,7 @@ extern void do_abort(void);
extern void do_final(void);
/// The main loop continues until runflag is CORE_ST_STOP
-enum E_CORE_ST
-{
+enum E_CORE_ST {
CORE_ST_STOP = 0,
CORE_ST_RUN,
CORE_ST_LAST
diff --git a/src/common/db.c b/src/common/db.c
index 204c6d2ea..7ac9b2dc7 100644
--- a/src/common/db.c
+++ b/src/common/db.c
@@ -47,6 +47,7 @@
* - create a db that organizes itself by splaying
*
* HISTORY:
+ * 2013/04/27 - Added ERS to speed up iterator memory allocation [Ind/Hercules]
* 2012/03/09 - Added enum for data types (int, uint, void*)
* 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly.
* 2007/11/09 - Added an iterator to the database.
@@ -319,6 +320,10 @@ static struct db_stats {
#define DB_COUNTSTAT(token)
#endif /* !defined(DB_ENABLE_STATS) */
+/* [Ind/Hercules] */
+struct eri *db_iterator_ers;
+struct eri *db_alloc_ers;
+
/*****************************************************************************\
* (2) Section of private functions used by the database system. *
* db_rotate_left - Rotate a tree node to the left. *
@@ -1366,7 +1371,7 @@ void dbit_obj_destroy(DBIterator* self)
// unlock the database
db_free_unlock(it->db);
// free iterator
- aFree(self);
+ ers_free(db_iterator_ers,self);
}
/**
@@ -1384,7 +1389,7 @@ static DBIterator* db_obj_iterator(DBMap* self)
DBIterator_impl* it;
DB_COUNTSTAT(db_iterator);
- CREATE(it, struct DBIterator_impl, 1);
+ it = ers_alloc(db_iterator_ers, struct DBIterator_impl);
/* Interface of the iterator **/
it->vtable.first = dbit_obj_first;
it->vtable.last = dbit_obj_last;
@@ -2127,7 +2132,7 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args)
db->free_max = 0;
ers_destroy(db->nodes);
db_free_unlock(db);
- aFree(db);
+ ers_free(db_alloc_ers, db);
return sum;
}
@@ -2409,7 +2414,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi
case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break;
}
#endif /* DB_ENABLE_STATS */
- CREATE(db, struct DBMap_impl, 1);
+ db = ers_alloc(db_alloc_ers, struct DBMap_impl);
options = db_fix_options(type, options);
/* Interface of the database */
@@ -2602,8 +2607,9 @@ void* db_data2ptr(DBData *data)
* @public
* @see #db_final(void)
*/
-void db_init(void)
-{
+void db_init(void) {
+ db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE);
+ db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE);
DB_COUNTSTAT(db_init);
}
@@ -2696,6 +2702,8 @@ void db_final(void)
stats.db_data2ui, stats.db_data2ptr,
stats.db_init, stats.db_final);
#endif /* DB_ENABLE_STATS */
+ ers_destroy(db_iterator_ers);
+ ers_destroy(db_alloc_ers);
}
// Link DB System - jAthena
diff --git a/src/common/ers.c b/src/common/ers.c
index 3b354166e..13e54b393 100644
--- a/src/common/ers.c
+++ b/src/common/ers.c
@@ -1,7 +1,7 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
/*****************************************************************************\
- * Copyright (c) Athena Dev Teams - Licensed under GNU GPL *
- * For more information, see LICENCE in the main folder *
- * *
* <H1>Entry Reusage System</H1> *
* *
* There are several root entry managers, each with a different entry size. *
@@ -48,8 +48,7 @@
#ifndef DISABLE_ERS
-#define ERS_ROOT_SIZE 256
-#define ERS_BLOCK_ENTRIES 4096
+#define ERS_BLOCK_ENTRIES 2048
struct ers_list
{
diff --git a/src/common/netbuffer.c b/src/common/netbuffer.c
index 57742d612..60a299aa9 100644
--- a/src/common/netbuffer.c
+++ b/src/common/netbuffer.c
@@ -52,10 +52,10 @@ void netbuffer_init(){
// Set localsection name according to running serverype.
switch(SERVER_TYPE){
- case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break;
- case ATHENA_SERVER_CHAR: strcpy(localsection, "char-netbuffer"); break;
- case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break;
- case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break;
+ case SERVER_TYPE_LOGIN: strcpy(localsection, "login-netbuffer"); break;
+ case SERVER_TYPE_CHAR: strcpy(localsection, "char-netbuffer"); break;
+ //case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break;
+ case SERVER_TYPE_MAP: strcpy(localsection, "map-netbuffer"); break;
default: strcpy(localsection, "unsupported_type"); break;
}
diff --git a/src/common/showmsg.c b/src/common/showmsg.c
index 609ae3c50..50fa972f0 100644
--- a/src/common/showmsg.c
+++ b/src/common/showmsg.c
@@ -1,5 +1,6 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#include "../common/cbasetypes.h"
#include "../common/strlib.h" // StringBuf
@@ -687,22 +688,12 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap)
ShowError("Empty string passed to _vShowMessage().\n");
return 1;
}
- /**
- * For the buildbot, these result in a EXIT_FAILURE from core.c when done reading the params.
- **/
-#if defined(BUILDBOT)
- if( flag == MSG_WARNING ||
- flag == MSG_ERROR ||
- flag == MSG_SQL ) {
- buildbotflag = 1;
- }
-#endif
if(
( flag == MSG_WARNING && console_msg_log&1 ) ||
( ( flag == MSG_ERROR || flag == MSG_SQL ) && console_msg_log&2 ) ||
( flag == MSG_DEBUG && console_msg_log&4 ) ) {//[Ind]
FILE *log = NULL;
- if( (log = fopen(SERVER_TYPE == ATHENA_SERVER_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) {
+ if( (log = fopen(SERVER_TYPE == SERVER_TYPE_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) {
char timestring[255];
time_t curtime;
time(&curtime);
diff --git a/src/common/showmsg.h b/src/common/showmsg.h
index 0d6cb5c9f..a88985770 100644
--- a/src/common/showmsg.h
+++ b/src/common/showmsg.h
@@ -1,11 +1,13 @@
-// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
-// For more information, see LICENCE in the main folder
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+// Portions Copyright (c) Athena Dev Teams
#ifndef _SHOWMSG_H_
#define _SHOWMSG_H_
-#include "libconfig.h"
-
+#ifndef _HPMi_H_
+ #include "libconfig.h"
+#endif
// for help with the console colors look here:
// http://www.edoceo.com/liberum/?doc=printf-with-color
// some code explanation (used here):
@@ -85,15 +87,17 @@ enum msg_type {
};
extern void ClearScreen(void);
-extern void ShowMessage(const char *, ...);
-extern void ShowStatus(const char *, ...);
-extern void ShowSQL(const char *, ...);
-extern void ShowInfo(const char *, ...);
-extern void ShowNotice(const char *, ...);
-extern void ShowWarning(const char *, ...);
-extern void ShowDebug(const char *, ...);
-extern void ShowError(const char *, ...);
-extern void ShowFatalError(const char *, ...);
-extern void ShowConfigWarning(config_setting_t *config, const char *string, ...);
+#ifndef _HPMi_H_
+ extern void ShowMessage(const char *, ...);
+ extern void ShowStatus(const char *, ...);
+ extern void ShowSQL(const char *, ...);
+ extern void ShowInfo(const char *, ...);
+ extern void ShowNotice(const char *, ...);
+ extern void ShowWarning(const char *, ...);
+ extern void ShowDebug(const char *, ...);
+ extern void ShowError(const char *, ...);
+ extern void ShowFatalError(const char *, ...);
+ extern void ShowConfigWarning(config_setting_t *config, const char *string, ...);
+#endif
#endif /* _SHOWMSG_H_ */