diff options
| author | Shauren <shauren.trinity@gmail.com> | 2016-03-26 13:39:46 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2016-04-09 12:30:00 +0200 |
| commit | 778f1725f8b085161d28a48806b1d2ec56a53e6b (patch) | |
| tree | 41219161647fee7bb7c63089a3b91c7e3fc688fe /src/server/shared | |
| parent | 3f7e6af49ede1a352b20bc02f59db1ac42a393ad (diff) | |
Core/Misc: Moved RealmList to shared
(cherry picked from commit cfe8a6a58b37280e4ed922e4d70878579dbc8bee)
Diffstat (limited to 'src/server/shared')
| -rw-r--r-- | src/server/shared/Realm/Realm.cpp | 35 | ||||
| -rw-r--r-- | src/server/shared/Realm/Realm.h | 24 | ||||
| -rw-r--r-- | src/server/shared/Realm/RealmList.cpp | 185 | ||||
| -rw-r--r-- | src/server/shared/Realm/RealmList.h | 61 |
4 files changed, 294 insertions, 11 deletions
diff --git a/src/server/shared/Realm/Realm.cpp b/src/server/shared/Realm/Realm.cpp index 0c8f4d1d492..11c52f281a9 100644 --- a/src/server/shared/Realm/Realm.cpp +++ b/src/server/shared/Realm/Realm.cpp @@ -16,3 +16,38 @@ */ #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 index 83a344dd817..241ccd2bca8 100644 --- a/src/server/shared/Realm/Realm.h +++ b/src/server/shared/Realm/Realm.h @@ -37,7 +37,7 @@ enum RealmFlags REALM_FLAG_FULL = 0x80 }; -struct RealmHandle +struct TC_SHARED_API RealmHandle { RealmHandle() : Realm(0) { } RealmHandle(uint32 index) : Realm(index) { } @@ -53,20 +53,20 @@ struct RealmHandle /// 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, + 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, + 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 + 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 Realm +struct TC_SHARED_API Realm { RealmHandle Id; uint32 Build; @@ -75,11 +75,13 @@ struct Realm ip::address LocalSubnetMask; uint16 Port; std::string Name; - uint8 Type; // icon + 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 |
