mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-16 16:56:07 +00:00
feat(Core): replace ACE network with Boost.Asio (#6574)
This commit is contained in:
@@ -16,9 +16,9 @@
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
#if BOOST_VERSION >= 106600
|
||||
#define WARHEAD_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_listen_connections
|
||||
#define ACORE_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_listen_connections
|
||||
#else
|
||||
#define WARHEAD_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_connections
|
||||
#define ACORE_MAX_LISTEN_CONNECTIONS boost::asio::socket_base::max_connections
|
||||
#endif
|
||||
|
||||
class AsyncAcceptor
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WARHEAD_PLATFORM != WARHEAD_PLATFORM_WINDOWS
|
||||
#if AC_PLATFORM != AC_PLATFORM_WINDOWS
|
||||
_acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true), errorCode);
|
||||
if (errorCode)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
_acceptor.listen(WARHEAD_MAX_LISTEN_CONNECTIONS, errorCode);
|
||||
_acceptor.listen(ACORE_MAX_LISTEN_CONNECTIONS, errorCode);
|
||||
if (errorCode)
|
||||
{
|
||||
LOG_INFO("network", "Failed to start listening on %s:%u %s", _endpoint.address().to_string().c_str(), _endpoint.port(), errorCode.message().c_str());
|
||||
|
||||
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*/
|
||||
|
||||
#include "Log.h"
|
||||
#include "RealmSocket.h"
|
||||
#include <ace/INET_Addr.h>
|
||||
#include <ace/OS_NS_string.h>
|
||||
|
||||
RealmSocket::Session::Session() = default;
|
||||
|
||||
RealmSocket::Session::~Session() = default;
|
||||
|
||||
RealmSocket::RealmSocket() :
|
||||
input_buffer_(4096),
|
||||
_remoteAddress()
|
||||
{
|
||||
reference_counting_policy().value(ACE_Event_Handler::Reference_Counting_Policy::ENABLED);
|
||||
|
||||
msg_queue()->high_water_mark(8 * 1024 * 1024);
|
||||
msg_queue()->low_water_mark(8 * 1024 * 1024);
|
||||
}
|
||||
|
||||
RealmSocket::~RealmSocket()
|
||||
{
|
||||
if (msg_queue())
|
||||
msg_queue()->close();
|
||||
|
||||
// delete RealmSocketObject must never be called from our code.
|
||||
closing_ = true;
|
||||
|
||||
delete session_;
|
||||
|
||||
peer().close();
|
||||
}
|
||||
|
||||
int RealmSocket::open(void* arg)
|
||||
{
|
||||
ACE_INET_Addr addr;
|
||||
|
||||
if (peer().get_remote_addr(addr) == -1)
|
||||
{
|
||||
LOG_ERROR("network", "Error %s while opening realm socket!", ACE_OS::strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
_remoteAddress = addr.get_host_addr();
|
||||
_remotePort = addr.get_port_number();
|
||||
|
||||
// Register with ACE Reactor
|
||||
if (Base::open(arg) == -1)
|
||||
return -1;
|
||||
|
||||
if (session_)
|
||||
session_->OnAccept();
|
||||
|
||||
// reactor takes care of the socket from now on
|
||||
remove_reference();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealmSocket::close(u_long)
|
||||
{
|
||||
shutdown();
|
||||
|
||||
closing_ = true;
|
||||
|
||||
remove_reference();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const std::string& RealmSocket::getRemoteAddress() const
|
||||
{
|
||||
return _remoteAddress;
|
||||
}
|
||||
|
||||
uint16 RealmSocket::getRemotePort() const
|
||||
{
|
||||
return _remotePort;
|
||||
}
|
||||
|
||||
size_t RealmSocket::recv_len() const
|
||||
{
|
||||
return input_buffer_.length();
|
||||
}
|
||||
|
||||
bool RealmSocket::recv_soft(char* buf, size_t len)
|
||||
{
|
||||
if (input_buffer_.length() < len)
|
||||
return false;
|
||||
|
||||
ACE_OS::memcpy(buf, input_buffer_.rd_ptr(), len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RealmSocket::recv(char* buf, size_t len)
|
||||
{
|
||||
bool ret = recv_soft(buf, len);
|
||||
|
||||
if (ret)
|
||||
recv_skip(len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void RealmSocket::recv_skip(size_t len)
|
||||
{
|
||||
input_buffer_.rd_ptr(len);
|
||||
}
|
||||
|
||||
ssize_t RealmSocket::noblk_send(ACE_Message_Block& message_block)
|
||||
{
|
||||
const size_t len = message_block.length();
|
||||
|
||||
if (len == 0)
|
||||
return -1;
|
||||
|
||||
// Try to send the message directly.
|
||||
#ifdef MSG_NOSIGNAL
|
||||
ssize_t n = peer().send(message_block.rd_ptr(), len, MSG_NOSIGNAL);
|
||||
#else
|
||||
ssize_t n = peer().send(message_block.rd_ptr(), len);
|
||||
#endif // MSG_NOSIGNAL
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
if (errno == EWOULDBLOCK) // Blocking signal
|
||||
return 0;
|
||||
else // Error happened
|
||||
return -1;
|
||||
}
|
||||
else if (n == 0)
|
||||
{
|
||||
// Can this happen ?
|
||||
return -1;
|
||||
}
|
||||
|
||||
// return bytes transmitted
|
||||
return n;
|
||||
}
|
||||
|
||||
bool RealmSocket::send(const char* buf, size_t len)
|
||||
{
|
||||
if (buf == nullptr || len == 0)
|
||||
return true;
|
||||
|
||||
ACE_Data_Block db(len, ACE_Message_Block::MB_DATA, (const char*)buf, nullptr, nullptr, ACE_Message_Block::DONT_DELETE, nullptr);
|
||||
ACE_Message_Block message_block(&db, ACE_Message_Block::DONT_DELETE, nullptr);
|
||||
|
||||
message_block.wr_ptr(len);
|
||||
|
||||
if (msg_queue()->is_empty())
|
||||
{
|
||||
// Try to send it directly.
|
||||
ssize_t n = noblk_send(message_block);
|
||||
|
||||
if (n < 0)
|
||||
return false;
|
||||
|
||||
size_t un = size_t(n);
|
||||
if (un == len)
|
||||
return true;
|
||||
|
||||
// fall down
|
||||
message_block.rd_ptr(un);
|
||||
}
|
||||
|
||||
ACE_Message_Block* mb = message_block.clone();
|
||||
|
||||
if (msg_queue()->enqueue_tail(mb, (ACE_Time_Value*)(&ACE_Time_Value::zero)) == -1)
|
||||
{
|
||||
mb->release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reactor()->schedule_wakeup(this, ACE_Event_Handler::WRITE_MASK) == -1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int RealmSocket::handle_output(ACE_HANDLE)
|
||||
{
|
||||
if (closing_)
|
||||
return -1;
|
||||
|
||||
ACE_Message_Block* mb = nullptr;
|
||||
|
||||
if (msg_queue()->is_empty())
|
||||
{
|
||||
reactor()->cancel_wakeup(this, ACE_Event_Handler::WRITE_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msg_queue()->dequeue_head(mb, (ACE_Time_Value*)(&ACE_Time_Value::zero)) == -1)
|
||||
return -1;
|
||||
|
||||
ssize_t n = noblk_send(*mb);
|
||||
|
||||
if (n < 0)
|
||||
{
|
||||
mb->release();
|
||||
return -1;
|
||||
}
|
||||
else if (size_t(n) == mb->length())
|
||||
{
|
||||
mb->release();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
mb->rd_ptr(n);
|
||||
|
||||
if (msg_queue()->enqueue_head(mb, (ACE_Time_Value*) &ACE_Time_Value::zero) == -1)
|
||||
{
|
||||
mb->release();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ACE_NOTREACHED(return -1);
|
||||
}
|
||||
|
||||
int RealmSocket::handle_close(ACE_HANDLE h, ACE_Reactor_Mask)
|
||||
{
|
||||
// As opposed to WorldSocket::handle_close, we don't need locks here.
|
||||
closing_ = true;
|
||||
|
||||
if (h == ACE_INVALID_HANDLE)
|
||||
peer().close_writer();
|
||||
|
||||
if (session_)
|
||||
session_->OnClose();
|
||||
|
||||
reactor()->remove_handler(this, ACE_Event_Handler::DONT_CALL | ACE_Event_Handler::ALL_EVENTS_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RealmSocket::handle_input(ACE_HANDLE)
|
||||
{
|
||||
if (closing_)
|
||||
return -1;
|
||||
|
||||
const ssize_t space = input_buffer_.space();
|
||||
|
||||
ssize_t n = peer().recv(input_buffer_.wr_ptr(), space);
|
||||
|
||||
if (n < 0)
|
||||
return errno == EWOULDBLOCK ? 0 : -1;
|
||||
else if (n == 0) // EOF
|
||||
return -1;
|
||||
|
||||
input_buffer_.wr_ptr((size_t)n);
|
||||
|
||||
if (session_ != nullptr)
|
||||
{
|
||||
session_->OnRead();
|
||||
input_buffer_.crunch();
|
||||
}
|
||||
|
||||
// return 1 in case there is more data to read from OS
|
||||
return n == space ? 1 : 0;
|
||||
}
|
||||
|
||||
void RealmSocket::set_session(Session* session)
|
||||
{
|
||||
delete session_;
|
||||
|
||||
session_ = session;
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*/
|
||||
|
||||
#ifndef __REALMSOCKET_H__
|
||||
#define __REALMSOCKET_H__
|
||||
|
||||
#include "Common.h"
|
||||
#include <ace/Message_Block.h>
|
||||
#include <ace/SOCK_Stream.h>
|
||||
#include <ace/Svc_Handler.h>
|
||||
#include <ace/Synch_Traits.h>
|
||||
|
||||
class RealmSocket : public ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH>
|
||||
{
|
||||
private:
|
||||
typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> Base;
|
||||
|
||||
public:
|
||||
class Session
|
||||
{
|
||||
public:
|
||||
Session();
|
||||
virtual ~Session();
|
||||
|
||||
virtual void OnRead() = 0;
|
||||
virtual void OnAccept() = 0;
|
||||
virtual void OnClose() = 0;
|
||||
};
|
||||
|
||||
RealmSocket();
|
||||
~RealmSocket() override;
|
||||
|
||||
[[nodiscard]] size_t recv_len() const;
|
||||
bool recv_soft(char* buf, size_t len);
|
||||
bool recv(char* buf, size_t len);
|
||||
void recv_skip(size_t len);
|
||||
|
||||
bool send(const char* buf, size_t len);
|
||||
|
||||
[[nodiscard]] const std::string& getRemoteAddress() const;
|
||||
|
||||
[[nodiscard]] uint16 getRemotePort() const;
|
||||
|
||||
int open(void*) override;
|
||||
|
||||
int close(u_long) override;
|
||||
|
||||
int handle_input(ACE_HANDLE = ACE_INVALID_HANDLE) override;
|
||||
int handle_output(ACE_HANDLE = ACE_INVALID_HANDLE) override;
|
||||
|
||||
int handle_close(ACE_HANDLE = ACE_INVALID_HANDLE, ACE_Reactor_Mask = ACE_Event_Handler::ALL_EVENTS_MASK) override;
|
||||
|
||||
void set_session(Session* session);
|
||||
|
||||
private:
|
||||
ssize_t noblk_send(ACE_Message_Block& message_block);
|
||||
|
||||
ACE_Message_Block input_buffer_;
|
||||
Session* session_{nullptr};
|
||||
std::string _remoteAddress;
|
||||
uint16 _remotePort{0};
|
||||
};
|
||||
|
||||
#endif /* __REALMSOCKET_H__ */
|
||||
44
src/server/shared/Realms/Realm.cpp
Normal file
44
src/server/shared/Realms/Realm.cpp
Normal 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);
|
||||
}
|
||||
@@ -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__
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user