diff options
Diffstat (limited to 'src/server/shared')
| -rw-r--r-- | src/server/shared/CMakeLists.txt | 90 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DBCFileLoader.h | 2 | ||||
| -rw-r--r-- | src/server/shared/DataStores/DBCStore.h | 115 | ||||
| -rw-r--r-- | src/server/shared/Networking/AsyncAcceptor.h | 1 | ||||
| -rw-r--r-- | src/server/shared/Networking/MessageBuffer.h | 138 | ||||
| -rw-r--r-- | src/server/shared/Networking/Socket.h | 33 | ||||
| -rw-r--r-- | src/server/shared/Networking/SocketMgr.h | 12 | ||||
| -rw-r--r-- | src/server/shared/Packets/ByteBuffer.h | 29 | ||||
| -rw-r--r-- | src/server/shared/Realm/Realm.cpp | 53 | ||||
| -rw-r--r-- | src/server/shared/Realm/Realm.h | 87 | ||||
| -rw-r--r-- | src/server/shared/Realm/RealmList.cpp | 185 | ||||
| -rw-r--r-- | src/server/shared/Realm/RealmList.h | 61 | ||||
| -rw-r--r-- | src/server/shared/Service/ServiceWin32.cpp | 264 | ||||
| -rw-r--r-- | src/server/shared/Service/ServiceWin32.h | 29 |
14 files changed, 582 insertions, 517 deletions
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index b6e5c8b1c6f..e99a81a084b 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -8,62 +8,60 @@ # 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_DataStores DataStores/*.cpp DataStores/*.h) -file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h) -file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h) -file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h) -if( WIN32 ) - file(GLOB_RECURSE sources_Service Service/*.cpp Service/*.h) -endif( WIN32 ) -file(GLOB sources_localdir *.cpp *.h) - -# -# Build shared sourcelist -# +CollectSourceFiles( + ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE_SOURCES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) if (USE_COREPCH) - set(shared_STAT_PCH_HDR PrecompiledHeaders/sharedPCH.h) - set(shared_STAT_PCH_SRC PrecompiledHeaders/sharedPCH.cpp) + set(PRIVATE_PCH_HEADER PrecompiledHeaders/sharedPCH.h) + set(PRIVATE_PCH_SOURCE PrecompiledHeaders/sharedPCH.cpp) endif() -set(shared_STAT_SRCS - ${shared_STAT_SRCS} - ${sources_DataStores} - ${sources_Dynamic} - ${sources_Networking} - ${sources_Packets} - ${sources_Utilities} - ${sources_Service} - ${sources_localdir} -) +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) -include_directories( - ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic - ${CMAKE_CURRENT_SOURCE_DIR}/Networking - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/common/ - ${CMAKE_SOURCE_DIR}/src/common/Debugging - ${CMAKE_SOURCE_DIR}/src/common/Logging - ${CMAKE_SOURCE_DIR}/src/common/Utilities - ${MYSQL_INCLUDE_DIR} - ${OPENSSL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} +add_definitions(-DTRINITY_API_EXPORT_SHARED) + +add_library(shared + ${PRIVATE_PCH_SOURCE} + ${PRIVATE_SOURCES} ) -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) +CollectIncludeDirectories( + ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC_INCLUDES + # Exclude + ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders) -add_library(shared STATIC - ${shared_STAT_SRCS} - ${shared_STAT_PCH_SRC} -) +target_include_directories(shared + PUBLIC + ${PUBLIC_INCLUDES} + PRIVATE + ${CMAKE_CURRENT_BINARY_DIR}) -add_dependencies(shared revision_data.h) +target_link_libraries(shared + PUBLIC + database) + +set_target_properties(shared + PROPERTIES + FOLDER + "server") + +if( BUILD_SHARED_LIBS ) + if( UNIX ) + install(TARGETS shared + LIBRARY + DESTINATION lib) + elseif( WIN32 ) + install(TARGETS shared + RUNTIME + DESTINATION "${CMAKE_INSTALL_PREFIX}") + endif() +endif() # Generate precompiled header if (USE_COREPCH) - add_cxx_pch(shared ${shared_STAT_PCH_HDR} ${shared_STAT_PCH_SRC}) + add_cxx_pch(shared ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE}) endif () diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h index 00b1ee54a4a..abe18d1425e 100644 --- a/src/server/shared/DataStores/DBCFileLoader.h +++ b/src/server/shared/DataStores/DBCFileLoader.h @@ -37,7 +37,7 @@ enum DbcFieldFormat FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc }; -class DBCFileLoader +class TC_SHARED_API DBCFileLoader { public: DBCFileLoader(); diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h index b93bbdaea12..7c2cab1e36a 100644 --- a/src/server/shared/DataStores/DBCStore.h +++ b/src/server/shared/DataStores/DBCStore.h @@ -25,6 +25,121 @@ #include "DatabaseWorkerPool.h" #include "Implementation/WorldDatabase.h" #include "DatabaseEnv.h" +#include <G3D/Vector3.h> +#include <G3D/AABox.h> + + // Structures for M4 file. Source: https://wowdev.wiki +template<typename T> +struct M2SplineKey +{ + T p0; + T p1; + T p2; +}; + +struct M2Header +{ + char Magic[4]; // "MD20" + uint32 Version; // The version of the format. + uint32 lName; // Length of the model's name including the trailing \0 + uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess. + uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related. + uint32 nGlobalSequences; + uint32 ofsGlobalSequences; // A list of timestamps. + uint32 nAnimations; + uint32 ofsAnimations; // Information about the animations in the model. + uint32 nAnimationLookup; + uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block. + uint32 nBones; // MAX_BONES = 0x100 + uint32 ofsBones; // Information about the bones in this model. + uint32 nKeyBoneLookup; + uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones. + uint32 nVertices; + uint32 ofsVertices; // Vertices of the model. + uint32 nViews; // Views (LOD) are now in .skins. + uint32 nSubmeshAnimations; + uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions. + uint32 nTextures; + uint32 ofsTextures; // Textures of this model. + uint32 nTransparency; + uint32 ofsTransparency; // Transparency of textures. + uint32 nUVAnimation; + uint32 ofsUVAnimation; + uint32 nTexReplace; + uint32 ofsTexReplace; // Replaceable Textures. + uint32 nRenderFlags; + uint32 ofsRenderFlags; // Blending modes / render flags. + uint32 nBoneLookupTable; + uint32 ofsBoneLookupTable; // A bone lookup table. + uint32 nTexLookup; + uint32 ofsTexLookup; // The same for textures. + uint32 nTexUnits; // possibly removed with cata?! + uint32 ofsTexUnits; // And texture units. Somewhere they have to be too. + uint32 nTransLookup; + uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies. + uint32 nUVAnimLookup; + uint32 ofsUVAnimLookup; + G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height + float BoundingSphereRadius; + G3D::AABox CollisionBox; + float CollisionSphereRadius; + uint32 nBoundingTriangles; + uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews. + uint32 nBoundingVertices; + uint32 ofsBoundingVertices; + uint32 nBoundingNormals; + uint32 ofsBoundingNormals; + uint32 nAttachments; + uint32 ofsAttachments; // Attachments are for weapons etc. + uint32 nAttachLookup; + uint32 ofsAttachLookup; // Of course with a lookup. + uint32 nEvents; + uint32 ofsEvents; // Used for playing sounds when dying and a lot else. + uint32 nLights; + uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too. + uint32 nCameras; // Format of Cameras changed with version 271! + uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab. + uint32 nCameraLookup; + uint32 ofsCameraLookup; // And lookup-time again. + uint32 nRibbonEmitters; + uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails. + uint32 nParticleEmitters; + uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles. + uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides + uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.}; +}; + +struct M2Array +{ + uint32_t number; + uint32 offset_elements; +}; +struct M2Track +{ + uint16_t interpolation_type; + uint16_t global_sequence; + M2Array timestamps; + M2Array values; +}; + +struct M2Camera +{ + uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table. + float fov; // No radians, no degrees. Multiply by 35 to get degrees. + float far_clip; + float near_clip; + M2Track positions; // How the camera's position moves. Should be 3*3 floats. + G3D::Vector3 position_base; + M2Track target_positions; // How the target moves. Should be 3*3 floats. + G3D::Vector3 target_position_base; + M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi. +}; + +struct FlyByCamera +{ + uint32 timeStamp; + G3D::Vector4 locations; +}; struct SqlDbc { diff --git a/src/server/shared/Networking/AsyncAcceptor.h b/src/server/shared/Networking/AsyncAcceptor.h index 0f3fd9a145b..f68da230553 100644 --- a/src/server/shared/Networking/AsyncAcceptor.h +++ b/src/server/shared/Networking/AsyncAcceptor.h @@ -21,6 +21,7 @@ #include "Log.h" #include <boost/asio.hpp> #include <functional> +#include <atomic> using boost::asio::ip::tcp; diff --git a/src/server/shared/Networking/MessageBuffer.h b/src/server/shared/Networking/MessageBuffer.h deleted file mode 100644 index d68bee181b1..00000000000 --- a/src/server/shared/Networking/MessageBuffer.h +++ /dev/null @@ -1,138 +0,0 @@ -/* -* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> -* -* 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/>. -*/ - -#ifndef __MESSAGEBUFFER_H_ -#define __MESSAGEBUFFER_H_ - -#include "Define.h" -#include <vector> - -class MessageBuffer -{ - typedef std::vector<uint8>::size_type size_type; - -public: - MessageBuffer() : _wpos(0), _rpos(0), _storage() - { - _storage.resize(4096); - } - - explicit MessageBuffer(std::size_t initialSize) : _wpos(0), _rpos(0), _storage() - { - _storage.resize(initialSize); - } - - MessageBuffer(MessageBuffer const& right) : _wpos(right._wpos), _rpos(right._rpos), _storage(right._storage) - { - } - - MessageBuffer(MessageBuffer&& right) : _wpos(right._wpos), _rpos(right._rpos), _storage(right.Move()) { } - - void Reset() - { - _wpos = 0; - _rpos = 0; - } - - void Resize(size_type bytes) - { - _storage.resize(bytes); - } - - uint8* GetBasePointer() { return _storage.data(); } - - uint8* GetReadPointer() { return GetBasePointer() + _rpos; } - - uint8* GetWritePointer() { return GetBasePointer() + _wpos; } - - void ReadCompleted(size_type bytes) { _rpos += bytes; } - - void WriteCompleted(size_type bytes) { _wpos += bytes; } - - size_type GetActiveSize() const { return _wpos - _rpos; } - - size_type GetRemainingSpace() const { return _storage.size() - _wpos; } - - size_type GetBufferSize() const { return _storage.size(); } - - // Discards inactive data - void Normalize() - { - if (_rpos) - { - if (_rpos != _wpos) - memmove(GetBasePointer(), GetReadPointer(), GetActiveSize()); - _wpos -= _rpos; - _rpos = 0; - } - } - - // Ensures there's "some" free space, make sure to call Normalize() before this - void EnsureFreeSpace() - { - // resize buffer if it's already full - if (GetRemainingSpace() == 0) - _storage.resize(_storage.size() * 3 / 2); - } - - void Write(void const* data, std::size_t size) - { - if (size) - { - memcpy(GetWritePointer(), data, size); - WriteCompleted(size); - } - } - - std::vector<uint8>&& Move() - { - _wpos = 0; - _rpos = 0; - return std::move(_storage); - } - - MessageBuffer& operator=(MessageBuffer const& right) - { - if (this != &right) - { - _wpos = right._wpos; - _rpos = right._rpos; - _storage = right._storage; - } - - return *this; - } - - MessageBuffer& operator=(MessageBuffer&& right) - { - if (this != &right) - { - _wpos = right._wpos; - _rpos = right._rpos; - _storage = right.Move(); - } - - return *this; - } - -private: - size_type _wpos; - size_type _rpos; - std::vector<uint8> _storage; -}; - -#endif /* __MESSAGEBUFFER_H_ */ diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h index d1ba7f49aa4..0674ede57d8 100644 --- a/src/server/shared/Networking/Socket.h +++ b/src/server/shared/Networking/Socket.h @@ -55,11 +55,11 @@ public: virtual bool Update() { - if (!IsOpen()) + if (_closed) return false; #ifndef TC_SOCKET_USE_IOCP - if (_isWritingAsync || _writeQueue.empty()) + if (_isWritingAsync || (_writeQueue.empty() && !_closing)) return true; for (; HandleQueue();) @@ -90,6 +90,17 @@ public: std::bind(&Socket<T>::ReadHandlerInternal, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } + void AsyncReadWithCallback(void (T::*callback)(boost::system::error_code, std::size_t)) + { + if (!IsOpen()) + return; + + _readBuffer.Normalize(); + _readBuffer.EnsureFreeSpace(); + _socket.async_read_some(boost::asio::buffer(_readBuffer.GetWritePointer(), _readBuffer.GetRemainingSpace()), + std::bind(callback, this->shared_from_this(), std::placeholders::_1, std::placeholders::_2)); + } + void QueuePacket(MessageBuffer&& buffer) { _writeQueue.push(std::move(buffer)); @@ -144,6 +155,15 @@ protected: return false; } + void SetNoDelay(bool enable) + { + boost::system::error_code err; + _socket.set_option(tcp::no_delay(enable), err); + if (err) + TC_LOG_DEBUG("network", "Socket::SetNoDelay: failed to set_option(boost::asio::ip::tcp::no_delay) for %s - %d (%s)", + GetRemoteIpAddress().to_string().c_str(), err.value(), err.message().c_str()); + } + private: void ReadHandlerInternal(boost::system::error_code error, size_t transferredBytes) { @@ -187,9 +207,6 @@ private: bool HandleQueue() { - if (!IsOpen()) - return false; - if (_writeQueue.empty()) return false; @@ -206,11 +223,15 @@ private: return AsyncProcessQueue(); _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return false; } else if (bytesSent == 0) { _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return false; } else if (bytesSent < bytesToSend) // now n > 0 @@ -220,6 +241,8 @@ private: } _writeQueue.pop(); + if (_closing && _writeQueue.empty()) + CloseSocket(); return !_writeQueue.empty(); } diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h index b14aac4ca47..e479cd2450d 100644 --- a/src/server/shared/Networking/SocketMgr.h +++ b/src/server/shared/Networking/SocketMgr.h @@ -19,7 +19,6 @@ #define SocketMgr_h__ #include "AsyncAcceptor.h" -#include "Config.h" #include "Errors.h" #include "NetworkThread.h" #include <boost/asio/ip/tcp.hpp> @@ -36,15 +35,9 @@ public: ASSERT(!_threads && !_acceptor && !_threadCount, "StopNetwork must be called prior to SocketMgr destruction"); } - virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) + virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount) { - _threadCount = sConfigMgr->GetIntDefault("Network.Threads", 1); - - if (_threadCount <= 0) - { - TC_LOG_ERROR("misc", "Network.Threads is wrong in your config file"); - return false; - } + ASSERT(threadCount > 0); try { @@ -56,6 +49,7 @@ public: return false; } + _threadCount = threadCount; _threads = CreateThreads(); ASSERT(_threads); diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h index 5ebe5258a44..d24a91ed458 100644 --- a/src/server/shared/Packets/ByteBuffer.h +++ b/src/server/shared/Packets/ByteBuffer.h @@ -23,22 +23,12 @@ #include "Errors.h" #include "ByteConverter.h" #include "Util.h" - -#include <exception> -#include <list> -#include <map> -#include <string> -#include <vector> #include <cstring> -#include <time.h> -#include <cmath> -#include <type_traits> -#include <boost/asio/buffer.hpp> class MessageBuffer; // Root of ByteBuffer exception hierarchy -class ByteBufferException : public std::exception +class TC_SHARED_API ByteBufferException : public std::exception { public: ~ByteBufferException() throw() { } @@ -52,7 +42,7 @@ private: std::string msg_; }; -class ByteBufferPositionException : public ByteBufferException +class TC_SHARED_API ByteBufferPositionException : public ByteBufferException { public: ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize); @@ -60,7 +50,7 @@ public: ~ByteBufferPositionException() throw() { } }; -class ByteBufferSourceException : public ByteBufferException +class TC_SHARED_API ByteBufferSourceException : public ByteBufferException { public: ByteBufferSourceException(size_t pos, size_t size, size_t valueSize); @@ -68,7 +58,7 @@ public: ~ByteBufferSourceException() throw() { } }; -class ByteBuffer +class TC_SHARED_API ByteBuffer { public: const static size_t DEFAULT_SIZE = 0x1000; @@ -628,15 +618,4 @@ inline void ByteBuffer::read_skip<std::string>() read_skip<char*>(); } -namespace boost -{ - namespace asio - { - inline const_buffers_1 buffer(ByteBuffer const& packet) - { - return buffer(packet.contents(), packet.size()); - } - } -} - #endif diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp new file mode 100644 index 00000000000..11c52f281a9 --- /dev/null +++ b/src/server/shared/Realm/Realm.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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/>. + */ + +#include "Realm.h" + +ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const +{ + ip::address realmIp; + + // Attempt to send best address for client + if (clientAddr.is_loopback()) + { + // Try guessing if realm is also connected locally + if (LocalAddress.is_loopback() || ExternalAddress.is_loopback()) + realmIp = clientAddr; + else + { + // Assume that user connecting from the machine that bnetserver is located on + // has all realms available in his local network + realmIp = LocalAddress; + } + } + else + { + if (clientAddr.is_v4() && + (clientAddr.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong()) == + (LocalAddress.to_v4().to_ulong() & LocalSubnetMask.to_v4().to_ulong())) + { + realmIp = LocalAddress; + } + else + realmIp = ExternalAddress; + } + + ip::tcp::endpoint endpoint(realmIp, Port); + + // Return external IP + return endpoint; +} diff --git a/src/server/shared/Realm/Realm.h b/src/server/shared/Realm/Realm.h new file mode 100644 index 00000000000..241ccd2bca8 --- /dev/null +++ b/src/server/shared/Realm/Realm.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/> + * + * 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/>. + */ + +#ifndef Realm_h__ +#define Realm_h__ + +#include "Common.h" +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/tcp.hpp> + +using namespace boost::asio; + +enum RealmFlags +{ + REALM_FLAG_NONE = 0x00, + REALM_FLAG_VERSION_MISMATCH = 0x01, + REALM_FLAG_OFFLINE = 0x02, + REALM_FLAG_SPECIFYBUILD = 0x04, + REALM_FLAG_UNK1 = 0x08, + REALM_FLAG_UNK2 = 0x10, + REALM_FLAG_RECOMMENDED = 0x20, + REALM_FLAG_NEW = 0x40, + REALM_FLAG_FULL = 0x80 +}; + +struct TC_SHARED_API RealmHandle +{ + RealmHandle() : Realm(0) { } + RealmHandle(uint32 index) : Realm(index) { } + + uint32 Realm; // primary key in `realmlist` table + + bool operator<(RealmHandle const& r) const + { + return Realm < r.Realm; + } +}; + +/// Type of server, this is values from second column of Cfg_Configs.dbc +enum RealmType +{ + REALM_TYPE_NORMAL = 0, + REALM_TYPE_PVP = 1, + REALM_TYPE_NORMAL2 = 4, + REALM_TYPE_RP = 6, + REALM_TYPE_RPPVP = 8, + + MAX_CLIENT_REALM_TYPE = 14, + + REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries + // replaced by REALM_PVP in realm list +}; + +// Storage object for a realm +struct TC_SHARED_API Realm +{ + RealmHandle Id; + uint32 Build; + ip::address ExternalAddress; + ip::address LocalAddress; + ip::address LocalSubnetMask; + uint16 Port; + std::string Name; + uint8 Type; + RealmFlags Flags; + uint8 Timezone; + AccountTypes AllowedSecurityLevel; + float PopulationLevel; + + ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const; +}; + +#endif // Realm_h__ diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp new file mode 100644 index 00000000000..e941800cd76 --- /dev/null +++ b/src/server/shared/Realm/RealmList.cpp @@ -0,0 +1,185 @@ +/* + * 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/>. + */ + +#include "RealmList.h" +#include "Database/DatabaseEnv.h" +#include "Util.h" + +RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr) +{ +} + +RealmList::~RealmList() +{ + delete _updateTimer; +} + +RealmList* RealmList::Instance() +{ + static RealmList instance; + return &instance; +} + +// Load the realm list from the database +void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInterval) +{ + _updateInterval = updateInterval; + _updateTimer = new boost::asio::deadline_timer(ioService); + _resolver = new boost::asio::ip::tcp::resolver(ioService); + + // Get the content of the realmlist table in the database + UpdateRealms(boost::system::error_code()); +} + +void RealmList::Close() +{ + _updateTimer->cancel(); +} + +void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, + float population) +{ + // Create new if not exist or update existed + Realm& realm = _realms[id]; + + realm.Id = id; + realm.Build = build; + realm.Name = name; + realm.Type = icon; + realm.Flags = flag; + realm.Timezone = timezone; + realm.AllowedSecurityLevel = allowedSecurityLevel; + realm.PopulationLevel = population; + realm.ExternalAddress = address; + realm.LocalAddress = localAddr; + realm.LocalSubnetMask = localSubmask; + realm.Port = port; +} + +void RealmList::UpdateRealms(boost::system::error_code const& error) +{ + if (error) + return; + + TC_LOG_DEBUG("server.authserver", "Updating Realm List..."); + + PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST); + PreparedQueryResult result = LoginDatabase.Query(stmt); + + std::map<RealmHandle, std::string> existingRealms; + for (auto const& p : _realms) + existingRealms[p.first] = p.second.Name; + + _realms.clear(); + + // Circle through results and add them to the realm map + if (result) + { + do + { + try + { + boost::asio::ip::tcp::resolver::iterator end; + + Field* fields = result->Fetch(); + uint32 realmId = fields[0].GetUInt32(); + std::string name = fields[1].GetString(); + boost::asio::ip::tcp::resolver::query externalAddressQuery(ip::tcp::v4(), fields[2].GetString(), ""); + + boost::system::error_code ec; + boost::asio::ip::tcp::resolver::iterator endPoint = _resolver->resolve(externalAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve address %s for realm \"%s\" id %u", fields[2].GetString().c_str(), name.c_str(), realmId); + continue; + } + + ip::address externalAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localAddressQuery(ip::tcp::v4(), fields[3].GetString(), ""); + endPoint = _resolver->resolve(localAddressQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve localAddress %s for realm \"%s\" id %u", fields[3].GetString().c_str(), name.c_str(), realmId); + continue; + } + + ip::address localAddress = (*endPoint).endpoint().address(); + + boost::asio::ip::tcp::resolver::query localSubmaskQuery(ip::tcp::v4(), fields[4].GetString(), ""); + endPoint = _resolver->resolve(localSubmaskQuery, ec); + if (endPoint == end || ec) + { + TC_LOG_ERROR("server.authserver", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", fields[4].GetString().c_str(), name.c_str(), realmId); + continue; + } + + ip::address localSubmask = (*endPoint).endpoint().address(); + + uint16 port = fields[5].GetUInt16(); + uint8 icon = fields[6].GetUInt8(); + if (icon == REALM_TYPE_FFA_PVP) + icon = REALM_TYPE_PVP; + if (icon >= MAX_CLIENT_REALM_TYPE) + icon = REALM_TYPE_NORMAL; + RealmFlags flag = RealmFlags(fields[7].GetUInt8()); + uint8 timezone = fields[8].GetUInt8(); + uint8 allowedSecurityLevel = fields[9].GetUInt8(); + float pop = fields[10].GetFloat(); + uint32 build = fields[11].GetUInt32(); + + RealmHandle id{ realmId }; + + UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag, + timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop); + + if (!existingRealms.count(id)) + TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + else + TC_LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port); + + existingRealms.erase(id); + } + catch (std::exception& ex) + { + TC_LOG_ERROR("server.authserver", "Realmlist::UpdateRealms has thrown an exception: %s", ex.what()); + ABORT(); + } + } + while (result->NextRow()); + } + + for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr) + TC_LOG_INFO("server.authserver", "Removed realm \"%s\".", itr->second.c_str()); + + if (_updateInterval) + { + _updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval)); + _updateTimer->async_wait(std::bind(&RealmList::UpdateRealms, this, std::placeholders::_1)); + } +} + +Realm const* RealmList::GetRealm(RealmHandle const& id) const +{ + auto itr = _realms.find(id); + if (itr != _realms.end()) + return &itr->second; + + return NULL; +} diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h new file mode 100644 index 00000000000..3b81337e762 --- /dev/null +++ b/src/server/shared/Realm/RealmList.h @@ -0,0 +1,61 @@ +/* + * 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/>. + */ + +#ifndef _REALMLIST_H +#define _REALMLIST_H + +#include "Common.h" +#include "Realm/Realm.h" +#include <boost/asio/ip/address.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/io_service.hpp> +#include <boost/asio/deadline_timer.hpp> + +using namespace boost::asio; + +/// Storage object for the list of realms on the server +class TC_SHARED_API RealmList +{ +public: + typedef std::map<RealmHandle, Realm> RealmMap; + + static RealmList* Instance(); + + ~RealmList(); + + void Initialize(boost::asio::io_service& ioService, uint32 updateInterval); + void Close(); + + RealmMap const& GetRealms() const { return _realms; } + Realm const* GetRealm(RealmHandle const& id) const; + +private: + RealmList(); + + void UpdateRealms(boost::system::error_code const& error); + void UpdateRealm(RealmHandle const& id, uint32 build, const std::string& name, ip::address const& address, ip::address const& localAddr, + ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population); + + RealmMap _realms; + uint32 _updateInterval; + boost::asio::deadline_timer* _updateTimer; + boost::asio::ip::tcp::resolver* _resolver; +}; + +#define sRealmList RealmList::Instance() +#endif diff --git a/src/server/shared/Service/ServiceWin32.cpp b/src/server/shared/Service/ServiceWin32.cpp deleted file mode 100644 index b6a1682993b..00000000000 --- a/src/server/shared/Service/ServiceWin32.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* - * 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/server/shared/Service/ServiceWin32.h b/src/server/shared/Service/ServiceWin32.h deleted file mode 100644 index 3d67bfe5445..00000000000 --- a/src/server/shared/Service/ServiceWin32.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 - |
