diff options
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/CMakeLists.txt | 99 | ||||
-rw-r--r-- | src/common/Collision/Models/GameObjectModel.h | 2 | ||||
-rw-r--r-- | src/common/Configuration/Config.cpp | 6 | ||||
-rw-r--r-- | src/common/Configuration/Config.h | 6 | ||||
-rw-r--r-- | src/common/Debugging/Errors.cpp | 7 | ||||
-rw-r--r-- | src/common/Debugging/Errors.h | 2 | ||||
-rw-r--r-- | src/common/Logging/Log.cpp | 13 | ||||
-rw-r--r-- | src/common/Logging/Log.h | 7 | ||||
-rw-r--r-- | src/common/Platform/ServiceWin32.cpp | 263 | ||||
-rw-r--r-- | src/common/Platform/ServiceWin32.h | 28 | ||||
-rw-r--r-- | src/common/Threading/LockedQueue.h | 8 | ||||
-rw-r--r-- | src/common/Utilities/StringFormat.h | 2 | ||||
-rw-r--r-- | src/common/Utilities/Util.cpp | 30 | ||||
-rw-r--r-- | src/common/Utilities/Util.h | 4 |
14 files changed, 406 insertions, 71 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8dee99c65e7..6f13dc821a9 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -8,42 +8,31 @@ # WITHOUT ANY WARRANTY, to the extent permitted by law; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Common Common.cpp Common.h) -file(GLOB_RECURSE sources_Collision Collision/*.cpp Collision/*.h) -file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h) -file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) -file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) -file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) -if (SERVERS) - file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) -endif (SERVERS) +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging + ${CMAKE_CURRENT_SOURCE_DIR}/Platform + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) # Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in common project # It needs to be included both in authserver and worldserver for the static global variable to be properly initialized # and to handle crash logs on windows -set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) -file(GLOB sources_localdir *.cpp *.h) +list(APPEND PRIVATE_SOURCES + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/Debugging/Errors.h) if (USE_COREPCH) - set(common_STAT_PCH_HDR PrecompiledHeaders/commonPCH.h) - set(common_STAT_PCH_SRC PrecompiledHeaders/commonPCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/commonPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/commonPCH.cpp) endif (USE_COREPCH) -set(common_STAT_SRCS - ${common_STAT_SRCS} - ${sources_Common} - ${sources_Collision} - ${sources_Threading} - ${sources_Utilities} - ${sources_Debugging} - ${sources_Configuration} - ${sources_Logging} - ${sources_Cryptography} - ${sources_localdir} +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(common + ${PRIVATE_SOURCES} + ${PRIVATE_PCH_SOURCE} ) # Do NOT add any extra include directory here, as we don't want the common @@ -55,37 +44,41 @@ set(common_STAT_SRCS # linkage (enums, defines...) it is discouraged to do so unless necessary, as it will pullute # include_directories leading to further unnoticed dependency aditions # Linker Depencency requirements: none -include_directories( - ${CMAKE_BINARY_DIR} +CollectIncludeDirectories( ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Collision - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Management - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Collision/Models - ${CMAKE_CURRENT_SOURCE_DIR}/Configuration - ${CMAKE_CURRENT_SOURCE_DIR}/Cryptography - ${CMAKE_CURRENT_SOURCE_DIR}/Debugging - ${CMAKE_CURRENT_SOURCE_DIR}/Logging - ${CMAKE_CURRENT_SOURCE_DIR}/Utilities - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/SFMT - ${CMAKE_SOURCE_DIR}/dep/utf8cpp - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories(common + PUBLIC + # Provide the binary dir for all child targets + ${CMAKE_BINARY_DIR} + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_library(common STATIC - ${common_STAT_SRCS} - ${common_STAT_PCH_SRC} -) +target_link_libraries(common + PUBLIC + boost + cppformat + g3dlib + Detour + sfmt + utf8cpp + openssl + valgrind + threads + jemalloc) add_dependencies(common revision_data.h) +set_target_properties(common + PROPERTIES + FOLDER + "server") + # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(common ${common_STAT_PCH_HDR} ${common_STAT_PCH_SRC}) + add_cxx_pch(common ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index 9d8687233c1..7834f53c63a 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -84,4 +84,6 @@ private: std::unique_ptr<GameObjectModelOwnerBase> owner; }; +void LoadGameObjectModelList(std::string const& dataPath); + #endif // _GAMEOBJECT_MODEL_H diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index 5db333c8aff..fba438dbd33 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -56,6 +56,12 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) return true; } +ConfigMgr* ConfigMgr::instance() +{ + static ConfigMgr instance; + return &instance; +} + bool ConfigMgr::Reload(std::string& error) { return LoadInitial(_filename, error); diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index ada910d8fcc..6882517b509 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -33,11 +33,7 @@ public: /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) bool LoadInitial(std::string const& file, std::string& error); - static ConfigMgr* instance() - { - static ConfigMgr instance; - return &instance; - } + static ConfigMgr* instance(); bool Reload(std::string& error); diff --git a/src/common/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp index 1ec66ff6d59..2ce00229e53 100644 --- a/src/common/Debugging/Errors.cpp +++ b/src/common/Debugging/Errors.cpp @@ -96,4 +96,11 @@ void Abort(char const* file, int line, char const* function) exit(1); } +void AbortHandler(int /*sigval*/) +{ + // nothing useful to log here, no way to pass args + *((volatile int*)NULL) = 0; + exit(1); +} + } // namespace Trinity diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h index 38e311a6b13..37d247ada82 100644 --- a/src/common/Debugging/Errors.h +++ b/src/common/Debugging/Errors.h @@ -34,6 +34,8 @@ namespace Trinity void Warning(char const* file, int line, char const* function, char const* message); + DECLSPEC_NORETURN void AbortHandler(int sigval) ATTR_NORETURN; + } // namespace Trinity #if COMPILER == COMPILER_MICROSOFT diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index a80a4671822..f7a84fb8b47 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -320,6 +320,12 @@ void Log::Close() appenders.clear(); } +Log* Log::instance() +{ + static Log instance; + return &instance; +} + void Log::Initialize(boost::asio::io_service* ioService) { if (ioService) @@ -331,6 +337,13 @@ void Log::Initialize(boost::asio::io_service* ioService) LoadFromConfig(); } +void Log::SetSynchronous() +{ + delete _strand; + _strand = nullptr; + _ioService = nullptr; +} + void Log::LoadFromConfig() { Close(); diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index a90481ad5d2..062f14d525c 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -44,13 +44,10 @@ class Log public: - static Log* instance() - { - static Log instance; - return &instance; - } + static Log* instance(); void Initialize(boost::asio::io_service* ioService); + void SetSynchronous(); // Not threadsafe - should only be called from main() after all threads are joined void LoadFromConfig(); void Close(); bool ShouldLog(std::string const& type, LogLevel level) const; diff --git a/src/common/Platform/ServiceWin32.cpp b/src/common/Platform/ServiceWin32.cpp new file mode 100644 index 00000000000..3c34f3e322c --- /dev/null +++ b/src/common/Platform/ServiceWin32.cpp @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef _WIN32 + +#include "Common.h" +#include "Log.h" +#include <cstring> +#include <windows.h> +#include <winsvc.h> + +#if !defined(WINADVAPI) +#if !defined(_ADVAPI32_) +#define WINADVAPI DECLSPEC_IMPORT +#else +#define WINADVAPI +#endif +#endif + +extern int main(int argc, char ** argv); +extern char serviceLongName[]; +extern char serviceName[]; +extern char serviceDescription[]; + +extern int m_ServiceStatus; + +SERVICE_STATUS serviceStatus; + +SERVICE_STATUS_HANDLE serviceStatusHandle = 0; + +typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID); + +bool WinServiceInstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE); + + if (serviceControlManager) + { + char path[_MAX_PATH + 10]; + if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0) + { + SC_HANDLE service; + std::strcat(path, " --service run"); + service = CreateService(serviceControlManager, + serviceName, // name of service + serviceLongName, // service name to display + SERVICE_ALL_ACCESS, // desired access + // service type + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_AUTO_START, // start type + SERVICE_ERROR_IGNORE, // error control type + path, // service's binary + 0, // no load ordering group + 0, // no tag identifier + 0, // no dependencies + 0, // LocalSystem account + 0); // no password + if (service) + { + HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL"); + if (!advapi32) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + CSD_T ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A"); + if (!ChangeService_Config2) + { + CloseServiceHandle(service); + CloseServiceHandle(serviceControlManager); + return false; + } + + SERVICE_DESCRIPTION sdBuf; + sdBuf.lpDescription = serviceDescription; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_DESCRIPTION, // change: description + &sdBuf); // new data + + SC_ACTION _action[1]; + _action[0].Type = SC_ACTION_RESTART; + _action[0].Delay = 10000; + SERVICE_FAILURE_ACTIONS sfa; + ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS)); + sfa.lpsaActions = _action; + sfa.cActions = 1; + sfa.dwResetPeriod =INFINITE; + ChangeService_Config2( + service, // handle to service + SERVICE_CONFIG_FAILURE_ACTIONS, // information level + &sfa); // new data + + CloseServiceHandle(service); + + } + } + CloseServiceHandle(serviceControlManager); + } + + printf("Service installed\n"); + return true; +} + +bool WinServiceUninstall() +{ + SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT); + + if (serviceControlManager) + { + SC_HANDLE service = OpenService(serviceControlManager, + serviceName, SERVICE_QUERY_STATUS | DELETE); + if (service) + { + SERVICE_STATUS serviceStatus2; + if (QueryServiceStatus(service, &serviceStatus2)) + { + if (serviceStatus2.dwCurrentState == SERVICE_STOPPED) + DeleteService(service); + } + CloseServiceHandle(service); + } + + CloseServiceHandle(serviceControlManager); + } + + printf("Service uninstalled\n"); + return true; +} + +void WINAPI ServiceControlHandler(DWORD controlCode) +{ + switch (controlCode) + { + case SERVICE_CONTROL_INTERROGATE: + break; + + case SERVICE_CONTROL_SHUTDOWN: + case SERVICE_CONTROL_STOP: + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + m_ServiceStatus = 0; + return; + + case SERVICE_CONTROL_PAUSE: + m_ServiceStatus = 2; + serviceStatus.dwCurrentState = SERVICE_PAUSED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + break; + + case SERVICE_CONTROL_CONTINUE: + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + m_ServiceStatus = 1; + break; + + default: + if ( controlCode >= 128 && controlCode <= 255 ) + // user defined control code + break; + else + // unrecognized control code + break; + } + + SetServiceStatus(serviceStatusHandle, &serviceStatus); +} + +void WINAPI ServiceMain(DWORD argc, char *argv[]) +{ + // initialise service status + serviceStatus.dwServiceType = SERVICE_WIN32; + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; + serviceStatus.dwWin32ExitCode = NO_ERROR; + serviceStatus.dwServiceSpecificExitCode = NO_ERROR; + serviceStatus.dwCheckPoint = 0; + serviceStatus.dwWaitHint = 0; + + serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler); + + if ( serviceStatusHandle ) + { + char path[_MAX_PATH + 1]; + unsigned int i, last_slash = 0; + + GetModuleFileName(0, path, sizeof(path)/sizeof(path[0])); + + size_t pathLen = std::strlen(path); + for (i = 0; i < pathLen; i++) + { + if (path[i] == '\\') last_slash = i; + } + + path[last_slash] = 0; + + // service is starting + serviceStatus.dwCurrentState = SERVICE_START_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do initialisation here + SetCurrentDirectory(path); + + // running + serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_RUNNING; + SetServiceStatus( serviceStatusHandle, &serviceStatus ); + + //////////////////////// + // service main cycle // + //////////////////////// + + m_ServiceStatus = 1; + argc = 1; + main(argc, argv); + + // service was stopped + serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + + // do cleanup here + + // service is now stopped + serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); + serviceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(serviceStatusHandle, &serviceStatus); + } +} + +bool WinServiceRun() +{ + SERVICE_TABLE_ENTRY serviceTable[] = + { + { serviceName, ServiceMain }, + { 0, 0 } + }; + + if (!StartServiceCtrlDispatcher(serviceTable)) + { + TC_LOG_ERROR("server.worldserver", "StartService Failed. Error [%u]", uint32(::GetLastError())); + return false; + } + return true; +} +#endif diff --git a/src/common/Platform/ServiceWin32.h b/src/common/Platform/ServiceWin32.h new file mode 100644 index 00000000000..b892ba4e3b6 --- /dev/null +++ b/src/common/Platform/ServiceWin32.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef _WIN32 +#ifndef _WIN32_SERVICE_ +#define _WIN32_SERVICE_ + +bool WinServiceInstall(); +bool WinServiceUninstall(); +bool WinServiceRun(); + +#endif // _WIN32_SERVICE_ +#endif // _WIN32 diff --git a/src/common/Threading/LockedQueue.h b/src/common/Threading/LockedQueue.h index c6faaaf81ca..21a29d7e53b 100644 --- a/src/common/Threading/LockedQueue.h +++ b/src/common/Threading/LockedQueue.h @@ -57,6 +57,14 @@ public: unlock(); } + //! Adds items back to front of the queue + template<class Iterator> + void readd(Iterator begin, Iterator end) + { + std::lock_guard<std::mutex> lock(_lock); + _queue.insert(_queue.begin(), begin, end); + } + //! Gets the next result in the queue, if any. bool next(T& result) { diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h index d85523bc11f..e21b1024e87 100644 --- a/src/common/Utilities/StringFormat.h +++ b/src/common/Utilities/StringFormat.h @@ -19,7 +19,7 @@ #ifndef TRINITYCORE_STRING_FORMAT_H #define TRINITYCORE_STRING_FORMAT_H -#include "format.h" +#include "cppformat/format.h" namespace Trinity { diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 1360253294f..6572280d00b 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -218,22 +218,29 @@ bool IsIPAddress(char const* ipaddress) } /// create PID file -uint32 CreatePIDFile(const std::string& filename) +uint32 CreatePIDFile(std::string const& filename) { - FILE* pid_file = fopen (filename.c_str(), "w" ); + FILE* pid_file = fopen(filename.c_str(), "w"); if (pid_file == NULL) return 0; + uint32 pid = GetPID(); + + fprintf(pid_file, "%u", pid); + fclose(pid_file); + + return pid; +} + +uint32 GetPID() +{ #ifdef _WIN32 DWORD pid = GetCurrentProcessId(); #else pid_t pid = getpid(); #endif - fprintf(pid_file, "%u", pid ); - fclose(pid_file); - - return (uint32)pid; + return uint32(pid); } size_t utf8length(std::string& utf8str) @@ -487,6 +494,17 @@ void vutf8printf(FILE* out, const char *str, va_list* ap) #endif } +bool Utf8ToUpperOnlyLatin(std::string& utf8String) +{ + std::wstring wstr; + if (!Utf8toWStr(utf8String, wstr)) + return false; + + std::transform(wstr.begin(), wstr.end(), wstr.begin(), wcharToUpperOnlyLatin); + + return WStrToUtf8(wstr, utf8String); +} + std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse /* = false */) { int32 init = 0; diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index ab5cabca8d2..25fce88954d 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -310,10 +310,12 @@ bool consoleToUtf8(const std::string& conStr, std::string& utf8str); bool Utf8FitTo(const std::string& str, std::wstring const& search); void utf8printf(FILE* out, const char *str, ...); void vutf8printf(FILE* out, const char *str, va_list* ap); +bool Utf8ToUpperOnlyLatin(std::string& utf8String); bool IsIPAddress(char const* ipaddress); -uint32 CreatePIDFile(const std::string& filename); +uint32 CreatePIDFile(std::string const& filename); +uint32 GetPID(); std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); |