aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-03-26 13:39:46 +0100
committerShauren <shauren.trinity@gmail.com>2016-04-09 12:30:00 +0200
commit778f1725f8b085161d28a48806b1d2ec56a53e6b (patch)
tree41219161647fee7bb7c63089a3b91c7e3fc688fe /src/server/shared
parent3f7e6af49ede1a352b20bc02f59db1ac42a393ad (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.cpp35
-rw-r--r--src/server/shared/Realm/Realm.h24
-rw-r--r--src/server/shared/Realm/RealmList.cpp185
-rw-r--r--src/server/shared/Realm/RealmList.h61
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