diff options
Diffstat (limited to 'src/common')
63 files changed, 2351 insertions, 4641 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt deleted file mode 100644 index dbc30734c..000000000 --- a/src/common/CMakeLists.txt +++ /dev/null @@ -1,170 +0,0 @@ - -# -# Create svnversion.h -# -message( STATUS "Creating svnversion.h" ) -if( SVNVERSION ) - file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h - "#ifndef SVNVERSION\n#define SVNVERSION ${SVNVERSION}\n#endif\n" ) -else() - file( WRITE ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h "" ) -endif() -set( GLOBAL_INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} CACHE INTERNAL "" ) -set( SVNVERSION ${SVNVERSION} - CACHE STRING "SVN version of the source code" ) -if( INSTALL_COMPONENT_DEVELOPMENT ) - install( FILES ${CMAKE_CURRENT_BINARY_DIR}/svnversion.h - DESTINATION "src/common" - COMPONENT Development_base ) -endif( INSTALL_COMPONENT_DEVELOPMENT ) -message( STATUS "Creating svnversion.h - done" ) - - -##################################################################### -# setup -# -set( COMMON_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" - CACHE PATH "common source directory" ) -mark_as_advanced( COMMON_SOURCE_DIR ) - -set( COMMON_ALL_HEADERS - "${CMAKE_CURRENT_BINARY_DIR}/svnversion.h" - "${COMMON_SOURCE_DIR}/cbasetypes.h" - "${COMMON_SOURCE_DIR}/mmo.h" - ) - -set( COMMON_MINI_HEADERS - ${COMMON_ALL_HEADERS} - "${COMMON_SOURCE_DIR}/core.h" - "${COMMON_SOURCE_DIR}/console.h" - "${COMMON_SOURCE_DIR}/malloc.h" - "${COMMON_SOURCE_DIR}/showmsg.h" - "${COMMON_SOURCE_DIR}/strlib.h" - ${LIBCONFIG_HEADERS} # needed by showmsg.h - CACHE INTERNAL "" ) -set( COMMON_MINI_SOURCES - "${COMMON_SOURCE_DIR}/core.c" - "${COMMON_SOURCE_DIR}/console.c" - "${COMMON_SOURCE_DIR}/malloc.c" - "${COMMON_SOURCE_DIR}/showmsg.c" - "${COMMON_SOURCE_DIR}/strlib.c" - ${LIBCONFIG_SOURCES} # needed by showmsg.c - CACHE INTERNAL "" ) -set( COMMON_MINI_INCLUDE_DIRS ${LIBCONFIG_INCLUDE_DIRS} CACHE INTERNAL "" ) -set( COMMON_MINI_DEFINITIONS "-DMINICORE ${LIBCONFIG_DEFINITIONS}" CACHE INTERNAL "" ) - - -# -# common_base -# -if( WITH_ZLIB ) -message( STATUS "Creating target common_base" ) -set( COMMON_BASE_HEADERS - ${COMMON_ALL_HEADERS} - "${COMMON_SOURCE_DIR}/conf.h" - "${COMMON_SOURCE_DIR}/core.h" - "${COMMON_SOURCE_DIR}/console.h" - "${COMMON_SOURCE_DIR}/db.h" - "${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" - "${COMMON_SOURCE_DIR}/nullpo.h" - "${COMMON_SOURCE_DIR}/random.h" - "${COMMON_SOURCE_DIR}/showmsg.h" - "${COMMON_SOURCE_DIR}/socket.h" - "${COMMON_SOURCE_DIR}/strlib.h" - "${COMMON_SOURCE_DIR}/timer.h" - "${COMMON_SOURCE_DIR}/utils.h" - "${COMMON_SOURCE_DIR}/atomic.h" - "${COMMON_SOURCE_DIR}/spinlock.h" - "${COMMON_SOURCE_DIR}/thread.h" - "${COMMON_SOURCE_DIR}/mutex.h" - "${COMMON_SOURCE_DIR}/raconf.h" - "${COMMON_SOURCE_DIR}/mempool.h" - ${LIBCONFIG_HEADERS} # needed by conf.h/showmsg.h - CACHE INTERNAL "common_base headers" ) -set( COMMON_BASE_SOURCES - "${COMMON_SOURCE_DIR}/conf.c" - "${COMMON_SOURCE_DIR}/core.c" - "${COMMON_SOURCE_DIR}/console.c" - "${COMMON_SOURCE_DIR}/db.c" - "${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" - "${COMMON_SOURCE_DIR}/nullpo.c" - "${COMMON_SOURCE_DIR}/random.c" - "${COMMON_SOURCE_DIR}/showmsg.c" - "${COMMON_SOURCE_DIR}/socket.c" - "${COMMON_SOURCE_DIR}/strlib.c" - "${COMMON_SOURCE_DIR}/timer.c" - "${COMMON_SOURCE_DIR}/utils.c" - "${COMMON_SOURCE_DIR}/thread.c" - "${COMMON_SOURCE_DIR}/mutex.c" - "${COMMON_SOURCE_DIR}/mempool.c" - "${COMMON_SOURCE_DIR}/raconf.c" - ${LIBCONFIG_SOURCES} # needed by conf.c/showmsg.c - CACHE INTERNAL "common_base sources" ) -set( COMMON_BASE_INCLUDE_DIRS - ${LIBCONFIG_INCLUDE_DIRS} - CACHE INTERNAL "common_base include dirs" ) -set( COMMON_BASE_DEFINITIONS - ${LIBCONFIG_DEFINITIONS} - CACHE INTERNAL "common_base definitions" ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ${ZLIB_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MT19937AR_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ${COMMON_BASE_INCLUDE_DIRS} ) -set( DEFINITIONS "${GLOBAL_DEFINITIONS} ${COMMON_BASE_DEFINITIONS}" ) -set( SOURCE_FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) -source_group( mt19937ar FILES ${MT19937AR_HEADERS} ${MT19937AR_SOURCES} ) -source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_BASE_SOURCES} ) -add_library( common_base ${SOURCE_FILES} ) -target_link_libraries( common_base ${LIBRARIES} ) -set_target_properties( common_base PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -include_directories( ${INCLUDE_DIRS} ) -set( HAVE_common_base ON CACHE INTERNAL "" ) -set( TARGET_LIST ${TARGET_LIST} common_base CACHE INTERNAL "" ) -message( STATUS "Creating target common_base - done" ) -else() -message( STATUS "Skipping target common_base (requires ZLIB)" ) -unset( HAVE_common_base CACHE ) -endif() - - -# -# common_sql -# -if( HAVE_common_base AND WITH_MYSQL ) -message( STATUS "Creating target common_sql" ) -set( COMMON_SQL_HEADERS - ${COMMON_ALL_HEADERS} - "${CMAKE_CURRENT_SOURCE_DIR}/sql.h" - CACHE INTERNAL "common_sql headers" ) -set( COMMON_SQL_SOURCES - "${CMAKE_CURRENT_SOURCE_DIR}/sql.c" - CACHE INTERNAL "common_sql sources" ) -set( DEPENDENCIES common_base ) -set( LIBRARIES ${GLOBAL_LIBRARIES} ${MYSQL_LIBRARIES} ) -set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ${MYSQL_INCLUDE_DIRS} ) -set( DEFINITIONS "${GLOBAL_DEFINITIONS}" ) -set( SOURCE_FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) -source_group( common FILES ${COMMON_SQL_HEADERS} ${COMMON_SQL_SOURCES} ) -add_library( common_sql ${SOURCE_FILES} ) -add_dependencies( common_sql ${DEPENDENCIES} ) -target_link_libraries( common_sql ${LIBRARIES} ${DEPENDENCIES} ) -set_target_properties( common_sql PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) -include_directories( ${INCLUDE_DIRS} ) -set( HAVE_common_sql ON CACHE INTERNAL "" ) -set( TARGET_LIST ${TARGET_LIST} common_sql CACHE INTERNAL "" ) -message( STATUS "Creating target common_sql - done" ) -else() -message( STATUS "Skipping target common_sql (requires common_base and MYSQL)" ) -unset( HAVE_common_sql CACHE ) -endif() diff --git a/src/common/HPM.c b/src/common/HPM.c index 971eb83bd..f39954175 100644 --- a/src/common/HPM.c +++ b/src/common/HPM.c @@ -1,25 +1,31 @@ // 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; @@ -404,7 +410,7 @@ void hplugins_addToHPData(enum HPluginDataTypes type, unsigned int pluginID, voi *(action.hdatac) += 1; RECREATE(*(action.HPDataSRCPtr),struct HPluginData *,*(action.hdatac)); - /* RECREATE modified the addresss */ + /* RECREATE modified the address */ HPDataSRC = *(action.HPDataSRCPtr); HPDataSRC[*(action.hdatac) - 1] = HPData; } @@ -499,7 +505,7 @@ bool hplugins_addpacket(unsigned short cmd, short length,void (*receive) (int fd return true; } -/* +/* 0 = unknown 1 = OK 2 = incomplete @@ -572,7 +578,7 @@ void* HPM_reallocz(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. */ +/* 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); @@ -629,7 +635,7 @@ bool hpm_add_arg(unsigned int pluginID, char *name, bool has_param, void (*func) CREATE(data, struct HPMArgData, 1); - data->pluginID = pluginID; + data->pluginID = pluginID; data->name = aStrdup(name); data->func = func; data->help = help; @@ -685,7 +691,7 @@ bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType po void hplugins_share_defaults(void) { /* console */ #ifdef CONSOLE_INPUT - HPM->share(console->addCommand,"addCPCommand"); + HPM->share(console->input->addCommand,"addCPCommand"); #endif /* our own */ HPM->share(hplugins_addpacket,"addPacket"); @@ -703,8 +709,6 @@ void hplugins_share_defaults(void) { 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(HPMiMalloc, "iMalloc"); /* socket */ @@ -719,6 +723,8 @@ void hplugins_share_defaults(void) { HPM->share(timer,"timer"); /* libconfig */ HPM->share(libconfig,"libconfig"); + /* sysinfo */ + HPM->share(sysinfo,"sysinfo"); } void hpm_init(void) { @@ -754,7 +760,7 @@ void hpm_init(void) { HPM->symbol_defaults(); #ifdef CONSOLE_INPUT - console->addCommand("plugins",CPCMD_A(plugins)); + console->input->addCommand("plugins",CPCMD_A(plugins)); #endif return; } diff --git a/src/common/HPM.h b/src/common/HPM.h index b466cb4f3..fe8d45066 100644 --- a/src/common/HPM.h +++ b/src/common/HPM.h @@ -1,11 +1,15 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _COMMON_HPM_H_ -#define _COMMON_HPM_H_ +#ifndef COMMON_HPM_H +#define COMMON_HPM_H + +#ifndef HERCULES_CORE +#error You should never include HPM.h from a plugin. +#endif -#include "../common/cbasetypes.h" #include "../common/HPMi.h" +#include "../common/cbasetypes.h" #ifdef WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -20,7 +24,7 @@ #define DLL HINSTANCE #else // ! WIN32 #include <dlfcn.h> - #ifdef RTLD_DEEPBIND // Certain linux ditributions require this, but it's not available everywhere + #ifdef RTLD_DEEPBIND // Certain linux distributions require this, but it's not available everywhere #define plugin_open(x) dlopen((x),RTLD_NOW|RTLD_DEEPBIND) #else // ! RTLD_DEEPBIND #define plugin_open(x) dlopen((x),RTLD_NOW) @@ -154,4 +158,4 @@ struct HPM_interface *HPM; void hpm_defaults(void); -#endif /* _COMMON_HPM_H_ */ +#endif /* COMMON_HPM_H */ diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h index 6eef028b2..79ec36472 100644 --- a/src/common/HPMDataCheck.h +++ b/src/common/HPMDataCheck.h @@ -3,134 +3,140 @@ // // NOTE: This file was auto-generated and should never be manually edited, // as it will get overwritten. -#ifndef _HPM_DATA_CHECK_H_ -#define _HPM_DATA_CHECK_H_ +#ifndef HPM_DATA_CHECK_H +#define HPM_DATA_CHECK_H HPExport const struct s_HPMDataCheck HPMDataCheck[] = { - #ifdef _COMMON_CONF_H_ + #ifdef COMMON_CONF_H { "libconfig_interface", sizeof(struct libconfig_interface) }, #else - #define _COMMON_CONF_H_ - #endif // _COMMON_CONF_H_ - #ifdef _COMMON_DB_H_ + #define COMMON_CONF_H + #endif // COMMON_CONF_H + #ifdef COMMON_DB_H { "DBData", sizeof(struct DBData) }, { "DBIterator", sizeof(struct DBIterator) }, { "DBMap", sizeof(struct DBMap) }, #else - #define _COMMON_DB_H_ - #endif // _COMMON_DB_H_ - #ifdef _COMMON_DES_H_ + #define COMMON_DB_H + #endif // COMMON_DB_H + #ifdef COMMON_DES_H { "BIT64", sizeof(struct BIT64) }, #else - #define _COMMON_DES_H_ - #endif // _COMMON_DES_H_ - #ifdef _COMMON_ERS_H_ + #define COMMON_DES_H + #endif // COMMON_DES_H + #ifdef COMMON_ERS_H { "eri", sizeof(struct eri) }, #else - #define _COMMON_ERS_H_ - #endif // _COMMON_ERS_H_ - #ifdef _COMMON_MAPINDEX_H_ + #define COMMON_ERS_H + #endif // COMMON_ERS_H + #ifdef COMMON_MAPINDEX_H { "mapindex_interface", sizeof(struct mapindex_interface) }, #else - #define _COMMON_MAPINDEX_H_ - #endif // _COMMON_MAPINDEX_H_ - #ifdef _COMMON_MMO_H_ + #define COMMON_MAPINDEX_H + #endif // COMMON_MAPINDEX_H + #ifdef COMMON_MMO_H { "quest", sizeof(struct quest) }, #else - #define _COMMON_MMO_H_ - #endif // _COMMON_MMO_H_ - #ifdef _COMMON_SOCKET_H_ + #define COMMON_MMO_H + #endif // COMMON_MMO_H + #ifdef COMMON_SOCKET_H { "socket_interface", sizeof(struct socket_interface) }, #else - #define _COMMON_SOCKET_H_ - #endif // _COMMON_SOCKET_H_ - #ifdef _COMMON_STRLIB_H_ + #define COMMON_SOCKET_H + #endif // COMMON_SOCKET_H + #ifdef COMMON_STRLIB_H { "StringBuf", sizeof(struct StringBuf) }, { "s_svstate", sizeof(struct s_svstate) }, #else - #define _COMMON_STRLIB_H_ - #endif // _COMMON_STRLIB_H_ - #ifdef _MAP_ATCOMMAND_H_ + #define COMMON_STRLIB_H + #endif // COMMON_STRLIB_H + #ifdef COMMON_SYSINFO_H + { "sysinfo_interface", sizeof(struct sysinfo_interface) }, + #else + #define COMMON_SYSINFO_H + #endif // COMMON_SYSINFO_H + #ifdef MAP_ATCOMMAND_H { "AliasInfo", sizeof(struct AliasInfo) }, { "atcommand_interface", sizeof(struct atcommand_interface) }, #else - #define _MAP_ATCOMMAND_H_ - #endif // _MAP_ATCOMMAND_H_ - #ifdef _MAP_BATTLE_H_ + #define MAP_ATCOMMAND_H + #endif // MAP_ATCOMMAND_H + #ifdef MAP_BATTLE_H { "Damage", sizeof(struct Damage) }, { "battle_interface", sizeof(struct battle_interface) }, #else - #define _MAP_BATTLE_H_ - #endif // _MAP_BATTLE_H_ - #ifdef _MAP_BUYINGSTORE_H_ + #define MAP_BATTLE_H + #endif // MAP_BATTLE_H + #ifdef MAP_BUYINGSTORE_H { "buyingstore_interface", sizeof(struct buyingstore_interface) }, { "s_buyingstore_item", sizeof(struct s_buyingstore_item) }, #else - #define _MAP_BUYINGSTORE_H_ - #endif // _MAP_BUYINGSTORE_H_ - #ifdef _MAP_CHRIF_H_ + #define MAP_BUYINGSTORE_H + #endif // MAP_BUYINGSTORE_H + #ifdef MAP_CHRIF_H { "auth_node", sizeof(struct auth_node) }, #else - #define _MAP_CHRIF_H_ - #endif // _MAP_CHRIF_H_ - #ifdef _MAP_CLIF_H_ + #define MAP_CHRIF_H + #endif // MAP_CHRIF_H + #ifdef MAP_CLIF_H { "clif_interface", sizeof(struct clif_interface) }, #else - #define _MAP_CLIF_H_ - #endif // _MAP_CLIF_H_ - #ifdef _MAP_ELEMENTAL_H_ + #define MAP_CLIF_H + #endif // MAP_CLIF_H + #ifdef MAP_ELEMENTAL_H { "elemental_skill", sizeof(struct elemental_skill) }, #else - #define _MAP_ELEMENTAL_H_ - #endif // _MAP_ELEMENTAL_H_ - #ifdef _MAP_GUILD_H_ + #define MAP_ELEMENTAL_H + #endif // MAP_ELEMENTAL_H + #ifdef MAP_GUILD_H { "eventlist", sizeof(struct eventlist) }, + { "guardian_data", sizeof(struct guardian_data) }, #else - #define _MAP_GUILD_H_ - #endif // _MAP_GUILD_H_ - #ifdef _MAP_MAPREG_H_ + #define MAP_GUILD_H + #endif // MAP_GUILD_H + #ifdef MAP_MAPREG_H { "mapreg_save", sizeof(struct mapreg_save) }, #else - #define _MAP_MAPREG_H_ - #endif // _MAP_MAPREG_H_ - #ifdef _MAP_MAP_H_ + #define MAP_MAPREG_H + #endif // MAP_MAPREG_H + #ifdef MAP_MAP_H { "map_data_other_server", sizeof(struct map_data_other_server) }, #else - #define _MAP_MAP_H_ - #endif // _MAP_MAP_H_ - #ifdef _MAP_PACKETS_STRUCT_H_ + #define MAP_MAP_H + #endif // MAP_MAP_H + #ifdef MAP_PACKETS_STRUCT_H { "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO) }, #else - #define _MAP_PACKETS_STRUCT_H_ - #endif // _MAP_PACKETS_STRUCT_H_ - #ifdef _MAP_PC_H_ + #define MAP_PACKETS_STRUCT_H + #endif // MAP_PACKETS_STRUCT_H + #ifdef MAP_PC_H { "autotrade_vending", sizeof(struct autotrade_vending) }, { "item_cd", sizeof(struct item_cd) }, #else - #define _MAP_PC_H_ - #endif // _MAP_PC_H_ - #ifdef _MAP_SCRIPT_H_ + #define MAP_PC_H + #endif // MAP_PC_H + #ifdef MAP_SCRIPT_H { "Script_Config", sizeof(struct Script_Config) }, { "reg_db", sizeof(struct reg_db) }, { "script_interface", sizeof(struct script_interface) }, #else - #define _MAP_SCRIPT_H_ - #endif // _MAP_SCRIPT_H_ - #ifdef _MAP_SEARCHSTORE_H_ + #define MAP_SCRIPT_H + #endif // MAP_SCRIPT_H + #ifdef MAP_SEARCHSTORE_H { "searchstore_interface", sizeof(struct searchstore_interface) }, #else - #define _MAP_SEARCHSTORE_H_ - #endif // _MAP_SEARCHSTORE_H_ - #ifdef _MAP_SKILL_H_ + #define MAP_SEARCHSTORE_H + #endif // MAP_SEARCHSTORE_H + #ifdef MAP_SKILL_H { "skill_cd", sizeof(struct skill_cd) }, { "skill_condition", sizeof(struct skill_condition) }, { "skill_interface", sizeof(struct skill_interface) }, { "skill_unit_save", sizeof(struct skill_unit_save) }, #else - #define _MAP_SKILL_H_ - #endif // _MAP_SKILL_H_ + #define MAP_SKILL_H + #endif // MAP_SKILL_H }; HPExport unsigned int HPMDataCheckLen = ARRAYLENGTH(HPMDataCheck); -#endif /* _HPM_DATA_CHECK_H_ */ +#endif /* HPM_DATA_CHECK_H */ diff --git a/src/common/HPMi.h b/src/common/HPMi.h index 95037fd14..478cfbdd9 100644 --- a/src/common/HPMi.h +++ b/src/common/HPMi.h @@ -1,12 +1,12 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _COMMON_HPMI_H_ -#define _COMMON_HPMI_H_ +#ifndef COMMON_HPMI_H +#define COMMON_HPMI_H #include "../common/cbasetypes.h" -#include "../common/core.h" #include "../common/console.h" +#include "../common/core.h" #include "../common/sql.h" struct script_state; @@ -20,18 +20,6 @@ struct map_session_data; #define HPExport #endif -#ifndef _COMMON_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" @@ -67,13 +55,13 @@ enum hp_event_types { }; 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) */ + 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, }; @@ -192,8 +180,8 @@ HPExport struct HPMi_interface { /* pc group permission */ void (*addPCGPermission) (unsigned int pluginID, char *name, unsigned int *mask); } HPMi_s; -#ifndef _COMMON_HPM_H_ +#ifndef HERCULES_CORE HPExport struct HPMi_interface *HPMi; #endif -#endif /* _COMMON_HPMI_H_ */ +#endif /* COMMON_HPMI_H */ diff --git a/src/common/Makefile.in b/src/common/Makefile.in index 7bb9ae630..5dfdd35bd 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -1,3 +1,7 @@ +# Copyright (c) Hercules Dev Team, licensed under GNU GPL. +# See the LICENSE file + +# @configure_input@ CONFIG_D = ../config CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h) @@ -15,8 +19,8 @@ MT19937AR_H = $(MT19937AR_D)/mt19937ar.h MT19937AR_INCLUDE = -I$(MT19937AR_D) COMMON_SHARED_C = conf.c db.c des.c ers.c grfio.c HPM.c mapindex.c md5calc.c \ - mutex.c nullpo.c random.c showmsg.c strlib.c thread.c \ - timer.c utils.c + mutex.c nullpo.c random.c showmsg.c strlib.c sysinfo.c \ + thread.c timer.c utils.c COMMON_C = $(COMMON_SHARED_C) COMMON_SHARED_OBJ = $(patsubst %.c,%.o,$(COMMON_SHARED_C)) COMMON_OBJ = $(addprefix obj_all/, $(COMMON_SHARED_OBJ) \ @@ -27,11 +31,12 @@ COMMON_C += console.c core.c malloc.c socket.c COMMON_H = atomic.h cbasetypes.h conf.h console.h core.h db.h des.h ers.h \ grfio.h HPM.h HPMi.h malloc.h mapindex.h md5calc.h mmo.h mutex.h \ nullpo.h random.h showmsg.h socket.h spinlock.h sql.h strlib.h \ - thread.h timer.h utils.h winapi.h + sysinfo.h thread.h timer.h utils.h winapi.h COMMON_SQL_OBJ = obj_sql/sql.o COMMON_SQL_H = sql.h COMMON_C += sql.c +SYSINFO_INC = sysinfo.inc HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) @@ -54,7 +59,7 @@ sql: $(SQL_DEPENDS) buildclean: @echo " CLEAN common (build temp files)" - @rm -rf *.o obj_all obj_sql + @rm -rf *.o obj_all obj_sql sysinfo.inc clean: buildclean @echo " CLEAN common" @@ -71,6 +76,10 @@ help: Makefile: Makefile.in @$(MAKE) -C ../.. src/common/Makefile +$(SYSINFO_INC): $(COMMON_C) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) + @echo " MAKE $@" + @$(MAKE) -C ../.. sysinfo + needs_mysql: @echo "MySQL not found or disabled by the configure script" @exit 1 @@ -103,18 +112,19 @@ common_mini: $(COMMON_MINI_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) obj_all/common common_sql: $(COMMON_SQL_OBJ) obj_sql/common_sql.a Makefile -obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_all - @echo " CC $<" - @$(CC) @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/sysinfo.o: sysinfo.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) $(SYSINFO_INC) | obj_all -obj_all/mini%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_all +obj_all/%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all @echo " CC $<" - @$(CC) @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) | obj_sql +obj_all/mini%.o: %.c $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_all @echo " CC $<" - @$(CC) @CFLAGS@ $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DMINICORE @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(CONFIG_H) $(LIBCONFIG_H) | $(SYSINFO_INC) obj_sql + @echo " CC $<" + @$(CC) @CFLAGS@ @DEFS@ $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files $(MT19937AR_OBJ): diff --git a/src/common/atomic.h b/src/common/atomic.h index 8c01943e7..e73b1c464 100644 --- a/src/common/atomic.h +++ b/src/common/atomic.h @@ -1,19 +1,19 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _COMMON_ATOMIC_H_ -#define _COMMON_ATOMIC_H_ +#ifndef COMMON_ATOMIC_H +#define COMMON_ATOMIC_H -// Atomic Operations +// Atomic Operations // (Interlocked CompareExchange, Add .. and so on ..) -// +// // Implementation varies / depends on: // - Architecture // - Compiler // - Operating System // -// our Abstraction is fully API-Compatible to Microsofts implementation @ NT5.0+ -// +// our Abstraction is fully API-Compatible to Microsoft's implementation @ NT5.0+ +// #include "../common/cbasetypes.h" #if defined(_MSC_VER) @@ -23,7 +23,7 @@ #if _MSC_VER < 1800 #if !defined(_M_X64) -// When compiling for windows 32bit, the 8byte interlocked operations are not provided by microsoft +// When compiling for windows 32bit, the 8byte interlocked operations are not provided by Microsoft // (because they need at least i586 so its not generic enough.. ... ) forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, int64 _cmp){ _asm{ @@ -36,7 +36,7 @@ forceinline int64 InterlockedCompareExchange64(volatile int64 *dest, int64 exch, mov ecx,4[edi]; mov esi,dest; - lock CMPXCHG8B [esi]; + lock CMPXCHG8B [esi]; } } @@ -143,7 +143,7 @@ static forceinline int32 InterlockedExchange(volatile int32 *target, int32 val){ }//end: InterlockedExchange() -#endif //endif compiler decission +#endif //endif compiler decision -#endif /* _COMMON_ATOMIC_H_ */ +#endif /* COMMON_ATOMIC_H */ diff --git a/src/common/cbasetypes.h b/src/common/cbasetypes.h index f44e80413..6ca67382f 100644 --- a/src/common/cbasetypes.h +++ b/src/common/cbasetypes.h @@ -1,5 +1,5 @@ -#ifndef _COMMON_CBASETYPES_H_ -#define _COMMON_CBASETYPES_H_ +#ifndef COMMON_CBASETYPES_H +#define COMMON_CBASETYPES_H /* +--------+-----------+--------+---------+ * | ILP32 | LP64 | ILP64 | (LL)P64 | @@ -94,12 +94,6 @@ // portable printf/scanf format macros and integer definitions // NOTE: Visual C++ uses <inttypes.h> and <stdint.h> provided in /3rdparty ////////////////////////////////////////////////////////////////////////// -#ifdef __cplusplus -#define __STDC_CONSTANT_MACROS -#define __STDC_FORMAT_MACROS -#define __STDC_LIMIT_MACROS -#endif - #include <inttypes.h> #include <stdint.h> #include <limits.h> @@ -280,11 +274,6 @@ typedef uintptr_t uintptr; #endif -///////////////////////////// -// for those still not building c++ -#ifndef __cplusplus -////////////////////////////// - // boolean types for C #if !defined(_MSC_VER) || _MSC_VER >= 1800 // MSVC doesn't have stdbool.h yet as of Visual Studio 2012 (MSVC version 17.00) @@ -302,10 +291,6 @@ typedef char bool; #define __bool_true_false_are_defined #endif // __bool_true_false_are_defined -////////////////////////////// -#endif // not __cplusplus -////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // macro tools @@ -313,7 +298,7 @@ typedef char bool; #undef swap #endif // hmm only ints? -//#define swap(a,b) { int temp=a; a=b; b=temp;} +//#define swap(a,b) { int temp=a; a=b; b=temp;} // if using macros then something that is type independent //#define swap(a,b) ((a == b) || ((a ^= b), (b ^= a), (a ^= b))) // Avoid "value computed is not used" warning and generates the same assembly code @@ -421,26 +406,11 @@ typedef char bool; #define EXPAND_AND_QUOTE(x) QUOTE(x) -////////////////////////////////////////////////////////////////////////// -// Set a pointer variable to a pointer value. -#ifdef __cplusplus -template <typename T1, typename T2> -void SET_POINTER(T1*&var, T2* p) -{ - var = static_cast<T1*>(p); -} -template <typename T1, typename T2> -void SET_FUNCPOINTER(T1& var, T2 p) -{ - char ASSERT_POINTERSIZE[sizeof(T1) == sizeof(void*) && sizeof(T2) == sizeof(void*)?1:-1];// 1 if true, -1 if false - union{ T1 out; T2 in; } tmp;// /!\ WARNING casting a pointer to a function pointer is against the C++ standard - tmp.in = p; - var = tmp.out; -} +/* pointer size fix which fixes several gcc warnings */ +#ifdef __64BIT__ + #define h64BPTRSIZE(y) ((intptr)(y)) #else -#define SET_POINTER(var,p) ((var) = (p)) -#define SET_FUNCPOINTER(var,p) ((var) = (p)) + #define h64BPTRSIZE(y) (y) #endif - -#endif /* _COMMON_CBASETYPES_H_ */ +#endif /* COMMON_CBASETYPES_H */ diff --git a/src/common/conf.c b/src/common/conf.c index b816b2f7f..46a034497 100644 --- a/src/common/conf.c +++ b/src/common/conf.c @@ -2,7 +2,10 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + #include "conf.h" + #include "../../3rdparty/libconfig/libconfig.h" #include "../common/showmsg.h" // ShowError diff --git a/src/common/conf.h b/src/common/conf.h index 9aff3df47..c232a035c 100644 --- a/src/common/conf.h +++ b/src/common/conf.h @@ -2,14 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_CONF_H_ -#define _COMMON_CONF_H_ +#ifndef COMMON_CONF_H +#define COMMON_CONF_H #include "../common/cbasetypes.h" + #include "../../3rdparty/libconfig/libconfig.h" /** - * The libconfig interface -- specially for plugins, but we enforce it throughought the core to be consistent + * The libconfig interface -- specially for plugins, but we enforce it throughout the core to be consistent **/ struct libconfig_interface { int (*read) (config_t *config, FILE *stream); @@ -94,4 +95,4 @@ struct libconfig_interface *libconfig; void libconfig_defaults(void); -#endif // _COMMON_CONF_H_ +#endif // COMMON_CONF_H diff --git a/src/common/console.c b/src/common/console.c index ec228b563..6a82db555 100644 --- a/src/common/console.c +++ b/src/common/console.c @@ -2,47 +2,51 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#include "../config/core.h" // CONSOLE_INPUT, MAX_CONSOLE_INPUT +#include "console.h" + +#include <stdio.h> +#include <stdlib.h> + #include "../common/cbasetypes.h" -#include "../common/showmsg.h" #include "../common/core.h" -#include "../config/core.h" -#include "console.h" +#include "../common/showmsg.h" +#include "../common/sysinfo.h" #ifndef MINICORE - #include "../common/ers.h" - #include "../common/malloc.h" - #include "../common/atomic.h" - #include "../common/spinlock.h" - #include "../common/thread.h" - #include "../common/mutex.h" - #include "../common/timer.h" - #include "../common/strlib.h" - #include "../common/sql.h" +# include "../common/atomic.h" +# include "../common/ers.h" +# include "../common/malloc.h" +# include "../common/mutex.h" +# include "../common/spinlock.h" +# include "../common/sql.h" +# include "../common/strlib.h" +# include "../common/thread.h" +# include "../common/timer.h" #endif -#include <stdio.h> -#include <stdlib.h> #if !defined(WIN32) - #include <unistd.h> - #include <sys/time.h> +# include <sys/time.h> +# include <unistd.h> #else - #include "../common/winapi.h" // Console close event handling +# include "../common/winapi.h" // Console close event handling +# ifdef CONSOLE_INPUT +# include <conio.h> /* _kbhit() */ +# endif #endif +struct console_interface console_s; #ifdef CONSOLE_INPUT - #if defined(WIN32) - #include <conio.h> /* _kbhit() */ - #endif +struct console_input_interface console_input_s; #endif -struct console_interface console_s; - /*====================================== * CORE : Display title *--------------------------------------*/ void display_title(void) { - const char* svn = get_svn_revision(); - const char* git = get_git_hash(); + const char *vcstype = sysinfo->vcstype(); ShowMessage("\n"); ShowMessage(""CL_BG_RED""CL_BT_WHITE" "CL_CLL""CL_NORMAL"\n"); @@ -57,10 +61,13 @@ void display_title(void) { ShowMessage(""CL_BG_RED""CL_BT_WHITE" http://hercules.ws/board/ "CL_CLL""CL_NORMAL"\n"); ShowMessage(""CL_BG_RED""CL_BT_WHITE" "CL_CLL""CL_NORMAL"\n"); - if( git[0] != HERC_UNKNOWN_VER ) - ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git); - else if( svn[0] != HERC_UNKNOWN_VER ) - ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn); + ShowInfo("Hercules %d-bit for %s\n", sysinfo->is64bit() ? 64 : 32, sysinfo->platform()); + ShowInfo("%s revision (src): '"CL_WHITE"%s"CL_RESET"'\n", vcstype, sysinfo->vcsrevision_src()); + ShowInfo("%s revision (scripts): '"CL_WHITE"%s"CL_RESET"'\n", vcstype, sysinfo->vcsrevision_scripts()); + ShowInfo("OS version: '"CL_WHITE"%s"CL_RESET" [%s]'\n", sysinfo->osversion(), sysinfo->arch()); + ShowInfo("CPU: '"CL_WHITE"%s [%d]"CL_RESET"'\n", sysinfo->cpu(), sysinfo->cpucores()); + ShowInfo("Compiled with %s\n", sysinfo->compiler()); + ShowInfo("Compile Flags: %s\n", sysinfo->cflags()); } #ifdef CONSOLE_INPUT #if defined(WIN32) @@ -113,12 +120,12 @@ CPCMD_C(mem_report,server) { **/ 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); + for ( i = 0; i < console->input->cmd_list_count; i++ ) { + if( console->input->cmd_list[i]->next_count ) { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->input->cmd_list[i]->cmd); + console->input->parse_list_subs(console->input->cmd_list[i],2); } else { - ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->cmd_list[i]->cmd); + ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->input->cmd_list[i]->cmd); } } } @@ -141,7 +148,7 @@ CPCMD_C(skip,update) { ShowDebug("usage example: sql update skip 2013-02-14--16-15.sql\n"); return; } - Sql_HerculesUpdateSkip(console->SQL, line); + Sql_HerculesUpdateSkip(console->input->SQL, line); } /** @@ -203,7 +210,7 @@ void console_load_defaults(void) { unsigned int i, len = ARRAYLENGTH(default_list); struct CParseEntry *cmd; - RECREATE(console->cmds,struct CParseEntry *, len); + RECREATE(console->input->cmds,struct CParseEntry *, len); for(i = 0; i < len; i++) { CREATE(cmd, struct CParseEntry, 1); @@ -217,12 +224,12 @@ void console_load_defaults(void) { cmd->next_count = 0; - console->cmd_count++; - console->cmds[i] = cmd; + console->input->cmd_count++; + console->input->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; + RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count); + console->input->cmd_list[console->input->cmd_list_count - 1] = cmd; } } @@ -230,11 +237,11 @@ void console_load_defaults(void) { 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 ) { + for(k = 0; k < console->input->cmd_count; k++) { + if( strcmpi(default_list[i].connect,console->input->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; + RECREATE(console->input->cmds[k]->u.next, struct CParseEntry *, ++console->input->cmds[k]->next_count); + console->input->cmds[k]->u.next[console->input->cmds[k]->next_count - 1] = cmd; break; } } @@ -253,23 +260,23 @@ void console_parse_create(char *name, CParseFunc func) { 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 ) + for ( i = 0; i < console->input->cmd_list_count; i++ ) { + if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 ) break; } - if( i == console->cmd_list_count ) { - RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count); + if( i == console->input->cmd_list_count ) { + RECREATE(console->input->cmds,struct CParseEntry *, ++console->input->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; + console->input->cmds[console->input->cmd_count - 1] = cmd; + RECREATE(console->input->cmd_list,struct CParseEntry *, ++console->input->cmd_list_count); + console->input->cmd_list[console->input->cmd_list_count - 1] = cmd; + i = console->input->cmd_list_count - 1; } - cmd = console->cmd_list[i]; + cmd = console->input->cmd_list[i]; while( ( tok = strtok(NULL, ":") ) != NULL ) { for(i = 0; i < cmd->next_count; i++) { @@ -278,13 +285,13 @@ void console_parse_create(char *name, CParseFunc func) { } 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(console->input->cmds,struct CParseEntry *, ++console->input->cmd_count); + CREATE(console->input->cmds[console->input->cmd_count-1], struct CParseEntry, 1); + safestrncpy(console->input->cmds[console->input->cmd_count-1]->cmd, tok, CP_CMD_LENGTH); + console->input->cmds[console->input->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]; + cmd->u.next[cmd->next_count - 1] = console->input->cmds[console->input->cmd_count-1]; + cmd = console->input->cmds[console->input->cmd_count-1]; continue; } @@ -299,7 +306,7 @@ void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) { 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); + console->input->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); @@ -317,21 +324,21 @@ void console_parse_sub(char *line) { 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 ) + for ( i = 0; i < console->input->cmd_list_count; i++ ) { + if( strcmpi(tok,console->input->cmd_list[i]->cmd) == 0 ) break; } - if( i == console->cmd_list_count ) { + if( i == console->input->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]; + cmd = console->input->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 ) { + if( cmd->next_count == 0 && console->input->cmd_list[i]->u.func ) { char *r = NULL; if( (tok = strtok(NULL, " ")) ) { r = bline; @@ -348,7 +355,7 @@ void console_parse_sub(char *line) { if( strcmpi("help",tok) == 0 ) { if( cmd->next_count ) { ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist); - console->parse_list_subs(cmd,2); + console->input->parse_list_subs(cmd,2); } else { ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist); } @@ -389,95 +396,95 @@ void console_parse(char* line) { } void *cThread_main(void *x) { - while( console->ptstate ) {/* loopx */ - if( console->key_pressed() ) { + while( console->input->ptstate ) {/* loopx */ + if( console->input->key_pressed() ) { char input[MAX_CONSOLE_INPUT]; - console->parse(input); + console->input->parse(input); if( input[0] != '\0' ) {/* did we get something? */ - EnterSpinLock(&console->ptlock); + EnterSpinLock(&console->input->ptlock); if( cinput.count == CONSOLE_PARSE_SIZE ) { - LeaveSpinLock(&console->ptlock); + LeaveSpinLock(&console->input->ptlock); continue;/* drop */ } safestrncpy(cinput.queue[cinput.count++],input,MAX_CONSOLE_INPUT); - LeaveSpinLock(&console->ptlock); + LeaveSpinLock(&console->input->ptlock); } } - ramutex_lock( console->ptmutex ); - racond_wait( console->ptcond, console->ptmutex, -1 ); - ramutex_unlock( console->ptmutex ); + ramutex_lock( console->input->ptmutex ); + racond_wait( console->input->ptcond, console->input->ptmutex, -1 ); + ramutex_unlock( console->input->ptmutex ); } return NULL; } int console_parse_timer(int tid, int64 tick, int id, intptr_t data) { int i; - EnterSpinLock(&console->ptlock); + EnterSpinLock(&console->input->ptlock); for(i = 0; i < cinput.count; i++) { - console->parse_sub(cinput.queue[i]); + console->input->parse_sub(cinput.queue[i]); } cinput.count = 0; - LeaveSpinLock(&console->ptlock); - racond_signal(console->ptcond); + LeaveSpinLock(&console->input->ptlock); + racond_signal(console->input->ptcond); return 0; } void console_parse_final(void) { - if( console->ptstate ) { - InterlockedDecrement(&console->ptstate); - racond_signal(console->ptcond); + if( console->input->ptstate ) { + InterlockedDecrement(&console->input->ptstate); + racond_signal(console->input->ptcond); /* wait for thread to close */ - rathread_wait(console->pthread, NULL); + rathread_wait(console->input->pthread, NULL); - racond_destroy(console->ptcond); - ramutex_destroy(console->ptmutex); + racond_destroy(console->input->ptcond); + ramutex_destroy(console->input->ptmutex); } } void console_parse_init(void) { cinput.count = 0; - console->ptstate = 1; + console->input->ptstate = 1; - InitializeSpinLock(&console->ptlock); + InitializeSpinLock(&console->input->ptlock); - console->ptmutex = ramutex_create(); - console->ptcond = racond_create(); + console->input->ptmutex = ramutex_create(); + console->input->ptcond = racond_create(); - if( (console->pthread = rathread_create(console->pthread_main, NULL)) == NULL ){ + if( (console->input->pthread = rathread_create(console->input->pthread_main, NULL)) == NULL ){ ShowFatalError("console_parse_init: failed to spawn console_parse thread.\n"); exit(EXIT_FAILURE); } - timer->add_func_list(console->parse_timer, "console_parse_timer"); - timer->add_interval(timer->gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */ + timer->add_func_list(console->input->parse_timer, "console_parse_timer"); + timer->add_interval(timer->gettick() + 1000, console->input->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */ } void console_setSQL(Sql *SQL_handle) { - console->SQL = SQL_handle; + console->input->SQL = SQL_handle; } #endif /* CONSOLE_INPUT */ void console_init (void) { #ifdef CONSOLE_INPUT - console->cmd_count = console->cmd_list_count = 0; - console->load_defaults(); - console->parse_init(); + console->input->cmd_count = console->input->cmd_list_count = 0; + console->input->load_defaults(); + console->input->parse_init(); #endif } void console_final(void) { #ifdef CONSOLE_INPUT unsigned 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]); + console->input->parse_final(); + for( i = 0; i < console->input->cmd_count; i++ ) { + if( console->input->cmds[i]->next_count ) + aFree(console->input->cmds[i]->u.next); + aFree(console->input->cmds[i]); } - aFree(console->cmds); - aFree(console->cmd_list); + aFree(console->input->cmds); + aFree(console->input->cmd_list); #endif } void console_defaults(void) { @@ -486,17 +493,20 @@ void console_defaults(void) { console->final = console_final; console->display_title = display_title; #ifdef CONSOLE_INPUT - console->parse_init = console_parse_init; - console->parse_final = console_parse_final; - 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; - console->setSQL = console_setSQL; - console->SQL = NULL; + console->input = &console_input_s; + console->input->parse_init = console_parse_init; + console->input->parse_final = console_parse_final; + console->input->parse_timer = console_parse_timer; + console->input->pthread_main = cThread_main; + console->input->parse = console_parse; + console->input->parse_sub = console_parse_sub; + console->input->key_pressed = console_parse_key_pressed; + console->input->load_defaults = console_load_defaults; + console->input->parse_list_subs = console_parse_list_subs; + console->input->addCommand = console_parse_create; + console->input->setSQL = console_setSQL; + console->input->SQL = NULL; +#else + console->input = NULL; #endif } diff --git a/src/common/console.h b/src/common/console.h index bd1de4cbf..062d48bbe 100644 --- a/src/common/console.h +++ b/src/common/console.h @@ -1,14 +1,16 @@ // Copyright (c) Hercules Dev Team, licensed under GNU GPL. // See the LICENSE file -#ifndef _COMMON_CONSOLE_H_ -#define _COMMON_CONSOLE_H_ +#ifndef COMMON_CONSOLE_H +#define COMMON_CONSOLE_H -#include "../common/thread.h" +#include "../config/core.h" // MAX_CONSOLE_INPUT + +#include "../common/cbasetypes.h" #include "../common/mutex.h" #include "../common/spinlock.h" #include "../common/sql.h" -#include "../config/core.h" +#include "../common/thread.h" /** * Queue Max @@ -47,17 +49,14 @@ struct { unsigned short count; } cinput; -struct console_interface { - void (*init) (void); - void (*final) (void); - void (*display_title) (void); #ifdef CONSOLE_INPUT +struct console_input_interface { /* vars */ SPIN_LOCK ptlock;/* parse thread lock */ - rAthread pthread;/* parse thread */ + rAthread *pthread;/* parse thread */ volatile int32 ptstate;/* parse thread state */ - ramutex ptmutex;/* parse thread mutex */ - racond ptcond;/* parse thread cond */ + ramutex *ptmutex;/* parse thread mutex */ + racond *ptcond;/* parse thread cond */ /* */ struct CParseEntry **cmd_list; struct CParseEntry **cmds; @@ -77,11 +76,21 @@ struct console_interface { void (*parse_list_subs) (struct CParseEntry *cmd, unsigned char depth); void (*addCommand) (char *name, CParseFunc func); void (*setSQL) (Sql *SQL_handle); +}; +#else +struct console_input_interface; #endif + +struct console_interface { + void (*init) (void); + void (*final) (void); + void (*display_title) (void); + + struct console_input_interface *input; }; struct console_interface *console; void console_defaults(void); -#endif /* _COMMON_CONSOLE_H_ */ +#endif /* COMMON_CONSOLE_H */ diff --git a/src/common/core.c b/src/common/core.c index c6075da40..99dbc36ec 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -2,35 +2,41 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/malloc.h" -#include "../common/strlib.h" +#define HERCULES_CORE + +#include "../config/core.h" #include "core.h" + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "../common/cbasetypes.h" #include "../common/console.h" +#include "../common/malloc.h" +#include "../common/mmo.h" #include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/sysinfo.h" #ifndef MINICORE - #include "../common/db.h" - #include "../common/socket.h" - #include "../common/timer.h" - #include "../common/thread.h" - #include "../common/sql.h" - #include "../config/core.h" - #include "../common/HPM.h" - #include "../common/utils.h" - #include "../common/conf.h" - #include "../common/ers.h" +# include "../common/HPM.h" +# include "../common/conf.h" +# include "../common/db.h" +# include "../common/ers.h" +# include "../common/socket.h" +# include "../common/sql.h" +# include "../common/thread.h" +# include "../common/timer.h" +# include "../common/utils.h" #endif -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <string.h> #ifndef _WIN32 -#include <unistd.h> +# include <unistd.h> #else -#include "../common/winapi.h" // Console close event handling +# include "../common/winapi.h" // Console close event handling #endif /// Called when a terminate signal is received. @@ -78,7 +84,7 @@ sigfunc *compat_signal(int signo, sigfunc *func) { *--------------------------------------*/ #ifdef _WIN32 static BOOL WINAPI console_handler(DWORD c_event) { - switch(c_event) { + switch(c_event) { case CTRL_CLOSE_EVENT: case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: @@ -89,11 +95,11 @@ static BOOL WINAPI console_handler(DWORD c_event) { break; default: return FALSE; - } - return TRUE; + } + return TRUE; } -static void cevents_init() { +static void cevents_init(void) { if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) ShowWarning ("Unable to install the console handler!\n"); } @@ -152,134 +158,21 @@ void signals_init (void) { } #endif -const char* get_svn_revision(void) { - static char svn_version_buffer[16] = ""; - FILE *fp; - - if( svn_version_buffer[0] != '\0' ) - return svn_version_buffer; - - // subversion 1.7 uses a sqlite3 database - // FIXME this is hackish at best... - // - ignores database file structure - // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)" - // - since it's a cache column, the data might not even exist - if( (fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL ) - { - #ifndef SVNNODEPATH - //not sure how to handle branches, so i'll leave this overridable define until a better solution comes up - #define SVNNODEPATH trunk - #endif - const char* prefix = "!svn/ver/"; - const char* postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this - size_t prefix_len = strlen(prefix); - size_t postfix_len = strlen(postfix); - size_t i,j,len; - char* buffer; - - // read file to buffer - fseek(fp, 0, SEEK_END); - len = ftell(fp); - buffer = (char*)aMalloc(len + 1); - fseek(fp, 0, SEEK_SET); - len = fread(buffer, 1, len, fp); - buffer[len] = '\0'; - fclose(fp); - - // parse buffer - for( i = prefix_len + 1; i + postfix_len <= len; ++i ) { - if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 ) - continue; // postfix missmatch - for( j = i; j > 0; --j ) {// skip digits - if( !ISDIGIT(buffer[j - 1]) ) - break; - } - if( memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0 ) - continue; // prefix missmatch - // done - snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(buffer + j)); - break; - } - aFree(buffer); - - if( svn_version_buffer[0] != '\0' ) - return svn_version_buffer; - } - - // subversion 1.6 and older? - if ((fp = fopen(".svn/entries", "r")) != NULL) { - char line[1024]; - int rev; - // Check the version - if (fgets(line, sizeof(line), fp)) { - if(!ISDIGIT(line[0])) { - // XML File format - while (fgets(line,sizeof(line),fp)) - if (strstr(line,"revision=")) break; - if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) { - snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev); - } - } else { - // Bin File format - if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get bin name\n"); } // Get the name - if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get entries kind\n"); } // Get the entries kind - if(fgets(line, sizeof(line), fp)) { // Get the rev numver - snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line)); - } - } - } - fclose(fp); - - if( svn_version_buffer[0] != '\0' ) - return svn_version_buffer; - } - - // fallback - svn_version_buffer[0] = HERC_UNKNOWN_VER; - return svn_version_buffer; -} -/* whats our origin */ -#define GIT_ORIGIN "refs/remotes/origin/master" -/* Grabs the hash from the last time the user updated his working copy (last pull) */ -const char *get_git_hash (void) { - static char HerculesGitHash[41] = "";//Sha(40) + 1 - FILE *fp; - - if( HerculesGitHash[0] != '\0' ) - return HerculesGitHash; - - if ( (fp = fopen (".git/"GIT_ORIGIN, "r")) != NULL) { - char line[64]; - char *rev = malloc (sizeof (char) * 50); - - if (fgets (line, sizeof (line), fp) && sscanf (line, "%50s", rev)) - snprintf (HerculesGitHash, sizeof (HerculesGitHash), "%s", rev); - - free (rev); - fclose (fp); - } else { - HerculesGitHash[0] = HERC_UNKNOWN_VER; - } - - if (! (*HerculesGitHash)) { - HerculesGitHash[0] = HERC_UNKNOWN_VER; - } - - return HerculesGitHash; -} -// Warning if executed as superuser (root) +/** + * Warns the user if executed as superuser (root) + */ void usercheck(void) { -#ifndef _WIN32 - if (geteuid() == 0) { - ShowWarning ("You are running Hercules with root privileges, it is not necessary.\n"); - } -#endif + if (sysinfo->is_superuser()) { + ShowWarning("You are running Hercules with root privileges, it is not necessary.\n"); + } } + void core_defaults(void) { #ifndef MINICORE hpm_defaults(); HCache_defaults(); #endif + sysinfo_defaults(); console_defaults(); strlib_defaults(); malloc_defaults(); @@ -295,6 +188,7 @@ void core_defaults(void) { * CORE : MAINROUTINE *--------------------------------------*/ int main (int argc, char **argv) { + int retval = EXIT_SUCCESS; {// initialize program arguments char *p1 = SERVER_NAME = argv[0]; char *p2 = p1; @@ -318,16 +212,18 @@ int main (int argc, char **argv) { iMalloc->init();// needed for Show* in display_title() [FlavioJS] + sysinfo->init(); + if (!(msg_silent&0x1)) console->display_title(); - -#ifdef MINICORE // minimalist Core + usercheck(); + +#ifdef MINICORE // minimalist Core do_init(argc,argv); do_final(); #else// not MINICORE set_server_type(); - usercheck(); Sql_Init(); rathread_init(); @@ -348,10 +244,8 @@ int main (int argc, char **argv) { HCache->init(); -#ifndef MINICORE HPM->init(); -#endif - + sockt->init(); do_init(argc,argv); @@ -365,18 +259,17 @@ int main (int argc, char **argv) { console->final(); - do_final(); -#ifndef MINICORE + retval = do_final(); HPM->final(); -#endif timer->final(); sockt->final(); DB->final(); rathread_final(); ers_final(); #endif + //sysinfo->final(); Called by iMalloc->final() iMalloc->final(); - return 0; + return retval; } diff --git a/src/common/core.h b/src/common/core.h index 72f956e1d..a8337e1b9 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -2,16 +2,15 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_CORE_H_ -#define _COMMON_CORE_H_ +#ifndef COMMON_CORE_H +#define COMMON_CORE_H #include "../common/db.h" #include "../common/mmo.h" -#include "../config/core.h" /* so that developers with --enable-debug can raise signals from any section of the code they'd like */ #ifdef DEBUG - #include <signal.h> +# include <signal.h> #endif extern int arg_c; @@ -24,20 +23,18 @@ extern int runflag; extern char *SERVER_NAME; enum server_types { - SERVER_TYPE_UNKNOWN = 0x0, - SERVER_TYPE_LOGIN = 0x1, - SERVER_TYPE_CHAR = 0x2, - SERVER_TYPE_MAP = 0x4, + SERVER_TYPE_UNKNOWN = 0x0, + SERVER_TYPE_LOGIN = 0x1, + SERVER_TYPE_CHAR = 0x2, + SERVER_TYPE_MAP = 0x4, }; enum server_types SERVER_TYPE; -const char *get_svn_revision(void); -const char *get_git_hash (void); extern int do_init(int,char**); extern void set_server_type(void); extern void do_abort(void); -extern void do_final(void); +extern int do_final(void); /// The main loop continues until runflag is CORE_ST_STOP enum E_CORE_ST { @@ -50,4 +47,4 @@ enum E_CORE_ST { /// If NULL, runflag is set to CORE_ST_STOP instead. extern void (*shutdown_callback)(void); -#endif /* _COMMON_CORE_H_ */ +#endif /* COMMON_CORE_H */ diff --git a/src/common/db.c b/src/common/db.c index 8d6b08815..f414ca04d 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -3,7 +3,7 @@ * For more information, see LICENCE in the main folder * * This file is separated in five sections: - * (1) Private typedefs, enums, structures, defines and gblobal variables + * (1) Private typedefs, enums, structures, defines and global variables * (2) Private functions * (3) Protected functions used internally * (4) Protected functions used in the interface of the database @@ -67,14 +67,18 @@ * @encoding US-ASCII * @see #db.h \*****************************************************************************/ + +#define HERCULES_CORE + +#include "db.h" + #include <stdio.h> #include <stdlib.h> -#include "db.h" -#include "../common/mmo.h" +#include "../common/ers.h" #include "../common/malloc.h" +#include "../common/mmo.h" #include "../common/showmsg.h" -#include "../common/ers.h" #include "../common/strlib.h" /*****************************************************************************\ @@ -85,15 +89,15 @@ * DBNColor - Enumeration of colors of the nodes. * * DBNode - Structure of a node in RED-BLACK trees. * * struct db_free - Structure that holds a deleted node to be freed. * - * DBMap_impl - Struture of the database. * + * DBMap_impl - Structure of the database. * * stats - Statistics about the database system. * \*****************************************************************************/ /** - * If defined statistics about database nodes, database creating/destruction - * and function usage are keept and displayed when finalizing the database + * If defined statistics about database nodes, database creating/destruction + * and function usage are kept and displayed when finalizing the database * system. - * WARNING: This adds overhead to every database operation (not shure how much). + * WARNING: This adds overhead to every database operation (not sure how much). * @private * @see #DBStats * @see #stats @@ -141,7 +145,7 @@ typedef struct dbn { // Other node_color color; unsigned deleted : 1; -} *DBNode; +} DBNode; /** * Structure that holds a deleted node. @@ -151,8 +155,8 @@ typedef struct dbn { * @see DBMap_impl#free_list */ struct db_free { - DBNode node; - DBNode *root; + DBNode *node; + DBNode **root; }; /** @@ -189,12 +193,12 @@ typedef struct DBMap_impl { unsigned int free_max; unsigned int free_lock; // Other - ERS nodes; + ERS *nodes; DBComparator cmp; DBHasher hash; DBReleaser release; - DBNode ht[HASH_SIZE]; - DBNode cache; + DBNode *ht[HASH_SIZE]; + DBNode *cache; DBType type; DBOptions options; uint32 item_count; @@ -218,7 +222,7 @@ typedef struct DBIterator_impl { struct DBIterator vtable; DBMap_impl* db; int ht_index; - DBNode node; + DBNode *node; } DBIterator_impl; #if defined(DB_ENABLE_STATS) @@ -326,7 +330,7 @@ static struct db_stats { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#define DB_COUNTSTAT(token) do { if (stats. ## token != UINT32_MAX) ++stats. ## token ; } while(0) +#define DB_COUNTSTAT(token) do { if ((stats.token) != UINT32_MAX) ++(stats.token); } while(0) #else /* !defined(DB_ENABLE_STATS) */ #define DB_COUNTSTAT(token) #endif /* !defined(DB_ENABLE_STATS) */ @@ -357,12 +361,12 @@ struct eri *db_alloc_ers; * @param node Node to be rotated * @param root Pointer to the root of the tree * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) + * @see #db_rebalance(DBNode *,DBNode **) + * @see #db_rebalance_erase(DBNode *,DBNode **) */ -static void db_rotate_left(DBNode node, DBNode *root) +static void db_rotate_left(DBNode *node, DBNode **root) { - DBNode y = node->right; + DBNode *y = node->right; DB_COUNTSTAT(db_rotate_left); // put the left of y at the right of node @@ -388,12 +392,12 @@ static void db_rotate_left(DBNode node, DBNode *root) * @param node Node to be rotated * @param root Pointer to the root of the tree * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) + * @see #db_rebalance(DBNode *,DBNode **) + * @see #db_rebalance_erase(DBNode *,DBNode **) */ -static void db_rotate_right(DBNode node, DBNode *root) +static void db_rotate_right(DBNode *node, DBNode **root) { - DBNode y = node->left; + DBNode *y = node->left; DB_COUNTSTAT(db_rotate_right); // put the right of y at the left of node @@ -420,13 +424,13 @@ static void db_rotate_right(DBNode node, DBNode *root) * @param node Node to be rebalanced * @param root Pointer to the root of the tree * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) + * @see #db_rotate_left(DBNode *,DBNode **) + * @see #db_rotate_right(DBNode *,DBNode **) * @see #db_obj_put(DBMap*,DBKey,DBData) */ -static void db_rebalance(DBNode node, DBNode *root) +static void db_rebalance(DBNode *node, DBNode **root) { - DBNode y; + DBNode *y; DB_COUNTSTAT(db_rebalance); // Restore the RED-BLACK properties @@ -482,16 +486,16 @@ static void db_rebalance(DBNode node, DBNode *root) * @param node Node to be erased from the tree * @param root Root of the tree * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) + * @see #db_rotate_left(DBNode *,DBNode **) + * @see #db_rotate_right(DBNode *,DBNode **) * @see #db_free_unlock(DBMap_impl*) */ -static void db_rebalance_erase(DBNode node, DBNode *root) +static void db_rebalance_erase(DBNode *node, DBNode **root) { - DBNode y = node; - DBNode x = NULL; - DBNode x_parent = NULL; - DBNode w; + DBNode *y = node; + DBNode *x = NULL; + DBNode *x_parent = NULL; + DBNode *w; DB_COUNTSTAT(db_rebalance_erase); // Select where to change the tree @@ -507,7 +511,7 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } // Remove the node from the tree - if (y != node) { // both childs existed + if (y != node) { // both child existed // put the left of 'node' in the left of 'y' node->left->parent = y; y->left = node->left; @@ -518,7 +522,7 @@ static void db_rebalance_erase(DBNode node, DBNode *root) x_parent = y->parent; if (x) x->parent = y->parent; y->parent->left = x; - // put the right of 'node' in 'y' + // put the right of 'node' in 'y' y->right = node->right; node->right->parent = y; // 'y' is a direct child of 'node' @@ -646,8 +650,8 @@ static int db_is_key_null(DBType type, DBKey key) * @param key Key to be duplicated * @param Duplicated key * @private - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) - * @see #db_free_remove(DBMap_impl*,DBNode) + * @see #db_free_add(DBMap_impl*,DBNode *,DBNode **) + * @see #db_free_remove(DBMap_impl*,DBNode *) * @see #db_obj_put(DBMap*,DBKey,void *) * @see #db_dup_key_free(DBMap_impl*,DBKey) */ @@ -706,9 +710,9 @@ static void db_dup_key_free(DBMap_impl* db, DBKey key) * @see DBMap_impl#free_count * @see DBMap_impl#free_max * @see #db_obj_remove(DBMap*,DBKey) - * @see #db_free_remove(DBMap_impl*,DBNode) + * @see #db_free_remove(DBMap_impl*,DBNode *) */ -static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) +static void db_free_add(DBMap_impl* db, DBNode *node, DBNode **root) { DBKey old_key; @@ -755,9 +759,9 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) * @see DBMap_impl#free_list * @see DBMap_impl#free_count * @see #db_obj_put(DBMap*,DBKey,DBData) - * @see #db_free_add(DBMap_impl*,DBNode*,DBNode) + * @see #db_free_add(DBMap_impl*,DBNode**,DBNode*) */ -static void db_free_remove(DBMap_impl* db, DBNode node) +static void db_free_remove(DBMap_impl* db, DBNode *node) { unsigned int i; @@ -806,7 +810,7 @@ static void db_free_lock(DBMap_impl* db) * @param db Target database * @private * @see DBMap_impl#free_lock - * @see #db_free_dbn(DBNode) + * @see #db_free_dbn(DBNode*) * @see #db_lock(DBMap_impl*) */ static void db_free_unlock(DBMap_impl* db) @@ -1151,7 +1155,10 @@ static void db_release_data(DBKey key, DBData data, DBRelease which) { (void)key;//not used DB_COUNTSTAT(db_release_data); - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /** @@ -1170,7 +1177,10 @@ static void db_release_both(DBKey key, DBData data, DBRelease which) { DB_COUNTSTAT(db_release_both); if (which&DB_RELEASE_KEY) aFree((char*)key.str); // needs to be a pointer - if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) aFree(data.u.ptr); + if (which&DB_RELEASE_DATA && data.type == DB_DATA_PTR) { + aFree(data.u.ptr); + data.u.ptr = NULL; + } } /*****************************************************************************\ @@ -1263,8 +1273,8 @@ DBData* dbit_obj_last(DBIterator* self, DBKey* out_key) DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; struct dbn fake; DB_COUNTSTAT(dbit_next); @@ -1339,8 +1349,8 @@ DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; struct dbn fake; DB_COUNTSTAT(dbit_prev); @@ -1405,7 +1415,7 @@ DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) /** * Returns true if the fetched entry exists. - * The databases entries might have NULL data, so use this to to test if + * The databases entries might have NULL data, so use this to to test if * the iterator is done. * @param self Iterator * @return true if the entry exists @@ -1422,9 +1432,9 @@ bool dbit_obj_exists(DBIterator* self) /** * Removes the current entry from the database. - * NOTE: {@link DBIterator#exists} will return false until another entry + * NOTE: {@link DBIterator#exists} will return false until another entry * is fetched - * Puts data of the removed entry in out_data, if out_data is not NULL. + * Puts data of the removed entry in out_data, if out_data is not NULL (unless data has been released) * @param self Iterator * @param out_data Data of the removed entry. * @return 1 if entry was removed, 0 otherwise @@ -1435,7 +1445,7 @@ bool dbit_obj_exists(DBIterator* self) int dbit_obj_remove(DBIterator* self, DBData *out_data) { DBIterator_impl* it = (DBIterator_impl*)self; - DBNode node; + DBNode *node; int retval = 0; DB_COUNTSTAT(dbit_remove); @@ -1445,10 +1455,10 @@ int dbit_obj_remove(DBIterator* self, DBData *out_data) DBMap_impl* db = it->db; if( db->cache == node ) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if( out_data ) memcpy(out_data, &node->data, sizeof(DBData)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[it->ht_index]); } return retval; @@ -1473,7 +1483,7 @@ void dbit_obj_destroy(DBIterator* self) /** * Returns a new iterator for this database. * The iterator keeps the database locked until it is destroyed. - * The database will keep functioning normally but will only free internal + * The database will keep functioning normally but will only free internal * memory when unlocked, so destroy the iterator as soon as possible. * @param self Database * @return New iterator @@ -1514,7 +1524,7 @@ static DBIterator* db_obj_iterator(DBMap* self) static bool db_obj_exists(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; int c; bool found = false; @@ -1565,7 +1575,7 @@ static bool db_obj_exists(DBMap* self, DBKey key) static DBData* db_obj_get(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; int c; DBData *data = NULL; @@ -1611,7 +1621,7 @@ static DBData* db_obj_get(DBMap* self, DBKey key) * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Interface of the database * @param buf Buffer to put the data of the matched entries @@ -1626,8 +1636,8 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, { DBMap_impl* db = (DBMap_impl*)self; unsigned int i; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; unsigned int ret = 0; DB_COUNTSTAT(db_vgetall); @@ -1682,7 +1692,7 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Interface of the database * @param buf Buffer to put the data of the matched entries @@ -1710,7 +1720,7 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D /** * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Interface of the database * @param key Key that identifies the entry @@ -1723,8 +1733,8 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; - DBNode parent = NULL; + DBNode *node; + DBNode *parent = NULL; unsigned int hash; int c = 0; DBData *data = NULL; @@ -1809,7 +1819,7 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li /** * Just calls {@link DBMap#vensure}. * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Interface of the database * @param key Key that identifies the entry @@ -1836,7 +1846,7 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) /** * Put the data identified by the key in the database. - * Puts the previous data in out_data, if out_data is not NULL. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) * NOTE: Uses the new key, the old one is released. * @param self Interface of the database * @param key Key that identifies the data @@ -1852,8 +1862,8 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; - DBNode parent = NULL; + DBNode *node; + DBNode *parent = NULL; int c = 0, retval = 0; unsigned int hash; @@ -1889,9 +1899,9 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) if (node->deleted) { db_free_remove(db, node); } else { + db->release(node->key, node->data, DB_RELEASE_BOTH); if (out_data) memcpy(out_data, &node->data, sizeof(*out_data)); - db->release(node->key, node->data, DB_RELEASE_BOTH); retval = 1; } break; @@ -1944,20 +1954,20 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) /** * Remove an entry from the database. - * Puts the previous data in out_data, if out_data is not NULL. - * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode,DBNode *)}. + * Puts the previous data in out_data, if out_data is not NULL. (unless data has been released) + * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode*,DBNode **)}. * @param self Interface of the database * @param key Key that identifies the entry * @param out_data Previous data if the entry exists * @return 1 if if the entry already exists, 0 otherwise * @protected - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) + * @see #db_free_add(DBMap_impl*,DBNode*,DBNode **) * @see DBMap#remove */ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; - DBNode node; + DBNode *node; unsigned int hash; int c = 0, retval = 0; @@ -1982,10 +1992,10 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) if (!(node->deleted)) { if (db->cache == node) db->cache = NULL; + db->release(node->key, node->data, DB_RELEASE_DATA); if (out_data) memcpy(out_data, &node->data, sizeof(*out_data)); retval = 1; - db->release(node->key, node->data, DB_RELEASE_DATA); db_free_add(db, node, &db->ht[hash]); } break; @@ -2014,8 +2024,8 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) DBMap_impl* db = (DBMap_impl*)self; unsigned int i; int sum = 0; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; DB_COUNTSTAT(db_vforeach); if (db == NULL) return 0; // nullpo candidate @@ -2062,7 +2072,7 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) * Apply <code>func</code> to every entry in the database. * Returns the sum of values returned by func. * @param self Interface of the database - * @param func Function to be applyed + * @param func Function to be applied * @param ... Extra arguments for func * @return Sum of the values returned by func * @protected @@ -2100,8 +2110,8 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) DBMap_impl* db = (DBMap_impl*)self; int sum = 0; unsigned int i; - DBNode node; - DBNode parent; + DBNode *node; + DBNode *parent; DB_COUNTSTAT(db_vclear); if (db == NULL) return 0; // nullpo candidate @@ -2159,7 +2169,7 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database * @param func Function to be applied to every entry before deleting @@ -2187,7 +2197,7 @@ static int db_obj_clear(DBMap* self, DBApply func, ...) * Finalize the database, feeing all the memory it uses. * Before deleting an entry, func is applied to it. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Interface of the database * @param func Function to be applied to every entry before deleting @@ -2242,7 +2252,7 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted. * @param self Database * @param func Function to be applied to every entry before deleting @@ -2341,7 +2351,7 @@ static DBOptions db_obj_options(DBMap* self) * db_default_cmp - Get the default comparator for a type of database. * db_default_hash - Get the default hasher for a type of database. * db_default_release - Get the default releaser for a type of database with the specified options. - * db_custom_release - Get a releaser that behaves a certains way. + * db_custom_release - Get a releaser that behaves a certain way. * db_alloc - Allocate a new database. * db_i2key - Manual cast from 'int' to 'DBKey'. * db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. @@ -2444,7 +2454,7 @@ DBHasher db_default_hash(DBType type) } /** - * Returns the default releaser for the specified type of database with the + * Returns the default releaser for the specified type of database with the * specified options. * NOTE: the options are fixed with {@link #db_fix_options(DBType,DBOptions)} * before choosing the releaser. @@ -2505,7 +2515,7 @@ DBReleaser db_custom_release(DBRelease which) * @param line Line of the file where the database is being allocated * @param type Type of database * @param options Options of the database - * @param maxlen Maximum length of the string to be used as key in string + * @param maxlen Maximum length of the string to be used as key in string * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public @@ -2776,15 +2786,15 @@ void db_final(void) "DB_INT : allocated %10u, destroyed %10u\n" "DB_UINT : allocated %10u, destroyed %10u\n" "DB_STRING : allocated %10u, destroyed %10u\n" - "DB_ISTRING : allocated %10u, destroyed %10u\n", + "DB_ISTRING : allocated %10u, destroyed %10u\n" "DB_INT64 : allocated %10u, destroyed %10u\n" - "DB_UINT64 : allocated %10u, destroyed %10u\n" + "DB_UINT64 : allocated %10u, destroyed %10u\n", stats.db_int_alloc, stats.db_int_destroy, stats.db_uint_alloc, stats.db_uint_destroy, stats.db_string_alloc, stats.db_string_destroy, stats.db_istring_alloc, stats.db_istring_destroy, stats.db_int64_alloc, stats.db_int64_destroy, - stats.db_uint64_alloc, stats.db_uint64_destroy,); + stats.db_uint64_alloc, stats.db_uint64_destroy); ShowInfo(CL_WHITE"Database function counters"CL_RESET":\n" "db_rotate_left %10u, db_rotate_right %10u,\n" "db_rebalance %10u, db_rebalance_erase %10u,\n" diff --git a/src/common/db.h b/src/common/db.h index 67abe6f19..bf59e37d6 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -39,12 +39,13 @@ * @encoding US-ASCII * * @see common#db.c * \*****************************************************************************/ -#ifndef _COMMON_DB_H_ -#define _COMMON_DB_H_ +#ifndef COMMON_DB_H +#define COMMON_DB_H -#include "../common/cbasetypes.h" #include <stdarg.h> +#include "../common/cbasetypes.h" + /*****************************************************************************\ * (1) Section with public typedefs, enums, unions, structures and defines. * * DBRelease - Enumeration of release options. * @@ -78,7 +79,7 @@ typedef enum DBRelease { /** * Supported types of database. - * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the + * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the * types of databases. * @param DB_INT Uses int's for keys * @param DB_UINT Uses unsigned int's for keys @@ -105,17 +106,17 @@ typedef enum DBType { } DBType; /** - * Bitfield of options that define the behaviour of the database. - * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the + * Bitfield of options that define the behavior of the database. + * See {@link #db_fix_options(DBType,DBOptions)} for restrictions of the * types of databases. * @param DB_OPT_BASE Base options: does not duplicate keys, releases nothing * and does not allow NULL keys or NULL data. - * @param DB_OPT_DUP_KEY Duplicates the keys internally. If DB_OPT_RELEASE_KEY + * @param DB_OPT_DUP_KEY Duplicates the keys internally. If DB_OPT_RELEASE_KEY * is defined, the real key is freed as soon as the entry is added. * @param DB_OPT_RELEASE_KEY Releases the key. - * @param DB_OPT_RELEASE_DATA Releases the data whenever an entry is removed + * @param DB_OPT_RELEASE_DATA Releases the data whenever an entry is removed * from the database. - * WARNING: for funtions that return the data (like DBMap::remove), + * WARNING: for functions that return the data (like DBMap::remove), * a dangling pointer will be returned. * @param DB_OPT_RELEASE_BOTH Releases both key and data. * @param DB_OPT_ALLOW_NULL_KEY Allow NULL keys in the database. @@ -187,7 +188,7 @@ typedef struct DBData { } DBData; /** - * Format of functions that create the data for the key when the entry doesn't + * Format of functions that create the data for the key when the entry doesn't * exist in the database yet. * @param key Key of the database entry * @param args Extra arguments of the function @@ -199,9 +200,9 @@ typedef struct DBData { typedef DBData (*DBCreateData)(DBKey key, va_list args); /** - * Format of functions to be applied to an unspecified quantity of entries of + * Format of functions to be applied to an unspecified quantity of entries of * a database. - * Any function that applies this function to the database will return the sum + * Any function that applies this function to the database will return the sum * of values returned by this function. * @param key Key of the database entry * @param data Data of the database entry @@ -279,7 +280,7 @@ typedef struct DBMap DBMap; * Database iterator. * Supports forward iteration, backward iteration and removing entries from the database. * The iterator is initially positioned before the first entry of the database. - * While the iterator exists the database is locked internally, so invoke + * While the iterator exists the database is locked internally, so invoke * {@link DBIterator#destroy} as soon as possible. * @public * @see #DBMap @@ -333,7 +334,7 @@ struct DBIterator /** * Returns true if the fetched entry exists. - * The databases entries might have NULL data, so use this to to test if + * The databases entries might have NULL data, so use this to to test if * the iterator is done. * @param self Iterator * @return true is the entry exists @@ -343,7 +344,7 @@ struct DBIterator /** * Removes the current entry from the database. - * NOTE: {@link DBIterator#exists} will return false until another entry + * NOTE: {@link DBIterator#exists} will return false until another entry * is fetched * Puts data of the removed entry in out_data, if out_data is not NULL. * @param self Iterator @@ -364,7 +365,7 @@ struct DBIterator }; /** - * Public interface of a database. Only contains funtions. + * Public interface of a database. Only contains functions. * All the functions take the interface as the first argument. * @public * @see #db_alloc(const char*,int,DBType,DBOptions,unsigned short) @@ -374,7 +375,7 @@ struct DBMap { /** * Returns a new iterator for this database. * The iterator keeps the database locked until it is destroyed. - * The database will keep functioning normally but will only free internal + * The database will keep functioning normally but will only free internal * memory when unlocked, so destroy the iterator as soon as possible. * @param self Database * @return New iterator @@ -406,7 +407,7 @@ struct DBMap { * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Database * @param buf Buffer to put the data of the matched entries @@ -424,7 +425,7 @@ struct DBMap { * It puts a maximum of <code>max</code> entries into <code>buf</code>. * If <code>buf</code> is NULL, it only counts the matches. * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the + * NOTE: if the value returned is greater than <code>max</code>, only the * first <code>max</code> entries found are put into the buffer. * @param self Database * @param buf Buffer to put the data of the matched entries @@ -440,7 +441,7 @@ struct DBMap { /** * Just calls {@link DBMap#vensure}. * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Database * @param key Key that identifies the entry @@ -454,7 +455,7 @@ struct DBMap { /** * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by + * If the entry does not exist, an entry is added with the data returned by * <code>create</code>. * @param self Database * @param key Key that identifies the entry @@ -551,7 +552,7 @@ struct DBMap { * Before deleting an entry, func is applied to it. * Releases the key and the data. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Database * @param func Function to be applied to every entry before deleting @@ -566,7 +567,7 @@ struct DBMap { * Finalize the database, feeing all the memory it uses. * Before deleting an entry, func is applied to it. * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove + * NOTE: This locks the database globally. Any attempt to insert or remove * a database entry will give an error and be aborted (except for clearing). * @param self Database * @param func Function to be applied to every entry before deleting @@ -758,7 +759,7 @@ DBComparator (*default_cmp) (DBType type); DBHasher (*default_hash) (DBType type); /** - * Returns the default releaser for the specified type of database with the + * Returns the default releaser for the specified type of database with the * specified options. * NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)} * before choosing the releaser @@ -787,7 +788,7 @@ DBReleaser (*custom_release) (DBRelease which); /** * Allocate a new database of the specified type. - * It uses the default comparator, hasher and releaser of the specified + * It uses the default comparator, hasher and releaser of the specified * database type and fixed options. * NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)} * before creating the database. @@ -795,7 +796,7 @@ DBReleaser (*custom_release) (DBRelease which); * @param line Line of the file where the database is being allocated * @param type Type of database * @param options Options of the database - * @param maxlen Maximum length of the string to be used as key in string + * @param maxlen Maximum length of the string to be used as key in string * databases. If 0, the maximum number of maxlen is used (64K). * @return The interface of the database * @public @@ -1137,8 +1138,8 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...); do{ \ if( (__n) > VECTOR_CAPACITY(__vec) ) \ { /* increase size */ \ - if( VECTOR_CAPACITY(__vec) == 0 ) SET_POINTER(VECTOR_DATA(__vec), aMalloc((__n)*sizeof(VECTOR_FIRST(__vec)))); /* allocate new */ \ - else SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \ + if( VECTOR_CAPACITY(__vec) == 0 ) VECTOR_DATA(__vec) = aMalloc((__n)*sizeof(VECTOR_FIRST(__vec))); /* allocate new */ \ + else VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \ memset(VECTOR_DATA(__vec)+VECTOR_LENGTH(__vec), 0, (VECTOR_CAPACITY(__vec)-VECTOR_LENGTH(__vec))*sizeof(VECTOR_FIRST(__vec))); /* clear new data */ \ VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \ } \ @@ -1150,7 +1151,7 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...); } \ else if( (__n) < VECTOR_CAPACITY(__vec) ) \ { /* reduce size */ \ - SET_POINTER(VECTOR_DATA(__vec), aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec)))); /* reallocate */ \ + VECTOR_DATA(__vec) = aRealloc(VECTOR_DATA(__vec),(__n)*sizeof(VECTOR_FIRST(__vec))); /* reallocate */ \ VECTOR_CAPACITY(__vec) = (__n); /* update capacity */ \ if( VECTOR_LENGTH(__vec) > (__n) ) VECTOR_LENGTH(__vec) = (__n); /* update length */ \ } \ @@ -1548,4 +1549,4 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...); -#endif /* _COMMON_DB_H_ */ +#endif /* COMMON_DB_H */ diff --git a/src/common/des.c b/src/common/des.c index ed6d098dc..7f952be76 100644 --- a/src/common/des.c +++ b/src/common/des.c @@ -1,8 +1,11 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#include "../common/cbasetypes.h" -#include "../common/des.h" +#define HERCULES_CORE + +#include "des.h" + +#include "../common/cbasetypes.h" /// DES (Data Encryption Standard) algorithm, modified version. /// @see http://www.eathena.ws/board/index.php?autocom=bugtracker&showbug=5099. diff --git a/src/common/des.h b/src/common/des.h index 3f55448ba..2c7190f23 100644 --- a/src/common/des.h +++ b/src/common/des.h @@ -1,8 +1,9 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _COMMON_DES_H_ -#define _COMMON_DES_H_ +#ifndef COMMON_DES_H +#define COMMON_DES_H +#include "../common/cbasetypes.h" /// One 64-bit block. typedef struct BIT64 { uint8_t b[8]; } BIT64; @@ -12,4 +13,4 @@ void des_decrypt_block(BIT64* block); void des_decrypt(unsigned char* data, size_t size); -#endif // _COMMON_DES_H_ +#endif // COMMON_DES_H diff --git a/src/common/ers.c b/src/common/ers.c index 5a3d7314a..c8a11d2a9 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -13,16 +13,16 @@ * If it has reusable entries (freed entry), it uses one. * * So no assumption should be made about the data of the entry. * * Entries should be freed in the manager they where allocated from. * - * Failure to do so can lead to unexpected behaviours. * + * Failure to do so can lead to unexpected behaviors. * * * * <H2>Advantages:</H2> * * - The same manager is used for entries of the same size. * * So entries freed in one instance of the manager can be used by other * * instances of the manager. * * - Much less memory allocation/deallocation - program will be faster. * - * - Avoids memory fragmentaion - program will run better for longer. * + * - Avoids memory fragmentation - program will run better for longer. * * * - * <H2>Disavantages:</H2> * + * <H2>Disadvantages:</H2> * * - Unused entries are almost inevitable - memory being wasted. * * - A manager will only auto-destroy when all of its instances are * * destroyed so memory will usually only be recovered near the end. * @@ -39,14 +39,18 @@ * @encoding US-ASCII * * @see common#ers.h * \*****************************************************************************/ + +#define HERCULES_CORE + +#include "ers.h" + #include <stdlib.h> #include <string.h> #include "../common/cbasetypes.h" #include "../common/malloc.h" // CREATE, RECREATE, aMalloc, aFree -#include "../common/showmsg.h" // ShowMessage, ShowError, ShowFatalError, CL_BOLD, CL_NORMAL #include "../common/nullpo.h" -#include "ers.h" +#include "../common/showmsg.h" // ShowMessage, ShowError, ShowFatalError, CL_BOLD, CL_NORMAL #ifndef DISABLE_ERS @@ -74,7 +78,7 @@ typedef struct ers_cache // Memory blocks array unsigned char **Blocks; - // Max number of blocks + // Max number of blocks unsigned int Max; // Free objects count @@ -100,7 +104,7 @@ struct ers_instance_t { // Interface to ERS struct eri VTable; - // Name, used for debbuging purpouses + // Name, used for debugging purposes char *Name; // Misc options @@ -181,31 +185,24 @@ static void ers_free_cache(ers_cache_t *cache, bool remove) aFree(cache); } -static void *ers_obj_alloc_entry(ERS self) +static void *ers_obj_alloc_entry(ERS *self) { struct ers_instance_t *instance = (struct ers_instance_t *)self; void *ret; - if (instance == NULL) - { + if (instance == NULL) { ShowError("ers_obj_alloc_entry: NULL object, aborting entry freeing.\n"); return NULL; } - if (instance->Cache->ReuseList != NULL) - { + if (instance->Cache->ReuseList != NULL) { ret = (void *)((unsigned char *)instance->Cache->ReuseList + sizeof(struct ers_list)); instance->Cache->ReuseList = instance->Cache->ReuseList->Next; - } - else if (instance->Cache->Free > 0) - { + } else if (instance->Cache->Free > 0) { instance->Cache->Free--; ret = &instance->Cache->Blocks[instance->Cache->Used - 1][instance->Cache->Free * instance->Cache->ObjectSize + sizeof(struct ers_list)]; - } - else - { - if (instance->Cache->Used == instance->Cache->Max) - { + } else { + if (instance->Cache->Used == instance->Cache->Max) { instance->Cache->Max = (instance->Cache->Max * 4) + 3; RECREATE(instance->Cache->Blocks, unsigned char *, instance->Cache->Max); } @@ -228,18 +225,15 @@ static void *ers_obj_alloc_entry(ERS self) return ret; } -static void ers_obj_free_entry(ERS self, void *entry) +static void ers_obj_free_entry(ERS *self, void *entry) { struct ers_instance_t *instance = (struct ers_instance_t *)self; struct ers_list *reuse = (struct ers_list *)((unsigned char *)entry - sizeof(struct ers_list)); - if (instance == NULL) - { + if (instance == NULL) { ShowError("ers_obj_free_entry: NULL object, aborting entry freeing.\n"); return; - } - else if (entry == NULL) - { + } else if (entry == NULL) { ShowError("ers_obj_free_entry: NULL entry, nothing to free.\n"); return; } @@ -253,25 +247,23 @@ static void ers_obj_free_entry(ERS self, void *entry) instance->Cache->UsedObjs--; } -static size_t ers_obj_entry_size(ERS self) +static size_t ers_obj_entry_size(ERS *self) { struct ers_instance_t *instance = (struct ers_instance_t *)self; - if (instance == NULL) - { + if (instance == NULL) { ShowError("ers_obj_entry_size: NULL object, aborting entry freeing.\n"); return 0; - } + } return instance->Cache->ObjectSize; } -static void ers_obj_destroy(ERS self) +static void ers_obj_destroy(ERS *self) { struct ers_instance_t *instance = (struct ers_instance_t *)self; - if (instance == NULL) - { + if (instance == NULL) { ShowError("ers_obj_destroy: NULL object, aborting entry freeing.\n"); return; } @@ -297,7 +289,7 @@ static void ers_obj_destroy(ERS self) aFree(instance); } -void ers_cache_size(ERS self, unsigned int new_size) { +void ers_cache_size(ERS *self, unsigned int new_size) { struct ers_instance_t *instance = (struct ers_instance_t *)self; nullpo_retv(instance); @@ -310,7 +302,7 @@ void ers_cache_size(ERS self, unsigned int new_size) { } -ERS ers_new(uint32 size, char *name, enum ERSOptions options) +ERS *ers_new(uint32 size, char *name, enum ERSOptions options) { struct ers_instance_t *instance; CREATE(instance,struct ers_instance_t, 1); @@ -395,7 +387,7 @@ void ers_final(void) { while( instance ) { next = instance->Next; - ers_obj_destroy((ERS)instance); + ers_obj_destroy((ERS*)instance); instance = next; } } diff --git a/src/common/ers.h b/src/common/ers.h index 23a996923..904f7fb81 100644 --- a/src/common/ers.h +++ b/src/common/ers.h @@ -13,16 +13,16 @@ * If it has reusable entries (freed entry), it uses one. * * So no assumption should be made about the data of the entry. * * Entries should be freed in the manager they where allocated from. * - * Failure to do so can lead to unexpected behaviours. * + * Failure to do so can lead to unexpected behaviors. * * * * <H2>Advantages:</H2> * * - The same manager is used for entries of the same size. * * So entries freed in one instance of the manager can be used by other * * instances of the manager. * * - Much less memory allocation/deallocation - program will be faster. * - * - Avoids memory fragmentaion - program will run better for longer. * + * - Avoids memory fragmentation - program will run better for longer. * * * - * <H2>Disavantages:</H2> * + * <H2>Disadvantages:</H2> * * - Unused entries are almost inevitable - memory being wasted. * * - A manager will only auto-destroy when all of its instances are * * destroyed so memory will usually only be recovered near the end. * @@ -37,8 +37,8 @@ * @author Flavio @ Amazon Project * * @encoding US-ASCII * \*****************************************************************************/ -#ifndef _COMMON_ERS_H_ -#define _COMMON_ERS_H_ +#ifndef COMMON_ERS_H +#define COMMON_ERS_H #include "../common/cbasetypes.h" @@ -49,13 +49,13 @@ * ERS - Entry manager. * * ers_new - Allocate an instance of an entry manager. * * ers_report - Print a report about the current state. * - * ers_final - Clears the remainder of the manangers. * + * ers_final - Clears the remainder of the managers. * \*****************************************************************************/ /** * Define this to disable the Entry Reusage System. * All code except the typedef of ERInterface will be disabled. - * To allow a smooth transition, + * To allow a smooth transition, */ //#define DISABLE_ERS @@ -63,8 +63,8 @@ * Entries are aligned to ERS_ALIGNED bytes in the blocks of entries. * By default it aligns to one byte, using the "natural order" of the entries. * This should NEVER be set to zero or less. - * If greater than one, some memory can be wasted. This should never be needed - * but is here just in case some aligment issues arise. + * If greater than one, some memory can be wasted. This should never be needed + * but is here just in case some alignment issues arise. */ #ifndef ERS_ALIGNED # define ERS_ALIGNED 1 @@ -102,7 +102,7 @@ typedef struct eri { /** * Free an entry allocated from this manager. * WARNING: Does not check if the entry was allocated by this manager. - * Freeing such an entry can lead to unexpected behaviour. + * Freeing such an entry can lead to unexpected behavior. * @param self Interface of the entry manager * @param entry Entry to be freed */ @@ -118,7 +118,7 @@ typedef struct eri { /** * Destroy this instance of the manager. * The manager is actually only destroyed when all the instances are destroyed. - * When destroying the manager a warning is shown if the manager has + * When destroying the manager a warning is shown if the manager has * missing/extra entries. * @param self Interface of the entry manager */ @@ -126,7 +126,7 @@ typedef struct eri { /* */ void (*chunk_size) (struct eri *self, unsigned int new_size); -} *ERS; +} ERS; #ifdef DISABLE_ERS // Use memory manager to allocate/free and disable other interface functions @@ -140,7 +140,7 @@ typedef struct eri { # define ers_report() # define ers_final() #else /* not DISABLE_ERS */ -// These defines should be used to allow the code to keep working whenever +// These defines should be used to allow the code to keep working whenever // the system is disabled # define ers_alloc(obj,type) ((type *)(obj)->alloc(obj)) # define ers_free(obj,entry) ((obj)->free((obj),(entry))) @@ -151,14 +151,14 @@ typedef struct eri { /** * Get a new instance of the manager that handles the specified entry size. * Size has to greater than 0. - * If the specified size is smaller than a pointer, the size of a pointer is + * If the specified size is smaller than a pointer, the size of a pointer is * used instead. - * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of + * It's also aligned to ERS_ALIGNED bytes, so the smallest multiple of * ERS_ALIGNED that is greater or equal to size is what's actually used. * @param The requested size of the entry in bytes * @return Interface of the object */ -ERS ers_new(uint32 size, char *name, enum ERSOptions options); +ERS *ers_new(uint32 size, char *name, enum ERSOptions options); /** * Print a report about the current state of the Entry Reusage System. @@ -170,9 +170,9 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options); void ers_report(void); /** - * Clears the remainder of the manangers + * Clears the remainder of the managers **/ void ers_final(void); #endif /* DISABLE_ERS / not DISABLE_ERS */ -#endif /* _COMMON_ERS_H_ */ +#endif /* COMMON_ERS_H */ diff --git a/src/common/evdp.h b/src/common/evdp.h deleted file mode 100644 index bc3454686..000000000 --- a/src/common/evdp.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef _rA_EVDP_H_ -#define _rA_EVDP_H_ - -#include "../common/cbasetypes.h" - -typedef struct EVDP_DATA EVDP_DATA; - - -//#idef EVDP_EPOLL -#include <sys/epoll.h> -struct EVDP_DATA{ - struct epoll_event ev_data; - bool ev_added; -}; -//#endif - - -enum EVDP_EVENTFLAGS{ - EVDP_EVENT_IN = 1, // Incomming data - EVDP_EVENT_OUT = 2, // Connection accepts writing. - EVDP_EVENT_HUP = 4 // Connection Closed. -}; - -typedef struct EVDP_EVENT{ - int32 events; // due to performance reasons, this should be the first member. - int32 fd; // Connection Identifier -} EVDP_EVENT; - - - -/** - * Network Event Dispatcher Initialization / Finalization routines - */ -void evdp_init(); -void evdp_final(); - - -/** - * Will Wait for events. - * - * @param *out_ev pointer to array in size at least of max_events. - * @param max_events max no of events to report with this call (coalesc) - * @param timeout_ticks max time to wait in ticks (milliseconds) - * - * @Note: - * The function will block until an event has occured on one of the monitored connections - * or the timeout of timeout_ticks has passed by. - * Upon successfull call (changed connections) this function will write the connection - * Identifier & event to the out_fds array. - * - * @return 0 -> Timeout, > 0 no of changed connections. - */ -int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks); - - -/** - * Applys the given mask on the given connection. - * - * @param fd connection identifier - * @param *ep event data pointer for the connection - * @param mask new event mask we're monitoring for. - */ -//void evdp_apply(int32 fd, EVDP_DATA *ep, int32 mask); - - -/** - * Adds a connection (listner) to the event notification system. - * - * @param fd connection identifier - * @param *ep event data pointer for the connection - * - * @note: - * Listener type sockets are edge triggered, (see epoll manual for more information) - * - This basicaly means that youll receive one event, adn you have to accept until accept returns an error (nothing to accept) - * - * MONITORS by default: IN - * - * @return success indicator. - */ -bool evdp_addlistener(int32 fd, EVDP_DATA *ep); - -/** - * Adds a connection (client connectioN) to the event notification system - * - * @param fd connection identifier - * @param *ep event data pointr for the connection - * - * @note: - * - * MONITORS by default: IN, HUP - * - * @return success indicator. - */ -bool evdp_addclient(int32 fd, EVDP_DATA *ep); - -/** - * Adds a connection (pending / outgoing connection!) to the event notification system. - * - * @param fd connection identifier - * @param *ep event data pointer for the conneciton. - * - * @note: - * Outgoing connection type sockets are getting monitored for connection established - * successfull - * - if the connection has been established - we're generitng a writable notification .. (send) - * this is typical for BSD / posix conform network stacks. - * - Additinionally its edge triggered. - * - * @see evdp_outgoingconnection_established - * - * - * @return success indicator - */ -bool evdp_addconnecting(int32 fd, EVDP_DATA *ep); - -/** - * Adds an outgoing connection to the normal event notification system after it has been successfully established. - * - * @param fd connection identifier - * @param *ep event data pointer for the conneciton. - - * @note - * after this call, its handled like a normal "client" connection (incomming) - * - * @rturn success indicator - */ -bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep); - -/** - * Marks a connection to be monitored for writable. - * - * @param fd connection identifier - * @param *ep event data pointer for the connection - * - * @note: - * the connection must be already added (as client or listener) - * - * - * @return sucess indicator - */ -bool evdp_writable_add(int32 fd, EVDP_DATA *ep); - -/** - * Removes the connection from writable notification monitoring - * - * @param fd connection identifier - * @param *ep event data pointr for the connection - * - */ -void evdp_writable_remove(int32 fd, EVDP_DATA *ep); - -/** - * Removes an connectio from the event notification system. - * - * @param fd connection iditentfir - * @param *ep event data pointer for th connection - * - * - * @note: - * this will also clear the given EVENT_DATA block - * so the connection slot is in an "initial" blank status / ready to get reused. - * - */ -void evdp_remove(int32 fd, EVDP_DATA *ep); - - - -#endif diff --git a/src/common/evdp_epoll.c b/src/common/evdp_epoll.c deleted file mode 100644 index 0357dfc66..000000000 --- a/src/common/evdp_epoll.c +++ /dev/null @@ -1,232 +0,0 @@ -// -// Event Dispatcher Abstraction for EPOLL -// -// Author: Florian Wilkemeyer <fw@f-ws.de> -// -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -// -// - -#include <stdio.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <unistd.h> - -#include <sys/epoll.h> -#include <sys/fcntl.h> -#include <sys/socket.h> - -#include "../common/cbasetypes.h" -#include "../common/showmsg.h" -#include "../common/evdp.h" - - -#define EPOLL_MAX_PER_CYCLE 10 // Max Events to coalesc. per cycle. - - -static int epoll_fd = -1; - - -void evdp_init(){ - - epoll_fd = epoll_create( EPOLL_MAX_PER_CYCLE ); - if(epoll_fd == -1){ - ShowFatalError("evdp [EPOLL]: Cannot create event dispatcher (errno: %u / %s)\n", errno, strerror(errno) ); - exit(1); - } - -}//end: evdp_init() - - -void evdp_final(){ - - if(epoll_fd != -1){ - close(epoll_fd); - epoll_fd = -1; - } - -}//end: evdp_final() - - -int32 evdp_wait(EVDP_EVENT *out_fds, int32 max_events, int32 timeout_ticks){ - struct epoll_event l_events[EPOLL_MAX_PER_CYCLE]; - register struct epoll_event *ev; - register int nfds, n; - - if(max_events > EPOLL_MAX_PER_CYCLE) - max_events = EPOLL_MAX_PER_CYCLE; - - nfds = epoll_wait( epoll_fd, l_events, max_events, timeout_ticks); - if(nfds == -1){ - // @TODO: check if core is in shutdown mode. if - ignroe error. - - ShowFatalError("evdp [EPOLL]: epoll_wait returned bad / unexpected status (errno: %u / %s)\n", errno, strerror(errno)); - exit(1); //.. - } - - // Loop thru all events and copy it to the local ra evdp_event.. struct. - for(n = 0; n < nfds; n++){ - ev = &l_events[n]; - - out_fds->fd = ev->data.fd; - out_fds->events = 0; // clear - - if(ev->events & EPOLLHUP) - out_fds->events |= EVDP_EVENT_HUP; - - if(ev->events & EPOLLIN) - out_fds->events |= EVDP_EVENT_IN; - - if(ev->events & EPOLLOUT) - out_fds->events |= EVDP_EVENT_OUT; - - out_fds++; - } - - return nfds; // 0 on timeout or > 0 .. -}//end: evdp_wait() - - -void evdp_remove(int32 fd, EVDP_DATA *ep){ - - if(ep->ev_added == true){ - - if( epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, &ep->ev_data) != 0){ - ShowError("evdp [EPOLL]: evdp_remove - epoll_ctl (EPOLL_CTL_DEL) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - } - - ep->ev_data.events = 0; // clear struct. - ep->ev_data.data.fd = -1; // .. clear struct .. - - ep->ev_added = false; // not added! - } - - -}//end: evdp_remove() - - -bool evdp_addlistener(int32 fd, EVDP_DATA *ep){ - - ep->ev_data.events = EPOLLET|EPOLLIN; - ep->ev_data.data.fd = fd; - - // No check here for 'added ?' - // listeners cannot be added twice. - // - if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0 ){ - ShowError("evdp [EPOLL]: evdp_addlistener - epoll_ctl (EPOLL_CTL_ADD) faield! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - ep->ev_data.events = 0; - ep->ev_data.data.fd = -1; - return false; - } - - ep->ev_added = true; - - return true; -}//end: evdp_addlistener() - - -bool evdp_addclient(int32 fd, EVDP_DATA *ep){ - - ep->ev_data.events = EPOLLIN | EPOLLHUP; - ep->ev_data.data.fd = fd; - - // No check for "added?" here, - // this function only gets called upon accpept. - // - - if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){ - ShowError("evdp [EPOLL]: evdp_addclient - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - ep->ev_data.events = 0; - ep->ev_data.data.fd = -1; - return false; - } - - ep->ev_added = true; - - return true; -}//end: evdp_addclient() - - -bool evdp_addconnecting(int32 fd, EVDP_DATA *ep){ - - ep->ev_data.events = EPOLLET | EPOLLOUT | EPOLLHUP; - ep->ev_data.data.fd = fd; - - if( epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ep->ev_data) != 0){ - ShowError("evdp [EPOLL]: evdp_addconnecting - epoll_ctl (EPOLL_CTL_ADD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - ep->ev_data.events = 0; - ep->ev_data.data.fd = -1; - } - - ep->ev_added = true; - - return true; -}//end: evdp_addconnecting() - - -bool evdp_outgoingconnection_established(int32 fd, EVDP_DATA *ep){ - int32 saved_mask; - - if(ep->ev_added != true){ - // ! - ShowError("evdp [EPOLL]: evdp_outgoingconnection_established fd #%u is not added to event dispatcher! invalid call.\n", fd); - return false; - } - - saved_mask = ep->ev_data.events; - - ep->ev_data.events = EPOLLIN | EPOLLHUP; - - if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){ - ep->ev_data.events = saved_mask; // restore old mask. - ShowError("evdp [EPOLL]: evdp_outgoingconnection_established - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - return false; - } - - return true; -}//end: evdp_outgoingconnection_established() - - -bool evdp_writable_add(int32 fd, EVDP_DATA *ep){ - - if(ep->ev_added != true){ - ShowError("evdp [EPOLL]: evdp_writable_add - tried to add not added fd #%u\n",fd); - return false; - } - - if(! (ep->ev_data.events & EPOLLOUT) ){ // - - ep->ev_data.events |= EPOLLOUT; - if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0 ){ - ShowError("evdp [EPOLL]: evdp_writable_add - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno: %u / %s)\n", fd, errno, strerror(errno)); - ep->ev_data.events &= ~EPOLLOUT; // remove from local flagmask due to failed syscall. - return false; - } - } - - return true; -}//end: evdp_writable_add() - - -void evdp_writable_remove(int32 fd, EVDP_DATA *ep){ - - if(ep->ev_added != true){ - ShowError("evdp [EPOLL]: evdp_writable_remove - tried to remove not added fd #%u\n", fd); - return; - } - - if( ep->ev_data.events & EPOLLOUT ){ - - ep->ev_data.events &= ~EPOLLOUT; - if( epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fd, &ep->ev_data) != 0){ - ShowError("evdp [EPOLL]: evdp_writable_remove - epoll_ctl (EPOLL_CTL_MOD) failed! fd #%u (errno %u / %s)\n", fd, errno, strerror(errno)); - ep->ev_data.events |= EPOLLOUT; // add back to local flagmask because of failed syscall. - return; - } - } - - return; -}//end: evdp_writable_remove() diff --git a/src/common/grfio.c b/src/common/grfio.c index bde0ed720..6e628a512 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -2,13 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/des.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../common/utils.h" -#include "../common/nullpo.h" +#define HERCULES_CORE + #include "grfio.h" #include <stdio.h> @@ -17,10 +12,18 @@ #include <sys/stat.h> #include <zlib.h> +#include "../common/cbasetypes.h" +#include "../common/des.h" +#include "../common/malloc.h" +#include "../common/nullpo.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/utils.h" + //---------------------------- // file entry table struct //---------------------------- -typedef struct _FILELIST { +typedef struct FILELIST { int srclen; ///< compressed size int srclen_aligned; int declen; ///< original size @@ -415,7 +418,7 @@ void* grfio_reads(const char* fname, int* size) declen = (int)ftell(in); fseek(in,0,SEEK_SET); buf2 = (unsigned char *)aMalloc(declen+1); // +1 for resnametable zero-termination - if(fread(buf2, 1, declen, in) != (size_t)declen) ShowError("An error occured in fread grfio_reads, fname=%s \n",fname); + if(fread(buf2, 1, declen, in) != (size_t)declen) ShowError("An error occurred in fread grfio_reads, fname=%s \n",fname); fclose(in); if( size ) @@ -437,7 +440,7 @@ void* grfio_reads(const char* fname, int* size) int fsize = entry->srclen_aligned; unsigned char *buf = (unsigned char *)aMalloc(fsize); fseek(in, entry->srcpos, 0); - if(fread(buf, 1, fsize, in) != (size_t)fsize) ShowError("An error occured in fread in grfio_reads, grfname=%s\n",grfname); + if(fread(buf, 1, fsize, in) != (size_t)fsize) ShowError("An error occurred in fread in grfio_reads, grfname=%s\n",grfname); fclose(in); buf2 = (unsigned char *)aMalloc(entry->declen+1); // +1 for resnametable zero-termination @@ -580,7 +583,7 @@ static int grfio_entryread(const char* grfname, int gentry) unsigned char *rBuf; uLongf rSize, eSize; - if(fread(eheader,1,8,fp) != 8) ShowError("An error occured in fread while reading eheader buffer\n"); + if(fread(eheader,1,8,fp) != 8) ShowError("An error occurred in fread while reading header buffer\n"); rSize = getlong(eheader); // Read Size eSize = getlong(eheader+4); // Extend Size @@ -592,7 +595,7 @@ static int grfio_entryread(const char* grfname, int gentry) rBuf = (unsigned char *)aMalloc(rSize); // Get a Read Size grf_filelist = (unsigned char *)aMalloc(eSize); // Get a Extend Size - if(fread(rBuf,1,rSize,fp) != rSize) ShowError("An error occured in fread \n"); + if(fread(rBuf,1,rSize,fp) != rSize) ShowError("An error occurred in fread \n"); fclose(fp); decode_zip(grf_filelist, &eSize, rBuf, rSize); // Decode function aFree(rBuf); @@ -824,7 +827,7 @@ void grfio_init(const char* fname) if( grf_num == 0 ) ShowInfo("No GRF loaded, using default data directory\n"); - // Unneccessary area release of filelist + // Unnecessary area release of filelist filelist_compact(); // Resource check diff --git a/src/common/grfio.h b/src/common/grfio.h index 4f5d0d6bc..15659c17c 100644 --- a/src/common/grfio.h +++ b/src/common/grfio.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _COMMON_GRFIO_H_ -#define _COMMON_GRFIO_H_ +#ifndef COMMON_GRFIO_H +#define COMMON_GRFIO_H void grfio_init(const char* fname); void grfio_final(void); @@ -14,4 +14,4 @@ unsigned long grfio_crc32(const unsigned char *buf, unsigned int len); int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen); int encode_zip(void* dest, unsigned long* destLen, const void* source, unsigned long sourceLen); -#endif /* _COMMON_GRFIO_H_ */ +#endif /* COMMON_GRFIO_H */ diff --git a/src/common/malloc.c b/src/common/malloc.c index f7f108304..3c9fa9c54 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -2,22 +2,26 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/malloc.h" -#include "../common/core.h" -#include "../common/showmsg.h" +#define HERCULES_CORE + +#include "malloc.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include "../common/core.h" +#include "../common/showmsg.h" +#include "../common/sysinfo.h" + struct malloc_interface iMalloc_s; ////////////// Memory Libraries ////////////////// #if defined(MEMWATCH) -# include <string.h> +# include <string.h> # include "memwatch.h" # define MALLOC(n,file,line,func) mwMalloc((n),(file),(line)) # define CALLOC(m,n,file,line,func) mwCalloc((m),(n),(file),(line)) @@ -231,14 +235,13 @@ static size_t hash2size( unsigned short hash ) } } -void* _mmalloc(size_t size, const char *file, int line, const char *func ) -{ +void *mmalloc_(size_t size, const char *file, int line, const char *func) { struct block *block; short size_hash = size2hash( size ); struct unit_head *head; if (((long) size) < 0) { - ShowError("_mmalloc: %d\n", size); + ShowError("mmalloc_: %d\n", size); return NULL; } @@ -337,15 +340,13 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) return (char *)head + sizeof(struct unit_head) - sizeof(long); } -void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func ) -{ +void *mcalloc_(size_t num, size_t size, const char *file, int line, const char *func) { void *p = iMalloc->malloc(num * size,file,line,func); memset(p,0,num * size); return p; } -void* _mrealloc(void *memblock, size_t size, const char *file, int line, const char *func ) -{ +void *mrealloc_(void *memblock, size_t size, const char *file, int line, const char *func) { size_t old_size; if(memblock == NULL) { return iMalloc->malloc(size,file,line,func); @@ -369,8 +370,8 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c } } -/* a _mrealloc clone with the difference it 'z'eroes the newly created memory */ -void* _mreallocz(void *memblock, size_t size, const char *file, int line, const char *func ) { +/* a mrealloc_ clone with the difference it 'z'eroes the newly created memory */ +void *mreallocz_(void *memblock, size_t size, const char *file, int line, const char *func) { size_t old_size; void *p = NULL; @@ -400,8 +401,7 @@ void* _mreallocz(void *memblock, size_t size, const char *file, int line, const } -char* _mstrdup(const char *p, const char *file, int line, const char *func ) -{ +char *mstrdup_(const char *p, const char *file, int line, const char *func) { if(p == NULL) { return NULL; } else { @@ -412,12 +412,11 @@ char* _mstrdup(const char *p, const char *file, int line, const char *func ) } } -void _mfree(void *ptr, const char *file, int line, const char *func ) -{ +void mfree_(void *ptr, const char *file, int line, const char *func) { struct unit_head *head; if (ptr == NULL) - return; + return; head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); if(head->size == 0) { @@ -569,22 +568,18 @@ size_t memmgr_usage (void) static char memmer_logfile[128]; static FILE *log_fp; -static void memmgr_log (char *buf) -{ +static void memmgr_log(char *buf, char *vcsinfo) { if( !log_fp ) { time_t raw; struct tm* t; - const char* svn = get_svn_revision(); - const char* git = get_git_hash(); log_fp = fopen(memmer_logfile,"at"); if (!log_fp) log_fp = stdout; time(&raw); t = localtime(&raw); - fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (rev %s).\n", - (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, - git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown"); + fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (%s).\n", + (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, vcsinfo); } fprintf(log_fp, "%s", buf); return; @@ -641,10 +636,12 @@ static void memmgr_final (void) { struct block *block = block_first; struct unit_head_large *large = unit_head_large_first; - + char vcsinfo[256]; #ifdef LOG_MEMMGR int count = 0; #endif /* LOG_MEMMGR */ + snprintf(vcsinfo, sizeof(vcsinfo), "%s rev '%s'", sysinfo->vcstype(), sysinfo->vcsrevision_src()); // Cache VCS info before we free() it + sysinfo->final(); while (block) { if (block->unit_used) { @@ -658,7 +655,7 @@ static void memmgr_final (void) sprintf (buf, "%04d : %s line %d size %lu address 0x%p\n", ++count, head->file, head->line, (unsigned long)head->size, ptr); - memmgr_log (buf); + memmgr_log(buf, vcsinfo); #endif /* LOG_MEMMGR */ // get block pointer and free it [celest] iMalloc->free(ptr, ALC_MARK); @@ -675,7 +672,7 @@ static void memmgr_final (void) sprintf (buf, "%04d : %s line %d size %lu address 0x%p\n", ++count, large->unit_head.file, large->unit_head.line, (unsigned long)large->size, &large->unit_head.checksum); - memmgr_log (buf); + memmgr_log(buf, vcsinfo); #endif /* LOG_MEMMGR */ large2 = large->next; FREE(large,file,line,func); @@ -775,7 +772,7 @@ static void memmgr_init (void) { #ifdef LOG_MEMMGR sprintf(memmer_logfile, "log/%s.leaks", SERVER_NAME); - ShowStatus("Memory manager initialised: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); + ShowStatus("Memory manager initialized: "CL_WHITE"%s"CL_RESET"\n", memmer_logfile); memset(hash_unfill, 0, sizeof(hash_unfill)); #endif /* LOG_MEMMGR */ } @@ -783,7 +780,7 @@ static void memmgr_init (void) /*====================================== -* Initialise +* Initialize *-------------------------------------- */ @@ -850,12 +847,12 @@ void malloc_defaults(void) { // Athena's built-in Memory Manager #ifdef USE_MEMMGR - iMalloc->malloc = _mmalloc; - iMalloc->calloc = _mcalloc; - iMalloc->realloc = _mrealloc; - iMalloc->reallocz= _mreallocz; - iMalloc->astrdup = _mstrdup; - iMalloc->free = _mfree; + iMalloc->malloc = mmalloc_; + iMalloc->calloc = mcalloc_; + iMalloc->realloc = mrealloc_; + iMalloc->reallocz= mreallocz_; + iMalloc->astrdup = mstrdup_; + iMalloc->free = mfree_; #else iMalloc->malloc = aMalloc_; iMalloc->calloc = aCalloc_; diff --git a/src/common/malloc.h b/src/common/malloc.h index 7309bb0f7..8dace2d68 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _COMMON_MALLOC_H_ -#define _COMMON_MALLOC_H_ +#ifndef COMMON_MALLOC_H +#define COMMON_MALLOC_H #include "../common/cbasetypes.h" @@ -88,4 +88,4 @@ struct malloc_interface { void memmgr_report (int extra); struct malloc_interface *iMalloc; -#endif /* _COMMON_MALLOC_H_ */ +#endif /* COMMON_MALLOC_H */ diff --git a/src/common/mapindex.c b/src/common/mapindex.c index 3128a3cb0..644f2f619 100644 --- a/src/common/mapindex.c +++ b/src/common/mapindex.c @@ -2,16 +2,19 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/mmo.h" -#include "../common/showmsg.h" -#include "../common/malloc.h" -#include "../common/strlib.h" -#include "../common/db.h" +#define HERCULES_CORE + #include "mapindex.h" -#include <string.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> + +#include "../common/db.h" +#include "../common/malloc.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" /* mapindex.c interface source */ struct mapindex_interface mapindex_s; @@ -67,7 +70,7 @@ const char* mapindex_getmapname_ext(const char* string, char* output) { } /// Adds a map to the specified index -/// Returns 1 if successful, 0 oherwise +/// Returns 1 if successful, 0 otherwise int mapindex_addmap(int index, const char* name) { char map_name[MAP_NAME_LENGTH]; diff --git a/src/common/mapindex.h b/src/common/mapindex.h index fa9b9e920..446a2422d 100644 --- a/src/common/mapindex.h +++ b/src/common/mapindex.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_MAPINDEX_H_ -#define _COMMON_MAPINDEX_H_ +#ifndef COMMON_MAPINDEX_H +#define COMMON_MAPINDEX_H #include "../common/db.h" #include "../common/mmo.h" @@ -90,4 +90,4 @@ struct mapindex_interface *mapindex; void mapindex_defaults(void); -#endif /* _COMMON_MAPINDEX_H_ */ +#endif /* COMMON_MAPINDEX_H */ diff --git a/src/common/md5calc.c b/src/common/md5calc.c index 05fde42cc..e7b506e27 100644 --- a/src/common/md5calc.c +++ b/src/common/md5calc.c @@ -6,11 +6,15 @@ * ***********************************************************/ -#include "../common/random.h" +#define HERCULES_CORE + #include "md5calc.h" -#include <string.h> + #include <stdio.h> #include <stdlib.h> +#include <string.h> + +#include "../common/random.h" #ifndef UINT_MAX #define UINT_MAX 4294967295U diff --git a/src/common/md5calc.h b/src/common/md5calc.h index d0caf6787..740e2edcc 100644 --- a/src/common/md5calc.h +++ b/src/common/md5calc.h @@ -1,8 +1,8 @@ -#ifndef _COMMON_MD5CALC_H_ -#define _COMMON_MD5CALC_H_ +#ifndef COMMON_MD5CALC_H +#define COMMON_MD5CALC_H void MD5_String(const char * string, char * output); void MD5_Binary(const char * string, unsigned char * output); void MD5_Salt(unsigned int len, char * output); -#endif /* _COMMON_MD5CALC_H_ */ +#endif /* COMMON_MD5CALC_H */ diff --git a/src/common/mempool.c b/src/common/mempool.c deleted file mode 100644 index 4559d8f2a..000000000 --- a/src/common/mempool.c +++ /dev/null @@ -1,568 +0,0 @@ - -// -// Memory Pool Implementation (Threadsafe) -// -// -// Author: Florian Wilkemeyer <fw@f-ws.de> -// -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -// -// - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#ifdef WIN32 -#include "../common/winapi.h" -#else -#include <unistd.h> -#endif - -#include "../common/cbasetypes.h" -#include "../common/showmsg.h" -#include "../common/mempool.h" -#include "../common/atomic.h" -#include "../common/spinlock.h" -#include "../common/thread.h" -#include "../common/malloc.h" -#include "../common/mutex.h" - -#define ALIGN16 ra_align(16) -#define ALIGN_TO(x, a) ((x) + ( (a) - ( (x) % (a)) ) ) -#define ALIGN_TO_16(x) ALIGN_TO((x), 16) - -#undef MEMPOOL_DEBUG -#define MEMPOOLASSERT - - -#define NODE_TO_DATA(x) ( ((char*)(x)) + sizeof(struct node) ) -#define DATA_TO_NODE(x) ( (struct node*)(((char*)(x)) - sizeof(struct node)) ) -struct ra_align(16) node{ - void *next; - void *segment; -#ifdef MEMPOOLASSERT - bool used; - uint64 magic; - #define NODE_MAGIC 0xBEEF00EAEACAFE07ll -#endif -}; - - -// The Pointer to this struct is the base address of the segment itself. -struct pool_segment{ - mempool pool; // pool, this segment belongs to - struct pool_segment *next; - int64 num_nodes_total; - int64 num_bytes; -}; - - -struct mempool{ - // Settings - char *name; - uint64 elem_size; - uint64 elem_realloc_step; - int64 elem_realloc_thresh; - - // Callbacks that get called for every node that gets allocated - // Example usage: initialization of mutex/lock for each node. - memPoolOnNodeAllocationProc onalloc; - memPoolOnNodeDeallocationProc ondealloc; - - // Locks - SPIN_LOCK segmentLock; - SPIN_LOCK nodeLock; - - - // Internal - struct pool_segment *segments; - struct node *free_list; - - volatile int64 num_nodes_total; - volatile int64 num_nodes_free; - - volatile int64 num_segments; - volatile int64 num_bytes_total; - - volatile int64 peak_nodes_used; // Peak Node Usage - volatile int64 num_realloc_events; // Number of reallocations done. (allocate additional nodes) - - // list (used for global management such as allocator..) - struct mempool *next; -} ra_align(8); // Dont touch the alignment, otherwise interlocked functions are broken .. - - -/// -// Implementation: -// -static void segment_allocate_add(mempool p, uint64 count); - -static SPIN_LOCK l_mempoolListLock; -static mempool l_mempoolList = NULL; -static rAthread l_async_thread = NULL; -static ramutex l_async_lock = NULL; -static racond l_async_cond = NULL; -static volatile int32 l_async_terminate = 0; - -static void *mempool_async_allocator(void *x){ - mempool p; - - - while(1){ - if(l_async_terminate > 0) - break; - - EnterSpinLock(&l_mempoolListLock); - - for(p = l_mempoolList; p != NULL; p = p->next){ - - if(p->num_nodes_free < p->elem_realloc_thresh){ - // add new segment. - segment_allocate_add(p, p->elem_realloc_step); - // increase stats counter - InterlockedIncrement64(&p->num_realloc_events); - } - - } - - LeaveSpinLock(&l_mempoolListLock); - - ramutex_lock( l_async_lock ); - racond_wait( l_async_cond, l_async_lock, -1 ); - ramutex_unlock( l_async_lock ); - } - - - return NULL; -}//end: mempool_async_allocator() - - -void mempool_init(){ - - if( rand()%2 + 1 ) - return; - - if(sizeof(struct node)%16 != 0 ){ - ShowFatalError("mempool_init: struct node alignment failure. %u != multiple of 16\n", sizeof(struct node)); - exit(EXIT_FAILURE); - } - - // Global List start - InitializeSpinLock(&l_mempoolListLock); - l_mempoolList = NULL; - - // Initialize mutex + stuff needed for async allocator worker. - l_async_terminate = 0; - l_async_lock = ramutex_create(); - l_async_cond = racond_create(); - - l_async_thread = rathread_createEx(mempool_async_allocator, NULL, 1024*1024, RAT_PRIO_NORMAL); - if(l_async_thread == NULL){ - ShowFatalError("mempool_init: cannot spawn Async Allocator Thread.\n"); - exit(EXIT_FAILURE); - } - -}//end: mempool_init() - - -void mempool_final(){ - mempool p, pn; - - if( rand()%2 + 1 ) - return; - - ShowStatus("Mempool: Terminating async. allocation worker and remaining pools.\n"); - - // Terminate worker / wait until its terminated. - InterlockedIncrement(&l_async_terminate); - racond_signal(l_async_cond); - rathread_wait(l_async_thread, NULL); - - // Destroy cond var and mutex. - racond_destroy( l_async_cond ); - ramutex_destroy( l_async_lock ); - - // Free remaining mempools - // ((bugged code! this should halppen, every mempool should - // be freed by the subsystem that has allocated it.) - // - EnterSpinLock(&l_mempoolListLock); - p = l_mempoolList; - while(1){ - if(p == NULL) - break; - - pn = p->next; - - ShowWarning("Mempool [%s] was not properly destroyed - forcing destroy.\n", p->name); - mempool_destroy(p); - - p = pn; - } - LeaveSpinLock(&l_mempoolListLock); - -}//end: mempool_final() - - -static void segment_allocate_add(mempool p, uint64 count){ - - // Required Memory: - // sz( segment ) - // count * sz( real_node_size ) - // - // where real node size is: - // ALIGN_TO_16( sz( node ) ) + p->elem_size - // so the nodes usable address is nodebase + ALIGN_TO_16(sz(node)) - // - size_t total_sz; - struct pool_segment *seg = NULL; - struct node *nodeList = NULL; - struct node *node = NULL; - char *ptr = NULL; - uint64 i; - - total_sz = ALIGN_TO_16( sizeof(struct pool_segment) ) - + ( (size_t)count * (sizeof(struct node) + (size_t)p->elem_size) ) ; - -#ifdef MEMPOOL_DEBUG - ShowDebug("Mempool [%s] Segment AllocateAdd (num: %u, total size: %0.2fMiB)\n", p->name, count, (float)total_sz/1024.f/1024.f); -#endif - - // allocate! (spin forever until weve got the memory.) - i=0; - while(1){ - ptr = (char*)aMalloc(total_sz); - if(ptr != NULL) break; - - i++; // increase failcount. - if(!(i & 7)){ - ShowWarning("Mempool [%s] Segment AllocateAdd => System seems to be Out of Memory (%0.2f MiB). Try #%u\n", (float)total_sz/1024.f/1024.f, i); -#ifdef WIN32 - Sleep(1000); -#else - sleep(1); -#endif - }else{ - rathread_yield(); /// allow/force vuln. ctxswitch - } - }//endwhile: allocation spinloop. - - // Clear Memory. - memset(ptr, 0x00, total_sz); - - // Initialize segment struct. - seg = (struct pool_segment*)ptr; - ptr += ALIGN_TO_16(sizeof(struct pool_segment)); - - seg->pool = p; - seg->num_nodes_total = count; - seg->num_bytes = total_sz; - - - // Initialze nodes! - nodeList = NULL; - for(i = 0; i < count; i++){ - node = (struct node*)ptr; - ptr += sizeof(struct node); - ptr += p->elem_size; - - node->segment = seg; -#ifdef MEMPOOLASSERT - node->used = false; - node->magic = NODE_MAGIC; -#endif - - if(p->onalloc != NULL) p->onalloc( NODE_TO_DATA(node) ); - - node->next = nodeList; - nodeList = node; - } - - - - // Link in Segment. - EnterSpinLock(&p->segmentLock); - seg->next = p->segments; - p->segments = seg; - LeaveSpinLock(&p->segmentLock); - - // Link in Nodes - EnterSpinLock(&p->nodeLock); - nodeList->next = p->free_list; - p->free_list = nodeList; - LeaveSpinLock(&p->nodeLock); - - - // Increase Stats: - InterlockedExchangeAdd64(&p->num_nodes_total, count); - InterlockedExchangeAdd64(&p->num_nodes_free, count); - InterlockedIncrement64(&p->num_segments); - InterlockedExchangeAdd64(&p->num_bytes_total, total_sz); - -}//end: segment_allocate_add() - - -mempool mempool_create(const char *name, - uint64 elem_size, - uint64 initial_count, - uint64 realloc_count, - memPoolOnNodeAllocationProc onNodeAlloc, - memPoolOnNodeDeallocationProc onNodeDealloc){ - //.. - uint64 realloc_thresh; - mempool pool; - pool = (mempool)aCalloc( 1, sizeof(struct mempool) ); - - if(pool == NULL){ - ShowFatalError("mempool_create: Failed to allocate %u bytes memory.\n", sizeof(struct mempool) ); - exit(EXIT_FAILURE); - } - - // Check minimum initial count / realloc count requirements. - if(initial_count < 50) - initial_count = 50; - if(realloc_count < 50) - realloc_count = 50; - - // Set Reallocation threshold to 5% of realloc_count, at least 10. - realloc_thresh = (realloc_count/100)*5; // - if(realloc_thresh < 10) - realloc_thresh = 10; - - // Initialize members.. - pool->name = aStrdup(name); - pool->elem_size = ALIGN_TO_16(elem_size); - pool->elem_realloc_step = realloc_count; - pool->elem_realloc_thresh = realloc_thresh; - pool->onalloc = onNodeAlloc; - pool->ondealloc = onNodeDealloc; - - InitializeSpinLock(&pool->segmentLock); - InitializeSpinLock(&pool->nodeLock); - - // Initial Statistic values: - pool->num_nodes_total = 0; - pool->num_nodes_free = 0; - pool->num_segments = 0; - pool->num_bytes_total = 0; - pool->peak_nodes_used = 0; - pool->num_realloc_events = 0; - - // -#ifdef MEMPOOL_DEBUG - ShowDebug("Mempool [%s] Init (ElemSize: %u, Initial Count: %u, Realloc Count: %u)\n", pool->name, pool->elem_size, initial_count, pool->elem_realloc_step); -#endif - - // Allocate first segment directly :) - segment_allocate_add(pool, initial_count); - - - // Add Pool to the global pool list - EnterSpinLock(&l_mempoolListLock); - pool->next = l_mempoolList; - l_mempoolList = pool; - LeaveSpinLock(&l_mempoolListLock); - - - return pool; -}//end: mempool_create() - - -void mempool_destroy(mempool p){ - struct pool_segment *seg, *segnext; - struct node *niter; - mempool piter, pprev; - char *ptr; - int64 i; - -#ifdef MEMPOOL_DEBUG - ShowDebug("Mempool [%s] Destroy\n", p->name); -#endif - - // Unlink from global list. - EnterSpinLock(&l_mempoolListLock); - piter = l_mempoolList; - pprev = l_mempoolList; - while(1){ - if(piter == NULL) - break; - - - if(piter == p){ - // unlink from list, - // - if(pprev == l_mempoolList){ - // this (p) is list begin. so set next as head. - l_mempoolList = p->next; - }else{ - // replace prevs next wuth our next. - pprev->next = p->next; - } - break; - } - - pprev = piter; - piter = piter->next; - } - - p->next = NULL; - LeaveSpinLock(&l_mempoolListLock); - - - // Get both locks. - EnterSpinLock(&p->segmentLock); - EnterSpinLock(&p->nodeLock); - - - if(p->num_nodes_free != p->num_nodes_total) - ShowWarning("Mempool [%s] Destroy - %u nodes are not freed properly!\n", p->name, (p->num_nodes_total - p->num_nodes_free) ); - - // Free All Segments (this will also free all nodes) - // The segment pointer is the base pointer to the whole segment. - seg = p->segments; - while(1){ - if(seg == NULL) - break; - - segnext = seg->next; - - // .. - if(p->ondealloc != NULL){ - // walk over the segment, and call dealloc callback! - ptr = (char*)seg; - ptr += ALIGN_TO_16(sizeof(struct pool_segment)); - for(i = 0; i < seg->num_nodes_total; i++){ - niter = (struct node*)ptr; - ptr += sizeof(struct node); - ptr += p->elem_size; -#ifdef MEMPOOLASSERT - if(niter->magic != NODE_MAGIC){ - ShowError("Mempool [%s] Destroy - walk over segment - node %p invalid magic!\n", p->name, niter); - continue; - } -#endif - - p->ondealloc( NODE_TO_DATA(niter) ); - - - } - }//endif: ondealloc callback? - - // simple .. - aFree(seg); - - seg = segnext; - } - - // Clear node ptr - p->free_list = NULL; - InterlockedExchange64(&p->num_nodes_free, 0); - InterlockedExchange64(&p->num_nodes_total, 0); - InterlockedExchange64(&p->num_segments, 0); - InterlockedExchange64(&p->num_bytes_total, 0); - - LeaveSpinLock(&p->nodeLock); - LeaveSpinLock(&p->segmentLock); - - // Free pool itself :D - aFree(p->name); - aFree(p); - -}//end: mempool_destroy() - - -void *mempool_node_get(mempool p){ - struct node *node; - int64 num_used; - - if(p->num_nodes_free < p->elem_realloc_thresh) - racond_signal(l_async_cond); - - while(1){ - - EnterSpinLock(&p->nodeLock); - - node = p->free_list; - if(node != NULL) - p->free_list = node->next; - - LeaveSpinLock(&p->nodeLock); - - if(node != NULL) - break; - - rathread_yield(); - } - - InterlockedDecrement64(&p->num_nodes_free); - - // Update peak value - num_used = (p->num_nodes_total - p->num_nodes_free); - if(num_used > p->peak_nodes_used){ - InterlockedExchange64(&p->peak_nodes_used, num_used); - } - -#ifdef MEMPOOLASSERT - node->used = true; -#endif - - return NODE_TO_DATA(node); -}//end: mempool_node_get() - - -void mempool_node_put(mempool p, void *data){ - struct node *node; - - node = DATA_TO_NODE(data); -#ifdef MEMPOOLASSERT - if(node->magic != NODE_MAGIC){ - ShowError("Mempool [%s] node_put failed, given address (%p) has invalid magic.\n", p->name, data); - return; // lost, - } - - { - struct pool_segment *node_seg = node->segment; - if(node_seg->pool != p){ - ShowError("Mempool [%s] node_put faild, given node (data address %p) doesnt belongs to this pool. ( Node Origin is [%s] )\n", p->name, data, node_seg->pool); - return; - } - } - - // reset used flag. - node->used = false; -#endif - - // - EnterSpinLock(&p->nodeLock); - node->next = p->free_list; - p->free_list = node; - LeaveSpinLock(&p->nodeLock); - - InterlockedIncrement64(&p->num_nodes_free); - -}//end: mempool_node_put() - - -mempool_stats mempool_get_stats(mempool pool){ - mempool_stats stats; - - // initialize all with zeros - memset(&stats, 0x00, sizeof(mempool_stats)); - - stats.num_nodes_total = pool->num_nodes_total; - stats.num_nodes_free = pool->num_nodes_free; - stats.num_nodes_used = (stats.num_nodes_total - stats.num_nodes_free); - stats.num_segments = pool->num_segments; - stats.num_realloc_events= pool->num_realloc_events; - stats.peak_nodes_used = pool->peak_nodes_used; - stats.num_bytes_total = pool->num_bytes_total; - - // Pushing such a large block over the stack as return value isnt nice - // but lazy :) and should be okay in this case (Stats / Debug..) - // if you dont like it - feel free and refactor it. - return stats; -}//end: mempool_get_stats() - diff --git a/src/common/mempool.h b/src/common/mempool.h deleted file mode 100644 index aeaebe7fe..000000000 --- a/src/common/mempool.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef _rA_MEMPOOL_H_ -#define _rA_MEMPOOL_H_ - -#include "../common/cbasetypes.h" - -typedef struct mempool *mempool; - -typedef void (*memPoolOnNodeAllocationProc)(void *ptr); -typedef void (*memPoolOnNodeDeallocationProc)(void *ptr); - -typedef struct mempool_stats{ - int64 num_nodes_total; - int64 num_nodes_free; - int64 num_nodes_used; - - int64 num_segments; - int64 num_realloc_events; - - int64 peak_nodes_used; - - int64 num_bytes_total; -} mempool_stats; - - -// -void mempool_init(); -void mempool_final(); - - -/** - * Creates a new Mempool - * - * @param name - Name of the pool (used for debug / error messages) - * @param elem_size - size of each element - * @param initial_count - preallocation count - * @param realloc_count - #no of nodes being allocated when pool is running empty. - * @param onNodeAlloc - Node Allocation callback (see @note!) - * @param onNodeDealloc - Node Deallocation callback (see @note!) - * - * @note: - * The onNode(De)alloc callbacks are only called once during segment allocation - * (pool initialization / rallocation ) - * you can use this callbacks for example to initlaize a mutex or somethingelse - * you definitly need during runtime - * - * @return not NULL - */ -mempool mempool_create(const char *name, - uint64 elem_size, - uint64 initial_count, - uint64 realloc_count, - - memPoolOnNodeAllocationProc onNodeAlloc, - memPoolOnNodeDeallocationProc onNodeDealloc); - - -/** - * Destroys a Mempool - * - * @param pool - the mempool to destroy - * - * @note: - * Everything gets deallocated, regardless if everything was freed properly! - * So you have to ensure that all references are cleared properly! - */ -void mempool_destroy(mempool pool); - - -/** - * Gets a new / empty node from the given mempool. - * - * @param pool - the pool to get an empty node from. - * - * @return Address of empty Node - */ -void *mempool_node_get(mempool pool); - - -/** - * Returns the given node to the given mempool - * - * @param pool - the pool to put the node, to - * @param node - the node to return - */ -void mempool_node_put(mempool pool, void *node); - - -/** - * Returns Statistics for the given mempool - * - * @param pool - the pool to get thats for - * - * @note: i dont like pushing masses of values over the stack, too - but its lazy and okay for stats. (blacksirius) - * - * @return stats struct - */ -mempool_stats mempool_get_stats(mempool pool); - - -#endif diff --git a/src/common/mmo.h b/src/common/mmo.h index 476d12d3f..feeb06524 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -2,13 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_MMO_H_ -#define _COMMON_MMO_H_ +#ifndef COMMON_MMO_H +#define COMMON_MMO_H -#include "cbasetypes.h" -#include "../common/db.h" #include <time.h> +#include "../common/cbasetypes.h" +#include "../common/db.h" + // server->client protocol version // 0 - pre-? // 1 - ? - 0x196 @@ -25,7 +26,7 @@ // 20071106 - 2007-11-06aSakexe+ - 0x78, 0x7c, 0x22c // 20080102 - 2008-01-02aSakexe+ - 0x2ec, 0x2ed , 0x2ee // 20081126 - 2008-11-26aSakexe+ - 0x1a2 -// 20090408 - 2009-04-08aSakexe+ - 0x44a (dont use as it overlaps with RE client packets) +// 20090408 - 2009-04-08aSakexe+ - 0x44a (don't use as it overlaps with RE client packets) // 20080827 - 2008-08-27aRagexeRE+ - First RE Client // 20081217 - 2008-12-17aRagexeRE+ - 0x6d (Note: This one still use old Char Info Packet Structure) // 20081218 - 2008-12-17bRagexeRE+ - 0x6d (Note: From this one client use new Char Info Packet Structure) @@ -60,7 +61,7 @@ // Client support for experimental RagexeRE UI present in 2012-04-10 and 2012-04-18 #if defined(PACKETVER_RE) && ( PACKETVER == 20120410 || PACKETVER == 20120418 ) -#define PARTY_RECRUIT +#define PARTY_RECRUIT #endif // PACKETVER_RE && (PACKETVER == 20120410 || PACKETVER == 10120418) // Comment the following line to disable sc_data saving. [Skotlex] @@ -83,6 +84,14 @@ #endif // 20090603 #endif // 20070227 +/* Feb 1st 2012 */ +#if PACKETVER >= 20120201 +# define NEW_CARTS +# define MAX_CARTS 9 +#else +# define MAX_CARTS 5 +#endif + #define MAX_INVENTORY 100 //Max number of characters per account. Note that changing this setting alone is not enough if the client is not hexed to support more characters as well. #define MAX_CHARS 9 @@ -96,13 +105,13 @@ //Official Limit: 2.1b ( the var that stores the money doesn't go much higher than this by default ) #define MAX_BANK_ZENY 2100000000 +#define MAX_LEVEL 175 #define MAX_FAME 1000000000 #define MAX_CART 100 #define MAX_SKILL 1478 #define MAX_SKILL_ID 10015 // [Ind/Hercules] max used skill ID -//Update this max as necessary. 55 is the value needed for Super Baby currently -//Raised to 84 since Expanded Super Novice needs it. -#define MAX_SKILL_TREE 84 +// Update this max as necessary. 86 is the value needed for Expanded Super Novice. +#define MAX_SKILL_TREE 86 #define DEFAULT_WALK_SPEED 150 #define MIN_WALK_SPEED 20 /* below 20 clips animation */ #define MAX_WALK_SPEED 1000 @@ -110,14 +119,14 @@ #define MAX_GUILD_STORAGE 600 #define MAX_PARTY 12 #define MAX_GUILD (16+10*6) // Increased max guild members +6 per 1 extension levels [Lupus] -#define MAX_GUILDPOSITION 20 // Increased max guild positions to accomodate for all members [Valaris] (removed) [PoW] +#define MAX_GUILDPOSITION 20 // Increased max guild positions to accommodate for all members [Valaris] (removed) [PoW] #define MAX_GUILDEXPULSION 32 #define MAX_GUILDALLIANCE 16 -#define MAX_GUILDSKILL 15 // Increased max guild skills because of new skills [Sara-chan] +#define MAX_GUILDSKILL 15 // Increased max guild skills because of new skills [Sara-chan] #define MAX_GUILDLEVEL 50 #define MAX_GUARDIANS 8 // Local max per castle. [Skotlex] #define MAX_QUEST_OBJECTIVES 3 // Max quest objectives for a quest -#define MAX_START_ITEMS 32 // Max number of items allowed to be given to a char whenever it's created. [mkbu95] +#define MAX_START_ITEMS 32 // Max number of items allowed to be given to a char whenever it's created. [mkbu95] // for produce #define MIN_ATTRIBUTE 0 @@ -158,7 +167,7 @@ // Base Homun skill. #define HM_SKILLBASE 8001 #define MAX_HOMUNSKILL 43 -#define MAX_HOMUNCULUS_CLASS 52 // [orn] Increased to 60 from 16 to allow new Homun-S. +#define MAX_HOMUNCULUS_CLASS 52 // [orn] Increased to 60 from 16 to allow new Homun-S. #define HM_CLASS_BASE 6001 #define HM_CLASS_MAX (HM_CLASS_BASE+MAX_HOMUNCULUS_CLASS-1) @@ -266,17 +275,17 @@ enum e_skill_flag SKILL_FLAG_PERMANENT, SKILL_FLAG_TEMPORARY, SKILL_FLAG_PLAGIARIZED, - SKILL_FLAG_UNUSED, /* needed to maintain the order since the values are saved, can be renamed and used if a new flag is necessary */ - SKILL_FLAG_PERM_GRANTED, // Permanent, granted through someway (e.g. script). + SKILL_FLAG_UNUSED, ///< needed to maintain the order since the values are saved, can be renamed and used if a new flag is necessary + SKILL_FLAG_PERM_GRANTED, ///< Permanent, granted through someway (e.g. script). /* */ /* MUST be the last, because with it the flag value stores a dynamic value (flag+lv) */ SKILL_FLAG_REPLACED_LV_0, // Temporary skill overshadowing permanent skill of level 'N - SKILL_FLAG_REPLACED_LV_0', }; enum e_mmo_charstatus_opt { - OPT_NONE = 0x0, - OPT_SHOW_EQUIP = 0x1, - OPT_ALLOW_PARTY = 0x2, + OPT_NONE = 0x0, + OPT_SHOW_EQUIP = 0x1, + OPT_ALLOW_PARTY = 0x2, }; enum e_item_bound_type { @@ -342,17 +351,17 @@ struct s_pet { short hungry;//pet hungry char name[NAME_LENGTH]; char rename_flag; - char incuvate; + char incubate; }; -struct s_homunculus { //[orn] +struct s_homunculus { //[orn] char name[NAME_LENGTH]; int hom_id; int char_id; short class_; short prev_class; int hp,max_hp,sp,max_sp; - unsigned int intimacy; //[orn] + unsigned int intimacy; short hunger; struct s_skill hskill[MAX_HOMUNSKILL]; //albator short skillpts; @@ -461,6 +470,8 @@ struct mmo_charstatus { unsigned short mod_exp,mod_drop,mod_death; unsigned char font; + + uint32 uniqueitem_counter; }; typedef enum mail_status { @@ -527,7 +538,7 @@ struct party { unsigned char count; //Count of online characters. unsigned exp : 1, item : 2; //&1: Party-Share (round-robin), &2: pickup style: shared. - struct party_member member[MAX_PARTY]; + struct party_member member[MAX_PARTY]; }; struct map_session_data; @@ -630,15 +641,25 @@ enum fame_list_type { RANKTYPE_PK = 3, //Not supported yet }; -enum { //Change Guild Infos - GBI_EXP =1, // Guild Experience (EXP) - GBI_GUILDLV, // Guild level - GBI_SKILLPOINT, // Guild skillpoints - GBI_SKILLLV, // Guild skill_lv ?? seem unused +/** + * Guild Basic Information + * It is used to request changes via intif_guild_change_basicinfo in map-server and to + * signalize changes made in char-server via mapif_parse_GuildMemberInfoChange + **/ +enum guild_basic_info { + GBI_EXP = 1, ///< Guild Experience (EXP) + GBI_GUILDLV, ///< Guild level + GBI_SKILLPOINT, ///< Guild skillpoints + + /** + * Changes a skill level, struct guild_skill should be sent. + * All checks regarding max skill level should be done in _map-server_ + **/ + GBI_SKILLLV, ///< Guild skill_lv }; enum { //Change Member Infos - GMI_POSITION =0, + GMI_POSITION = 0, GMI_EXP, GMI_HAIR, GMI_HAIR_COLOR, @@ -835,50 +856,50 @@ enum { }; enum weapon_type { - W_FIST, //Bare hands - W_DAGGER, //1 - W_1HSWORD, //2 - W_2HSWORD, //3 - W_1HSPEAR, //4 - W_2HSPEAR, //5 - W_1HAXE, //6 - W_2HAXE, //7 - W_MACE, //8 - W_2HMACE, //9 (unused) - W_STAFF, //10 - W_BOW, //11 - W_KNUCKLE, //12 - W_MUSICAL, //13 - W_WHIP, //14 - W_BOOK, //15 - W_KATAR, //16 - W_REVOLVER, //17 - W_RIFLE, //18 - W_GATLING, //19 - W_SHOTGUN, //20 - W_GRENADE, //21 - W_HUUMA, //22 - W_2HSTAFF, //23 + W_FIST, ///< Bare hands + W_DAGGER, //1 + W_1HSWORD, //2 + W_2HSWORD, //3 + W_1HSPEAR, //4 + W_2HSPEAR, //5 + W_1HAXE, //6 + W_2HAXE, //7 + W_MACE, //8 + W_2HMACE, //9 (unused) + W_STAFF, //10 + W_BOW, //11 + W_KNUCKLE, //12 + W_MUSICAL, //13 + W_WHIP, //14 + W_BOOK, //15 + W_KATAR, //16 + W_REVOLVER, //17 + W_RIFLE, //18 + W_GATLING, //19 + W_SHOTGUN, //20 + W_GRENADE, //21 + W_HUUMA, //22 + W_2HSTAFF, //23 MAX_WEAPON_TYPE, // dual-wield constants - W_DOUBLE_DD, // 2 daggers - W_DOUBLE_SS, // 2 swords - W_DOUBLE_AA, // 2 axes - W_DOUBLE_DS, // dagger + sword - W_DOUBLE_DA, // dagger + axe - W_DOUBLE_SA, // sword + axe + W_DOUBLE_DD, ///< 2 daggers + W_DOUBLE_SS, ///< 2 swords + W_DOUBLE_AA, ///< 2 axes + W_DOUBLE_DS, ///< dagger + sword + W_DOUBLE_DA, ///< dagger + axe + W_DOUBLE_SA, ///< sword + axe }; enum ammo_type { - A_ARROW = 1, - A_DAGGER, //2 - A_BULLET, //3 - A_SHELL, //4 - A_GRENADE, //5 - A_SHURIKEN, //6 - A_KUNAI, //7 - A_CANNONBALL, //8 - A_THROWWEAPON //9 + A_ARROW = 1, + A_DAGGER, //2 + A_BULLET, //3 + A_SHELL, //4 + A_GRENADE, //5 + A_SHURIKEN, //6 + A_KUNAI, //7 + A_CANNONBALL, //8 + A_THROWWEAPON, //9 }; enum e_char_server_type { @@ -911,4 +932,4 @@ enum e_pc_reg_loading { #error MAX_ZENY is too big #endif -#endif /* _COMMON_MMO_H_ */ +#endif /* COMMON_MMO_H */ diff --git a/src/common/mutex.c b/src/common/mutex.c index 0668dbc41..ea3e0f8ce 100644 --- a/src/common/mutex.c +++ b/src/common/mutex.c @@ -1,6 +1,12 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder +#define HERCULES_CORE + +#include "mutex.h" + +#include "../common/cbasetypes.h" // for WIN32 + #ifdef WIN32 #include "../common/winapi.h" #else @@ -9,11 +15,9 @@ #include <sys/time.h> #endif -#include "../common/cbasetypes.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/timer.h" -#include "../common/mutex.h" struct ramutex{ #ifdef WIN32 @@ -46,7 +50,7 @@ struct racond{ // -ramutex ramutex_create(){ +ramutex *ramutex_create(void) { struct ramutex *m; m = (struct ramutex*)aMalloc( sizeof(struct ramutex) ); @@ -65,7 +69,7 @@ ramutex ramutex_create(){ }//end: ramutex_create() -void ramutex_destroy( ramutex m ){ +void ramutex_destroy(ramutex *m) { #ifdef WIN32 DeleteCriticalSection(&m->hMutex); @@ -78,7 +82,7 @@ void ramutex_destroy( ramutex m ){ }//end: ramutex_destroy() -void ramutex_lock( ramutex m ){ +void ramutex_lock(ramutex *m) { #ifdef WIN32 EnterCriticalSection(&m->hMutex); @@ -88,7 +92,7 @@ void ramutex_lock( ramutex m ){ }//end: ramutex_lock -bool ramutex_trylock( ramutex m ){ +bool ramutex_trylock(ramutex *m) { #ifdef WIN32 if(TryEnterCriticalSection(&m->hMutex) == TRUE) return true; @@ -103,7 +107,7 @@ bool ramutex_trylock( ramutex m ){ }//end: ramutex_trylock() -void ramutex_unlock( ramutex m ){ +void ramutex_unlock(ramutex *m) { #ifdef WIN32 LeaveCriticalSection(&m->hMutex); #else @@ -116,11 +120,11 @@ void ramutex_unlock( ramutex m ){ /////////////// // Condition Variables -// +// // Implementation: // -racond racond_create(){ +racond *racond_create(void) { struct racond *c; c = (struct racond*)aMalloc( sizeof(struct racond) ); @@ -142,7 +146,7 @@ racond racond_create(){ }//end: racond_create() -void racond_destroy( racond c ){ +void racond_destroy(racond *c) { #ifdef WIN32 CloseHandle( c->events[ EVENT_COND_SIGNAL ] ); CloseHandle( c->events[ EVENT_COND_BROADCAST ] ); @@ -155,7 +159,7 @@ void racond_destroy( racond c ){ }//end: racond_destroy() -void racond_wait( racond c, ramutex m, sysint timeout_ticks){ +void racond_wait(racond *c, ramutex *m, sysint timeout_ticks) { #ifdef WIN32 register DWORD ms; int result; @@ -213,7 +217,7 @@ void racond_wait( racond c, ramutex m, sysint timeout_ticks){ }//end: racond_wait() -void racond_signal( racond c ){ +void racond_signal(racond *c) { #ifdef WIN32 // bool has_waiters = false; // EnterCriticalSection(&c->waiters_lock); @@ -229,7 +233,7 @@ void racond_signal( racond c ){ }//end: racond_signal() -void racond_broadcast( racond c ){ +void racond_broadcast(racond *c) { #ifdef WIN32 // bool has_waiters = false; // EnterCriticalSection(&c->waiters_lock); diff --git a/src/common/mutex.h b/src/common/mutex.h index eeb24e6ff..d298c05af 100644 --- a/src/common/mutex.h +++ b/src/common/mutex.h @@ -1,92 +1,93 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder +// For more information, see LICENCE in the main folder -#ifndef _COMMON_MUTEX_H_ -#define _COMMON_MUTEX_H_ +#ifndef COMMON_MUTEX_H +#define COMMON_MUTEX_H +#include "../common/cbasetypes.h" -typedef struct ramutex *ramutex; // Mutex -typedef struct racond *racond; // Condition Var +typedef struct ramutex ramutex; // Mutex +typedef struct racond racond; // Condition Var /** - * Creates a Mutex + * Creates a Mutex * * @return not NULL */ -ramutex ramutex_create(); +ramutex *ramutex_create(); -/** +/** * Destroys a Mutex - * + * * @param m - the mutex to destroy */ -void ramutex_destroy( ramutex m ); +void ramutex_destroy(ramutex *m); -/** +/** * Gets a lock * * @param m - the mutex to lock */ -void ramutex_lock( ramutex m); +void ramutex_lock(ramutex *m); -/** +/** * Trys to get the Lock - * + * * @param m - the mutex try to lock - * + * * @return boolean (true = got the lock) */ -bool ramutex_trylock( ramutex m ); +bool ramutex_trylock(ramutex *m); -/** +/** * Unlocks a mutex * * @param m - the mutex to unlock */ -void ramutex_unlock( ramutex m); +void ramutex_unlock(ramutex *m); -/** +/** * Creates a Condition variable * * @return not NULL */ -racond racond_create(); +racond *racond_create(); -/** +/** * Destroy a Condition variable * - * @param c - the condition varaible to destroy + * @param c - the condition variable to destroy */ -void racond_destroy( racond c ); +void racond_destroy(racond *c); /** - * Waits Until state is signalled - * - * @param c - the condition var to wait for signalled state - * @param m - the mutex used for syncronization + * Waits Until state is signaled + * + * @param c - the condition var to wait for signaled state + * @param m - the mutex used for synchronization * @param timeout_ticks - timeout in ticks ( -1 = INFINITE ) */ -void racond_wait( racond c, ramutex m, sysint timeout_ticks); +void racond_wait(racond *c, ramutex *m, sysint timeout_ticks); -/** - * Sets the given condition var to signalled state +/** + * Sets the given condition var to signaled state * - * @param c - condition var to set in signalled state. + * @param c - condition var to set in signaled state. * * @note: * Only one waiter gets notified. */ -void racond_signal( racond c ); +void racond_signal(racond *c); -/** - * Sets notifys all waiting threads thats signalled. - * @param c - condition var to set in signalled state - * +/** + * Sets notifies all waiting threads thats signaled. + * @param c - condition var to set in signaled state + * * @note: * All Waiters getting notified. - */ -void racond_broadcast( racond c ); + */ +void racond_broadcast(racond *c); -#endif /* _COMMON_MUTEX_H_ */ +#endif /* COMMON_MUTEX_H */ diff --git a/src/common/netbuffer.c b/src/common/netbuffer.c deleted file mode 100644 index 60a299aa9..000000000 --- a/src/common/netbuffer.c +++ /dev/null @@ -1,221 +0,0 @@ - -// -// Network Buffer Subsystem (iobuffer) -// -// -// Author: Florian Wilkemeyer <fw@f-ws.de> -// -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -// -// - -#include <stdlib.h> -#include <string.h> -#include <stdio.h> - -#include "../common/cbasetypes.h" -#include "../common/atomic.h" -#include "../common/mempool.h" -#include "../common/showmsg.h" -#include "../common/raconf.h" -#include "../common/thread.h" -#include "../common/malloc.h" -#include "../common/core.h" - -#include "../common/netbuffer.h" - - -// -// Buffers are available in the following sizes: -// 48, 192, 2048, 8192 -// 65536 (inter server connects may use it for charstatus struct..) -// - - -/// -// Implementation: -// -static volatile int32 l_nEmergencyAllocations = 0; // stats. -static sysint l_nPools = 0; -static sysint *l_poolElemSize = NULL; -static mempool *l_pool = NULL; - - -void netbuffer_init(){ - char localsection[32]; - raconf conf; - sysint i; - - // Initialize Statistic counters: - l_nEmergencyAllocations = 0; - - // Set localsection name according to running serverype. - switch(SERVER_TYPE){ - 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; - } - - - conf = raconf_parse("conf/network.conf"); - if(conf == NULL){ - ShowFatalError("Failed to Parse required Configuration (conf/network.conf)"); - exit(EXIT_FAILURE); - } - - // Get Values from config file - l_nPools = (sysint)raconf_getintEx(conf, localsection, "netbuffer", "num", 0); - if(l_nPools == 0){ - ShowFatalError("Netbuffer (network.conf) failure - requires at least 1 Pool.\n"); - exit(EXIT_FAILURE); - } - - // Allocate arrays. - l_poolElemSize = (sysint*)aCalloc( l_nPools, sizeof(sysint) ); - l_pool = (mempool*)aCalloc( l_nPools, sizeof(mempool) ); - - - for(i = 0; i < l_nPools; i++){ - int64 num_prealloc, num_realloc; - char key[32]; - - sprintf(key, "pool_%u_size", (uint32)i+1); - l_poolElemSize[i] = (sysint)raconf_getintEx(conf, localsection, "netbuffer", key, 4096); - if(l_poolElemSize[i] < 32){ - ShowWarning("Netbuffer (network.conf) failure - minimum allowed buffer size is 32 byte) - fixed.\n"); - l_poolElemSize[i] = 32; - } - - sprintf(key, "pool_%u_prealloc", (uint32)i+1); - num_prealloc = raconf_getintEx(conf, localsection, "netbuffer", key, 150); - - sprintf(key, "pool_%u_realloc_step", (uint32)i+1); - num_realloc = raconf_getintEx(conf, localsection, "netbuffer", key, 100); - - // Create Pool! - sprintf(key, "Netbuffer %u", (uint32)l_poolElemSize[i]); // name. - - // Info - ShowInfo("NetBuffer: Creating Pool %u (Prealloc: %u, Realloc Step: %u) - %0.2f MiB\n", l_poolElemSize[i], num_prealloc, num_realloc, (float)((sizeof(struct netbuf) + l_poolElemSize[i] - 32)* num_prealloc)/1024.0f/1024.0f); - - // - // Size Calculation: - // struct netbuf + requested buffer size - 32 (because the struct already contains 32 byte buffer space at the end of struct) - l_pool[i] = mempool_create(key, (sizeof(struct netbuf) + l_poolElemSize[i] - 32), num_prealloc, num_realloc, NULL, NULL); - if(l_pool[i] == NULL){ - ShowFatalError("Netbuffer: cannot create Pool for %u byte buffers.\n", l_poolElemSize[i]); - // @leak: clean everything :D - exit(EXIT_FAILURE); - } - - }// - - - raconf_destroy(conf); - -}//end: netbuffer_init() - - -void netbuffer_final(){ - sysint i; - - if(l_nPools > 0){ - /// .. finalize mempools - for(i = 0; i < l_nPools; i++){ - mempool_stats stats = mempool_get_stats(l_pool[i]); - - ShowInfo("Netbuffer: Freeing Pool %u (Peak Usage: %u, Realloc Events: %u)\n", l_poolElemSize[i], stats.peak_nodes_used, stats.num_realloc_events); - - mempool_destroy(l_pool[i]); - } - - if(l_nEmergencyAllocations > 0){ - ShowWarning("Netbuffer: did %u Emergency Allocations, please tune your network.conf!\n", l_nEmergencyAllocations); - l_nEmergencyAllocations = 0; - } - - aFree(l_poolElemSize); l_poolElemSize = NULL; - aFree(l_pool); l_pool = NULL; - l_nPools = 0; - } - - -}//end: netbuffer_final() - - -netbuf netbuffer_get( sysint sz ){ - sysint i; - netbuf nb = NULL; - - // Search an appropriate pool - for(i = 0; i < l_nPools; i++){ - if(sz <= l_poolElemSize[i]){ - // match - - nb = (netbuf)mempool_node_get(l_pool[i]); - nb->pool = i; - - break; - } - } - - // No Bufferpool found that mets there quirements?.. (thats bad..) - if(nb == NULL){ - ShowWarning("Netbuffer: get(%u): => no appropriate pool found - emergency allocation required.\n", sz); - ShowWarning("Please reconfigure your network.conf!"); - - InterlockedIncrement(&l_nEmergencyAllocations); - - // .. better to check (netbuf struct provides 32 byte bufferspace itself. - if(sz < 32) sz = 32; - - // allocate memory using malloc .. - while(1){ - nb = (netbuf) aMalloc( (sizeof(struct netbuf) + sz - 32) ); - if(nb != NULL){ - memset(nb, 0x00, (sizeof(struct netbuf) + sz - 32) ); // zero memory! (to enforce commit @ os.) - nb->pool = -1; // emergency alloc. - break; - } - - rathread_yield(); - }// spin allocation. - - } - - - nb->refcnt = 1; // Initial refcount is 1 - - return nb; -}//end: netbuffer_get() - - -void netbuffer_put( netbuf nb ){ - - // Decrement reference counter, if > 0 do nothing :) - if( InterlockedDecrement(&nb->refcnt) > 0 ) - return; - - // Is this buffer an emergency allocated buffer? - if(nb->pool == -1){ - aFree(nb); - return; - } - - - // Otherwise its a normal mempool based buffer - // return it to the according mempool: - mempool_node_put( l_pool[nb->pool], nb); - - -}//end: netbuffer_put() - - -void netbuffer_incref( netbuf nb ){ - - InterlockedIncrement(&nb->refcnt); - -}//end: netbuf_incref() diff --git a/src/common/netbuffer.h b/src/common/netbuffer.h deleted file mode 100644 index 6ddecfdd9..000000000 --- a/src/common/netbuffer.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _rA_NETBUFFER_H_ -#define _rA_NETBUFFER_H_ - -#include "../common/cbasetypes.h" - -typedef struct netbuf{ - sysint pool; // The pool ID this buffer belongs to, - // is set to -1 if its an emergency allocated buffer - - struct netbuf *next; // Used by Network system. - - volatile int32 refcnt; // Internal Refcount, it gets lowered every call to netbuffer_put, - // if its getting zero, the buffer will returned back to the pool - // and can be reused. - - int32 dataPos; // Current Offset - // Used only for Reading (recv job) - // write cases are using the sessions local datapos member due to - // shared write buffer support. - - int32 dataLen; // read buffer case: - // The length expected to read to. - // when this->dataPos == dateLen, read job has been completed. - // write buffer case: - // The lngth of data in te buffer - // when s->dataPos == dataLen, write job has been completed - // - // Note: - // leftBytes = (dateLen - dataPos) - // - // Due to shared buffer support - // dataPos gets not used in write case (each connection has its local offset) - // - - // The Bufferspace itself. - char buf[32]; -} *netbuf; - - -void netbuffer_init(); -void netbuffer_final(); - -/** - * Gets a netbuffer that has atleast (sz) byes space. - * - * @note: The netbuffer system guarantees that youll always recevie a buffer. - * no check for null is required! - * - * @param sz - minimum size needed. - * - * @return pointer to netbuf struct - */ -netbuf netbuffer_get( sysint sz ); - - -/** - * Returns the given netbuffer (decreases refcount, if its 0 - the buffer will get returned to the pool) - * - * @param buf - the buffer to return - */ -void netbuffer_put( netbuf buf ); - - -/** - * Increases the Refcount on the given buffer - * (used for areasends .. etc) - * - */ -void netbuffer_incref( netbuf buf ); - - -// Some Useful macros -#define NBUFP(netbuf,pos) (((uint8*)((netbuf)->buf)) + (pos)) -#define NBUFB(netbuf,pos) (*(uint8*)(((netbuf)->buf) + (pos))) -#define NBUFW(netbuf,pos) (*(uint16*)(((netbuf)->buf) + (pos))) -#define NBUFL(netbuf,pos) (*(uint32*)(((netbuf)->buf) + (pos))) - -#endif diff --git a/src/common/network.c b/src/common/network.c deleted file mode 100644 index a40cbd602..000000000 --- a/src/common/network.c +++ /dev/null @@ -1,1061 +0,0 @@ -// -// Network Subsystem (previously known as socket system) -// -// Author: Florian Wilkemeyer <fw@f-ws.de> -// -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -// -// -//#ifdef HAVE_ACCETP4 -#define _GNU_SOURCE -//#endif - -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/fcntl.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/tcp.h> -#include <arpa/inet.h> - - -#include "../common/cbasetypes.h" -#include "../common/showmsg.h" -#include "../common/timer.h" -#include "../common/evdp.h" -#include "../common/netbuffer.h" - -#include "../common/network.h" - -#define ENABLE_IPV6 -#define HAVE_ACCEPT4 -#define EVENTS_PER_CYCLE 10 -#define PARANOID_CHECKS - -// Local Vars (settings..) -static int l_ListenBacklog = 64; - -// -// Global Session Array (previously exported as session[] -// -SESSION g_Session[MAXCONN]; - - -// -static bool onSend(int32 fd); - - -#define _network_free_netbuf_async( buf ) add_timer( 0, _network_async_free_netbuf_proc, 0, (intptr_t)(buf)) -static int _network_async_free_netbuf_proc(int tid, unsigned int tick, int id, intptr_t data){ - // netbuf is in data - netbuffer_put( (netbuf)data ); - - return 0; -}//end: _network_async_free_netbuf_proc() - - - -void network_init(){ - SESSION *s; - int32 i; - - memset(g_Session, 0x00, (sizeof(SESSION) * MAXCONN) ); - - for(i = 0; i < MAXCONN; i++){ - s = &g_Session[i]; - - s->type = NST_FREE; - s->disconnect_in_progress = false; - - } - - // Initialize the correspondig event dispatcher - evdp_init(); - - // - add_timer_func_list(_network_async_free_netbuf_proc, "_network_async_free_netbuf_proc"); - -}//end: network_init() - - -void network_final(){ - - // @TODO: - // .. disconnect and cleanup everything! - - evdp_final(); - -}//end: network_final() - - -void network_do(){ - struct EVDP_EVENT l_events[EVENTS_PER_CYCLE]; - register struct EVDP_EVENT *ev; - register int n, nfds; - register SESSION *s; - - nfds = evdp_wait( l_events, EVENTS_PER_CYCLE, 1000); // @TODO: timer_getnext() - - for(n = 0; n < nfds; n++){ - ev = &l_events[n]; - s = &g_Session[ ev->fd ]; - - if(ev->events & EVDP_EVENT_HUP){ - network_disconnect( ev->fd ); - continue; // no further event processing. - }// endif vent is HUP (disconnect) - - - if(ev->events & EVDP_EVENT_IN){ - - if(s->onRecv != NULL){ - if( false == s->onRecv(ev->fd) ){ - network_disconnect(ev->fd); - continue; // .. - } - }else{ - ShowError("network_do: fd #%u has no onRecv proc set. - disconnecting\n", ev->fd); - network_disconnect(ev->fd); - continue; - } - - }// endif event is IN (recv) - - - if(ev->events & EVDP_EVENT_OUT){ - if(s->onSend != NULL){ - if( false == s->onSend(ev->fd) ){ - network_disconnect(ev->fd); - continue; - } - }else{ - ShowError("network_do: fd #%u has no onSend proc set. - disconnecting\n", ev->fd); - network_disconnect(ev->fd); - continue; - } - }// endif event is OUT (send) - - }//endfor - -}//end: network_do() - - -static bool _setnonblock(int32 fd){ - int flags = fcntl(fd, F_GETFL, 0); - if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) != 0) - return false; - - return true; -}//end: _setnonblock() - - -static bool _network_accept(int32 fd){ - SESSION *listener = &g_Session[fd]; - SESSION *s; - union{ - struct sockaddr_in v4; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 v6; -#endif - } _addr; - int newfd; - socklen_t addrlen; - struct sockaddr *addr; - - // Accept until OS returns - nothing to accept anymore - // - this is required due to our EVDP abstraction. (which handles on listening sockets similar to epoll's EPOLLET flag.) - while(1){ -#ifdef ENABLE_IPV6 - if(listener->v6 == true){ - addrlen = sizeof(_addr.v6); - addr = (struct sockaddr*)&_addr.v6; - }else{ -#endif - addrlen = sizeof(_addr.v4); - addr = (struct sockaddr*)&_addr.v4; -#ifdef ENABLE_IPV6 - } -#endif - -#ifdef HAVE_ACCEPT4 - newfd = accept4(fd, addr, &addrlen, SOCK_NONBLOCK); -#else - newfd = accept(fd, addr, &addrlen); -#endif - - if(newfd == -1){ - if(errno == EAGAIN || errno == EWOULDBLOCK) - break; // this is fully valid & whished., se explaination on top of while(1) - - // Otherwis .. we have serious problems :( seems tahat our listner has gone away.. - // @TODO handle this .. - ShowError("_network_accept: accept() returned error. closing listener. (errno: %u / %s)\n", errno, strerror(errno)); - - return false; // will call disconnect after return. - //break; - } - -#ifndef HAVE_ACCEPT4 // no accept4 means, we have to set nonblock by ourself. .. - if(_setnonblock(newfd) == false){ - ShowError("_network_accept: failed to set newly accepted connection nonblocking (errno: %u / %s). - disconnecting.\n", errno, strerror(errno)); - close(newfd); - continue; - } -#endif - - // Check connection limits. - if(newfd >= MAXCONN){ - ShowError("_network_accept: failed to accept connection - MAXCONN (%u) exceeded.\n", MAXCONN); - close(newfd); - continue; // we have to loop over the events (and disconnect them too ..) but otherwise we would leak event notifications. - } - - - // Create new Session. - s = &g_Session[newfd]; - s->type = NST_CLIENT; - - // The new connection inherits listenr's handlers. - s->onDisconnect = listener->onDisconnect; - s->onConnect = listener->onConnect; // maybe useless but .. fear the future .. :~ - - // Register the new connection @ EVDP - if( evdp_addclient(newfd, &s->evdp_data) == false){ - ShowError("_network_accept: failed to accept connection - event subsystem returned an error.\n"); - close(newfd); - s->type = NST_FREE; - } - - // Call the onConnect handler on the listener. - if( listener->onConnect(newfd) == false ){ - // Resfused by onConnect handler.. - evdp_remove(newfd, &s->evdp_data); - - close(newfd); - s->type = NST_FREE; - - s->data = NULL; // be on the safe side ~ ! - continue; - } - - - } - - return true; -}//end: _network_accept() - - -void network_disconnect(int32 fd){ - SESSION *s = &g_Session[fd]; - netbuf b, bn; - - // Prevent recursive calls - // by wrong implemented on disconnect handlers.. and such.. - if(s->disconnect_in_progress == true) - return; - - s->disconnect_in_progress = true; - - - // Disconnect Todo: - // - Call onDisconnect Handler - // - Release all Assigned buffers. - // - remove from event system (notifications) - // - cleanup session structure - // - close connection. - // - - if(s->onDisconnect != NULL && - s->type != NST_LISTENER){ - - s->onDisconnect( fd ); - } - - // Read Buffer - if(s->read.buf != NULL){ - netbuffer_put(s->read.buf); - s->read.buf = NULL; - } - - // Write Buffer(s) - b = s->write.buf; - while(1){ - if(b == NULL) break; - - bn = b->next; - - netbuffer_put(b); - - b = bn; - } - s->write.buf = NULL; - s->write.buf_last = NULL; - - s->write.n_outstanding = 0; - s->write.max_outstanding = 0; - - - // Remove from event system. - evdp_remove(fd, &s->evdp_data); - - // Cleanup Session Structure. - s->type = NST_FREE; - s->data = NULL; // no application level data assigned - s->disconnect_in_progress = false; - - - // Close connection - close(fd); - -}//end: network_disconnect() - - -int32 network_addlistener(bool v6, const char *addr, uint16 port){ - SESSION *s; - int optval, fd; - -#if !defined(ENABLE_IPV6) - if(v6 == true){ - ShowError("network_addlistener(%c, '%s', %u): this release has no IPV6 support.\n", (v6==true?'t':'f'), addr, port); - return -1; - } -#endif - - -#ifdef ENABLE_IPV6 - if(v6 == true) - fd = socket(AF_INET6, SOCK_STREAM, 0); - else -#endif - fd = socket(AF_INET, SOCK_STREAM, 0); - - // Error? - if(fd == -1){ - ShowError("network_addlistener(%c, '%s', %u): socket() failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - return -1; - } - - // Too many connections? - if(fd >= MAXCONN){ - ShowError("network_addlistener(%c, '%s', %u): cannot create listener, exceeds more than supported connections (%u).\n", (v6==true?'t':'f'), addr, port, MAXCONN); - close(fd); - return -1; - } - - - s = &g_Session[fd]; - if(s->type != NST_FREE){ // additional checks.. :) - ShowError("network_addlistener(%c, '%s', %u): failed, got fd #%u which is already in use in local session table?!\n", (v6==true?'t':'f'), addr, port, fd); - close(fd); - return -1; - } - - - // Fill ip addr structs -#ifdef ENABLE_IPV6 - if(v6 == true){ - memset(&s->addr.v6, 0x00, sizeof(s->addr.v6)); - s->addr.v6.sin6_family = AF_INET6; - s->addr.v6.sin6_port = htons(port); - if(inet_pton(AF_INET6, addr, &s->addr.v6.sin6_addr) != 1){ - ShowError("network_addlistener(%c, '%s', %u): failed to parse the given IPV6 address.\n", (v6==true?'t':'f'), addr, port); - close(fd); - return -1; - } - - }else{ -#endif - memset(&s->addr.v4, 0x00, sizeof(s->addr.v4)); - s->addr.v4.sin_family = AF_INET; - s->addr.v4.sin_port = htons(port); - s->addr.v4.sin_addr.s_addr = inet_addr(addr); -#ifdef ENABLE_IPV6 - } -#endif - - - // if OS has support for SO_REUSEADDR, apply the flag - // so the address could be used when there're still time_wait sockets outstanding from previous application run. -#ifdef SO_REUSEADDR - optval=1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); -#endif - - // Bind -#ifdef ENABLE_IPV6 - if(v6 == true){ - if( bind(fd, (struct sockaddr*)&s->addr.v6, sizeof(s->addr.v6)) == -1) { - ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - }else{ -#endif - if( bind(fd, (struct sockaddr*)&s->addr.v4, sizeof(s->addr.v4)) == -1) { - ShowError("network_addlistener(%c, '%s', %u): bind failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } -#ifdef ENABLE_IPV6 - } -#endif - - if( listen(fd, l_ListenBacklog) == -1){ - ShowError("network_addlistener(%c, '%s', %u): listen failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - - - // Set to nonblock! - if(_setnonblock(fd) == false){ - ShowError("network_addlistener(%c, '%s', %u): cannot set to nonblock (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - - - // Rgister @ evdp. - if( evdp_addlistener(fd, &s->evdp_data) != true){ - ShowError("network_addlistener(%c, '%s', %u): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port); - close(fd); - return -1; - } - - - // Apply flags on Session array for this conneciton. - if(v6 == true) s->v6 = true; - else s->v6 = false; - - s->type = NST_LISTENER; - s->onRecv = _network_accept; - - ShowStatus("Added Listener on '%s':%u\n", addr, port, (v6==true ? "(ipv6)":"(ipv4)") ); - - return fd; -}//end: network_addlistener() - - -static bool _network_connect_establishedHandler(int32 fd){ - register SESSION *s = &g_Session[fd]; - int val; - socklen_t val_len; - - if(s->type == NST_FREE) - return true; // due to multiple non coalesced event notifications - // this can happen .. when a previous handled event has already disconnected the connection - // within the same cycle.. - - val = -1; - val_len = sizeof(val); - getsockopt(fd, SOL_SOCKET, SO_ERROR, &val, &val_len); - - if(val != 0){ - // :( .. cleanup session.. - s->type = NST_FREE; - s->onSend = NULL; - s->onConnect = NULL; - s->onDisconnect = NULL; - - evdp_remove(fd, &s->evdp_data); - close(fd); - - return true; // we CANT return false, - // becuase the normal disconnect procedure would execute the ondisconnect handler, which we dont want .. in this case. - }else{ - // ok - if(s->onConnect(fd) == false) { - // onConnect handler has refused the connection .. - // cleanup .. and ok - s->type = NST_FREE; - s->onSend = NULL; - s->onConnect = NULL; - s->onDisconnect = NULL; - - evdp_remove(fd, &s->evdp_data); - close(fd); - - return true; // we dnot want the ondisconnect handler to be executed, so its okay to handle this by ourself. - } - - // connection established ! - // - if( evdp_outgoingconnection_established(fd, &s->evdp_data) == false ){ - return false; // we want the normal disconnect procedure.. with call to ondisconnect handler. - } - - s->onSend = NULL; - - ShowStatus("#%u connection successfull!\n", fd); - } - - return true; -}//end: _network_connect_establishedHandler() - - -int32 network_connect(bool v6, - const char *addr, - uint16 port, - const char *from_addr, - uint16 from_port, - bool (*onConnectionEstablishedHandler)(int32 fd), - void (*onConnectionLooseHandler)(int32 fd) -){ - register SESSION *s; - int32 fd, optval, ret; - struct sockaddr_in ip4; -#ifdef ENABLE_IPV6 - struct sockaddr_in6 ip6; -#endif - -#ifdef ENABLE_IPV6 - if(v6 == true) - fd = socket(AF_INET6, SOCK_STREAM, 0); - else -#endif - fd = socket(AF_INET, SOCK_STREAM, 0); - -#ifndef ENABLE_IPV6 - // check.. - if(v6 == true){ - ShowError("network_connect(%c, '%s', %u...): tried to create an ipv6 connection, IPV6 is not supported in this release.\n", (v6==true?'t':'f'), addr, port); - return -1; - } -#endif - - // check connection limits. - if(fd >= MAXCONN){ - ShowError("network_connect(%c, '%s', %u...): cannot create new connection, exceeeds more than supported connections (%u)\n", (v6==true?'t':'f'), addr, port ); - close(fd); - return -1; - } - - - // Originating IP/Port pair given ? - if(from_addr != NULL && *from_addr != 0){ - //.. - #ifdef SO_REUSEADDR - optval=1; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); - #endif - - #ifdef ENABLE_IPV6 - if(v6 == true){ - memset(&ip6, 0x00, sizeof(ip6)); - ip6.sin6_family = AF_INET6; - ip6.sin6_port = htons(from_port); - - if(inet_pton(AF_INET6, from_addr, &ip6.sin6_addr) != 1){ - ShowError("network_connect(%c, '%s', %u...): cannot parse originating (from) IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - - ret = bind(fd, (struct sockaddr*)&ip6, sizeof(ip6)); - }else{ - #endif - memset(&ip4, 0x00, sizeof(ip4)); - - ip4.sin_family = AF_INET; - ip4.sin_port = htons(from_port); - ip4.sin_addr.s_addr = inet_addr(from_addr); - ret = bind(fd, (struct sockaddr*)&ip4, sizeof(ip4)); - #ifdef ENABLE_IPV6 - } - #endif - - } - - - // Set non block - if(_setnonblock(fd) == false){ - ShowError("network_connect(%c, '%s', %u...): cannot set socket to nonblocking (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - - - // Create ip addr block to connect to .. -#ifdef ENABLE_IPV6 - if(v6 == true){ - memset(&ip6, 0x00, sizeof(ip6)); - ip6.sin6_family = AF_INET6; - ip6.sin6_port = htons(port); - - if(inet_pton(AF_INET6, addr, &ip6.sin6_addr) != 1){ - ShowError("network_connect(%c, '%s', %u...): cannot parse destination IPV6 address (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - close(fd); - return -1; - } - - }else{ -#endif - memset(&ip4, 0x00, sizeof(ip4)); - - ip4.sin_family = AF_INET; - ip4.sin_port = htons(port); - ip4.sin_addr.s_addr = inet_addr(addr); -#ifdef ENABLE_IPV6 - } -#endif - - - // Assign Session.. - s = &g_Session[fd]; - s->type = NST_OUTGOING; - s->v6 = v6; - s->onConnect = onConnectionEstablishedHandler; - s->onDisconnect = onConnectionLooseHandler; - s->onRecv = NULL; - s->onSend = _network_connect_establishedHandler; -#ifdef ENABLE_IPV6 - if(v6 == true) - memcpy(&s->addr.v6, &ip6, sizeof(ip6)); - else -#endif - memcpy(&s->addr.v4, &ip4, sizeof(ip4)); - - // Register @ EVDP. as outgoing (see doc of the function) - if(evdp_addconnecting(fd, &s->evdp_data) == false){ - ShowError("network_connect(%c, '%s', %u...): eventdispatcher subsystem returned an error.\n", (v6==true?'t':'f'), addr, port); - - // cleanup session x.x.. - s->type = NST_FREE; - s->onConnect = NULL; - s->onDisconnect = NULL; - s->onSend = NULL; - - // close, return error code. - close(fd); - return -1; - } - - -#ifdef ENABLE_IPV6 - if(v6 == true) - ret = connect(fd, (struct sockaddr*)&ip6, sizeof(ip6)); - else -#endif - ret = connect(fd, (struct sockaddr*)&ip4, sizeof(ip4)); - - - // - if(ret != 0 && errno != EINPROGRESS){ - ShowWarning("network_connect(%c, '%s', %u...): connection failed (errno: %u / %s)\n", (v6==true?'t':'f'), addr, port, errno, strerror(errno)); - - // Cleanup session .. - s->type = NST_FREE; - s->onConnect = NULL; - s->onDisconnect = NULL; - s->onSend = NULL; - - // .. remove from evdp and close fd. - evdp_remove(fd, &s->evdp_data); - close(fd); - return -1; - } - - - // ! The Info Message :~D - ShowStatus("network_connect fd#%u (%s:%u) in progress.. \n", fd, addr, port); - -return fd; -}//end: network_connect() - - -static bool _onSend(int32 fd){ - register SESSION *s = &g_Session[fd]; - register netbuf buf, buf_next; - register uint32 szNeeded; - register int wLen; - - if(s->type == NST_FREE) - return true; // Possible due to multipl non coalsced event notifications - // so onSend gets called after disconnect caused by an previous vent. - // we can ignore the call to onSend, then. - - buf = s->write.buf; - while(1){ - if(buf == NULL) - break; - - buf_next = buf->next; - - - szNeeded = (buf->dataLen - s->write.dataPos); // using th session-local .dataPos member, due to shared write buffer support. - - // try to write. - wLen = write(fd, &buf->buf[s->write.dataPos], szNeeded); - if(wLen == 0){ - return false; // eof. - }else if(wLen == -1){ - if(errno == EAGAIN || errno == EWOULDBLOCK) - return true; // dont disconnect / try again later. - - // all other errors. . - return false; - } - - // Wrote data.. => - szNeeded -= wLen; - if(szNeeded > 0){ - // still data left .. - // - s->write.dataPos += wLen; // fix offset. - return true; - }else{ - // this buffer has been written successfully - // could be returned to pool. - netbuffer_put(buf); - s->write.n_outstanding--; // When threadsafe -> Interlocked here. - s->write.dataPos = 0; - } - - - buf = buf_next; - } - - // okay, - // reaching this part means: - // while interrupted by break - - // which means all buffers are written, nothing left - // - - s->write.buf_last = NULL; - s->write.buf = NULL; - s->write.n_outstanding = 0; - s->write.dataPos = 0; - - // Remove from event dispatcher (write notification) - // - evdp_writable_remove(fd, &s->evdp_data); - - return true; -}//end: _onSend() - - -static bool _onRORecv(int32 fd){ - register SESSION *s = &g_Session[fd]; - register uint32 szNeeded; - register char *p; - register int rLen; - - if(s->type == NST_FREE) - return true; // Possible due to multiple non coalesced events by evdp. - // simply ignore this call returning positive result. - - // Initialize p and szNeeded depending on change - // - switch(s->read.state){ - case NRS_WAITOP: - szNeeded = s->read.head_left; - p = ((char*)&s->read.head[0]) + (2-szNeeded); - break; - - case NRS_WAITLEN: - szNeeded = s->read.head_left; - p = ((char*)&s->read.head[1]) + (2-szNeeded); - break; - - case NRS_WAITDATA:{ - register netbuf buf = s->read.buf; - - szNeeded = (buf->dataLen - buf->dataPos); - p = (char*)&buf->buf[ buf->dataPos ]; - } - break; - - default: - // .. the impossible gets possible .. - ShowError("_onRORecv: fd #%u has unknown read.state (%d) - disconnecting\n", fd, s->read.state); - return false; - break; - } - - - // - - rLen = read(fd, p, szNeeded); - if(rLen == 0){ - // eof.. - return false; - }else if(rLen == -1){ - - if(errno == EAGAIN || errno == EWOULDBLOCK){ - // try again later .. (this case shouldnt happen, because we're event trigered.. but .. sometimes it happens :) - return true; - } - - // an additional interesting case would be - // EINTR, this 'could' be handled .. but: - // posix says that its possible that data gets currupted during irq - // or data gor read and not reported.., so we'd have a data loss.. - // (which shouldnt happen with stream based protocols such as tcp) - // its better to disonnect the client in that case. - - return false; - } - - // - // Got Data: - // next action also depends on current state .. - // - szNeeded -= rLen; - switch(s->read.state){ - case NRS_WAITOP: - - if(szNeeded > 0){ - // still data missing .. - s->read.head_left = szNeeded; - return true; // wait for completion. - }else{ - // complete .. - // next state depends on packet type. - - s->read.head[1] = ((uint16*)s->netparser_data)[ s->read.head[0] ]; // store lenght of packet by opcode head[0] to head[1] - - if(s->read.head[1] == ROPACKET_UNKNOWN){ - // unknown packet - disconnect - ShowWarning("_onRORecv: fd #%u got unlnown packet 0x%04x - disconnecting.\n", fd, s->read.head[0]); - return false; - } - else if(s->read.head[1] == ROPACKET_DYNLEN){ - // dynamic length - // next state: requrie len. - s->read.state = NRS_WAITLEN; - s->read.head_left = 2; - return true; // - } - else if(s->read.head[1] == 2){ - // packet has no data (only opcode) - register netbuf buf = netbuffer_get(2); // :D whoohoo its giant! - - NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin. - buf->dataPos = 2; - buf->dataLen = 2; - buf->next = NULL; - - // Back to initial state -> Need opcode. - s->read.state = NRS_WAITOP; - s->read.head_left = 2; - s->read.buf = NULL; - - // Call completion routine here. - s->onPacketComplete(fd, s->read.head[0], 2, buf); - - return true; // done :) - } - else{ - // paket needs .. data .. - register netbuf buf = netbuffer_get( s->read.head[1] ); - - NBUFW(buf, 0) = s->read.head[0]; // store opcode @ packet begin. - buf->dataPos = 2; - buf->dataLen = s->read.head[1]; - buf->next = NULL; - - // attach buffer. - s->read.buf = buf; - - // set state: - s->read.state = NRS_WAITDATA; - - return true; - } - - }//endif: szNeeded > 0 (opcode read completed?) - - break; - - - case NRS_WAITLEN: - - if(szNeeded > 0){ - // incomplete .. - s->read.head_left = szNeeded; - return true; - }else{ - - if(s->read.head[1] == 4){ - // packet has no data (only opcode + length) - register netbuf buf = netbuffer_get( 4 ); - - NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL - buf->dataPos = 4; - buf->dataLen = 4; - buf->next = NULL; - - // set initial state (need opcode) - s->read.state = NRS_WAITOP; - s->read.head_left = 2; - s->read.buf = NULL; - - // call completion routine. - s->onPacketComplete(fd, s->read.head[0], 4, buf); - - return true; - } - else if(s->read.head[1] < 4){ - // invalid header. - ShowWarning("_onRORecv: fd #%u invalid header - got packet 0x%04x, reported length < 4 - INVALID - disconnecting\n", fd, s->read.head[0]); - return false; - } - else{ - // Data needed - // next state -> waitdata! - register netbuf buf = netbuffer_get( s->read.head[1] ); - - NBUFL(buf, 0) = *((uint32*)&s->read.head[0]); // copy Opcode + length to netbuffer using MOVL - buf->dataPos = 4; - buf->dataLen = s->read.head[1]; - buf->next = NULL; - - // attach to session: - s->read.buf = buf; - s->read.state = NRS_WAITDATA; - - return true; - } - - }//endif: szNeeded > 0 (length read complete?) - - break; - - - case NRS_WAITDATA: - - if(szNeeded == 0){ - // Packet finished! - // compltion. - register netbuf buf = s->read.buf; - - // set initial state. - s->read.state = NRS_WAITOP; - s->read.head_left = 2; - s->read.buf = NULL; - - // Call completion routine. - s->onPacketComplete(fd, NBUFW(buf, 0), buf->dataLen, buf); - - return true; - }else{ - // still data needed - s->read.buf->dataPos += rLen; - - return true; - } - break; - - - // - default: - ShowError("_onRORecv: fd #%u has unknown read.state (%d) [2] - disconnecting\n", fd, s->read.state); - return false; - break; - } - - - return false; -}//end: _onRORecv() - - -void network_send(int32 fd, netbuf buf){ - register SESSION *s = &g_Session[fd]; - -#ifdef PARANOID_CHECKS - if(fd >= MAXCONN){ - ShowError("network_send: tried to attach buffer to connection idientifer #%u which is out of bounds.\n", fd); - _network_free_netbuf_async(buf); - return; - } -#endif - - - if(s->type == NST_FREE) - return; - - // Check Max Outstanding buffers limit. - if( (s->write.max_outstanding > 0) && - (s->write.n_outstanding >= s->write.max_outstanding) ){ - - ShowWarning("network_send: fd #%u max Outstanding buffers exceeded. - disconnecting.\n", fd); - network_disconnect(fd); - // - _network_free_netbuf_async(buf); - return; - } - - - // Attach to the end: - buf->next = NULL; - if(s->write.buf_last != NULL){ - s->write.buf_last->next = buf; - s->write.buf_last = buf; - - }else{ - // currently no buffer attached. - s->write.buf = s->write.buf_last = buf; - - // register @ evdp for writable notification. - evdp_writable_add(fd, &s->evdp_data); // - } - - - // - s->write.n_outstanding++; - -}//end: network_send() - - -void network_parser_set_ro(int32 fd, - int16 *packetlentable, - void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf) - ){ - register SESSION *s = &g_Session[fd]; - register netbuf b, nb; // used for potential free attached buffers. - - if(s->type == NST_FREE) - return; - - s->onPacketComplete = onPacketCompleteProc; - - s->onRecv = _onRORecv; // .. - s->onSend = _onSend; // Using the normal generic netbuf based send function. - - s->netparser_data = packetlentable; - - // Initial State -> Need Packet OPCode. - s->read.state = NRS_WAITOP; - s->read.head_left = 2; - - - // Detach (if..) all buffers. - if(s->read.buf != NULL){ - _network_free_netbuf_async(s->read.buf); // - s->read.buf = NULL; - } - - if(s->write.buf != NULL){ - b = s->write.buf; - while(1){ - nb = b->next; - - _network_free_netbuf_async(b); - - b = nb; - } - - s->write.buf = NULL; - s->write.buf_last = NULL; - s->write.n_outstanding = 0; - } - - // not changing any limits on outstanding .. - // - -}//end: network_parser_set_ro() diff --git a/src/common/network.h b/src/common/network.h deleted file mode 100644 index d7b463a2f..000000000 --- a/src/common/network.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef _rA_NETWORK_H_ -#define _rA_NETWORK_H_ - -#include <netinet/in.h> -#include "../common/cbasetypes.h" -#include "../common/netbuffer.h" -#include "../common/evdp.h" - -#ifndef MAXCONN -#define MAXCONN 16384 -#endif - - -typedef struct SESSION{ - EVDP_DATA evdp_data; // Must be always the frist member! (some evdp's may rely on this fact) - - // Connection Type - enum{ NST_FREE=0, NST_LISTENER = 1, NST_CLIENT=2, NST_OUTGOING=3} type; - - // Flags / Settings. - bool v6; // is v6? - bool disconnect_in_progress; // To prevent stack overflows / recursive calls. - - - union{ // union to save memory. - struct sockaddr_in v4; - struct sockaddr_in6 v6; - }addr; - - - // "lowlevel" Handlers - // (Implemented by the protocol specific parser) - // - bool (*onRecv)(int32 fd); // return false = disconnect - bool (*onSend)(int32 fd); // return false = disconnect - - // Event Handlers for LISTENER type sockets - // - // onConnect gets Called when a connection has been - // successfully accepted. - // Session entry is available in this Handler! - // A returncode of false will reejct the connection (disconnect) - // Note: When rejecting a connection in onConnect by returning false - // The onDisconnect handler wont get called! - // Note: the onConnect Handler is also responsible for setting - // the appropriate netparser (which implements onRecv/onSend..) [protocol specific] - // - // onDisconnect gets called when a connection gets disconnected - // (by peer as well as by core) - // - bool (*onConnect)(int32 fd); // return false = disconnect (wont accept) - void (*onDisconnect)(int32 fd); - - - // - // Parser specific data - // - void *netparser_data; // incase of RO Packet Parser, pointer to packet len table (uint16array) - void (*onPacketComplete)(int32 fd, uint16 op, uint16 len, netbuf buf); - - - // - // Buffers - // - struct{ - enum NETREADSTATE { NRS_WAITOP = 0, NRS_WAITLEN = 1, NRS_WAITDATA = 2} state; - - uint32 head_left; - uint16 head[2]; - - netbuf buf; - } read; - - struct{ - uint32 max_outstanding; - uint32 n_outstanding; - - uint32 dataPos; - - netbuf buf, buf_last; - } write; - - // Application Level data Pointer - // (required for backward compatibility with previous athena socket system.) - void *data; - -} SESSION; - - -/** - * Subsystem Initialization / Finalization. - * - */ -void network_init(); -void network_final(); - - -/** - * Will do the net work :) .. - */ -void network_do(); - - -/** - * Adds a new listner. - * - * @param v6 v6 listner? - * @param *addr the address to listen on. - * @param port port to listen on - * - * @return -1 on error otherwise the identifier of the new listener. - */ -int32 network_addlistener(bool v6, const char *addr, uint16 port); - - -/** - * Tries to establish an outgoing connection. - * - * @param v6 operate with IPv6 addresses? - * @param addr the address to connect to - * @param port the port to connect to - * @param from_addr the address to connect from (local source / optional if auto -> NULL) - * @param from_port the port to connect from (local source / optional if auto -> 0) - * @param onConnectionEstablishedHandler callback that gets called when the connection is established. - * @param onConnectionLooseHandler callback that gets called when the connection gets disconnected (or the connection couldnt be established) - * - * @return -1 on error otherwise the identifier of the new connection - */ -int32 network_connect(bool v6, - const char *addr, - uint16 port, - const char *from_addr, - uint16 from_port, - bool (*onConnectionEstablishedHandler)(int32 fd), - void (*onConnectionLooseHandler)(int32 fd) -); - - - -/** - * Disconnects the given connection - * - * @param fd connection identifier. - * - * @Note: - * - onDisconnect callback gets called! - * - cleares (returns) all assigned buffers - * - */ -void network_disconnect(int32 fd); - - -/** - * Attach's a netbuffer at the end of sending queue to the given connection - * - * @param fd connection identifier - * @param buf netbuffer to attach. - */ -void network_send(int32 fd, netbuf buf); - - -/** - * Sets the parser to RO Protocol like Packet Parser. - * - * @param fd connection identifier - * @param *packetlentable pointer to array of uint16 in size of UINT16_MAX, - * @param onComplteProc callback for packet completion. - * - * @note: - * PacketLen Table Fromat: - * each element's offsets represents th ro opcode. - * value is length. - * a length of 0 means the packet is dynamic. - * a length of UINT16_MAX means the packet is unknown. - * - * Static Packets must contain their hader in len so (0x64 == 55 ..) - * - */ -void network_parser_set_ro(int32 fd, - int16 *packetlentable, - void (*onPacketCompleteProc)(int32 fd, uint16 op, uint16 len, netbuf buf) - ); -#define ROPACKET_UNKNOWN UINT16_MAX -#define ROPACKET_DYNLEN 0 - - - - -#endif diff --git a/src/common/nullpo.c b/src/common/nullpo.c index 1cb471aff..a3471b00d 100644 --- a/src/common/nullpo.c +++ b/src/common/nullpo.c @@ -2,15 +2,19 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#include "nullpo.h" + #include <stdio.h> #include <stdarg.h> #include <string.h> -#include "../common/nullpo.h" + #include "../common/showmsg.h" /** * Reports failed assertions or NULL pointers - * + * * @param file Source file where the error was detected * @param line Line * @param func Function diff --git a/src/common/nullpo.h b/src/common/nullpo.h index fb1cf0feb..581252cca 100644 --- a/src/common/nullpo.h +++ b/src/common/nullpo.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_NULLPO_H_ -#define _COMMON_NULLPO_H_ +#ifndef COMMON_NULLPO_H +#define COMMON_NULLPO_H #include "../common/cbasetypes.h" @@ -125,4 +125,4 @@ void assert_report(const char *file, int line, const char *func, const char *targetname, const char *title); -#endif /* _COMMON_NULLPO_H_ */ +#endif /* COMMON_NULLPO_H */ diff --git a/src/common/raconf.c b/src/common/raconf.c deleted file mode 100644 index abeed444b..000000000 --- a/src/common/raconf.c +++ /dev/null @@ -1,583 +0,0 @@ -// -// Athena style config parser -// (would be better to have "one" implementation instead of .. 4 :) -// -// -// Author: Florian Wilkemeyer <fw@f-ws.de> -// -// Copyright (c) RAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -// - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "../common/cbasetypes.h" -#include "../common/showmsg.h" -#include "../common/db.h" -#include "../common/malloc.h" - -#include "../common/raconf.h" - -#define SECTION_LEN 32 -#define VARNAME_LEN 64 - -struct raconf { - DBMap *db; -}; - - -struct conf_value{ - int64 intval; - bool bval; - double floatval; - size_t strval_len; // not includung \0 - char strval[16]; -}; - - - -static struct conf_value *makeValue(const char *key, char *val, size_t val_len){ - struct conf_value *v; -/* size_t sz; - - sz = sizeof(struct conf_value); - if(val_len >= sizeof(v->strval)) - sz += (val_len - sizeof(v->strval) + 1);*/ - - v = (struct conf_value*)aCalloc(1, sizeof(struct conf_value)); - if(v == NULL){ - ShowFatalError("raconf: makeValue => Out of Memory while allocating new node.\n"); - return NULL; - } - - memcpy(v->strval, val, val_len); - v->strval[val_len+1] = '\0'; - v->strval_len = val_len; - - - // Parse boolean value: - if((val_len == 4) && (strncmpi("true", val, 4) == 0)) - v->bval = true; - else if((val_len == 3) && (strncmpi("yes", val, 3) == 0)) - v->bval = true; - else if((val_len == 3) && (strncmpi("oui", val, 3) == 0)) - v->bval = true; - else if((val_len == 2) && (strncmpi("si", val, 2) == 0)) - v->bval = true; - else if((val_len == 2) && (strncmpi("ja", val, 2) == 0)) - v->bval = true; - else if((val_len == 1) && (*val == '1')) - v->bval = true; - else if((val_len == 5) && (strncmpi("false", val, 5) == 0)) - v->bval = false; - else if((val_len == 2) && (strncmpi("no", val, 2) == 0)) - v->bval = false; - else if((val_len == 3) && (strncmpi("non", val, 3) == 0)) - v->bval = false; - else if((val_len == 2) && (strncmpi("no", val, 2) == 0)) - v->bval = false; - else if((val_len == 4) && (strncmpi("nein", val, 4) == 0)) - v->bval = false; - else if((val_len == 1) && (*val == '0')) - v->bval = false; - else - v->bval = false; // assume false. - - // Parse number - // Supported formats: - // prefix: 0x hex . - // postix: h for hex - // b for bin (dual) - if( (val_len >= 1 && (val[val_len] == 'h')) || (val_len >= 2 && (val[0] == '0' && val[1] == 'x')) ){//HEX! - if(val[val_len] == 'h'){ - val[val_len]= '\0'; - v->intval = strtoull(val, NULL, 16); - val[val_len] = 'h'; - }else - v->intval = strtoull(&val[2], NULL, 16); - }else if( val_len >= 1 && (val[val_len] == 'b') ){ //BIN - val[val_len] = '\0'; - v->intval = strtoull(val, NULL, 2); - val[val_len] = 'b'; - }else if( *val >='0' && *val <= '9'){ // begins with normal digit, so assume its dec. - // is it float? - bool is_float = false; - char *p; - - for(p = val; *p != '\0'; p++){ - if(*p == '.'){ - v->floatval = strtod(val, NULL); - v->intval = (int64) v->floatval; - is_float = true; - break; - } - } - - if(is_float == false){ - v->intval = strtoull(val, NULL, 10); - v->floatval = (double) v->intval; - } - }else{ - // Everything else: lets use boolean for fallback - if(v->bval == true) - v->intval = 1; - else - v->intval = 0; - } - - return v; -}//end: makeValue() - - -static bool configParse(raconf inst, const char *fileName){ - FILE *fp; - char line[4096]; - char currentSection[SECTION_LEN]; - char *p; - char c; - int linecnt; - size_t linelen; - size_t currentSection_len; - - fp = fopen(fileName, "r"); - if(fp == NULL){ - ShowError("configParse: cannot open '%s' for reading.\n", fileName); - return false; - } - - - // Start with empty section: - currentSection[0] = '\0'; - currentSection_len = 0; - - // - linecnt = 0; - while(1){ - linecnt++; - - if(fgets(line, sizeof(line), fp) != line) - break; - - linelen = strlen(line); - p = line; - - // Skip whitespaces from beginning (space and tab) - _line_begin_skip_whities: - c = *p; - if(c == ' ' || c == '\t'){ - p++; - linelen--; - goto _line_begin_skip_whities; - } - - // Remove linebreaks as (cr or lf) and whitespaces from line end! - _line_end_skip_whities_and_breaks: - c = p[linelen-1]; - if(c == '\r' || c == '\n' || c == ' ' || c == '\t'){ - p[--linelen] = '\0'; - goto _line_end_skip_whities_and_breaks; - } - - // Empty line? - // or line starts with comment (commented out)? - if(linelen == 0 || (p[0] == '/' && p[1] == '/') || p[0] == ';') - continue; - - // Variable names can contain: - // A-Za-z-_.0-9 - // - // Sections start with [ .. ] (INI Style) - // - c = *p; - - // check what we have.. :) - if(c == '['){ // got section! - // Got Section! - // Search for ] - char *start = (p+1); - - while(1){ - ++p; - c = *p; - - if(c == '\0'){ - ShowError("Syntax Error: unterminated Section name in %s:%u (expected ']')\n", fileName, linecnt); - fclose(fp); - return false; - }else if(c == ']'){ // closing backet (section name termination) - if( (p - start + 1) > (sizeof(currentSection) ) ){ - ShowError("Syntax Error: Section name in %s:%u is too large (max Supported length: %u chars)\n", fileName, linecnt, sizeof(currentSection)-1); - fclose(fp); - return false; - } - - // Set section! - *p = '\0'; // add termination here. - memcpy(currentSection, start, (p-start)+1 ); // we'll copy \0, too! (we replaced the ] backet with \0.) - currentSection_len = (p-start); - - break; - - }else if( (c >= '0' && c <= '9') || (c == '-') || (c == ' ') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){ - // skip .. (allowed char / specifier) - continue; - }else{ - ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Section name.\n", c, fileName, linecnt, (p-line)); - fclose(fp); - return false; - } - - }//endwhile: parse section name - - - }else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){ - // Got variable! - // Search for '=' or ':' wich termiantes the name - char *start = p; - char *valuestart = NULL; - size_t start_len; - - while(1){ - ++p; - c = *p; - - if(c == '\0'){ - ShowError("Syntax Error: unterminated Variable name in %s:%u\n", fileName, linecnt); - fclose(fp); - return false; - }else if( (c == '=') || (c == ':') ){ - // got name termination - - *p = '\0'; // Terminate it so (start) will hold the pointer to the name. - - break; - - }else if( (c >= '0' && c <= '9') || (c == '-') || (c == '_') || (c == '.') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ){ - // skip .. allowed char - continue; - }else{ - ShowError("Syntax Error: Invalid Character '%c' in %s:%u (offset %u) for Variable name.\n", c, fileName, linecnt, (p-line)); - fclose(fp); - return false; - } - - }//endwhile: parse var name - - start_len = (p-start); - if(start_len >= VARNAME_LEN){ - ShowError("%s:%u Variable length exceeds limit of %u Characters.\n", fileName, linecnt, VARNAME_LEN-1); - fclose(fp); - return false; - }else if(start_len == 0){ - ShowError("%s:%u Empty Variable name is not allowed.\n", fileName, linecnt); - fclose(fp); - return false; - } - - - valuestart = (p+1); - - - // Skip whitespace from begin of value (tab and space) - _skip_value_begin_whities: - c = *valuestart; - if(c == ' ' || c == '\t'){ - valuestart++; - goto _skip_value_begin_whities; - } - - // Scan for value termination, - // wich can be \0 or comment start (// or ; (INI) ) - // - p = valuestart; - while(1){ - c = *p; - if(c == '\0'){ - // Terminated by line end. - break; - }else if(c == '/' && p[1] == '/'){ - // terminated by c++ style comment. - *p = '\0'; - break; - }else if(c == ';'){ - // terminated by ini style comment. - *p = '\0'; - break; - } - - p++; - }//endwhile: search var value end. - - - // Strip whitespaces from end of value. - if(valuestart != p){ // not empty! - p--; - _strip_value_end_whities: - c = *p; - if(c == ' ' || c == '\t'){ - *p = '\0'; - p--; - goto _strip_value_end_whities; - } - p++; - } - - - // Buildin Hook: - if( stricmp(start, "import") == 0){ - if( configParse(inst, valuestart) != true){ - ShowError("%s:%u - Import of '%s' failed!\n", fileName, linecnt, valuestart); - } - }else{ - // put it to db. - struct conf_value *v, *o; - char key[ (SECTION_LEN+VARNAME_LEN+1+1) ]; //+1 for delimiter, +1 for termination. - size_t section_len; - - if(*currentSection == '\0'){ // empty / none - strncpy(key, "<unnamed>",9); - section_len = 9; - }else{ - strncpy(key, currentSection, currentSection_len); - section_len = currentSection_len; - } - - key[section_len] = '.'; // Delim - - strncpy(&key[section_len+1], start, start_len); - - key[section_len + start_len + 1] = '\0'; - - - v = makeValue(key, valuestart, (p-valuestart) ); - - // Try to get the old one before - o = strdb_get(inst->db, key); - if(o != NULL){ - strdb_remove(inst->db, key); - aFree(o); // - } - - strdb_put( inst->db, key, v); - } - - - }else{ - ShowError("Syntax Error: unexpected Character '%c' in %s:%u (offset %u)\n", c, fileName, linecnt, (p-line) ); - fclose(fp); - return false; - } - - - - } - - - - fclose(fp); - return true; -}//end: configParse() - - -#define MAKEKEY(dest, section, key) do { \ - size_t section_len_, key_len_; \ - if((section) == NULL || *(section) == '\0'){ \ - strncpy((dest), "<unnamed>", 9); \ - section_len_ = 9; \ - } else { \ - section_len_ = strlen(section); \ - strncpy((dest), (section), section_len_); \ - } \ - (dest)[section_len_] = '.'; \ - key_len_ = strlen(key); \ - strncpy(&(dest)[section_len_+1], (key), key_len_); \ - (dest)[section_len_ + key_len_ + 1] = '\0'; \ -} while(0) - - -raconf raconf_parse(const char *file_name){ - struct raconf *rc; - - rc = aCalloc(1, sizeof(struct raconf) ); - if(rc == NULL){ - ShowFatalError("raconf_parse: failed to allocate memory for new handle\n"); - return NULL; - } - - rc->db = strdb_alloc(DB_OPT_BASE | DB_OPT_DUP_KEY, 98); - // - - if(configParse(rc, file_name) != true){ - ShowError("Failed to Parse Configuration file '%s'\n", file_name); - } - - return rc; -}//end: raconf_parse() - - -void raconf_destroy(raconf rc){ - DBIterator *iter; - struct conf_value *v; - - // Clear all entrys in db. - iter = db_iterator(rc->db); - for( v = (struct conf_value*)dbi_first(iter); dbi_exists(iter); v = (struct conf_value*)dbi_next(iter) ){ - aFree(v); - } - dbi_destroy(iter); - - db_destroy(rc->db); - - aFree(rc); - -}//end: raconf_destroy() - -bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - - v = strdb_get(rc->db, keystr); - if(v == NULL) - return _default; - else - return v->bval; -}//end: raconf_getbool() - - -float raconf_getfloat(raconf rc,const char *section, const char *key, float _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - - v = strdb_get(rc->db, keystr); - if(v == NULL) - return _default; - else - return (float)v->floatval; -}//end: raconf_getfloat() - - -int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - - v = strdb_get(rc->db, keystr); - if(v == NULL) - return _default; - else - return v->intval; - -}//end: raconf_getint() - - -const char* raconf_getstr(raconf rc, const char *section, const char *key, const char *_default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - - v = strdb_get(rc->db, keystr); - if(v == NULL) - return _default; - else - return v->strval; -}//end: raconf_getstr() - - -bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - - MAKEKEY(keystr, fallback_section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - return _default; - }else{ - return v->bval; - } - - }else{ - return v->bval; - } -}//end: raconf_getboolEx() - - -float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - - MAKEKEY(keystr, fallback_section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - return _default; - }else{ - return (float)v->floatval; - } - - }else{ - return (float)v->floatval; - } - -}//end: raconf_getfloatEx() - - -int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - - MAKEKEY(keystr, fallback_section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - return _default; - }else{ - return v->intval; - } - - }else{ - return v->intval; - } - -}//end: raconf_getintEx() - - -const char* raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default){ - char keystr[SECTION_LEN + VARNAME_LEN + 1 + 1]; - struct conf_value *v; - - MAKEKEY(keystr, section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - - MAKEKEY(keystr, fallback_section, key); - v = strdb_get(rc->db, keystr); - if(v == NULL){ - return _default; - }else{ - return v->strval; - } - - }else{ - return v->strval; - } - -}//end: raconf_getstrEx() diff --git a/src/common/raconf.h b/src/common/raconf.h deleted file mode 100644 index 68a2b51b2..000000000 --- a/src/common/raconf.h +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL -// For more information, see LICENCE in the main folder - -#ifndef _rA_CONF_H_ -#define _rA_CONF_H_ - -#include "../common/cbasetypes.h" - -// rAthena generic configuration file parser -// -// Config file Syntax is athena style -// extended with ini style support (including sections) -// -// Comments are started with // or ; (ini style) -// - -typedef struct raconf *raconf; - - -/** - * Parses a rAthna Configuration file - * - * @param file_name path to the file to parse - * - * @returns not NULL incase of success - */ -raconf raconf_parse(const char *file_name); - - -/** - * Frees a Handle received from raconf_parse - * - * @param rc - the handle to free - */ -void raconf_destroy(raconf rc); - - -/** - * Gets the value for Section / Key pair, if key not exists returns _default! - * - */ -bool raconf_getbool(raconf rc, const char *section, const char *key, bool _default); -float raconf_getfloat(raconf rc,const char *section, const char *key, float _default); -int64 raconf_getint(raconf rc, const char *section, const char *key, int64 _default); -const char* raconf_getstr(raconf rc, const char *section, const char *key, const char *_default); - -/** - * Gets the value for Section / Key pair, but has fallback section option if not found in section, - * if not found in both - default gets returned. - * - */ -bool raconf_getboolEx(raconf rc, const char *section, const char *fallback_section, const char *key, bool _default); -float raconf_getfloatEx(raconf rc,const char *section, const char *fallback_section, const char *key, float _default); -int64 raconf_getintEx(raconf rc, const char *section, const char *fallback_section, const char *key, int64 _default); -const char* raconf_getstrEx(raconf rc, const char *section, const char *fallback_section, const char *key, const char *_default); - - - -#endif diff --git a/src/common/random.c b/src/common/random.c index e46c52cad..88d5748cf 100644 --- a/src/common/random.c +++ b/src/common/random.c @@ -1,17 +1,24 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder +#define HERCULES_CORE + +#include "random.h" + +#include <time.h> // time + +#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53 + +#include "../common/cbasetypes.h" // for WIN32 #include "../common/showmsg.h" #include "../common/timer.h" // gettick -#include "random.h" + #if defined(WIN32) - #include "../common/winapi.h" +# include "../common/winapi.h" #elif defined(HAVE_GETPID) || defined(HAVE_GETTID) - #include <sys/types.h> - #include <unistd.h> +# include <sys/types.h> +# include <unistd.h> #endif -#include <time.h> // time -#include <mt19937ar.h> // init_genrand, genrand_int32, genrand_res53 /// Initializes the random number generator with an appropriate seed. diff --git a/src/common/random.h b/src/common/random.h index ab83fb4d4..15d7f8ab1 100644 --- a/src/common/random.h +++ b/src/common/random.h @@ -1,8 +1,8 @@ // Copyright (c) Athena Dev Teams - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#ifndef _COMMON_RANDOM_H_ -#define _COMMON_RANDOM_H_ +#ifndef COMMON_RANDOM_H +#define COMMON_RANDOM_H #include "../common/cbasetypes.h" @@ -15,4 +15,4 @@ int32 rnd_value(int32 min, int32 max);// [min, max] double rnd_uniform(void);// [0.0, 1.0) double rnd_uniform53(void);// [0.0, 1.0) -#endif /* _COMMON_RANDOM_H_ */ +#endif /* COMMON_RANDOM_H */ diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 14342fe5e..b9bcef9b2 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -2,23 +2,26 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/strlib.h" // StringBuf +#define HERCULES_CORE + #include "showmsg.h" -#include "core.h" //[Ind] - For SERVER_TYPE +#include <stdarg.h> #include <stdio.h> +#include <stdlib.h> // atexit #include <string.h> -#include <stdarg.h> #include <time.h> -#include <stdlib.h> // atexit #include "../../3rdparty/libconfig/libconfig.h" +#include "../common/cbasetypes.h" +#include "../common/core.h" //[Ind] - For SERVER_TYPE +#include "../common/strlib.h" // StringBuf + #ifdef WIN32 -#include "../common/winapi.h" +# include "../common/winapi.h" #else // not WIN32 -#include <unistd.h> +# include <unistd.h> #endif // WIN32 #if defined(DEBUGLOGMAP) @@ -85,10 +88,10 @@ int console_msg_log = 0;//[Ind] msg error logging // XXX adapted from eApp (comments are left untouched) [flaviojs] /////////////////////////////////////////////////////////////////////////////// -// ansi compatible printf with control sequence parser for windows +// ANSI compatible printf with control sequence parser for windows // fast hack, handle with care, not everything implemented // -// \033[#;...;#m - Set Graphics Rendition (SGR) +// \033[#;...;#m - Set Graphics Rendition (SGR) // // printf("\x1b[1;31;40m"); // Bright red on black // printf("\x1b[3;33;45m"); // Blinking yellow on magenta (blink not implemented) @@ -107,19 +110,19 @@ int console_msg_log = 0;//[Ind] msg error logging // 8 - Concealed (invisible) // // \033[#A - Cursor Up (CUU) -// Moves the cursor up by the specified number of lines without changing columns. +// Moves the cursor up by the specified number of lines without changing columns. // If the cursor is already on the top line, this sequence is ignored. \e[A is equivalent to \e[1A. // // \033[#B - Cursor Down (CUD) -// Moves the cursor down by the specified number of lines without changing columns. +// Moves the cursor down by the specified number of lines without changing columns. // If the cursor is already on the bottom line, this sequence is ignored. \e[B is equivalent to \e[1B. // // \033[#C - Cursor Forward (CUF) -// Moves the cursor forward by the specified number of columns without changing lines. +// Moves the cursor forward by the specified number of columns without changing lines. // If the cursor is already in the rightmost column, this sequence is ignored. \e[C is equivalent to \e[1C. // // \033[#D - Cursor Backward (CUB) -// Moves the cursor back by the specified number of columns without changing lines. +// Moves the cursor back by the specified number of columns without changing lines. // If the cursor is already in the leftmost column, this sequence is ignored. \e[D is equivalent to \e[1D. // // \033[#E - Cursor Next Line (CNL) @@ -132,19 +135,19 @@ int console_msg_log = 0;//[Ind] msg error logging // Moves the cursor to indicated column in current row. \e[G is equivalent to \e[1G. // // \033[#;#H - Cursor Position (CUP) -// Moves the cursor to the specified position. The first # specifies the line number, -// the second # specifies the column. If you do not specify a position, the cursor moves to the home position: +// Moves the cursor to the specified position. The first # specifies the line number, +// the second # specifies the column. If you do not specify a position, the cursor moves to the home position: // the upper-left corner of the screen (line 1, column 1). // // \033[#;#f - Horizontal & Vertical Position // (same as \033[#;#H) // // \033[s - Save Cursor Position (SCP) -// The current cursor position is saved. +// The current cursor position is saved. // // \033[u - Restore cursor position (RCP) // Restores the cursor position saved with the (SCP) sequence \033[s. -// (addition, restore to 0,0 if nothinh was saved before) +// (addition, restore to 0,0 if nothing was saved before) // // \033[#J - Erase Display (ED) @@ -210,7 +213,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) WriteFile(handle, p, (DWORD)(q-p), &written, 0); if( q[1]!='[' ) - { // write the escape char (whatever purpose it has) + { // write the escape char (whatever purpose it has) if(0==WriteConsole(handle, q, 1, &written, 0) ) WriteFile(handle,q, 1, &written, 0); p=q+1; //and start searching again @@ -230,7 +233,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) q=q+2; for(;;) { - if( ISDIGIT(*q) ) + if( ISDIGIT(*q) ) { // add number to number array, only accept 2digits, shift out the rest // so // \033[123456789m will become \033[89m numbers[numpoint] = (numbers[numpoint]<<4) | (*q-'0'); @@ -279,7 +282,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) } //case '2': // not existing //case '3': // blinking (not implemented) - //case '4': // unterline (not implemented) + //case '4': // underline (not implemented) //case '6': // not existing //case '8': // concealed (not implemented) //case '9': // not existing @@ -347,12 +350,12 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) else if(num==2) { // Number of chars on screen. cnt = info.dwSize.X * info.dwSize.Y; - SetConsoleCursorPosition(handle, origin); + SetConsoleCursorPosition(handle, origin); } else// 0 and default { // number of chars from cursor to end origin = info.dwCursorPosition; - cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X; + cnt = info.dwSize.X * (info.dwSize.Y - info.dwCursorPosition.Y) - info.dwCursorPosition.X; } FillConsoleOutputAttribute(handle, info.wAttributes, cnt, origin, &tmp); FillConsoleOutputCharacter(handle, ' ', cnt, origin, &tmp); @@ -386,7 +389,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) else if( *q == 'H' || *q == 'f' ) { // \033[#;#H - Cursor Position (CUP) // \033[#;#f - Horizontal & Vertical Position - // The first # specifies the line number, the second # specifies the column. + // The first # specifies the line number, the second # specifies the column. // The default for both is 1 info.dwCursorPosition.X = (numbers[numpoint])?(numbers[numpoint]>>4)*10+((numbers[numpoint]&0x0F)-1):0; info.dwCursorPosition.Y = (numpoint && numbers[numpoint-1])?(numbers[numpoint-1]>>4)*10+((numbers[numpoint-1]&0x0F)-1):0; @@ -483,7 +486,7 @@ int VFPRINTF(HANDLE handle, const char *fmt, va_list argptr) --q; } // skip the sequencer and search again - p = q+1; + p = q+1; break; }// end while } @@ -539,7 +542,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr) { // find the escape character fprintf(file, "%.*s", (int)(q-p), p); // write up to the escape if( q[1]!='[' ) - { // write the escape char (whatever purpose it has) + { // write the escape char (whatever purpose it has) fprintf(file, "%.*s", 1, q); p=q+1; //and start searching again } @@ -552,7 +555,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr) q=q+2; while(1) { - if( ISDIGIT(*q) ) + if( ISDIGIT(*q) ) { ++q; // and next character @@ -621,7 +624,7 @@ int VFPRINTF(FILE *file, const char *fmt, va_list argptr) --q; } // skip the sequencer and search again - p = q+1; + p = q+1; break; }// end while } @@ -651,7 +654,7 @@ int FPRINTF(FILE *file, const char *fmt, ...) char timestamp_format[20] = ""; //For displaying Timestamps -int _vShowMessage(enum msg_type flag, const char *string, va_list ap) +int vShowMessage_(enum msg_type flag, const char *string, va_list ap) { va_list apcopy; char prefix[100]; @@ -660,7 +663,7 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) #endif if (!string || *string == '\0') { - ShowError("Empty string passed to _vShowMessage().\n"); + ShowError("Empty string passed to vShowMessage_().\n"); return 1; } if( @@ -731,7 +734,7 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) strcat(prefix,CL_RED"[Fatal Error]"CL_RESET":"); break; default: - ShowError("In function _vShowMessage() -> Invalid flag passed.\n"); + ShowError("In function vShowMessage_() -> Invalid flag passed.\n"); return 1; } @@ -779,12 +782,12 @@ void ClearScreen(void) ShowMessage(CL_CLS); // to prevent empty string passed messages #endif } -int _ShowMessage(enum msg_type flag, const char *string, ...) +int ShowMessage_(enum msg_type flag, const char *string, ...) { int ret; va_list ap; va_start(ap, string); - ret = _vShowMessage(flag, string, ap); + ret = vShowMessage_(flag, string, ap); va_end(ap); return ret; } @@ -793,37 +796,37 @@ int _ShowMessage(enum msg_type flag, const char *string, ...) void ShowMessage(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_NONE, string, ap); + vShowMessage_(MSG_NONE, string, ap); va_end(ap); } void ShowStatus(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_STATUS, string, ap); + vShowMessage_(MSG_STATUS, string, ap); va_end(ap); } void ShowSQL(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_SQL, string, ap); + vShowMessage_(MSG_SQL, string, ap); va_end(ap); } void ShowInfo(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_INFORMATION, string, ap); + vShowMessage_(MSG_INFORMATION, string, ap); va_end(ap); } void ShowNotice(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_NOTICE, string, ap); + vShowMessage_(MSG_NOTICE, string, ap); va_end(ap); } void ShowWarning(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_WARNING, string, ap); + vShowMessage_(MSG_WARNING, string, ap); va_end(ap); } void ShowConfigWarning(config_setting_t *config, const char *string, ...) @@ -834,25 +837,25 @@ void ShowConfigWarning(config_setting_t *config, const char *string, ...) StrBuf->AppendStr(&buf, string); StrBuf->Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config)); va_start(ap, string); - _vShowMessage(MSG_WARNING, StrBuf->Value(&buf), ap); + vShowMessage_(MSG_WARNING, StrBuf->Value(&buf), ap); va_end(ap); StrBuf->Destroy(&buf); } void ShowDebug(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_DEBUG, string, ap); + vShowMessage_(MSG_DEBUG, string, ap); va_end(ap); } void ShowError(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_ERROR, string, ap); + vShowMessage_(MSG_ERROR, string, ap); va_end(ap); } void ShowFatalError(const char *string, ...) { va_list ap; va_start(ap, string); - _vShowMessage(MSG_FATALERROR, string, ap); + vShowMessage_(MSG_FATALERROR, string, ap); va_end(ap); } diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 49fbc34fb..83eb0ad89 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -2,15 +2,17 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_SHOWMSG_H_ -#define _COMMON_SHOWMSG_H_ - -#ifndef _COMMON_HPMI_H_ - #include "../../3rdparty/libconfig/libconfig.h" -#endif +#ifndef COMMON_SHOWMSG_H +#define COMMON_SHOWMSG_H #include <stdarg.h> +#ifdef HERCULES_CORE +# include "../../3rdparty/libconfig/libconfig.h" +#else +# include "../common/HPMi.h" +#endif + // for help with the console colors look here: // http://www.edoceo.com/liberum/?doc=printf-with-color // some code explanation (used here): @@ -70,9 +72,9 @@ #define CL_XXBL "\033[0;44m" // default on blue #define CL_PASS "\033[0;32;42m" // green on green -#define CL_SPACE " " // space aquivalent of the print messages +#define CL_SPACE " " // space equivalent of the print messages -extern int stdout_with_ansisequence; //If the color ansi sequences are to be used. [flaviojs] +extern int stdout_with_ansisequence; //If the color ANSI sequences are to be used. [flaviojs] extern int msg_silent; //Specifies how silent the console is. [Skotlex] extern int console_msg_log; //Specifies what error messages to log. [Ind] extern char timestamp_format[20]; //For displaying Timestamps [Skotlex] @@ -90,7 +92,7 @@ enum msg_type { }; extern void ClearScreen(void); -#ifndef _COMMON_HPMI_H_ +#ifdef HERCULES_CORE extern void ShowMessage(const char *, ...); extern void ShowStatus(const char *, ...); extern void ShowSQL(const char *, ...); @@ -101,7 +103,18 @@ extern void ClearScreen(void); extern void ShowError(const char *, ...); extern void ShowFatalError(const char *, ...); extern void ShowConfigWarning(config_setting_t *config, const char *string, ...); +#else + 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 -extern int _vShowMessage(enum msg_type flag, const char *string, va_list ap); -#endif /* _COMMON_SHOWMSG_H_ */ +extern int vShowMessage_(enum msg_type flag, const char *string, va_list ap); + +#endif /* COMMON_SHOWMSG_H */ diff --git a/src/common/socket.c b/src/common/socket.c index 35d350e95..85f0aa0ce 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -2,48 +2,50 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/mmo.h" -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/strlib.h" -#include "../config/core.h" -#include "../common/HPM.h" - -#define _H_SOCKET_C_ +#define HERCULES_CORE +#include "../config/core.h" // SHOW_SERVER_STATS +#define H_SOCKET_C #include "socket.h" +#undef H_SOCKET_C #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> +#include "../common/HPM.h" +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" +#include "../common/timer.h" + #ifdef WIN32 - #include "../common/winapi.h" +# include "../common/winapi.h" #else - #include <errno.h> - #include <sys/socket.h> - #include <netinet/in.h> - #include <netinet/tcp.h> - #include <net/if.h> - #include <unistd.h> - #include <sys/time.h> - #include <sys/ioctl.h> - #include <netdb.h> - #include <arpa/inet.h> - - #ifndef SIOCGIFCONF - #include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori] - #endif - #ifndef FIONBIO - #include <sys/filio.h> // FIONBIO on Solaris [FlavioJS] - #endif - - #ifdef HAVE_SETRLIMIT - #include <sys/resource.h> - #endif +# include <arpa/inet.h> +# include <errno.h> +# include <net/if.h> +# include <netdb.h> +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <sys/ioctl.h> +# include <sys/socket.h> +# include <sys/time.h> +# include <unistd.h> + +# ifndef SIOCGIFCONF +# include <sys/sockio.h> // SIOCGIFCONF on Solaris, maybe others? [Shinomori] +# endif +# ifndef FIONBIO +# include <sys/filio.h> // FIONBIO on Solaris [FlavioJS] +# endif + +# ifdef HAVE_SETRLIMIT +# include <sys/resource.h> +# endif #endif /** @@ -62,7 +64,7 @@ struct socket_interface sockt_s; ///////////////////////////////////////////////////////////////////// #if defined(WIN32) ///////////////////////////////////////////////////////////////////// -// windows portability layer +// windows portability layer typedef int socklen_t; @@ -108,7 +110,7 @@ int sock2fd(SOCKET s) /// Inserts the socket into the global array of sockets. /// Returns a new fd associated with the socket. -/// If there are too many sockets it closes the socket, sets an error and +/// If there are too many sockets it closes the socket, sets an error and // returns -1 instead. /// Since fd 0 is reserved, it returns values in the range [1,FD_SETSIZE[. /// @@ -291,8 +293,8 @@ void set_defaultparse(ParseFunc defaultparse) *--------------------------------------*/ void set_nonblocking(int fd, unsigned long yes) { - // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s. - // The argp parameter is zero if nonblocking is to be disabled. + // FIONBIO Use with a nonzero argp parameter to enable the nonblocking mode of socket s. + // The argp parameter is zero if nonblocking is to be disabled. if( sIoctl(fd, FIONBIO, &yes) != 0 ) ShowError("set_nonblocking: Failed to set socket #%d to non-blocking mode (%s) - Please report this!!!\n", fd, error_msg()); } @@ -358,7 +360,7 @@ int recv_to_fifo(int fd) len = sRecv(fd, (char *) session[fd]->rdata + session[fd]->rdata_size, (int)RFIFOSPACE(fd), 0); if( len == SOCKET_ERROR ) - {//An exception has occured + {//An exception has occurred if( sErrno != S_EWOULDBLOCK ) { //ShowDebug("recv_to_fifo: %s, closing connection #%d\n", error_msg(), fd); set_eof(fd); @@ -398,7 +400,7 @@ int send_from_fifo(int fd) len = sSend(fd, (const char *) session[fd]->wdata, (int)session[fd]->wdata_size, MSG_NOSIGNAL); if( len == SOCKET_ERROR ) - {//An exception has occured + {//An exception has occurred if( sErrno != S_EWOULDBLOCK ) { //ShowDebug("send_from_fifo: %s, ending connection #%d\n", error_msg(), fd); #ifdef SHOW_SERVER_STATS @@ -843,7 +845,7 @@ int do_sockets(int next) session[i]->func_send(i); if(session[i]->flag.eof) //func_send can't free a session, this is safe. - { //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex] + { //Finally, even if there is no data to parse, connections signaled eof should be closed, so we call parse_func [Skotlex] session[i]->func_parse(i); //This should close the session immediately. } } @@ -907,20 +909,20 @@ int do_sockets(int next) ////////////////////////////// // IP rules and DDoS protection -typedef struct _connect_history { - struct _connect_history* next; +typedef struct connect_history { + struct connect_history* next; uint32 ip; int64 tick; int count; unsigned ddos : 1; } ConnectHistory; -typedef struct _access_control { +typedef struct access_control { uint32 ip; uint32 mask; } AccessControl; -enum _aco { +enum aco { ACO_DENY_ALLOW, ACO_ALLOW_DENY, ACO_MUTUAL_FAILURE @@ -1232,7 +1234,7 @@ void socket_final(void) if(session[i]) sockt->close(i); - // session[0] Ě_~[f[^đí + // session[0] aFree(session[0]->rdata); aFree(session[0]->wdata); aFree(session[0]); @@ -1362,7 +1364,7 @@ void socket_init(void) } } #elif defined(HAVE_SETRLIMIT) && !defined(CYGWIN) - // NOTE: getrlimit and setrlimit have bogus behaviour in cygwin. + // NOTE: getrlimit and setrlimit have bogus behavior in cygwin. // "Number of fds is virtually unlimited in cygwin" (sys/param.h) {// set socket limit to FD_SETSIZE struct rlimit rlp; @@ -1403,7 +1405,7 @@ void socket_init(void) socket_config_read(SOCKET_CONF_FILENAME); - // initialise last send-receive tick + // initialize last send-receive tick sockt->last_tick = time(NULL); // session[0] is now currently used for disconnected sessions of the map server, and as such, @@ -1456,7 +1458,7 @@ uint32 str2ip(const char* ip_str) } // Reorders bytes from network to little endian (Windows). -// Neccessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls. +// Necessary for sending port numbers to the RO client until Gravity notices that they forgot ntohs() calls. uint16 ntows(uint16 netshort) { return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8); diff --git a/src/common/socket.h b/src/common/socket.h index ca9141716..42b0efe3b 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -2,22 +2,22 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_SOCKET_H_ -#define _COMMON_SOCKET_H_ +#ifndef COMMON_SOCKET_H +#define COMMON_SOCKET_H + +#include <time.h> #include "../common/cbasetypes.h" #ifdef WIN32 - #include "../common/winapi.h" +# include "../common/winapi.h" typedef long in_addr_t; #else - #include <sys/types.h> - #include <sys/socket.h> - #include <netinet/in.h> +# include <netinet/in.h> +# include <sys/socket.h> +# include <sys/types.h> #endif -#include <time.h> - struct HPluginData; #define FIFOSIZE_SERVERLINK 256*1024 @@ -174,7 +174,7 @@ struct socket_interface *sockt; void socket_defaults(void); /* the purpose of these macros is simply to not make calling them be an annoyance */ -#ifndef _H_SOCKET_C_ +#ifndef H_SOCKET_C #define make_listen_bind(ip, port) ( sockt->make_listen_bind(ip, port) ) #define make_connection(ip, port, opt) ( sockt->make_connection(ip, port, opt) ) #define realloc_fifo(fd, rfifo_size, wfifo_size) ( sockt->realloc_fifo(fd, rfifo_size, wfifo_size) ) @@ -194,6 +194,6 @@ void socket_defaults(void); #define ntows(netshort) ( sockt->ntows(netshort) ) #define getips(ips, max) ( sockt->getips(ips, max) ) #define set_eof(fd) ( sockt->set_eof(fd) ) -#endif /* _H_SOCKET_C_ */ +#endif /* H_SOCKET_C */ -#endif /* _COMMON_SOCKET_H_ */ +#endif /* COMMON_SOCKET_H */ diff --git a/src/common/spinlock.h b/src/common/spinlock.h index 29fbb355b..bde36b8e5 100644 --- a/src/common/spinlock.h +++ b/src/common/spinlock.h @@ -1,11 +1,10 @@ -#pragma once -#ifndef _COMMON_SPINLOCK_H_ -#define _COMMON_SPINLOCK_H_ +#ifndef COMMON_SPINLOCK_H +#define COMMON_SPINLOCK_H // // CAS based Spinlock Implementation // -// CamelCase names are choosen to be consistent with microsofts winapi +// CamelCase names are chosen to be consistent with Microsoft's WinAPI // which implements CriticalSection by this naming... // // Author: Florian Wilkemeyer <fw@f-ws.de> @@ -15,39 +14,39 @@ // // +#include "../common/atomic.h" +#include "../common/cbasetypes.h" +#include "../common/thread.h" + #ifdef WIN32 #include "../common/winapi.h" #endif -#include "../common/cbasetypes.h" -#include "../common/atomic.h" -#include "../common/thread.h" - #ifdef WIN32 typedef struct __declspec( align(64) ) SPIN_LOCK{ volatile LONG lock; volatile LONG nest; volatile LONG sync_lock; -} SPIN_LOCK, *PSPIN_LOCK; +} SPIN_LOCK; #else typedef struct SPIN_LOCK{ volatile int32 lock; volatile int32 nest; // nesting level. volatile int32 sync_lock; -} __attribute__((aligned(64))) SPIN_LOCK, *PSPIN_LOCK; +} __attribute__((aligned(64))) SPIN_LOCK; #endif -static forceinline void InitializeSpinLock(PSPIN_LOCK lck){ +static forceinline void InitializeSpinLock(SPIN_LOCK *lck){ lck->lock = 0; lck->nest = 0; lck->sync_lock = 0; } -static forceinline void FinalizeSpinLock(PSPIN_LOCK lck){ +static forceinline void FinalizeSpinLock(SPIN_LOCK *lck){ return; } @@ -55,10 +54,10 @@ static forceinline void FinalizeSpinLock(PSPIN_LOCK lck){ #define getsynclock(l) do { if(InterlockedCompareExchange((l), 1, 0) == 0) break; rathread_yield(); } while(/*always*/1) #define dropsynclock(l) do { InterlockedExchange((l), 0); } while(0) -static forceinline void EnterSpinLock(PSPIN_LOCK lck){ +static forceinline void EnterSpinLock(SPIN_LOCK *lck){ int tid = rathread_get_tid(); - // Get Sync Lock && Check if the requester thread already owns the lock. + // Get Sync Lock && Check if the requester thread already owns the lock. // if it owns, increase nesting level getsynclock(&lck->sync_lock); if(InterlockedCompareExchange(&lck->lock, tid, tid) == tid){ @@ -70,7 +69,7 @@ static forceinline void EnterSpinLock(PSPIN_LOCK lck){ dropsynclock(&lck->sync_lock); - // Spin until we've got it ! + // Spin until we've got it ! while(1){ if(InterlockedCompareExchange(&lck->lock, tid, 0) == 0){ @@ -85,7 +84,7 @@ static forceinline void EnterSpinLock(PSPIN_LOCK lck){ } -static forceinline void LeaveSpinLock(PSPIN_LOCK lck){ +static forceinline void LeaveSpinLock(SPIN_LOCK *lck){ int tid = rathread_get_tid(); getsynclock(&lck->sync_lock); @@ -101,4 +100,4 @@ static forceinline void LeaveSpinLock(PSPIN_LOCK lck){ -#endif /* _COMMON_SPINLOCK_H_ */ +#endif /* COMMON_SPINLOCK_H */ diff --git a/src/common/sql.c b/src/common/sql.c index 79ccc8e92..a562478ea 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -2,19 +2,23 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams +#define HERCULES_CORE + +#include "sql.h" + +#include <stdlib.h> // strtoul +#include <string.h> // strlen/strnlen/memcpy/memset + #include "../common/cbasetypes.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/strlib.h" #include "../common/timer.h" -#include "sql.h" #ifdef WIN32 -#include "../common/winapi.h" +# include "../common/winapi.h" // Needed before mysql.h #endif #include <mysql.h> -#include <string.h>// strlen/strnlen/memcpy/memset -#include <stdlib.h>// strtoul void hercules_mysql_error_handler(unsigned int ecode); @@ -34,7 +38,7 @@ struct Sql { // Column length receiver. -// Takes care of the possible size missmatch between uint32 and unsigned long. +// Takes care of the possible size mismatch between uint32 and unsigned long. struct s_column_length { uint32* out_length; unsigned long length; @@ -398,8 +402,7 @@ void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug /// Frees a Sql handle returned by Sql_Malloc. -void Sql_Free(Sql* self) -{ +void Sql_Free(Sql* self) { if( self ) { SQL->FreeResult(self); @@ -545,7 +548,7 @@ static void Sql_P_ShowDebugMysqlFieldInfo(const char* prefix, enum enum_field_ty SHOW_DEBUG_OF(MYSQL_TYPE_NULL); #undef SHOW_DEBUG_TYPE_OF } - ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix); + ShowDebug("%stype=%s%s, length=%d%s\n", prefix, sign, type_string, length, length_postfix); } @@ -566,7 +569,7 @@ static void SqlStmt_P_ShowDebugTruncatedColumn(SqlStmt* self, size_t i) Sql_P_ShowDebugMysqlFieldInfo("data - ", field->type, field->flags&UNSIGNED_FLAG, self->column_lengths[i].length, ""); column = &self->columns[i]; if( column->buffer_type == MYSQL_TYPE_STRING ) - Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "+1(nul-terminator)"); + Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, "+1(null-terminator)"); else Sql_P_ShowDebugMysqlFieldInfo("buffer - ", column->buffer_type, column->is_unsigned, column->buffer_length, ""); mysql_free_result(meta); @@ -762,10 +765,10 @@ int SqlStmt_BindColumn(SqlStmt* self, size_t idx, enum SqlDataType buffer_type, { if( buffer_len < 1 ) { - ShowDebug("SqlStmt_BindColumn: buffer_len(%d) is too small, no room for the nul-terminator\n", buffer_len); + ShowDebug("SqlStmt_BindColumn: buffer_len(%d) is too small, no room for the null-terminator\n", buffer_len); return SQL_ERROR; } - --buffer_len;// nul-terminator + --buffer_len;// null-terminator } if( !self->bind_columns ) {// initialize the bindings @@ -888,7 +891,7 @@ int SqlStmt_NextRow(SqlStmt* self) if( self->column_lengths[i].out_length ) *self->column_lengths[i].out_length = (uint32)length; if( column->buffer_type == MYSQL_TYPE_STRING ) - {// clear unused part of the string/enum buffer (and nul-terminate) + {// clear unused part of the string/enum buffer (and null-terminate) memset((char*)column->buffer + length, 0, column->buffer_length - length + 1); } else if( column->buffer_type == MYSQL_TYPE_BLOB && length < column->buffer_length ) diff --git a/src/common/sql.h b/src/common/sql.h index 1fb436853..f9593978c 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -2,13 +2,12 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_SQL_H_ -#define _COMMON_SQL_H_ +#ifndef COMMON_SQL_H +#define COMMON_SQL_H -#include "../common/cbasetypes.h" #include <stdarg.h>// va_list - +#include "../common/cbasetypes.h" // Return codes #define SQL_ERROR (-1) @@ -148,10 +147,10 @@ struct sql_interface { /////////////////////////////////////////////////////////////////////////////// // Prepared Statements /////////////////////////////////////////////////////////////////////////////// - // Parameters are placed in the statement by embedding question mark ('?') + // Parameters are placed in the statement by embedding question mark ('?') // characters into the query at the appropriate positions. // The markers are legal only in places where they represent data. - // The markers cannot be inside quotes. Quotes will be added automatically + // The markers cannot be inside quotes. Quotes will be added automatically // when they are required. // // example queries with parameters: @@ -167,7 +166,7 @@ struct sql_interface { /// It uses the connection of the parent Sql handle. /// Queries in Sql and SqlStmt are independent and don't affect each other. /// - /// @return SqlStmt handle or NULL if an error occured + /// @return SqlStmt handle or NULL if an error occurred struct SqlStmt* (*StmtMalloc)(Sql* sql); @@ -199,7 +198,7 @@ struct sql_interface { /// Returns the number of parameters in the prepared statement. /// - /// @return Number or paramenters + /// @return Number or parameters size_t (*StmtNumParams)(SqlStmt* self); @@ -237,8 +236,8 @@ struct sql_interface { /// Binds the result of a column to a buffer. /// The buffer will be filled with data when the next row is fetched. - /// For string/enum buffer types there has to be enough space for the data - /// and the nul-terminator (an extra byte). + /// For string/enum buffer types there has to be enough space for the data + /// and the null-terminator (an extra byte). /// /// @return SQL_SUCCESS or SQL_ERROR int (*StmtBindColumn)(SqlStmt* self, size_t idx, SqlDataType buffer_type, void* buffer, size_t buffer_len, uint32* out_length, int8* out_is_null); @@ -292,4 +291,4 @@ void Sql_HerculesUpdateSkip(Sql* self,const char *filename); void Sql_Init(void); -#endif /* _COMMON_SQL_H_ */ +#endif /* COMMON_SQL_H */ diff --git a/src/common/strlib.c b/src/common/strlib.c index 361595b07..e2382e6fc 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -2,16 +2,19 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#define STRLIB_C +#define HERCULES_CORE + +#define H_STRLIB_C #include "strlib.h" +#undef H_STRLIB_C +#include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <errno.h> +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" #define J_MAX_MALLOC_SIZE 65535 @@ -144,15 +147,15 @@ char* trim(char* str) if( start == end ) *str = '\0';// empty string else - {// move string with nul terminator + {// move string with null-terminator str[end] = '\0'; memmove(str,str+start,end-start+1); } return str; } -// Converts one or more consecutive occurences of the delimiters into a single space -// and removes such occurences from the beginning and end of string +// Converts one or more consecutive occurrences of the delimiters into a single space +// and removes such occurrences from the beginning and end of string // NOTE: make sure the string is not const!! char* normalize_name(char* str,const char* delims) { @@ -189,7 +192,7 @@ char* normalize_name(char* str,const char* delims) return str; } -//stristr: Case insensitive version of strstr, code taken from +//stristr: Case insensitive version of strstr, code taken from //http://www.daniweb.com/code/snippet313.html, Dave Sinkula // const char* stristr(const char* haystack, const char* needle) @@ -221,7 +224,7 @@ const char* stristr(const char* haystack, const char* needle) } #ifdef __WIN32 -char* _strtok_r(char *s1, const char *s2, char **lasts) { +char* strtok_r_(char *s1, const char *s2, char **lasts) { char *ret; if (s1 == NULL) @@ -355,18 +358,18 @@ int config_switch(const char* str) { return (int)strtol(str, NULL, 0); } -/// strncpy that always nul-terminates the string +/// strncpy that always null-terminates the string char* safestrncpy(char* dst, const char* src, size_t n) { if( n > 0 ) { char* d = dst; const char* s = src; - d[--n] = '\0';/* nul-terminate string */ + d[--n] = '\0';/* null-terminate string */ for( ; n > 0; --n ) { if( (*d++ = *s++) == '\0' ) - {/* nul-pad remaining bytes */ + {/* null-pad remaining bytes */ while( --n > 0 ) *d++ = '\0'; break; @@ -382,12 +385,12 @@ size_t safestrnlen(const char* string, size_t maxlen) return ( string != NULL ) ? strnlen(string, maxlen) : 0; } -/// Works like snprintf, but always nul-terminates the buffer. -/// Returns the size of the string (without nul-terminator) +/// Works like snprintf, but always null-terminates the buffer. +/// Returns the size of the string (without null-terminator) /// or -1 if the buffer is too small. /// /// @param buf Target buffer -/// @param sz Size of the buffer (including nul-terminator) +/// @param sz Size of the buffer (including null-terminator) /// @param fmt Format string /// @param ... Format arguments /// @return The size of the string or -1 if the buffer is too small @@ -401,7 +404,7 @@ int safesnprintf(char* buf, size_t sz, const char* fmt, ...) va_end(ap); if( ret < 0 || (size_t)ret >= sz ) {// overflow - buf[sz-1] = '\0';// always nul-terminate + buf[sz-1] = '\0';// always null-terminate return -1; } return ret; @@ -615,21 +618,21 @@ int sv_parse_next(struct s_svstate* svstate) /// out_pos[0] and out_pos[1] are the start and end of line. /// Other position pairs are the start and end of fields. /// Returns the number of fields found or -1 if an error occurs. -/// +/// /// out_pos can be NULL. /// If a line terminator is found, the end position is placed there. -/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] +/// out_pos[2] and out_pos[3] for the first field, out_pos[4] and out_pos[5] /// for the seconds field and so on. /// Unfilled positions are set to -1. -/// +/// /// @param str String to parse /// @param len Length of the string /// @param startoff Where to start parsing /// @param delim Field delimiter /// @param out_pos Array of resulting positions /// @param npos Size of the pos array -/// @param opt Options that determine the parsing behaviour -/// @return Number of fields found in the string or -1 if an error occured +/// @param opt Options that determine the parsing behavior +/// @return Number of fields found in the string or -1 if an error occurred int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) { struct s_svstate svstate; int count; @@ -663,21 +666,21 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i /// WARNING: this function modifies the input string /// Starts splitting at startoff and fills the out_fields array. /// out_fields[0] is the start of the next line. -/// Other entries are the start of fields (nul-teminated). +/// Other entries are the start of fields (null-terminated). /// Returns the number of fields found or -1 if an error occurs. -/// +/// /// out_fields can be NULL. -/// Fields that don't fit in out_fields are not nul-terminated. +/// Fields that don't fit in out_fields are not null-terminated. /// Extra entries in out_fields are filled with the end of the last field (empty string). -/// +/// /// @param str String to parse /// @param len Length of the string /// @param startoff Where to start parsing /// @param delim Field delimiter /// @param out_fields Array of resulting fields /// @param nfields Size of the field array -/// @param opt Options that determine the parsing behaviour -/// @return Number of fields found in the string or -1 if an error occured +/// @param opt Options that determine the parsing behavior +/// @return Number of fields found in the string or -1 if an error occurred int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt) { int pos[1024]; int i; diff --git a/src/common/strlib.h b/src/common/strlib.h index 10844d257..7f84d2893 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -2,27 +2,21 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_STRLIB_H_ -#define _COMMON_STRLIB_H_ +#ifndef COMMON_STRLIB_H +#define COMMON_STRLIB_H -#include "../common/cbasetypes.h" #include <stdarg.h> +#include <string.h> -#ifndef __USE_GNU - #define __USE_GNU // required to enable strnlen on some platforms - #include <string.h> - #undef __USE_GNU -#else - #include <string.h> -#endif +#include "../common/cbasetypes.h" #ifdef WIN32 #define HAVE_STRTOK_R - #define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr)) - char *_strtok_r(char* s1, const char* s2, char** lasts); + #define strtok_r(s,delim,save_ptr) strtok_r_((s),(delim),(save_ptr)) + char *strtok_r_(char* s1, const char* s2, char** lasts); #endif -/// Bitfield determining the behaviour of sv_parse and sv_split. +/// Bitfield determining the behavior of sv_parse and sv_split. typedef enum e_svopt { // default: no escapes and no line terminator SV_NOESCAPE_NOTERMINATE = 0, @@ -79,14 +73,14 @@ struct strlib_interface { int (*e_mail_check) (char* email); int (*config_switch) (const char* str); - /// strncpy that always nul-terminates the string + /// strncpy that always null-terminates the string char *(*safestrncpy) (char* dst, const char* src, size_t n); /// doesn't crash on null pointer size_t (*safestrnlen) (const char* string, size_t maxlen); - /// Works like snprintf, but always nul-terminates the buffer. - /// Returns the size of the string (without nul-terminator) + /// Works like snprintf, but always null-terminates the buffer. + /// Returns the size of the string (without null-terminator) /// or -1 if the buffer is too small. int (*safesnprintf) (char* buf, size_t sz, const char* fmt, ...); @@ -137,7 +131,7 @@ struct sv_interface { /// WARNING: this function modifies the input string /// Starts splitting at startoff and fills the out_fields array. /// out_fields[0] is the start of the next line. - /// Other entries are the start of fields (nul-teminated). + /// Other entries are the start of fields (null-terminated). /// Returns the number of fields found or -1 if an error occurs. int (*split) (char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt); @@ -165,7 +159,7 @@ struct sv_interface *sv; void strlib_defaults(void); /* the purpose of these macros is simply to not make calling them be an annoyance */ -#ifndef STRLIB_C +#ifndef H_STRLIB_C #define jstrescape(pt) (strlib->jstrescape(pt)) #define jstrescapecpy(pt,spt) (strlib->jstrescapecpy((pt),(spt))) #define jmemescapecpy(pt,spt,size) (strlib->jmemescapecpy((pt),(spt),(size))) @@ -189,6 +183,6 @@ void strlib_defaults(void); #define safesnprintf(buf,sz,fmt,...) (strlib->safesnprintf((buf),(sz),(fmt),##__VA_ARGS__)) #define strline(str,pos) (strlib->strline((str),(pos))) #define bin2hex(output,input,count) (strlib->bin2hex((output),(input),(count))) -#endif /* STRLIB_C */ +#endif /* H_STRLIB_C */ -#endif /* _COMMON_STRLIB_H_ */ +#endif /* COMMON_STRLIB_H */ diff --git a/src/common/sysinfo.c b/src/common/sysinfo.c new file mode 100644 index 000000000..605256100 --- /dev/null +++ b/src/common/sysinfo.c @@ -0,0 +1,1061 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base Author: Haru @ http://hercules.ws + +/// See sysinfo.h for a description of this file + +#define HERCULES_CORE + +#include "sysinfo.h" + +#include <stdio.h> // fopen +#include <stdlib.h> // atoi + +#include "../common/cbasetypes.h" +#include "../common/core.h" +#include "../common/malloc.h" +#include "../common/strlib.h" + +#ifdef WIN32 +# include <string.h> // strlen +# include <windows.h> +#else +# include <unistd.h> +#endif + +/// Private interface fields +struct sysinfo_private { + char *platform; + char *osversion; + char *cpu; + int cpucores; + char *arch; + char *compiler; + char *cflags; + char *vcstype_name; + int vcstype; + char *vcsrevision_src; + char *vcsrevision_scripts; +}; + +/// sysinfo.c interface source +struct sysinfo_interface sysinfo_s; +struct sysinfo_private sysinfo_p; + +#define VCSTYPE_UNKNOWN 0 +#define VCSTYPE_GIT 1 +#define VCSTYPE_SVN 2 +#define VCSTYPE_NONE -1 + +#ifdef WIN32 +/** + * Values to be used with GetProductInfo. + * + * These aren't defined in MSVC2008/WindowsXP, so we gotta define them here. + * Values from: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724358%28v=vs.85%29.aspx + */ +enum windows_product_type { + msPRODUCT_UNDEFINED = 0x00000000, ///< An unknown product + msPRODUCT_ULTIMATE = 0x00000001, ///< Ultimate + msPRODUCT_HOME_BASIC = 0x00000002, ///< Home Basic + msPRODUCT_HOME_PREMIUM = 0x00000003, ///< Home Premium + msPRODUCT_ENTERPRISE = 0x00000004, ///< Enterprise + msPRODUCT_HOME_BASIC_N = 0x00000005, ///< Home Basic N + msPRODUCT_BUSINESS = 0x00000006, ///< Business + msPRODUCT_STANDARD_SERVER = 0x00000007, ///< Server Standard + msPRODUCT_DATACENTER_SERVER = 0x00000008, ///< Server Datacenter (full installation) + msPRODUCT_SMALLBUSINESS_SERVER = 0x00000009, ///< Windows Small Business Server + msPRODUCT_ENTERPRISE_SERVER = 0x0000000A, ///< Server Enterprise (full installation) + msPRODUCT_STARTER = 0x0000000B, ///< Starter + msPRODUCT_DATACENTER_SERVER_CORE = 0x0000000C, ///< Server Datacenter (core installation) + msPRODUCT_ENTERPRISE_SERVER_CORE = 0x0000000E, ///< Server Enterprise (core installation) + msPRODUCT_STANDARD_SERVER_CORE = 0x0000000D, ///< Server Standard (core installation) + msPRODUCT_ENTERPRISE_SERVER_IA64 = 0x0000000F, ///< Server Enterprise for Itanium-based Systems + msPRODUCT_BUSINESS_N = 0x00000010, ///< Business N + msPRODUCT_WEB_SERVER = 0x00000011, ///< Web Server (full installation) + msPRODUCT_CLUSTER_SERVER = 0x00000012, ///< HPC Edition + msPRODUCT_HOME_SERVER = 0x00000013, ///< Windows Storage Server 2008 R2 Essentials + msPRODUCT_STORAGE_EXPRESS_SERVER = 0x00000014, ///< Storage Server Express + msPRODUCT_STORAGE_STANDARD_SERVER = 0x00000015, ///< Storage Server Standard + msPRODUCT_STORAGE_WORKGROUP_SERVER = 0x00000016, ///< Storage Server Workgroup + msPRODUCT_STORAGE_ENTERPRISE_SERVER = 0x00000017, ///< Storage Server Enterprise + msPRODUCT_SERVER_FOR_SMALLBUSINESS = 0x00000018, ///< Windows Server 2008 for Windows Essential Server Solutions + msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM = 0x00000019, ///< Small Business Server Premium + msPRODUCT_HOME_PREMIUM_N = 0x0000001A, ///< Home Premium N + msPRODUCT_ENTERPRISE_N = 0x0000001B, ///< Enterprise N + msPRODUCT_ULTIMATE_N = 0x0000001C, ///< Ultimate N + msPRODUCT_WEB_SERVER_CORE = 0x0000001D, ///< Web Server (core installation) + msPRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT = 0x0000001E, ///< Windows Essential Business Server Management Server + msPRODUCT_MEDIUMBUSINESS_SERVER_SECURITY = 0x0000001F, ///< Windows Essential Business Server Security Server + msPRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING = 0x00000020, ///< Windows Essential Business Server Messaging Server + msPRODUCT_SERVER_FOUNDATION = 0x00000021, ///< Server Foundation + msPRODUCT_HOME_PREMIUM_SERVER = 0x00000022, ///< Windows Home Server 2011 + msPRODUCT_SERVER_FOR_SMALLBUSINESS_V = 0x00000023, ///< Windows Server 2008 without Hyper-V for Windows Essential Server Solutions + msPRODUCT_STANDARD_SERVER_V = 0x00000024, ///< Server Standard without Hyper-V + msPRODUCT_DATACENTER_SERVER_V = 0x00000025, ///< Server Datacenter without Hyper-V (full installation) + msPRODUCT_ENTERPRISE_SERVER_V = 0x00000026, ///< Server Enterprise without Hyper-V (full installation) + msPRODUCT_DATACENTER_SERVER_CORE_V = 0x00000027, ///< Server Datacenter without Hyper-V (core installation) + msPRODUCT_STANDARD_SERVER_CORE_V = 0x00000028, ///< Server Standard without Hyper-V (core installation) + msPRODUCT_ENTERPRISE_SERVER_CORE_V = 0x00000029, ///< Server Enterprise without Hyper-V (core installation) + msPRODUCT_HYPERV = 0x0000002A, ///< Microsoft Hyper-V Server + msPRODUCT_STORAGE_EXPRESS_SERVER_CORE = 0x0000002B, ///< Storage Server Express (core installation) + msPRODUCT_STORAGE_STANDARD_SERVER_CORE = 0x0000002C, ///< Storage Server Standard (core installation) + msPRODUCT_STORAGE_WORKGROUP_SERVER_CORE = 0x0000002D, ///< Storage Server Workgroup (core installation) + msPRODUCT_STORAGE_ENTERPRISE_SERVER_CORE = 0x0000002E, ///< Storage Server Enterprise (core installation) + msPRODUCT_STARTER_N = 0x0000002F, ///< Starter N + msPRODUCT_PROFESSIONAL = 0x00000030, ///< Professional + msPRODUCT_PROFESSIONAL_N = 0x00000031, ///< Professional N + msPRODUCT_SB_SOLUTION_SERVER = 0x00000032, ///< Windows Small Business Server 2011 Essentials + msPRODUCT_SERVER_FOR_SB_SOLUTIONS = 0x00000033, ///< Server For SB Solutions + msPRODUCT_STANDARD_SERVER_SOLUTIONS = 0x00000034, ///< Server Solutions Premium + msPRODUCT_STANDARD_SERVER_SOLUTIONS_CORE = 0x00000035, ///< Server Solutions Premium (core installation) + msPRODUCT_SB_SOLUTION_SERVER_EM = 0x00000036, ///< Server For SB Solutions EM + msPRODUCT_SERVER_FOR_SB_SOLUTIONS_EM = 0x00000037, ///< Server For SB Solutions EM + msPRODUCT_SOLUTION_EMBEDDEDSERVER = 0x00000038, ///< Windows MultiPoint Server + msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMT = 0x0000003B, ///< Windows Essential Server Solution Management + msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDL = 0x0000003C, ///< Windows Essential Server Solution Additional + msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC = 0x0000003D, ///< Windows Essential Server Solution Management SVC + msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC = 0x0000003E, ///< Windows Essential Server Solution Additional SVC + msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE = 0x0000003F, ///< Small Business Server Premium (core installation) + msPRODUCT_CLUSTER_SERVER_V = 0x00000040, ///< Server Hyper Core V + msPRODUCT_STARTER_E = 0x00000042, ///< Not supported + msPRODUCT_HOME_BASIC_E = 0x00000043, ///< Not supported + msPRODUCT_HOME_PREMIUM_E = 0x00000044, ///< Not supported + msPRODUCT_PROFESSIONAL_E = 0x00000045, ///< Not supported + msPRODUCT_ENTERPRISE_E = 0x00000046, ///< Not supported + msPRODUCT_ULTIMATE_E = 0x00000047, ///< Not supported + msPRODUCT_ENTERPRISE_EVALUATION = 0x00000048, ///< Server Enterprise (evaluation installation) + msPRODUCT_MULTIPOINT_STANDARD_SERVER = 0x0000004C, ///< Windows MultiPoint Server Standard (full installation) + msPRODUCT_MULTIPOINT_PREMIUM_SERVER = 0x0000004D, ///< Windows MultiPoint Server Premium (full installation) + msPRODUCT_STANDARD_EVALUATION_SERVER = 0x0000004F, ///< Server Standard (evaluation installation) + msPRODUCT_DATACENTER_EVALUATION_SERVER = 0x00000050, ///< Server Datacenter (evaluation installation) + msPRODUCT_ENTERPRISE_N_EVALUATION = 0x00000054, ///< Enterprise N (evaluation installation) + msPRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER = 0x0000005F, ///< Storage Server Workgroup (evaluation installation) + msPRODUCT_STORAGE_STANDARD_EVALUATION_SERVER = 0x00000060, ///< Storage Server Standard (evaluation installation) + msPRODUCT_CORE_N = 0x00000062, ///< Windows 8 N + msPRODUCT_CORE_COUNTRYSPECIFIC = 0x00000063, ///< Windows 8 China + msPRODUCT_CORE_SINGLELANGUAGE = 0x00000064, ///< Windows 8 Single Language + msPRODUCT_CORE = 0x00000065, ///< Windows 8 + msPRODUCT_PROFESSIONAL_WMC = 0x00000067, ///< Professional with Media Center +}; + +/** + * Values to be used with GetSystemMetrics. + * + * Values from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724385%28v=vs.85%29.aspx + */ +enum windows_metrics { + msSM_SERVERR2 = 89, ///< Obtains the build number if the system is Windows Server 2003 R2; otherwise, 0. +}; + +/** + * Values to be used with OSVERSIONINFOEX.wSuiteMask. + * + * Values from http://msdn.microsoft.com/en-us/library/windows/desktop/ms724833%28v=vs.85%29.aspx + */ +enum windows_ver_suite { + msVER_SUITE_BLADE = 0x00000400, ///< Windows Server 2003, Web Edition is installed. + msVER_SUITE_STORAGE_SERVER = 0x00002000, ///< Windows Storage Server 2003 R2 or Windows Storage Server 2003 is installed. + msVER_SUITE_COMPUTE_SERVER = 0x00004000, ///< Windows Server 2003, Compute Cluster Edition is installed. + msVER_SUITE_WH_SERVER = 0x00008000, ///< Windows Home Server is installed. +}; + +#else // not WIN32 +// UNIX. Use build-time cached values +#include "sysinfo.inc" +#endif // WIN32 + +// Compiler detection <http://sourceforge.net/p/predef/wiki/Compilers/> +#if defined(__BORLANDC__) +#define SYSINFO_COMPILER "Borland C++" +#elif defined(__clang__) +#define SYSINFO_COMPILER "Clang v" EXPAND_AND_QUOTE(__clang_major__) "." EXPAND_AND_QUOTE(__clang_minor__) "." EXPAND_AND_QUOTE(__clang_patchlevel__) +#elif defined(__INTEL_COMPILER) +#define SYSINFO_COMPILER "Intel CC v" EXPAND_AND_QUOTE(__INTEL_COMPILER) +#elif defined(__MINGW32__) +#if defined(__MINGW64__) +#define SYSINFO_COMPILER "MinGW-w64 64 Bit v" EXPAND_AND_QUOTE(__MINGW64_VERSION_MAJOR) "." EXPAND_AND_QUOTE(__MINGW64_VERSION_MINOR) \ + " (MinGW " EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION) ")" +#elif defined(__MINGW64_VERSION_MAJOR) +#define SYSINFO_COMPILER "MinGW-w64 32 Bit v" EXPAND_AND_QUOTE(__MINGW64_VERSION_MAJOR) "." EXPAND_AND_QUOTE(__MINGW64_VERSION_MINOR) \ + " (MinGW " EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION) ")" +#else +#define SYSINFO_COMPILER "MinGW32 v" EXPAND_AND_QUOTE(__MINGW32_MAJOR_VERSION) "." EXPAND_AND_QUOTE(__MINGW32_MINOR_VERSION) +#endif +#elif defined(__GNUC__) +#define SYSINFO_COMPILER "GCC v" EXPAND_AND_QUOTE(__GNUC__) "." EXPAND_AND_QUOTE(__GNUC_MINOR__) "." EXPAND_AND_QUOTE(__GNUC_PATCHLEVEL__) +#elif defined(_MSC_VER) +#if _MSC_VER >= 1300 && _MSC_VER < 1310 +#define SYSINFO_COMPILER "Microsoft Visual C++ 7.0 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1310 && _MSC_VER < 1400 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2003 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1400 && _MSC_VER < 1500 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2005 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1500 && _MSC_VER < 1600 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2008 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1600 && _MSC_VER < 1700 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2010 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1700 && _MSC_VER < 1800 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2012 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#elif _MSC_VER >= 1800 && _MSC_VER < 1900 +#define SYSINFO_COMPILER "Microsoft Visual C++ 2013 (v" EXPAND_AND_QUOTE(_MSC_VER) ")" +#else // < 1300 || >= 1900 +#define SYSINFO_COMPILER "Microsoft Visual C++ v" EXPAND_AND_QUOTE(_MSC_VER) +#endif +#else +#define SYSINFO_COMPILER "Unknown" +#endif +// end compiler detection + +/** + * Retrieves the current SVN revision. + * + * @param out[out] a string pointer to return the value (to be aFree()'d.) + * @retval true if a revision was correctly detected. + * @retval false if no revision was detected. out is set to NULL in this case. + */ +bool sysinfo_svn_get_revision(char **out) { + // Only include SVN support if detected it, or we're on MSVC +#if !defined(SYSINFO_VCSTYPE) || SYSINFO_VCSTYPE == VCSTYPE_SVN || SYSINFO_VCSTYPE == VCSTYPE_UNKNOWN + FILE *fp; + + // subversion 1.7 uses a sqlite3 database + // FIXME this is hackish at best... + // - ignores database file structure + // - assumes the data in NODES.dav_cache column ends with "!svn/ver/<revision>/<path>)" + // - since it's a cache column, the data might not even exist + if ((fp = fopen(".svn"PATHSEP_STR"wc.db", "rb")) != NULL || (fp = fopen(".."PATHSEP_STR".svn"PATHSEP_STR"wc.db", "rb")) != NULL) { + +#ifndef SVNNODEPATH //not sure how to handle branches, so I'll leave this overridable define until a better solution comes up +#define SVNNODEPATH trunk +#endif // SVNNODEPATH + + const char* prefix = "!svn/ver/"; + const char* postfix = "/"EXPAND_AND_QUOTE(SVNNODEPATH)")"; // there should exist only 1 entry like this + size_t prefix_len = strlen(prefix); + size_t postfix_len = strlen(postfix); + size_t i,j,flen; + char* buffer; + + // read file to buffer + fseek(fp, 0, SEEK_END); + flen = ftell(fp); + buffer = (char*)aMalloc(flen + 1); + fseek(fp, 0, SEEK_SET); + flen = fread(buffer, 1, flen, fp); + buffer[flen] = '\0'; + fclose(fp); + + // parse buffer + for (i = prefix_len + 1; i + postfix_len <= flen; ++i) { + if (buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0) + continue; // postfix mismatch + for (j = i; j > 0; --j) { // skip digits + if (!ISDIGIT(buffer[j - 1])) + break; + } + if (memcmp(buffer + j - prefix_len, prefix, prefix_len) != 0) + continue; // prefix mismatch + // done + if (*out != NULL) + aFree(*out); + *out = aCalloc(1, 8); + snprintf(*out, 8, "%d", atoi(buffer + j)); + break; + } + aFree(buffer); + + if (*out != NULL) + return true; + } + + // subversion 1.6 and older? + if ((fp = fopen(".svn/entries", "r")) != NULL) { + char line[1024]; + int rev; + // Check the version + if (fgets(line, sizeof(line), fp)) { + if (!ISDIGIT(line[0])) { + // XML File format + while (fgets(line,sizeof(line),fp)) + if (strstr(line,"revision=")) break; + if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) { + if (*out != NULL) + aFree(*out); + *out = aCalloc(1, 8); + snprintf(*out, 8, "%d", rev); + } + } else { + // Bin File format + if (fgets(line, sizeof(line), fp) == NULL) { printf("Can't get bin name\n"); } // Get the name + if (fgets(line, sizeof(line), fp) == NULL) { printf("Can't get entries kind\n"); } // Get the entries kind + if (fgets(line, sizeof(line), fp)) { // Get the rev numver + if (*out != NULL) + aFree(*out); + *out = aCalloc(1, 8); + snprintf(*out, 8, "%d", atoi(line)); + } + } + } + fclose(fp); + + if (*out != NULL) + return true; + } +#endif + if (*out != NULL) + aFree(*out); + *out = NULL; + return false; +} + +/** + * Retrieves the current Git revision. + * + * @param out[out] a string pointer to return the value (to be aFree()'d.) + * @retval true if a revision was correctly detected. + * @retval false if no revision was detected. out is set to NULL in this case. + */ +bool sysinfo_git_get_revision(char **out) { + // Only include Git support if we detected it, or we're on MSVC +#if !defined(SYSINFO_VCSTYPE) || SYSINFO_VCSTYPE == VCSTYPE_GIT || SYSINFO_VCSTYPE == VCSTYPE_UNKNOWN + FILE *fp; + char ref[128], filepath[128], line[128]; + + strcpy(ref, "HEAD"); + + while (*ref) { + snprintf(filepath, sizeof(filepath), ".git/%s", ref); + if ((fp = fopen(filepath, "r")) != NULL) { + if (fgets(line, sizeof(line)-1, fp) == NULL) { + fclose(fp); + break; + } + fclose(fp); + if (sscanf(line, "ref: %127[^\n]", ref) == 1) { + continue; + } else if (sscanf(line, "%127[a-f0-9]", ref) == 1 && strlen(ref) == 40) { + if (*out != NULL) + aFree(*out); + *out = aStrdup(ref); + } + } + break; + } + if (*out != NULL) + return true; +#else + if (*out != NULL) + aFree(*out); + *out = NULL; +#endif + return false; +} + +#ifdef WIN32 + +/// Windows-specific runtime detection functions. + +typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD); +/** + * Retrieves the Operating System version (Windows only). + * + * Once retrieved, the version string is stored into sysinfo->p->osversion. + */ +void sysinfo_osversion_retrieve(void) { + OSVERSIONINFOEX osvi; + StringBuf buf; + ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); + StrBuf->Init(&buf); + + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + + if (sysinfo->p->osversion != NULL) { + aFree(sysinfo->p->osversion); + sysinfo->p->osversion = NULL; + } + + /* + * #pragma rantmode (on) + * Some engineer at Microsoft moronically decided that, since some applications use this information to do version checks and refuse to + * run if they detect a new, unknown version of Windows, now nobody will be able to rely on this information anymore, not even those who + * need it for reporting or logging. + * The correct fix was to let those applications break, and their developer fix them (and in the meanwhile let the users use the + * Compatibility settings to run them) but no, they decided they'd deprecate the API, and make it lie for those who use it, reporting + * windows 8 even if they're running on 8.1 or newer. + * The API wasn't broken, applications were. Now we have broken applications, and a broken API. Great move, Microsoft. Oh right, + * there's the Version API helper functions. Or maybe not, since you can only do 'are we running on at least version X?' checks with + * those, it's not what we need. + * You know what? I'll just silence your deprecation warning for the time being. Maybe by the time you release the next version of + * Windows, you'll have provided a less crippled API or something. + * #pragma rantmode (off) + */ +#pragma warning (push) +#pragma warning (disable : 4996) + if (!GetVersionEx((OSVERSIONINFO*) &osvi)) { + sysinfo->p->osversion = aStrdup("Unknown Version"); + return; + } +#pragma warning (pop) + + if (VER_PLATFORM_WIN32_NT == osvi.dwPlatformId // Windows NT Family + && ((osvi.dwMajorVersion > 4 && osvi.dwMajorVersion < 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 3)) // Between XP and 8.1 + ) { + if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 3) { // Between Vista and 8.1 + PGPI pGPI; + DWORD dwType; + if (osvi.dwMinorVersion == 0) { + StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows Vista" : "Windows Server 2008"); + } else if (osvi.dwMinorVersion == 1) { + StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 7" : "Windows Server 2008 R2"); + } else { + // If it's 2, it can be Windows 8, or any newer version (8.1 at the time of writing this) -- see above for the reason. + switch (osvi.dwMinorVersion) { + case 2: + { + ULONGLONG mask = 0; + OSVERSIONINFOEX osvi2; + ZeroMemory(&osvi2, sizeof(OSVERSIONINFOEX)); + osvi2.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + osvi2.dwMajorVersion = 6; + osvi2.dwMinorVersion = 2; + VER_SET_CONDITION(mask, VER_MAJORVERSION, VER_LESS_EQUAL); + VER_SET_CONDITION(mask, VER_MINORVERSION, VER_LESS_EQUAL); + if (VerifyVersionInfo(&osvi2, VER_MAJORVERSION | VER_MINORVERSION, mask)) { + StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 8" : "Windows Server 2012"); + break; + } + } + case 3: + StrBuf->AppendStr(&buf, osvi.wProductType == VER_NT_WORKSTATION ? "Windows 8.1" : "Windows Server 2012 R2"); + } + } + + pGPI = (PGPI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetProductInfo"); + + pGPI(osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType); + + switch (dwType) { + case msPRODUCT_ULTIMATE: + case msPRODUCT_ULTIMATE_N: + StrBuf->AppendStr(&buf, " Ultimate"); + break; + case msPRODUCT_PROFESSIONAL: + case msPRODUCT_PROFESSIONAL_N: + case msPRODUCT_PROFESSIONAL_WMC: + StrBuf->AppendStr(&buf, " Professional"); + break; + case msPRODUCT_HOME_PREMIUM: + case msPRODUCT_HOME_PREMIUM_N: + StrBuf->AppendStr(&buf, " Home Premium"); + break; + case msPRODUCT_HOME_BASIC: + case msPRODUCT_HOME_BASIC_N: + StrBuf->AppendStr(&buf, " Home Basic"); + break; + case msPRODUCT_ENTERPRISE: + case msPRODUCT_ENTERPRISE_N: + case msPRODUCT_ENTERPRISE_SERVER: + case msPRODUCT_ENTERPRISE_SERVER_CORE: + case msPRODUCT_ENTERPRISE_SERVER_IA64: + case msPRODUCT_ENTERPRISE_SERVER_V: + case msPRODUCT_ENTERPRISE_SERVER_CORE_V: + case msPRODUCT_ENTERPRISE_EVALUATION: + case msPRODUCT_ENTERPRISE_N_EVALUATION: + StrBuf->AppendStr(&buf, " Enterprise"); + break; + case msPRODUCT_BUSINESS: + case msPRODUCT_BUSINESS_N: + StrBuf->AppendStr(&buf, " Business"); + break; + case msPRODUCT_STARTER: + case msPRODUCT_STARTER_N: + StrBuf->AppendStr(&buf, " Starter"); + break; + case msPRODUCT_CLUSTER_SERVER: + case msPRODUCT_CLUSTER_SERVER_V: + StrBuf->AppendStr(&buf, " Cluster Server"); + break; + case msPRODUCT_DATACENTER_SERVER: + case msPRODUCT_DATACENTER_SERVER_CORE: + case msPRODUCT_DATACENTER_SERVER_V: + case msPRODUCT_DATACENTER_SERVER_CORE_V: + case msPRODUCT_DATACENTER_EVALUATION_SERVER: + StrBuf->AppendStr(&buf, " Datacenter"); + break; + case msPRODUCT_SMALLBUSINESS_SERVER: + case msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM: + case msPRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE: + StrBuf->AppendStr(&buf, " Small Business Server"); + break; + case PRODUCT_STANDARD_SERVER: + case PRODUCT_STANDARD_SERVER_CORE: + case msPRODUCT_STANDARD_SERVER_V: + case msPRODUCT_STANDARD_SERVER_CORE_V: + case msPRODUCT_STANDARD_EVALUATION_SERVER: + StrBuf->AppendStr(&buf, " Standard"); + break; + case msPRODUCT_WEB_SERVER: + case msPRODUCT_WEB_SERVER_CORE: + StrBuf->AppendStr(&buf, " Web Server"); + break; + case msPRODUCT_STORAGE_EXPRESS_SERVER: + case msPRODUCT_STORAGE_STANDARD_SERVER: + case msPRODUCT_STORAGE_WORKGROUP_SERVER: + case msPRODUCT_STORAGE_ENTERPRISE_SERVER: + case msPRODUCT_STORAGE_EXPRESS_SERVER_CORE: + case msPRODUCT_STORAGE_STANDARD_SERVER_CORE: + case msPRODUCT_STORAGE_WORKGROUP_SERVER_CORE: + case msPRODUCT_STORAGE_ENTERPRISE_SERVER_CORE: + case msPRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER: + case msPRODUCT_STORAGE_STANDARD_EVALUATION_SERVER: + StrBuf->AppendStr(&buf, " Storage Server"); + break; + case msPRODUCT_HOME_SERVER: + case msPRODUCT_SERVER_FOR_SMALLBUSINESS: + case msPRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT: + case msPRODUCT_MEDIUMBUSINESS_SERVER_SECURITY: + case msPRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING: + case msPRODUCT_SERVER_FOR_SMALLBUSINESS_V: + case msPRODUCT_SERVER_FOUNDATION: + case msPRODUCT_HOME_PREMIUM_SERVER: + case msPRODUCT_HYPERV: + case msPRODUCT_SB_SOLUTION_SERVER: + case msPRODUCT_SERVER_FOR_SB_SOLUTIONS: + case msPRODUCT_STANDARD_SERVER_SOLUTIONS: + case msPRODUCT_STANDARD_SERVER_SOLUTIONS_CORE: + case msPRODUCT_SB_SOLUTION_SERVER_EM: + case msPRODUCT_SERVER_FOR_SB_SOLUTIONS_EM: + case msPRODUCT_SOLUTION_EMBEDDEDSERVER: + case msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMT: + case msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDL: + case msPRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC: + case msPRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC: + case msPRODUCT_MULTIPOINT_STANDARD_SERVER: + case msPRODUCT_MULTIPOINT_PREMIUM_SERVER: + StrBuf->AppendStr(&buf, " Server (other)"); + break; + case msPRODUCT_CORE_N: + case msPRODUCT_CORE_COUNTRYSPECIFIC: + case msPRODUCT_CORE_SINGLELANGUAGE: + case msPRODUCT_CORE: + StrBuf->AppendStr(&buf, " Workstation (other)"); + break; + } + + } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) { // XP x64 and Server 2003 + if (osvi.wProductType == VER_NT_WORKSTATION) { + StrBuf->AppendStr(&buf, "Windows XP Professional"); + } else { + if (GetSystemMetrics(msSM_SERVERR2)) + StrBuf->AppendStr(&buf, "Windows Server 2003 R2"); + else if (osvi.wSuiteMask & msVER_SUITE_STORAGE_SERVER) + StrBuf->AppendStr(&buf, "Windows Storage Server 2003"); + else if (osvi.wSuiteMask & msVER_SUITE_WH_SERVER) + StrBuf->AppendStr(&buf, "Windows Home Server"); + else + StrBuf->AppendStr(&buf, "Windows Server 2003"); + + // Test for the server type. + if (osvi.wSuiteMask & msVER_SUITE_COMPUTE_SERVER) + StrBuf->AppendStr(&buf, " Compute Cluster"); + else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + StrBuf->AppendStr(&buf, " Datacenter"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + StrBuf->AppendStr(&buf, " Enterprise"); + else if (osvi.wSuiteMask & msVER_SUITE_BLADE) + StrBuf->AppendStr(&buf, " Web"); + else + StrBuf->AppendStr(&buf, " Standard"); + } + } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) { // XP + StrBuf->AppendStr(&buf, "Windows XP"); + if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT) + StrBuf->AppendStr(&buf, " Embedded"); + else if (osvi.wSuiteMask & VER_SUITE_PERSONAL) + StrBuf->AppendStr(&buf, " Home"); + else + StrBuf->AppendStr(&buf, " Professional"); + } else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) { // 2000 + StrBuf->AppendStr(&buf, "Windows 2000"); + + if (osvi.wProductType == VER_NT_WORKSTATION) + StrBuf->AppendStr(&buf, " Professional"); + else if (osvi.wSuiteMask & VER_SUITE_DATACENTER) + StrBuf->AppendStr(&buf, " Datacenter Server"); + else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE) + StrBuf->AppendStr(&buf, " Advanced Server"); + else + StrBuf->AppendStr(&buf, " Server"); + } else { + StrBuf->Printf(&buf, "Unknown Windows version %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion); + } + } + + // Include service pack (if any) and build number. + + if (strlen(osvi.szCSDVersion) > 0) { + StrBuf->Printf(&buf, " %s", osvi.szCSDVersion); + } + + StrBuf->Printf(&buf, " (build %d)", osvi.dwBuildNumber); + + sysinfo->p->osversion = aStrdup(StrBuf->Value(&buf)); + + StrBuf->Destroy(&buf); + return; +} + +typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO); + +/** + * Retrieves SYSTEM_INFO (Windows only) + * System info is not stored anywhere after retrieval + * @see http://msdn.microsoft.com/en-us/library/windows/desktop/ms724958(v=vs.85).aspx + **/ +void sysinfo_systeminfo_retrieve( LPSYSTEM_INFO info ) { + PGNSI pGNSI; + + // Call GetNativeSystemInfo if supported or GetSystemInfo otherwise. + pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); + if (NULL != pGNSI) + pGNSI(info); + else + GetSystemInfo(info); + + return; +} + +/** + * Returns number of bytes in a memory page + * Only needed when compiling with MSVC + **/ +long sysinfo_getpagesize( void ) { + SYSTEM_INFO si; + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + + sysinfo_systeminfo_retrieve(&si); + return si.dwPageSize; +} + +/** + * Retrieves the CPU type (Windows only). + * + * Once retrieved, the name is stored into sysinfo->p->cpu and the + * number of cores in sysinfo->p->cpucores. + */ +void sysinfo_cpu_retrieve(void) { + StringBuf buf; + SYSTEM_INFO si; + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + StrBuf->Init(&buf); + + if (sysinfo->p->cpu != NULL) { + aFree(sysinfo->p->cpu); + sysinfo->p->cpu = NULL; + } + + sysinfo_systeminfo_retrieve(&si); + + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL + || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 + ) { + StrBuf->Printf(&buf, "%s CPU, Family %d, Model %d, Stepping %d", + si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL ? "x86" : "x86_64", + si.wProcessorLevel, + (si.wProcessorRevision&0xff00)>>8, + (si.wProcessorRevision&0xff)); + } else { + StrBuf->AppendStr(&buf, "Unknown"); + } + + sysinfo->p->cpu = aStrdup(StrBuf->Value(&buf)); + sysinfo->p->cpucores = si.dwNumberOfProcessors; + + StrBuf->Destroy(&buf); +} + +/** + * Retrieves the OS architecture (Windows only). + * + * Once retrieved, the name is stored into sysinfo->p->arch. + */ +void sysinfo_arch_retrieve(void) { + SYSTEM_INFO si; + ZeroMemory(&si, sizeof(SYSTEM_INFO)); + + if (sysinfo->p->arch != NULL) { + aFree(sysinfo->p->arch); + sysinfo->p->arch = NULL; + } + + sysinfo_systeminfo_retrieve(&si); + + if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) // x64 + sysinfo->p->arch = aStrdup("x86_64"); + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL) // x32 + sysinfo->p->arch = aStrdup("x86"); + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM) // ARM + sysinfo->p->arch = aStrdup("ARM"); + else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64) // Itanium + sysinfo->p->arch = aStrdup("IA-64"); + else + sysinfo->p->arch = aStrdup("Unknown"); +} + +/** + * Retrieves the startup-time VCS revision information. + * + * Once retrieved, the value is stored in sysinfo->p->vcsrevision_src. + */ +void sysinfo_vcsrevision_src_retrieve(void) { + if (sysinfo->p->vcsrevision_src != NULL) { + aFree(sysinfo->p->vcsrevision_src); + sysinfo->p->vcsrevision_src = NULL; + } + // Try Git, then SVN + if (sysinfo_git_get_revision(&sysinfo->p->vcsrevision_src)) { + sysinfo->p->vcstype = VCSTYPE_GIT; + return; + } + if (sysinfo_svn_get_revision(&sysinfo->p->vcsrevision_src)) { + sysinfo->p->vcstype = VCSTYPE_SVN; + return; + } + sysinfo->p->vcstype = VCSTYPE_NONE; + sysinfo->p->vcsrevision_src = aStrdup("Unknown"); +} +#endif // WIN32 + +/** + * Retrieves the VCS type name. + * + * Once retrieved, the value is stored in sysinfo->p->vcstype_name. + */ +void sysinfo_vcstype_name_retrieve(void) { + if (sysinfo->p->vcstype_name != NULL) { + aFree(sysinfo->p->vcstype_name); + sysinfo->p->vcstype_name = NULL; + } + switch (sysinfo->p->vcstype) { + case VCSTYPE_GIT: + sysinfo->p->vcstype_name = aStrdup("Git"); + break; + case VCSTYPE_SVN: + sysinfo->p->vcstype_name = aStrdup("SVN"); + break; + default: + sysinfo->p->vcstype_name = aStrdup("Exported"); + break; + } +} + +/** + * Returns the platform (OS type) this application is running on. + * + * This information is cached at compile time, since it's unlikely to change. + * + * @return the OS platform name. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "Linux", "Darwin", "Windows", etc. + */ +const char *sysinfo_platform(void) { + return sysinfo->p->platform; +} + +/** + * Returns the Operating System version the application is running on. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time, since it is uncommon that an application is compiled and runs + * on different machines. + * + * @return the OS name. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "Windows 2008 Small Business Server", "OS X 10.8 Mountain Lion", + * "Gentoo Base System Release 2.2", "Debian GNU/Linux 6.0.6 (squeeze)", etc. + */ +const char *sysinfo_osversion(void) { + return sysinfo->p->osversion; +} + +/** + * Returns the CPU model the application is running on. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time, since it is uncommon that an application is compiled and runs + * on different machines. + * + * @return the CPU model name. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "Intel(R) Atom(TM) CPU D2500 @ 1.86GHz", + * "Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz", "Intel Core i7", + * "x86 CPU, Family 6, Model 54, Stepping 1", etc. + */ +const char *sysinfo_cpu(void) { + return sysinfo->p->cpu; +} + +/** + * Returns the number of CPU cores available. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time, since it is uncommon that an application is compiled and runs + * on different machines. + * + * @return the number of CPU cores. + */ +int sysinfo_cpucores(void) { + return sysinfo->p->cpucores; +} + +/** + * Returns the CPU architecture the application was compiled for. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time, since it is uncommon that an application is compiled and runs + * on different machines. + * + * @return the CPU architecture name. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "x86", "x86_64", "IA-64", "ARM", etc. + */ +const char *sysinfo_arch(void) { + return sysinfo->p->arch; +} + +/** + * Returns info about the 32 or 64 bit build of Hercules. + * + * @retval true if this is a 64 bit build. + * @retval false if this isn't a 64 bit build (i.e. it is a 32 bit build). + */ +bool sysinfo_is64bit(void) { +#ifdef _LP64 + return true; +#else + return false; +#endif +} + +/** + * Returns the compiler the application was compiled with. + * + * @return the compiler name. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "Microsoft Visual C++ 2012 (v170050727)", + * "Clang v5.0.0", "MinGW32 v3.20", "GCC v4.7.3", etc. + */ +const char *sysinfo_compiler(void) { + return sysinfo->p->compiler; +} + +/** + * Returns the compiler flags the application was compiled with. + * + * On Windows (MSVC), an empty string is returned instead. + * + * @return the compiler flags. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "-ggdb -O2 -flto -pipe -ffast-math ..." + */ +const char *sysinfo_cflags(void) { + return sysinfo->p->cflags; +} + +/** + * Returns the Version Control System the application was downloaded with. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time. On Windows (MSVC), it is cached when the function is first + * called (most likely on server startup). + * + * @return the VCS type (numerical). + * + * @see VCSTYPE_NONE, VCSTYPE_GIT, VCSTYPE_SVN, VCSTYPE_UNKNOWN + */ +int sysinfo_vcstypeid(void) { + return sysinfo->p->vcstype; +} + +/** + * Returns the Version Control System the application was downloaded with. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time. On Windows (MSVC), it is cached when the function is first + * called (most likely on server startup). + * + * @return the VCS type. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: "Git", "SVN", "Exported" + */ +const char *sysinfo_vcstype(void) { + return sysinfo->p->vcstype_name; +} + +/** + * Returns the Version Control System revision. + * + * On platforms other than Windows (MSVC), this information is cached at + * compile time for better reliability. On Windows (MSVC), it is cached when + * the function is first called (most likely on server startup), so it may + * diverge from the actual revision that was compiled. + * + * @return the VCS revision. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: Git: "9128feccf3bddda94a7f8a170305565416815b40", SVN: "17546" + */ +const char *sysinfo_vcsrevision_src(void) { + return sysinfo->p->vcsrevision_src; +} + +/** + * Returns the Version Control System revision. + * + * This information is cached during a script reload, so that it matches the + * version of the loaded scripts. + * + * @return the VCS revision. + * + * Note: Ownership is NOT transferred, the value should not be freed. + * + * Output example: Git: "9128feccf3bddda94a7f8a170305565416815b40", SVN: "17546" + */ +const char *sysinfo_vcsrevision_scripts(void) { + return sysinfo->p->vcsrevision_scripts; +} + +/** + * Reloads the run-time (scripts) VCS revision information. To be used during + * script reloads to refresh the cached version. + */ +void sysinfo_vcsrevision_reload(void) { + if (sysinfo->p->vcsrevision_scripts != NULL) { + aFree(sysinfo->p->vcsrevision_scripts); + sysinfo->p->vcsrevision_scripts = NULL; + } + // Try Git, then SVN + if (sysinfo_git_get_revision(&sysinfo->p->vcsrevision_scripts)) { + return; + } + if (sysinfo_svn_get_revision(&sysinfo->p->vcsrevision_scripts)) { + return; + } + sysinfo->p->vcsrevision_scripts = aStrdup("Unknown"); +} + +/** + * Checks if we're running (unnecessarily) as superuser. + * + * @retval true if the current process is running as UNIX super-user. + * @retval false if the current process is running as regular user, or + * in any case under Windows. + */ +bool sysinfo_is_superuser(void) { +#ifndef _WIN32 + if (geteuid() == 0) + return true; +#endif + return false; +} + +/** + * Interface runtime initialization. + */ +void sysinfo_init(void) { + sysinfo->p->compiler = SYSINFO_COMPILER; +#ifdef WIN32 + sysinfo->p->platform = "Windows"; + sysinfo->p->cflags = "N/A"; + sysinfo_osversion_retrieve(); + sysinfo_cpu_retrieve(); + sysinfo_arch_retrieve(); + sysinfo_vcsrevision_src_retrieve(); +#else + sysinfo->p->platform = SYSINFO_PLATFORM; + sysinfo->p->osversion = SYSINFO_OSVERSION; + sysinfo->p->cpucores = SYSINFO_CPUCORES; + sysinfo->p->cpu = SYSINFO_CPU; + sysinfo->p->arch = SYSINFO_ARCH; + sysinfo->p->cflags = SYSINFO_CFLAGS; + sysinfo->p->vcstype = SYSINFO_VCSTYPE; + sysinfo->p->vcsrevision_src = SYSINFO_VCSREV; +#endif + sysinfo->vcsrevision_reload(); + sysinfo_vcstype_name_retrieve(); // Must be called after setting vcstype +} + +/** + * Interface shutdown cleanup. + */ +void sysinfo_final(void) { +#ifdef WIN32 + // Only need to be free'd in win32, they're #defined elsewhere + if (sysinfo->p->osversion) + aFree(sysinfo->p->osversion); + if (sysinfo->p->cpu) + aFree(sysinfo->p->cpu); + if (sysinfo->p->arch) + aFree(sysinfo->p->arch); + if (sysinfo->p->vcsrevision_src) + aFree(sysinfo->p->vcsrevision_src); +#endif + sysinfo->p->platform = NULL; + sysinfo->p->osversion = NULL; + sysinfo->p->cpu = NULL; + sysinfo->p->arch = NULL; + sysinfo->p->vcsrevision_src = NULL; + sysinfo->p->cflags = NULL; + if (sysinfo->p->vcsrevision_scripts) + aFree(sysinfo->p->vcsrevision_scripts); + sysinfo->p->vcsrevision_scripts = NULL; + if (sysinfo->p->vcstype_name) + aFree(sysinfo->p->vcstype_name); + sysinfo->p->vcstype_name = NULL; +} + +/** + * Interface default values initialization. + */ +void sysinfo_defaults(void) { + sysinfo = &sysinfo_s; + memset(&sysinfo_p, '\0', sizeof(sysinfo_p)); + sysinfo->p = &sysinfo_p; +#if defined(WIN32) && !defined(__CYGWIN__) + sysinfo->getpagesize = sysinfo_getpagesize; +#else + sysinfo->getpagesize = getpagesize; +#endif + sysinfo->platform = sysinfo_platform; + sysinfo->osversion = sysinfo_osversion; + sysinfo->cpu = sysinfo_cpu; + sysinfo->cpucores = sysinfo_cpucores; + sysinfo->arch = sysinfo_arch; + sysinfo->is64bit = sysinfo_is64bit; + sysinfo->compiler = sysinfo_compiler; + sysinfo->cflags = sysinfo_cflags; + sysinfo->vcstype = sysinfo_vcstype; + sysinfo->vcstypeid = sysinfo_vcstypeid; + sysinfo->vcsrevision_src = sysinfo_vcsrevision_src; + sysinfo->vcsrevision_scripts = sysinfo_vcsrevision_scripts; + sysinfo->vcsrevision_reload = sysinfo_vcsrevision_reload; + sysinfo->is_superuser = sysinfo_is_superuser; + sysinfo->init = sysinfo_init; + sysinfo->final = sysinfo_final; +} diff --git a/src/common/sysinfo.h b/src/common/sysinfo.h new file mode 100644 index 000000000..600206a21 --- /dev/null +++ b/src/common/sysinfo.h @@ -0,0 +1,51 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base Author: Haru @ http://hercules.ws + +#ifndef COMMON_SYSINFO_H +#define COMMON_SYSINFO_H + +/** + * Provides various bits of information about the system Hercules is running on + * (note: on unix systems, to avoid runtime detection, most of the data is + * cached at compile time) + */ + +#include "../common/cbasetypes.h" + +struct sysinfo_private; + +/** + * sysinfo.c interface + **/ +struct sysinfo_interface { + struct sysinfo_private *p; + +#if defined(WIN32) && !defined(__CYGWIN__) + long (*getpagesize) (void); +#else + int (*getpagesize) (void); +#endif + const char *(*platform) (void); + const char *(*osversion) (void); + const char *(*cpu) (void); + int (*cpucores) (void); + const char *(*arch) (void); + bool (*is64bit) (void); + const char *(*compiler) (void); + const char *(*cflags) (void); + const char *(*vcstype) (void); + int (*vcstypeid) (void); + const char *(*vcsrevision_src) (void); + const char *(*vcsrevision_scripts) (void); + void (*vcsrevision_reload) (void); + bool (*is_superuser) (void); + void (*init) (void); + void (*final) (void); +}; + +struct sysinfo_interface *sysinfo; + +void sysinfo_defaults(void); + +#endif /* COMMON_SYSINFO_H */ diff --git a/src/common/thread.c b/src/common/thread.c index 4d110f2dd..1d0285302 100644 --- a/src/common/thread.c +++ b/src/common/thread.c @@ -6,30 +6,32 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder +#define HERCULES_CORE + +#include "thread.h" + +#include "../common/sysinfo.h" // sysinfo->getpagesize() +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" + #ifdef WIN32 -#include "../common/winapi.h" -#define getpagesize() 4096 // @TODO: implement this properly (GetSystemInfo .. dwPageSize..). (Atm as on all supported win platforms its 4k its static.) -#define __thread __declspec( thread ) +# include "../common/winapi.h" +# define __thread __declspec( thread ) #else -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <signal.h> -#include <pthread.h> -#include <sched.h> +# include <pthread.h> +# include <sched.h> +# include <signal.h> +# include <stdlib.h> +# include <string.h> +# include <unistd.h> #endif -#include "cbasetypes.h" -#include "malloc.h" -#include "showmsg.h" -#include "thread.h" - // When Compiling using MSC (on win32..) we know we have support in any case! -#ifdef _MSC_VER -#define HAS_TLS +#ifdef _MSC_VER +#define HAS_TLS #endif - #define RA_THREADS_MAX 64 struct rAthread { @@ -37,7 +39,7 @@ struct rAthread { RATHREAD_PRIO prio; rAthreadProc proc; - void *param; + void *param; #ifdef WIN32 HANDLE hThread; @@ -57,7 +59,7 @@ __thread int g_rathread_ID = -1; /// static struct rAthread l_threads[RA_THREADS_MAX]; -void rathread_init(){ +void rathread_init(void) { register unsigned int i; memset(&l_threads, 0x00, RA_THREADS_MAX * sizeof(struct rAthread) ); @@ -65,7 +67,7 @@ void rathread_init(){ l_threads[i].myID = i; } - // now lets init thread id 0, which represnts the main thread + // now lets init thread id 0, which represents the main thread #ifdef HAS_TLS g_rathread_ID = 0; #endif @@ -76,12 +78,12 @@ void rathread_init(){ -void rathread_final(){ +void rathread_final(void) { register unsigned int i; - // Unterminated Threads Left? - // Should'nt happen .. - // Kill 'em all! + // Unterminated Threads Left? + // Shouldn't happen .. + // Kill 'em all! // for(i = 1; i < RA_THREADS_MAX; i++){ if(l_threads[i].proc != NULL){ @@ -96,7 +98,7 @@ void rathread_final(){ // gets called whenever a thread terminated .. -static void rat_thread_terminated(rAthread handle) { +static void rat_thread_terminated(rAthread *handle) { // Preserve handle->myID and handle->hThread, set everything else to its default value handle->param = NULL; handle->proc = NULL; @@ -104,23 +106,23 @@ static void rat_thread_terminated(rAthread handle) { }//end: rat_thread_terminated() #ifdef WIN32 -DWORD WINAPI _raThreadMainRedirector(LPVOID p){ +DWORD WINAPI raThreadMainRedirector(LPVOID p){ #else -static void *_raThreadMainRedirector( void *p ){ +static void *raThreadMainRedirector( void *p ){ sigset_t set; // on Posix Thread platforms #endif void *ret; // Update myID @ TLS to right id. #ifdef HAS_TLS - g_rathread_ID = ((rAthread)p)->myID; + g_rathread_ID = ((rAthread*)p)->myID; #endif #ifndef WIN32 // When using posix threads - // the threads inherits the Signal mask from the thread which's spawned + // the threads inherits the Signal mask from the thread which spawned // this thread - // so we've to block everything we dont care about. + // so we've to block everything we don't care about. sigemptyset(&set); sigaddset(&set, SIGINT); sigaddset(&set, SIGTERM); @@ -131,19 +133,19 @@ static void *_raThreadMainRedirector( void *p ){ #endif - ret = ((rAthread)p)->proc( ((rAthread)p)->param ) ; + ret = ((rAthread*)p)->proc( ((rAthread*)p)->param ) ; -#ifdef WIN32 - CloseHandle( ((rAthread)p)->hThread ); +#ifdef WIN32 + CloseHandle( ((rAthread*)p)->hThread ); #endif - rat_thread_terminated( (rAthread)p ); + rat_thread_terminated( (rAthread*)p ); #ifdef WIN32 return (DWORD)ret; #else return ret; #endif -}//end: _raThreadMainRedirector() +}//end: raThreadMainRedirector() @@ -151,28 +153,28 @@ static void *_raThreadMainRedirector( void *p ){ /// /// API Level -/// -rAthread rathread_create( rAthreadProc entryPoint, void *param ){ +/// +rAthread *rathread_create(rAthreadProc entryPoint, void *param) { return rathread_createEx( entryPoint, param, (1<<23) /*8MB*/, RAT_PRIO_NORMAL ); }//end: rathread_create() -rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio ){ +rAthread *rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio) { #ifndef WIN32 pthread_attr_t attr; #endif size_t tmp; unsigned int i; - rAthread handle = NULL; + rAthread *handle = NULL; // given stacksize aligned to systems pagesize? - tmp = szStack % getpagesize(); + tmp = szStack % sysinfo->getpagesize(); if(tmp != 0) szStack += tmp; - // Get a free Thread Slot. + // Get a free Thread Slot. for(i = 0; i < RA_THREADS_MAX; i++){ if(l_threads[i].proc == NULL){ handle = &l_threads[i]; @@ -191,12 +193,12 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta handle->param = param; #ifdef WIN32 - handle->hThread = CreateThread(NULL, szStack, _raThreadMainRedirector, (void*)handle, 0, NULL); + handle->hThread = CreateThread(NULL, szStack, raThreadMainRedirector, (void*)handle, 0, NULL); #else pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, szStack); - if(pthread_create(&handle->hThread, &attr, _raThreadMainRedirector, (void*)handle) != 0){ + if(pthread_create(&handle->hThread, &attr, raThreadMainRedirector, (void*)handle) != 0){ handle->proc = NULL; handle->param = NULL; return NULL; @@ -210,7 +212,7 @@ rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szSta }//end: rathread_createEx -void rathread_destroy ( rAthread handle ){ +void rathread_destroy(rAthread *handle) { #ifdef WIN32 if( TerminateThread(handle->hThread, 0) != FALSE){ CloseHandle(handle->hThread); @@ -219,24 +221,23 @@ void rathread_destroy ( rAthread handle ){ #else if( pthread_cancel( handle->hThread ) == 0){ - // We have to join it, otherwise pthread wont re-cycle its internal ressources assoc. with this thread. - // + // We have to join it, otherwise pthread wont re-cycle its internal resources assoc. with this thread. pthread_join( handle->hThread, NULL ); - // Tell our manager to release ressources ;) + // Tell our manager to release resources ;) rat_thread_terminated(handle); } #endif }//end: rathread_destroy() -rAthread rathread_self( ){ +rAthread *rathread_self(void) { #ifdef HAS_TLS - rAthread handle = &l_threads[g_rathread_ID]; + rAthread *handle = &l_threads[g_rathread_ID]; - if(handle->proc != NULL) // entry point set, so its used! + if(handle->proc != NULL) // entry point set, so its used! return handle; #else - // .. so no tls means we have to search the thread by its api-handle .. + // .. so no tls means we have to search the thread by its api-handle .. int i; #ifdef WIN32 @@ -254,16 +255,16 @@ rAthread rathread_self( ){ #endif - return NULL; + return NULL; }//end: rathread_self() -int rathread_get_tid(){ +int rathread_get_tid(void) { -#ifdef HAS_TLS +#ifdef HAS_TLS return g_rathread_ID; #else - // todo + // TODO #ifdef WIN32 return (int)GetCurrentThreadId(); #else @@ -275,7 +276,7 @@ int rathread_get_tid(){ }//end: rathread_get_tid() -bool rathread_wait( rAthread handle, void* *out_exitCode ){ +bool rathread_wait(rAthread *handle, void **out_exitCode) { // Hint: // no thread data cleanup routine call here! @@ -283,7 +284,7 @@ bool rathread_wait( rAthread handle, void* *out_exitCode ){ // #ifdef WIN32 WaitForSingleObject(handle->hThread, INFINITE); - return true; + return true; #else if(pthread_join(handle->hThread, out_exitCode) == 0) return true; @@ -293,21 +294,21 @@ bool rathread_wait( rAthread handle, void* *out_exitCode ){ }//end: rathread_wait() -void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio ){ - handle->prio = RAT_PRIO_NORMAL; - //@TODO +void rathread_prio_set(rAthread *handle, RATHREAD_PRIO prio) { + handle->prio = RAT_PRIO_NORMAL; + //@TODO }//end: rathread_prio_set() -RATHREAD_PRIO rathread_prio_get( rAthread handle){ +RATHREAD_PRIO rathread_prio_get(rAthread *handle) { return handle->prio; }//end: rathread_prio_get() -void rathread_yield(){ -#ifdef WIN32 +void rathread_yield(void) { +#ifdef WIN32 SwitchToThread(); #else sched_yield(); -#endif +#endif }//end: rathread_yield() diff --git a/src/common/thread.h b/src/common/thread.h index d6b2bbc6e..c7582366d 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -1,19 +1,18 @@ // Copyright (c) rAthena Project (www.rathena.org) - Licensed under GNU GPL // For more information, see LICENCE in the main folder -#pragma once -#ifndef _COMMON_THREAD_H_ -#define _COMMON_THREAD_H_ +#ifndef COMMON_THREAD_H +#define COMMON_THREAD_H #include "../common/cbasetypes.h" -typedef struct rAthread *rAthread; +typedef struct rAthread rAthread; typedef void* (*rAthreadProc)(void*); typedef enum RATHREAD_PRIO { RAT_PRIO_LOW = 0, RAT_PRIO_NORMAL, - RAT_PRIO_HIGH + RAT_PRIO_HIGH } RATHREAD_PRIO; @@ -21,99 +20,99 @@ typedef enum RATHREAD_PRIO { * Creates a new Thread * * @param entyPoint - entryProc, - * @param param - general purpose parameter, would be given as parameter to the thread's entrypoint. - * + * @param param - general purpose parameter, would be given as parameter to the thread's entry point. + * * @return not NULL if success */ -rAthread rathread_create( rAthreadProc entryPoint, void *param ); +rAthread *rathread_create(rAthreadProc entryPoint, void *param); -/** +/** * Creates a new Thread (with more creation options) * * @param entyPoint - entryProc, - * @param param - general purpose parameter, would be given as parameter to the thread's entrypoint - * @param szStack - stack Size in bytes + * @param param - general purpose parameter, would be given as parameter to the thread's entry point + * @param szStack - stack Size in bytes * @param prio - Priority of the Thread @ OS Scheduler.. * * @return not NULL if success */ -rAthread rathread_createEx( rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio ); +rAthread *rathread_createEx(rAthreadProc entryPoint, void *param, size_t szStack, RATHREAD_PRIO prio); /** - * Destroys the given Thread immediatly + * Destroys the given Thread immediately * - * @note The Handle gets invalid after call! dont use it afterwards. + * @note The Handle gets invalid after call! don't use it afterwards. * * @param handle - thread to destroy. */ -void rathread_destroy ( rAthread handle ); +void rathread_destroy(rAthread *handle); -/** +/** * Returns the thread handle of the thread calling this function - * - * @note this wont work @ programms main thread - * @note the underlying implementation might not perform very well, cache the value received! - * + * + * @note this wont work @ programs main thread + * @note the underlying implementation might not perform very well, cache the value received! + * * @return not NULL if success */ -rAthread rathread_self( ); +rAthread *rathread_self(void); /** - * Returns own thrad id (TID) + * Returns own thread id (TID) * - * @note this is an unique identifier for the calling thread, and - * depends on platfrom / compiler, and may not be the systems Thread ID! + * @note this is an unique identifier for the calling thread, and + * depends on platform/ compiler, and may not be the systems Thread ID! * * @return -1 when fails, otherwise >= 0 */ -int rathread_get_tid(); +int rathread_get_tid(void); /** - * Waits for the given thread to terminate + * Waits for the given thread to terminate * * @param handle - thread to wait (join) for * @param out_Exitcode - [OPTIONAL] - if given => Exitcode (value) of the given thread - if it's terminated - * + * * @return true - if the given thread has been terminated. */ -bool rathread_wait( rAthread handle, void* *out_exitCode ); +bool rathread_wait(rAthread *handle, void **out_exitCode); -/** +/** * Sets the given PRIORITY @ OS Task Scheduler - * + * * @param handle - thread to set prio for * @param rio - the priority (RAT_PRIO_LOW ... ) */ -void rathread_prio_set( rAthread handle, RATHREAD_PRIO prio ); +void rathread_prio_set(rAthread *handle, RATHREAD_PRIO prio); -/** - * Gets the current Prio of the given trhead +/** + * Gets the current Prio of the given thread * * @param handle - the thread to get the prio for. */ -RATHREAD_PRIO rathread_prio_get( rAthread handle); +RATHREAD_PRIO rathread_prio_get(rAthread *handle); /** * Tells the OS scheduler to yield the execution of the calling thread - * + * * @note: this will not "pause" the thread, - * it just allows the OS to spent the remaining time + * it just allows the OS to spent the remaining time * of the slice to another thread. */ -void rathread_yield(); +void rathread_yield(void); -void rathread_init(); -void rathread_final(); +void rathread_init(void); +void rathread_final(void); -#endif /* _COMMON_THREAD_H_ */ +#endif /* COMMON_THREAD_H */ diff --git a/src/common/timer.c b/src/common/timer.c index 526854582..370eafd4c 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -2,11 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/db.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/utils.h" +#define HERCULES_CORE + #include "timer.h" #include <stdio.h> @@ -14,11 +11,17 @@ #include <string.h> #include <time.h> +#include "../common/cbasetypes.h" +#include "../common/db.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/utils.h" + #ifdef WIN32 -#include "../common/winapi.h" // GetTickCount() +# include "../common/winapi.h" // GetTickCount() #else -#include <unistd.h> -#include <sys/time.h> // struct timeval, gettimeofday() +# include <sys/time.h> // struct timeval, gettimeofday() +# include <unistd.h> #endif struct timer_interface timer_s; @@ -104,7 +107,7 @@ char* search_timer_func_list(TimerFunc func) #if defined(ENABLE_RDTSC) static uint64 RDTSC_BEGINTICK = 0, RDTSC_CLOCK = 0; -static __inline uint64 _rdtsc(){ +static __inline uint64 rdtsc_(void) { register union{ uint64 qw; uint32 dw[2]; @@ -115,7 +118,7 @@ static __inline uint64 _rdtsc(){ return t.qw; } -static void rdtsc_calibrate(){ +static void rdtsc_calibrate(void){ uint64 t1, t2; int32 i; @@ -124,14 +127,14 @@ static void rdtsc_calibrate(){ RDTSC_CLOCK = 0; for(i = 0; i < 5; i++){ - t1 = _rdtsc(); + t1 = rdtsc_(); usleep(1000000); //1000 MS - t2 = _rdtsc(); - RDTSC_CLOCK += (t2 - t1) / 1000; + t2 = rdtsc_(); + RDTSC_CLOCK += (t2 - t1) / 1000; } RDTSC_CLOCK /= 5; - RDTSC_BEGINTICK = _rdtsc(); + RDTSC_BEGINTICK = rdtsc_(); ShowMessage(" done. (Frequency: %u Mhz)\n", (uint32)(RDTSC_CLOCK/1000) ); } @@ -167,17 +170,17 @@ static int64 sys_tick(void) { } if (pGetTickCount64) return (int64)pGetTickCount64(); - // 32-bit fallback. Note: This will wrap around every ~49 days since system startup!!! + // 32-bit fall back. Note: This will wrap around every ~49 days since system startup!!! return (int64)GetTickCount(); #elif defined(ENABLE_RDTSC) // RDTSC: Returns the number of CPU cycles since reset. Unreliable if // the CPU frequency is variable. - return (int64)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK); + return (int64)((rdtsc_() - RDTSC_BEGINTICK) / RDTSC_CLOCK); #elif defined(HAVE_MONOTONIC_CLOCK) - // Monotinic clock: Implementation-defined. + // Monotonic clock: Implementation-defined. // Clock that cannot be set and represents monotonic time since some // unspecified starting point. This clock is not affected by - // discontinâuous jumps in the system time (e.g., if the system + // discontinuous jumps in the system time (e.g., if the system // administrator manually changes the clock), but is affected by // the incremental adjustments performed by adjtime(3) and NTP. struct timespec tval; @@ -185,7 +188,7 @@ static int64 sys_tick(void) { // int64 cast to avoid overflows on platforms where time_t is 32 bit return (int64)tval.tv_sec * 1000 + tval.tv_nsec / 1000000; #else - // Fallback, regular clock: Number of milliseconds since epoch. + // Fall back, regular clock: Number of milliseconds since epoch. // The time returned by gettimeofday() is affected by discontinuous // jumps in the system time (e.g., if the system administrator // manually changes the system time). If you need a monotonically @@ -450,7 +453,7 @@ void timer_final(void) { if (free_timer_list) aFree(free_timer_list); } /*===================================== -* Default Functions : timer.h +* Default Functions : timer.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ diff --git a/src/common/timer.h b/src/common/timer.h index ab3ffc21f..d0927adde 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -2,8 +2,8 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_TIMER_H_ -#define _COMMON_TIMER_H_ +#ifndef COMMON_TIMER_H +#define COMMON_TIMER_H #include "../common/cbasetypes.h" @@ -30,13 +30,13 @@ struct TimerData { int interval; // general-purpose storage - int id; + int id; intptr_t data; }; /*===================================== -* Interface : timer.h +* Interface : timer.h * Generated by HerculesInterfaceMaker * created by Susu *-------------------------------------*/ @@ -67,4 +67,4 @@ struct timer_interface *timer; void timer_defaults(void); -#endif /* _COMMON_TIMER_H_ */ +#endif /* COMMON_TIMER_H */ diff --git a/src/common/utils.c b/src/common/utils.c index 9a7d4971b..4e6cb49c2 100644 --- a/src/common/utils.c +++ b/src/common/utils.c @@ -2,33 +2,35 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#include "../common/cbasetypes.h" -#include "../common/mmo.h" -#include "../common/malloc.h" -#include "../common/showmsg.h" -#include "../common/core.h" -#include "socket.h" +#define HERCULES_CORE + #include "utils.h" -#include <stdio.h> +#include <math.h> // floor() #include <stdarg.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> // floor() +#include <sys/stat.h> // cache purposes [Ind/Hercules] + +#include "../common/cbasetypes.h" +#include "../common/core.h" +#include "../common/malloc.h" +#include "../common/mmo.h" +#include "../common/showmsg.h" +#include "../common/socket.h" #ifdef WIN32 - #include "../common/winapi.h" - #ifndef F_OK - #define F_OK 0x0 - #endif /* F_OK */ +# include "../common/winapi.h" +# ifndef F_OK +# define F_OK 0x0 +# endif /* F_OK */ #else - #include <unistd.h> - #include <dirent.h> - #include <sys/stat.h> +# include <dirent.h> +# include <sys/stat.h> +# include <unistd.h> #endif -#include <sys/stat.h> // cache purposes [Ind/Hercules] - struct HCache_interface HCache_s; /// Dumps given buffer into file pointed to by a handle. @@ -198,7 +200,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*)) sprintf(tmppath,"%s%c%s",path, PATHSEP, entry->d_name); - // check if the pattern matchs. + // check if the pattern matches. if (entry->d_name && strstr(entry->d_name, pattern)) { func( tmppath ); } @@ -209,7 +211,7 @@ void findfile(const char *p, const char *pat, void (func)(const char*)) } // is this a directory? if (S_ISDIR(dir_stat.st_mode)) { - // decent recursivly + // decent recursively findfile(tmppath, pat, func); } }//end while @@ -264,6 +266,58 @@ uint32 MakeDWord(uint16 word0, uint16 word1) ( (uint32)(word1 << 0x10) ); } +/************************************* +* Big-endian compatibility functions * +*************************************/ + +// Converts an int16 from current machine order to little-endian +int16 MakeShortLE(int16 val) +{ + unsigned char buf[2]; + buf[0] = (unsigned char)( (val & 0x00FF) ); + buf[1] = (unsigned char)( (val & 0xFF00) >> 0x08 ); + return *((int16*)buf); +} + +// Converts an int32 from current machine order to little-endian +int32 MakeLongLE(int32 val) +{ + unsigned char buf[4]; + buf[0] = (unsigned char)( (val & 0x000000FF) ); + buf[1] = (unsigned char)( (val & 0x0000FF00) >> 0x08 ); + buf[2] = (unsigned char)( (val & 0x00FF0000) >> 0x10 ); + buf[3] = (unsigned char)( (val & 0xFF000000) >> 0x18 ); + return *((int32*)buf); +} + +// Reads an uint16 in little-endian from the buffer +uint16 GetUShort(const unsigned char* buf) +{ + return ( ((uint16)(buf[0])) ) + |( ((uint16)(buf[1])) << 0x08 ); +} + +// Reads an uint32 in little-endian from the buffer +uint32 GetULong(const unsigned char* buf) +{ + return ( ((uint32)(buf[0])) ) + |( ((uint32)(buf[1])) << 0x08 ) + |( ((uint32)(buf[2])) << 0x10 ) + |( ((uint32)(buf[3])) << 0x18 ); +} + +// Reads an int32 in little-endian from the buffer +int32 GetLong(const unsigned char* buf) +{ + return (int32)GetULong(buf); +} + +// Reads a float (32 bits) from the buffer +float GetFloat(const unsigned char* buf) +{ + uint32 val = GetULong(buf); + return *((float*)(void*)&val); +} /// calculates the value of A / B, in percent (rounded down) unsigned int get_percentage(const unsigned int A, const unsigned int B) @@ -272,7 +326,7 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B) if( B == 0 ) { - ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B); + ShowError("get_percentage(): division by zero! (A=%u,B=%u)\n", A, B); return ~0U; } diff --git a/src/common/utils.h b/src/common/utils.h index 68dd01ac4..421698d95 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -2,13 +2,14 @@ // See the LICENSE file // Portions Copyright (c) Athena Dev Teams -#ifndef _COMMON_UTILS_H_ -#define _COMMON_UTILS_H_ +#ifndef COMMON_UTILS_H +#define COMMON_UTILS_H -#include "../common/cbasetypes.h" #include <stdio.h> // FILE* #include <time.h> +#include "../common/cbasetypes.h" + /* [HCache] 1-byte key to ensure our method is the latest, we can modify to ensure the method matches */ #define HCACHE_KEY 'k' @@ -36,6 +37,16 @@ extern uint16 GetWord(uint32 val, int idx); extern uint16 MakeWord(uint8 byte0, uint8 byte1); extern uint32 MakeDWord(uint16 word0, uint16 word1); +////////////////////////////////////////////////////////////////////////// +// Big-endian compatibility functions +////////////////////////////////////////////////////////////////////////// +extern int16 MakeShortLE(int16 val); +extern int32 MakeLongLE(int32 val); +extern uint16 GetUShort(const unsigned char* buf); +extern uint32 GetULong(const unsigned char* buf); +extern int32 GetLong(const unsigned char* buf); +extern float GetFloat(const unsigned char* buf); + size_t hread(void * ptr, size_t size, size_t count, FILE * stream); size_t hwrite(const void * ptr, size_t size, size_t count, FILE * stream); @@ -54,4 +65,4 @@ struct HCache_interface *HCache; void HCache_defaults(void); -#endif /* _COMMON_UTILS_H_ */ +#endif /* COMMON_UTILS_H */ diff --git a/src/common/winapi.h b/src/common/winapi.h index 7ce555049..b7c2bea1e 100644 --- a/src/common/winapi.h +++ b/src/common/winapi.h @@ -7,7 +7,7 @@ #define WINVER 0x0500 #define _WIN32_IE 0x0600 #define WIN32_LEAN_AND_MEAN -#define NOCOMM +#define NOCOMM #define NOKANJI #define NOHELP #define NOMCX @@ -32,5 +32,3 @@ #include <Ws2tcpip.h> #include <Mswsock.h> #include <MMSystem.h> - - |