feat(Core): replace ACE network with Boost.Asio (#6574)

This commit is contained in:
Kargatum
2021-07-16 15:43:56 +07:00
committed by GitHub
parent 7449496bb5
commit 8568c4fb33
64 changed files with 3242 additions and 4712 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
*/
#include "Realm.h"
#include "IpAddress.h"
#include "IpNetwork.h"
#include <boost/asio/ip/tcp.hpp>
boost::asio::ip::tcp_endpoint Realm::GetAddressForClient(boost::asio::ip::address const& clientAddr) const
{
boost::asio::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() && Acore::Net::IsInNetwork(LocalAddress->to_v4(), LocalSubnetMask->to_v4(), clientAddr.to_v4()))
{
realmIp = *LocalAddress;
}
else
{
realmIp = *ExternalAddress;
}
}
// Return external IP
return boost::asio::ip::tcp_endpoint(realmIp, Port);
}

View File

@@ -6,9 +6,8 @@
#ifndef Realm_h__
#define Realm_h__
#include "AsioHacksFwd.h"
#include "Common.h"
// #include "AsioHacksFwd.h"
#include <ace/INET_Addr.h>
enum RealmFlags
{
@@ -56,9 +55,9 @@ struct AC_SHARED_API Realm
{
RealmHandle Id;
uint32 Build;
std::unique_ptr<ACE_INET_Addr> ExternalAddress;
std::unique_ptr<ACE_INET_Addr> LocalAddress;
std::unique_ptr<ACE_INET_Addr> LocalSubnetMask;
std::unique_ptr<boost::asio::ip::address> ExternalAddress;
std::unique_ptr<boost::asio::ip::address> LocalAddress;
std::unique_ptr<boost::asio::ip::address> LocalSubnetMask;
uint16 Port;
std::string Name;
uint8 Type;
@@ -67,7 +66,7 @@ struct AC_SHARED_API Realm
AccountTypes AllowedSecurityLevel;
float PopulationLevel;
// boost::asio::ip::tcp_endpoint GetAddressForClient(boost::asio::ip::address const& clientAddr) const;
boost::asio::ip::tcp_endpoint GetAddressForClient(boost::asio::ip::address const& clientAddr) const;
};
#endif // Realm_h__

View File

@@ -6,28 +6,38 @@
#include "RealmList.h"
#include "DatabaseEnv.h"
#include "DeadlineTimer.h"
#include "IoContext.h"
#include "Log.h"
#include "Optional.h"
#include "Resolver.h"
#include "Util.h"
#include <boost/asio/ip/tcp.hpp>
RealmList::RealmList() :
_updateInterval(0) { }
RealmList* RealmList::instance()
RealmList* RealmList::Instance()
{
static RealmList instance;
return &instance;
}
// Load the realm list from the database
void RealmList::Initialize(uint32 updateInterval)
void RealmList::Initialize(Acore::Asio::IoContext& ioContext, uint32 updateInterval)
{
_updateInterval = updateInterval;
_updateTimer = std::make_unique<Acore::Asio::DeadlineTimer>(ioContext);
_resolver = std::make_unique<Acore::Asio::Resolver>(ioContext);
LoadBuildInfo();
// Get the content of the realmlist table in the database
UpdateRealms();
UpdateRealms(boost::system::error_code());
}
void RealmList::Close()
{
_updateTimer->cancel();
}
void RealmList::LoadBuildInfo()
@@ -72,7 +82,7 @@ void RealmList::LoadBuildInfo()
}
void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
ACE_INET_Addr&& address, ACE_INET_Addr&& localAddr, ACE_INET_Addr&& localSubmask,
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population)
{
// Create new if not exist or update existed
@@ -89,38 +99,30 @@ void RealmList::UpdateRealm(RealmHandle const& id, uint32 build, std::string con
if (!realm.ExternalAddress || *realm.ExternalAddress != address)
{
realm.ExternalAddress = std::make_unique<ACE_INET_Addr>(std::move(address));
realm.ExternalAddress = std::make_unique<boost::asio::ip::address>(std::move(address));
}
if (!realm.LocalAddress || *realm.LocalAddress != localAddr)
{
realm.LocalAddress = std::make_unique<ACE_INET_Addr>(std::move(localAddr));
realm.LocalAddress = std::make_unique<boost::asio::ip::address>(std::move(localAddr));
}
if (!realm.LocalSubnetMask || *realm.LocalSubnetMask != localSubmask)
{
realm.LocalSubnetMask = std::make_unique<ACE_INET_Addr>(std::move(localSubmask));
realm.LocalSubnetMask = std::make_unique<boost::asio::ip::address>(std::move(localSubmask));
}
realm.Port = port;
}
void RealmList::UpdateIfNeed()
void RealmList::UpdateRealms(boost::system::error_code const& error)
{
// maybe disabled or updated recently
if (!_updateInterval || _nextUpdateTime > time(nullptr))
if (error)
{
// Skip update if have errors
return;
}
_nextUpdateTime = time(nullptr) + _updateInterval;
// Get the content of the realmlist table in the database
UpdateRealms();
}
void RealmList::UpdateRealms()
{
LOG_DEBUG("server.authserver", "Updating Realm List...");
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
@@ -139,70 +141,87 @@ void RealmList::UpdateRealms()
{
do
{
Field* fields = result->Fetch();
uint32 realmId = fields[0].GetUInt32();
std::string name = fields[1].GetString();
std::string externalAddressString = fields[2].GetString();
std::string localAddressString = fields[3].GetString();
std::string localSubmaskString = fields[4].GetString();
uint16 port = fields[5].GetUInt16();
Optional<ACE_INET_Addr> externalAddress = ACE_INET_Addr(port, externalAddressString.c_str(), AF_INET);
if (!externalAddress)
try
{
LOG_ERROR("server.authserver", "Could not resolve address %s for realm \"%s\" id %u", externalAddressString.c_str(), name.c_str(), realmId);
continue;
}
Field* fields = result->Fetch();
uint32 realmId = fields[0].GetUInt32();
std::string name = fields[1].GetString();
std::string externalAddressString = fields[2].GetString();
std::string localAddressString = fields[3].GetString();
std::string localSubmaskString = fields[4].GetString();
uint16 port = fields[5].GetUInt16();
Optional<ACE_INET_Addr> localAddress = ACE_INET_Addr(port, localAddressString.c_str(), AF_INET);
if (!localAddress)
Optional<boost::asio::ip::tcp::endpoint> externalAddress = _resolver->Resolve(boost::asio::ip::tcp::v4(), externalAddressString, "");
if (!externalAddress)
{
LOG_ERROR("server.authserver", "Could not resolve address %s for realm \"%s\" id %u", externalAddressString.c_str(), name.c_str(), realmId);
continue;
}
Optional<boost::asio::ip::tcp::endpoint> localAddress = _resolver->Resolve(boost::asio::ip::tcp::v4(), localAddressString, "");
if (!localAddress)
{
LOG_ERROR("server.authserver", "Could not resolve localAddress %s for realm \"%s\" id %u", localAddressString.c_str(), name.c_str(), realmId);
continue;
}
Optional<boost::asio::ip::tcp::endpoint> localSubmask = _resolver->Resolve(boost::asio::ip::tcp::v4(), localSubmaskString, "");
if (!localSubmask)
{
LOG_ERROR("server.authserver", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", localSubmaskString.c_str(), name.c_str(), realmId);
continue;
}
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->address(), localAddress->address(), localSubmask->address(), port, icon, flag,
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
if (!existingRealms.count(id))
{
LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
}
else
{
LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
}
existingRealms.erase(id);
}
catch (std::exception const& ex)
{
LOG_ERROR("server.authserver", "Could not resolve localAddress %s for realm \"%s\" id %u", localAddressString.c_str(), name.c_str(), realmId);
continue;
LOG_ERROR("server.authserver", "Realmlist::UpdateRealms has thrown an exception: %s", ex.what());
ABORT();
}
Optional<ACE_INET_Addr> localSubmask = ACE_INET_Addr(0, localSubmaskString.c_str(), AF_INET);
if (!localSubmask)
{
LOG_ERROR("server.authserver", "Could not resolve localSubnetMask %s for realm \"%s\" id %u", localSubmaskString.c_str(), name.c_str(), realmId);
continue;
}
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, std::move(externalAddress.value()), std::move(localAddress.value()), std::move(localSubmask.value()), port, icon, flag,
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
if (!existingRealms.count(id))
{
LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
}
else
{
LOG_DEBUG("server.authserver", "Updating realm \"%s\" at %s:%u.", name.c_str(), externalAddressString.c_str(), port);
}
existingRealms.erase(id);
} while (result->NextRow());
}
for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr)
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

View File

@@ -11,8 +11,8 @@
#include "Realm.h"
#include <array>
#include <map>
#include <vector>
#include <unordered_set>
#include <vector>
struct RealmBuildInfo
{
@@ -25,19 +25,21 @@ struct RealmBuildInfo
std::array<uint8, 20> MacHash;
};
namespace boost::system
{
class error_code;
}
/// Storage object for the list of realms on the server
class AC_SHARED_API RealmList
{
public:
typedef std::map<RealmHandle, Realm> RealmMap;
RealmList();
~RealmList() = default;
static RealmList* Instance();
static RealmList* instance();
void Initialize(uint32 updateInterval);
void UpdateIfNeed();
void Initialize(Acore::Asio::IoContext& ioContext, uint32 updateInterval);
void Close();
RealmMap const& GetRealms() const { return _realms; }
Realm const* GetRealm(RealmHandle const& id) const;
@@ -45,18 +47,22 @@ public:
RealmBuildInfo const* GetBuildInfo(uint32 build) const;
private:
RealmList();
~RealmList() = default;
void LoadBuildInfo();
void UpdateRealms();
void UpdateRealms(boost::system::error_code const& error);
void UpdateRealm(RealmHandle const& id, uint32 build, std::string const& name,
ACE_INET_Addr&& address, ACE_INET_Addr&& localAddr, ACE_INET_Addr&& localSubmask,
boost::asio::ip::address&& address, boost::asio::ip::address&& localAddr, boost::asio::ip::address&& localSubmask,
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
std::vector<RealmBuildInfo> _builds;
RealmMap _realms;
uint32 _updateInterval;
time_t _nextUpdateTime;
std::unique_ptr<Acore::Asio::DeadlineTimer> _updateTimer;
std::unique_ptr<Acore::Asio::Resolver> _resolver;
};
#define sRealmList RealmList::instance()
#define sRealmList RealmList::Instance()
#endif