diff options
-rw-r--r-- | src/char/char.c | 34 | ||||
-rw-r--r-- | src/common/HPM.c | 267 | ||||
-rw-r--r-- | src/common/HPM.h | 32 | ||||
-rw-r--r-- | src/common/HPMi.h | 29 | ||||
-rw-r--r-- | src/common/malloc.c | 7 | ||||
-rw-r--r-- | src/common/malloc.h | 11 | ||||
-rw-r--r-- | src/common/socket.c | 26 | ||||
-rw-r--r-- | src/common/socket.h | 7 | ||||
-rw-r--r-- | src/login/account.h | 2 | ||||
-rw-r--r-- | src/login/account_sql.c | 3 | ||||
-rw-r--r-- | src/login/login.c | 49 | ||||
-rw-r--r-- | src/map/HPMmap.c | 89 | ||||
-rw-r--r-- | src/map/HPMmap.h | 18 | ||||
-rw-r--r-- | src/map/Makefile.in | 4 | ||||
-rw-r--r-- | src/map/chrif.c | 14 | ||||
-rw-r--r-- | src/map/clif.c | 9 | ||||
-rw-r--r-- | src/map/map.c | 5 | ||||
-rw-r--r-- | src/map/pc.h | 3 | ||||
-rw-r--r-- | src/map/pc_groups.c | 1 | ||||
-rw-r--r-- | src/map/unit.c | 11 | ||||
-rw-r--r-- | src/plugins/sample.c | 82 |
21 files changed, 639 insertions, 64 deletions
diff --git a/src/char/char.c b/src/char/char.c index b6ea8e2f6..e6e8732db 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -14,6 +14,7 @@ #include "../common/timer.h" #include "../common/utils.h" #include "../common/console.h" +#include "../common/HPM.h" #include "int_guild.h" #include "int_homun.h" #include "int_mercenary.h" @@ -2150,6 +2151,14 @@ int parse_fromlogin(int fd) { while(RFIFOREST(fd) >= 2) { uint16 command = RFIFOW(fd,0); + + if( HPM->packetsc[hpParse_FromLogin] ) { + if( (i = HPM->parse_packets(fd,hpParse_FromLogin)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + switch( command ) { // acknowledgement of connect-to-loginserver request @@ -2704,6 +2713,14 @@ int parse_frommap(int fd) } while(RFIFOREST(fd) >= 2) { + + if( HPM->packetsc[hpParse_FromMap] ) { + if( (i = HPM->parse_packets(fd,hpParse_FromMap)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + switch(RFIFOW(fd,0)) { case 0x2b0a: @@ -3752,6 +3769,13 @@ int parse_char(int fd) //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } + if( HPM->packetsc[hpParse_Char] ) { + if( (i = HPM->parse_packets(fd,hpParse_Char)) ) { + if( i == 1 ) continue; + if( i == 2 ) return 0; + } + } + cmd = RFIFOW(fd,0); switch( cmd ) { @@ -4874,8 +4898,11 @@ int char_config_read(const char* cfgName) void do_final(void) { int i; + ShowStatus("Terminating...\n"); + HPM->event(HPET_FINAL); + set_all_offline(-1); set_all_offline_sql(); @@ -4967,6 +4994,11 @@ int do_init(int argc, char **argv) { auth_db = idb_alloc(DB_OPT_RELEASE_DATA); online_char_db = idb_alloc(DB_OPT_RELEASE_DATA); + + HPM->share(sql_handle,"sql_handle"); + HPM->config_read(); + HPM->event(HPET_INIT); + mmo_char_sql_init(); char_read_fame_list(); //Read fame lists. @@ -5034,5 +5066,7 @@ int do_init(int argc, char **argv) { runflag = CHARSERVER_ST_RUNNING; } + HPM->event(HPET_READY); + return 0; } diff --git a/src/common/HPM.c b/src/common/HPM.c index 53059d224..3b79febd7 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -22,6 +22,9 @@ #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++ ) { @@ -189,12 +192,17 @@ void hplugin_load(const char* filename) { if( !HPM->populate(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"); - } + /* 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"); + /* server specific */ + if( HPM->load_sub ) + HPM->load_sub(plugin); plugin->info = info; plugin->filename = aStrdup(filename); @@ -209,7 +217,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; @@ -253,11 +262,191 @@ void hplugins_config_read(void) { 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_addToSession(struct socket_data *sess, void *data, unsigned int id, unsigned int type, bool autofree) { + struct HPluginData *HPData; + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + ShowError("HPM->addToSession:%s: error! attempting to insert duplicate struct of id %u and type %u\n",HPM->pid2name(id),id,type); + return; + } + } + + //HPluginData is always same size, probably better to use the ERS + CREATE(HPData, struct HPluginData, 1); + + HPData->pluginID = id; + HPData->type = type; + HPData->flag.free = autofree ? 1 : 0; + HPData->data = data; + + RECREATE(sess->hdata,struct HPluginData *,++sess->hdatac); + sess->hdata[sess->hdatac - 1] = HPData; +} +void *hplugins_getFromSession(struct socket_data *sess, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + break; + } + } + + if( i != sess->hdatac ) + return sess->hdata[i]->data; + + return NULL; +} +void hplugins_removeFromSession(struct socket_data *sess, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sess->hdatac; i++) { + if( sess->hdata[i]->pluginID == id && sess->hdata[i]->type == type ) { + break; + } + } + + if( i != sess->hdatac ) { + unsigned int cursor; + + aFree(sess->hdata[i]->data); + aFree(sess->hdata[i]); + sess->hdata[i] = NULL; + + for(i = 0, cursor = 0; i < sess->hdatac; i++) { + if( sess->hdata[i] == NULL ) + continue; + if( i != cursor ) + sess->hdata[cursor] = sess->hdata[i]; + cursor++; + } + sess->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); +} +char* HPM_astrdup(const char *p, const char *file, int line, const char *func) { + return iMalloc->astrdup(p,HPM_file2ptr(file),line,func); +} + void hplugins_share_defaults(void) { /* console */ #ifdef CONSOLE_INPUT HPM->share(console->addCommand,"addCPCommand"); #endif + /* our own */ + HPM->share(hplugins_addpacket,"addPacket"); + HPM->share(hplugins_addToSession,"addToSession"); + HPM->share(hplugins_getFromSession,"getFromSession"); + HPM->share(hplugins_removeFromSession,"removeFromSession"); /* core */ HPM->share(&runflag,"runflag"); HPM->share(arg_v,"arg_v"); @@ -267,15 +456,13 @@ void hplugins_share_defaults(void) { 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"); + //session,fd_max and addr_ are shared from within socket.c /* strlib */ HPM->share(strlib,"strlib"); HPM->share(sv,"sv"); @@ -286,31 +473,34 @@ void hplugins_share_defaults(void) { 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); - } - } -} + void hpm_init(void) { + unsigned int i; + HPM->symbols = NULL; HPM->plugins = NULL; HPM->plugin_count = HPM->symbol_count = 0; HPM->off = false; + memcpy(&iMalloc_HPM, iMalloc, sizeof(struct malloc_interface)); + HPMiMalloc = &iMalloc_HPM; + HPMiMalloc->malloc = HPM_mmalloc; + HPMiMalloc->calloc = HPM_calloc; + HPMiMalloc->realloc = HPM_realloc; + HPMiMalloc->astrdup = HPM_astrdup; + 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; } + + for(i = 0; i < hpPHP_MAX; i++) { + HPM->packets[i] = NULL; + HPM->packetsc[i] = 0; + } + HPM->symbol_defaults(); #ifdef CONSOLE_INPUT @@ -318,7 +508,18 @@ void hpm_init(void) { #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); +} void hpm_final(void) { unsigned int i; @@ -337,12 +538,23 @@ 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]); + } + + /* HPM->fnames is cleared after the memory manager goes down */ + iMalloc->post_shutdown = hpm_memdown; + return; } void hpm_defaults(void) { HPM = &HPM_s; + HPM->fnames = NULL; + HPM->fnamec = 0; + HPM->init = hpm_init; HPM->final = hpm_final; @@ -358,4 +570,7 @@ 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; } diff --git a/src/common/HPM.h b/src/common/HPM.h index 10b1f0e79..d2a1308f2 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -49,6 +49,27 @@ struct hpm_symbol { void *ptr; }; +struct HPluginData { + unsigned int pluginID; + unsigned int type; + struct { + unsigned int free : 1; + } flag; + void *data; +}; + +struct HPluginPacket { + unsigned int pluginID; + unsigned short cmd; + short len; + void (*receive) (int fd); +}; + +struct HPMFileNameCache { + const char *addr; + char *name; +}; + /* Hercules Plugin Manager Interface */ struct HPM_interface { /* vars */ @@ -59,6 +80,12 @@ struct HPM_interface { unsigned int plugin_count; struct hpm_symbol **symbols; unsigned int symbol_count; + /* packet hooking points */ + struct HPluginPacket *packets[hpPHP_MAX]; + unsigned int packetsc[hpPHP_MAX]; + /* plugin file ptr caching */ + struct HPMFileNameCache *fnames; + unsigned int fnamec; /* funcs */ void (*init) (void); void (*final) (void); @@ -73,7 +100,10 @@ struct HPM_interface { void (*symbol_defaults) (void); void (*config_read) (void); bool (*populate) (struct hplugin *plugin,const char *filename); - void (*symbol_defaults_sub) (void); + void (*symbol_defaults_sub) (void);//TODO drop + char *(*pid2name) (unsigned int pid); + unsigned char (*parse_packets) (int fd, enum HPluginPacketHookingPoints point); + void (*load_sub) (struct hplugin *plugin); } HPM_s; struct HPM_interface *HPM; diff --git a/src/common/HPMi.h b/src/common/HPMi.h index 3cdb804e0..5e44b80c7 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -11,6 +11,8 @@ struct script_state; struct AtCommandInfo; +struct socket_data; +struct map_session_data; #ifdef WIN32 #define HPExport __declspec(dllexport) @@ -33,7 +35,7 @@ struct AtCommandInfo; /* after */ #include "../common/showmsg.h" -#define HPM_VERSION "0.1" +#define HPM_VERSION "0.2" struct hplugin_info { char* name; @@ -56,12 +58,37 @@ enum hp_event_types { HPET_MAX, }; +enum HPluginPacketHookingPoints { + hpClif_Parse, /* map-server (client-map) */ + hpChrif_Parse, /* map-server (char-map) */ + hpParse_FromMap, /* char-server (map-char) */ + hpParse_FromLogin, /* char-server (login-char) */ + hpParse_Char, /* char-server (client-char) */ + hpParse_FromChar, /* login-server (char-login) */ + hpParse_Login, /* login-server (client-login) */ + /* */ + hpPHP_MAX, +}; + /* Hercules Plugin Mananger Include Interface */ HPExport struct HPMi_interface { + /* */ + unsigned int pid; + /* */ 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); + /* map_session_data */ + void (*addToMSD) (struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree); + void *(*getFromMSD) (struct map_session_data *sd, unsigned int id, unsigned int type); + void (*removeFromMSD) (struct map_session_data *sd, unsigned int id, unsigned int type); + /* session[] */ + void (*addToSession) (struct socket_data *sess, void *data, unsigned int id, unsigned int type, bool autofree); + void *(*getFromSession) (struct socket_data *sess, unsigned int id, unsigned int type); + 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); } HPMi_s; #ifndef _HPM_H_ HPExport struct HPMi_interface *HPMi; diff --git a/src/common/malloc.c b/src/common/malloc.c index d629aa63f..4d2c93b77 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -11,6 +11,8 @@ #include <string.h> #include <time.h> +struct malloc_interface iMalloc_s; + ////////////// Memory Libraries ////////////////// #if defined(MEMWATCH) @@ -672,7 +674,7 @@ void memmgr_report (int extra) { if( extra != 0 ) msize = extra; - + while (block) { if (block->unit_used) { int i; @@ -784,6 +786,8 @@ void malloc_final (void) { memmgr_final (); #endif MEMORY_CHECK(); + if( iMalloc->post_shutdown ) + iMalloc->post_shutdown(); } void malloc_init (void) { @@ -825,4 +829,5 @@ void malloc_defaults(void) { iMalloc->astrdup = aStrdup_; iMalloc->free = aFree_; #endif + iMalloc->post_shutdown = NULL; } diff --git a/src/common/malloc.h b/src/common/malloc.h index 834781905..bc8aa9a20 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -67,18 +67,21 @@ void malloc_defaults(void); struct malloc_interface { + void (*init) (void); + void (*final) (void); + /* */ void* (*malloc )(size_t size, const char *file, int line, const char *func); void* (*calloc )(size_t num, size_t size, const char *file, int line, const char *func); void* (*realloc )(void *p, size_t size, const char *file, int line, const char *func); char* (*astrdup )(const char *p, const char *file, int line, const char *func); void (*free )(void *p, const char *file, int line, const char *func); - + /* */ void (*memory_check)(void); bool (*verify_ptr)(void* ptr); size_t (*usage) (void); - void (*init) (void); - void (*final) (void); -} iMalloc_s; + /* */ + void (*post_shutdown) (void); +}; void memmgr_report (int extra); diff --git a/src/common/socket.c b/src/common/socket.c index f6d5849be..4f2e386ec 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -9,6 +9,7 @@ #include "../common/showmsg.h" #include "../common/strlib.h" #include "../config/core.h" +#include "../common/HPM.h" #include "socket.h" #include <stdio.h> @@ -239,8 +240,6 @@ static time_t socket_data_last_tick = 0; // The connection is closed if it goes over the limit. #define WFIFO_MAX (1*1024*1024) -struct socket_data* session[FD_SETSIZE]; - #ifdef SEND_SHORTLIST int send_shortlist_array[FD_SETSIZE];// we only support FD_SETSIZE sockets, limit the array to that int send_shortlist_count = 0;// how many fd's are in the shortlist @@ -594,13 +593,15 @@ static int create_session(int fd, RecvFunc func_recv, SendFunc func_send, ParseF session[fd]->func_parse = func_parse; session[fd]->rdata_tick = last_tick; session[fd]->session_data = NULL; + session[fd]->hdata = NULL; + session[fd]->hdatac = 0; return 0; } static void delete_session(int fd) { - if( session_isValid(fd) ) - { + if( session_isValid(fd) ) { + unsigned int i; #ifdef SHOW_SERVER_STATS socket_data_qi -= session[fd]->rdata_size - session[fd]->rdata_pos; socket_data_qo -= session[fd]->wdata_size; @@ -609,6 +610,14 @@ static void delete_session(int fd) aFree(session[fd]->wdata); if( session[fd]->session_data ) aFree(session[fd]->session_data); + for(i = 0; i < session[fd]->hdatac; i++) { + if( session[fd]->hdata[i]->flag.free ) { + aFree(session[fd]->hdata[i]->data); + aFree(session[fd]->hdata[i]); + } + } + if( session[fd]->hdata ) + aFree(session[fd]->hdata); aFree(session[fd]); session[fd] = NULL; } @@ -1214,6 +1223,8 @@ void socket_final(void) aFree(session[0]->rdata); aFree(session[0]->wdata); aFree(session[0]); + + aFree(session); } /// Closes a socket. @@ -1375,6 +1386,8 @@ void socket_init(void) memset(send_shortlist_set, 0, sizeof(send_shortlist_set)); #endif + CREATE(session, struct socket_data *, FD_SETSIZE); + socket_config_read(SOCKET_CONF_FILENAME); // initialise last send-receive tick @@ -1392,6 +1405,11 @@ void socket_init(void) #endif ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur); + + /* Hercules Plugin Manager */ + HPM->share(session,"session"); + HPM->share(&fd_max,"fd_max"); + HPM->share(addr_,"addr"); } bool session_isValid(int fd) diff --git a/src/common/socket.h b/src/common/socket.h index 82f8b84c3..0e34da660 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -18,6 +18,8 @@ #include <time.h> +struct HPluginData; + #define FIFOSIZE_SERVERLINK 256*1024 // socket I/O macros @@ -96,6 +98,9 @@ struct socket_data ParseFunc func_parse; void* session_data; // stores application-specific data related to the session + + struct HPluginData **hdata; + unsigned int hdatac; }; struct hSockOpt { @@ -105,7 +110,7 @@ struct hSockOpt { // Data prototype declaration -extern struct socket_data* session[FD_SETSIZE]; +struct socket_data **session; extern int fd_max; diff --git a/src/login/account.h b/src/login/account.h index 999c93075..f55e38b0c 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -135,6 +135,6 @@ struct AccountDB AccountDBIterator* (*iterator)(AccountDB* self); }; -void account_db_sql_up(AccountDB* self); +Sql *account_db_sql_up(AccountDB* self); #endif // __ACCOUNT_H_INCLUDED__ diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 218248c82..533b3d860 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -687,10 +687,11 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo return result; } -void account_db_sql_up(AccountDB* self) { +Sql* account_db_sql_up(AccountDB* self) { AccountDB_SQL* db = (AccountDB_SQL*)self; Sql_HerculesUpdateCheck(db->accounts); #ifdef CONSOLE_INPUT console->setSQL(db->accounts); #endif + return db->accounts; } diff --git a/src/login/login.c b/src/login/login.c index a17faa058..f92f0094d 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -11,6 +11,7 @@ #include "../common/socket.h" #include "../common/strlib.h" #include "../common/timer.h" +#include "../common/HPM.h" #include "account.h" #include "ipban.h" #include "login.h" @@ -372,12 +373,17 @@ int parse_fromchar(int fd) ipl = server[id].ip; ip2str(ipl, ip); - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_FromChar] ) { + if( (j = HPM->parse_packets(fd,hpParse_FromChar)) ) { + if( j == 1 ) continue; + if( j == 2 ) return 0; + } + } + + switch( command ) { case 0x2712: // request from char-server to authenticate an account if( RFIFOREST(fd) < 23 ) @@ -1324,12 +1330,17 @@ int parse_login(int fd) sd->fd = fd; } - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { uint16 command = RFIFOW(fd,0); - switch( command ) - { + if( HPM->packetsc[hpParse_Login] ) { + if( (result = HPM->parse_packets(fd,hpParse_Login)) ) { + if( result == 1 ) continue; + if( result == 2 ) return 0; + } + } + + switch( command ) { case 0x0200: // New alive packet: structure: 0x200 <account.userid>.24B. used to verify if client is always alive. if (RFIFOREST(fd) < 26) @@ -1688,15 +1699,17 @@ void do_final(void) int i; struct client_hash_node *hn = login_config.client_hash_nodes; - while (hn) - { + ShowStatus("Terminating...\n"); + + HPM->event(HPET_FINAL); + + while (hn) { struct client_hash_node *tmp = hn; hn = hn->next; aFree(tmp); } login_log(0, "login server", 100, "login server shutdown"); - ShowStatus("Terminating...\n"); if( login_config.log_login ) loginlog_final(); @@ -1770,7 +1783,7 @@ int do_init(int argc, char** argv) login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME); rnd_init(); - + for( i = 0; i < ARRAYLENGTH(server); ++i ) chrif_server_init(i); @@ -1780,7 +1793,7 @@ int do_init(int argc, char** argv) // initialize static and dynamic ipban system ipban_init(); - + // Online user database init online_db = idb_alloc(DB_OPT_RELEASE_DATA); iTimer->add_timer_func_list(waiting_disconnect_timer, "waiting_disconnect_timer"); @@ -1814,6 +1827,10 @@ int do_init(int argc, char** argv) } } + HPM->share(account_db_sql_up(accounts),"sql_handle"); + HPM->config_read(); + HPM->event(HPET_INIT); + // server port open & binding if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) { ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",login_config.login_port); @@ -1824,11 +1841,11 @@ int do_init(int argc, char** argv) shutdown_callback = do_shutdown; runflag = LOGINSERVER_ST_RUNNING; } - - account_db_sql_up(accounts); ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); - + + HPM->event(HPET_READY); + return 0; } diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c new file mode 100644 index 000000000..17d72bc98 --- /dev/null +++ b/src/map/HPMmap.c @@ -0,0 +1,89 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/HPM.h" + +#include "HPMmap.h" +#include "pc.h" +#include "map.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + + +void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree) { + struct HPluginData *HPData; + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + ShowError("HPMi->addToMSD:%s: error! attempting to insert duplicate struct of type %u on '%s'\n",HPM->pid2name(id),type,sd->status.name); + return; + } + } + + CREATE(HPData, struct HPluginData, 1); + + HPData->pluginID = id; + HPData->type = type; + HPData->flag.free = autofree ? 1 : 0; + HPData->data = data; + + RECREATE(sd->hdata,struct HPluginData *,++sd->hdatac); + sd->hdata[sd->hdatac - 1] = HPData; +} +void *HPM_map_getFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + break; + } + } + + if( i != sd->hdatac ) + return sd->hdata[i]->data; + + return NULL; +} +void HPM_map_removeFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type) { + unsigned int i; + + for(i = 0; i < sd->hdatac; i++) { + if( sd->hdata[i]->pluginID == id && sd->hdata[i]->type == type ) { + break; + } + } + + if( i != sd->hdatac ) { + unsigned int cursor; + + aFree(sd->hdata[i]->data); + aFree(sd->hdata[i]); + sd->hdata[i] = NULL; + + for(i = 0, cursor = 0; i < sd->hdatac; i++) { + if( sd->hdata[i] == NULL ) + continue; + if( i != cursor ) + sd->hdata[cursor] = sd->hdata[i]; + cursor++; + } + + sd->hdatac = cursor; + } + +} +void HPM_map_plugin_load_sub(struct hplugin *plugin) { + plugin->hpi->addCommand = HPM->import_symbol("addCommand"); + plugin->hpi->addScript = HPM->import_symbol("addScript"); + /* */ + plugin->hpi->addToMSD = HPM->import_symbol("addToMSD"); + plugin->hpi->getFromMSD = HPM->import_symbol("getFromMSD"); + plugin->hpi->removeFromMSD = HPM->import_symbol("removeFromMSD"); +} diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h new file mode 100644 index 000000000..a6cac4ace --- /dev/null +++ b/src/map/HPMmap.h @@ -0,0 +1,18 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _HPM_MAP_ +#define _HPM_MAP_ + +#include "../common/cbasetypes.h" + +struct hplugin; +struct map_session_data; + +void HPM_map_addToMSD(struct map_session_data *sd, void *data, unsigned int id, unsigned int type, bool autofree); +void *HPM_map_getFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); +void HPM_map_removeFromMSD(struct map_session_data *sd, unsigned int id, unsigned int type); + +void HPM_map_plugin_load_sub(struct hplugin *plugin); + +#endif /* _HPM_MAP_ */ diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 70c0cd900..588d19eae 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -17,7 +17,7 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o + buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o HPMmap.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ obj_sql/mapreg_sql.o MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ @@ -27,7 +27,7 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ buyingstore.h searchstore.h duel.h pc_groups.h \ ../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \ - ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h + ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h HPMmap.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) diff --git a/src/map/chrif.c b/src/map/chrif.c index d44ccf721..6b0397b56 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -10,6 +10,7 @@ #include "../common/showmsg.h" #include "../common/strlib.h" #include "../common/ers.h" +#include "../common/HPM.h" #include "map.h" #include "battle.h" @@ -1396,7 +1397,7 @@ void chrif_skillid2idx(int fd) { * *------------------------------------------*/ int chrif_parse(int fd) { - int packet_len, cmd; + int packet_len, cmd, r; // only process data from the char-server if ( fd != char_fd ) { @@ -1421,9 +1422,18 @@ int chrif_parse(int fd) { } while ( RFIFOREST(fd) >= 2 ) { + + if( HPM->packetsc[hpChrif_Parse] ) { + if( (r = HPM->parse_packets(fd,hpChrif_Parse)) ) { + if( r == 1 ) continue; + if( r == 2 ) return 0; + } + } + cmd = RFIFOW(fd,0); + if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(packet_len_table) || packet_len_table[cmd-0x2af8] == 0) { - int r = intif->parse(fd); // Passed on to the intif + r = intif->parse(fd); // Passed on to the intif if (r == 1) continue; // Treated in intif if (r == 2) return 0; // Didn't have enough data (len==-1) diff --git a/src/map/clif.c b/src/map/clif.c index 44df5b607..7171a48be 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -14,6 +14,7 @@ #include "../common/utils.h" #include "../common/ers.h" #include "../common/conf.h" +#include "../common/HPM.h" #include "map.h" #include "chrif.h" @@ -17621,6 +17622,14 @@ int clif_parse(int fd) { if (RFIFOREST(fd) < 2) return 0; + + if( HPM->packetsc[hpClif_Parse] ) { + int r; + if( (r = HPM->parse_packets(fd,hpClif_Parse)) ) { + if( r == 1 ) continue; + if( r == 2 ) return 0; + } + } if( sd ) parse_cmd_func = sd->parse_cmd_func; diff --git a/src/map/map.c b/src/map/map.c index 713577495..5753fbc1d 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -51,6 +51,7 @@ #include "log.h" #include "mail.h" #include "irc-bot.h" +#include "HPMmap.h" #include <stdio.h> #include <stdlib.h> @@ -5172,6 +5173,9 @@ void map_hp_symbols(void) { /* specific */ HPM->share(atcommand->create,"addCommand"); HPM->share(script->addScript,"addScript"); + HPM->share(HPM_map_addToMSD,"addToMSD"); + HPM->share(HPM_map_getFromMSD,"getFromMSD"); + HPM->share(HPM_map_removeFromMSD,"removeFromMSD"); /* vars */ HPM->share(map,"map"); } @@ -5379,6 +5383,7 @@ int do_init(int argc, char *argv[]) iTimer->add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); iTimer->add_timer_interval(iTimer->gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); + HPM->load_sub = HPM_map_plugin_load_sub; HPM->symbol_defaults_sub = map_hp_symbols; HPM->config_read(); HPM->event(HPET_INIT); diff --git a/src/map/pc.h b/src/map/pc.h index 1f1538e1f..c2e834d1c 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -507,6 +507,9 @@ struct map_session_data { unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules] + struct HPluginData **hdata; + unsigned int hdatac; + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 9ca0fd17a..be02b5f15 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -2,6 +2,7 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#include "../common/cbasetypes.h" #include "../common/conf.h" #include "../common/db.h" #include "../common/malloc.h" diff --git a/src/map/unit.c b/src/map/unit.c index 9becb128e..41d661169 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -8,6 +8,7 @@ #include "../common/db.h" #include "../common/malloc.h" #include "../common/random.h" +#include "../common/HPM.h" #include "map.h" #include "path.h" @@ -2330,6 +2331,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) { struct map_session_data *sd = (struct map_session_data*)bl; int i; + unsigned int k; if( iStatus->isdead(bl) ) pc->setrestartvalue(sd,2); @@ -2397,6 +2399,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) aFree(sd->queues); sd->queues = NULL; } + + for( k = 0; k < sd->hdatac; k++ ) { + if( sd->hdata[k]->flag.free ) { + aFree(sd->hdata[k]->data); + aFree(sd->hdata[k]); + } + } + if( sd->hdata ) + aFree(sd->hdata); break; } case BL_PET: diff --git a/src/plugins/sample.c b/src/plugins/sample.c index 7f7528cb7..4a8402560 100644 --- a/src/plugins/sample.c +++ b/src/plugins/sample.c @@ -4,9 +4,15 @@ #include <stdio.h> #include <string.h> +#include <stdlib.h> + #include "../common/HPMi.h" +#include "../common/mmo.h" +#include "../common/socket.h" +#include "../common/malloc.h" #include "../map/script.h" #include "../map/pc.h" +#include "../map/clif.h" HPExport struct hplugin_info pinfo = { "Sample", // Plugin name @@ -26,18 +32,81 @@ BUILDIN(sample) {//script command 'sample(num);' - 1 param: struct script_state* CPCMD(sample) {//console command 'sample' - 1 param: char *line ShowInfo("I'm being run! arg -> '%s'\n",line?line:"NONE"); } -struct script_interface *script;/* used by script commands */ +struct sample_data_struct { + struct point lastMSGPosition; + unsigned int someNumber; +}; +/* sample packet implementation */ +/* cmd 0xf3 - it is a client-server existent id, for clif_parse_GlobalMessage */ +/* in this sample we do nothing and simply redirect */ +void sample_packet0f3(int fd) { + struct map_session_data *sd = session[fd]->session_data; + struct sample_data_struct *data; + + if( !sd ) return;/* socket didn't fully log-in? this packet shouldn't do anything then! */ + + ShowInfo("sample_packet0f3: Hello World! received 0xf3 for '%s', redirecting!\n",sd->status.name); + + /* sample usage of appending data to a socket_data (session[]) entry */ + if( !(data = HPMi->getFromSession(session[fd],HPMi->pid,0)) ) { + CREATE(data,struct sample_data_struct,1); + + data->lastMSGPosition.map = sd->status.last_point.map; + data->lastMSGPosition.x = sd->status.last_point.x; + data->lastMSGPosition.y = sd->status.last_point.y; + data->someNumber = rand()%777; + + ShowInfo("Created Appended session[] data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + HPMi->addToSession(session[fd],data,HPMi->pid,0,true); + } else { + ShowInfo("Existent Appended session[] data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + if( rand()%4 == 2 ) { + ShowInfo("Removing Appended session[] data\n"); + HPMi->removeFromSession(session[fd],HPMi->pid,0); + } + } + + /* sample usage of appending data to a map_session_data (sd) entry */ + if( !(data = HPMi->getFromMSD(sd,HPMi->pid,0)) ) { + CREATE(data,struct sample_data_struct,1); + + data->lastMSGPosition.map = sd->status.last_point.map; + data->lastMSGPosition.x = sd->status.last_point.x; + data->lastMSGPosition.y = sd->status.last_point.y; + data->someNumber = rand()%777; + + ShowInfo("Created Appended map_session_data data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + HPMi->addToMSD(sd,data,HPMi->pid,0,true); + } else { + ShowInfo("Existent Appended map_session_data data, %d %d %d %d\n",data->lastMSGPosition.map,data->lastMSGPosition.x,data->lastMSGPosition.y,data->someNumber); + if( rand()%4 == 2 ) { + ShowInfo("Removing Appended map_session_data data\n"); + HPMi->removeFromMSD(sd,HPMi->pid,0); + } + } + + + clif->pGlobalMessage(fd,sd); +} /* run when server starts */ HPExport void plugin_init (void) { char *server_type; char *server_name; - - //get the symbols from the server + + /* core vars */ server_type = GET_SYMBOL("SERVER_TYPE"); server_name = GET_SYMBOL("SERVER_NAME"); + /* core interfaces */ + iMalloc = GET_SYMBOL("iMalloc"); + + /* map-server interfaces */ script = GET_SYMBOL("script"); - + clif = GET_SYMBOL("clif"); + + /* session[] */ + session = GET_SYMBOL("session"); + ShowInfo ("Server type is "); switch (*server_type) { @@ -59,6 +128,11 @@ HPExport void plugin_init (void) { if( HPMi->addCPCommand != NULL ) {//link our 'sample' console command HPMi->addCPCommand("this:is:a:sample",CPCMD_A(sample)); } + + if( HPMi->addPacket != NULL ) {//link our 'sample' packet to map-server + HPMi->addPacket(0xf3,-1,sample_packet0f3,hpClif_Parse,HPMi->pid); + } + } /* run when server is ready (online) */ HPExport void server_online (void) { |