mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Battle.net: Implemented updating realm list after initial login
This commit is contained in:
@@ -77,7 +77,7 @@ void RealmList::Initialize(boost::asio::io_service& ioService, uint32 updateInte
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm(uint32 id, 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, uint32 build, uint8 region, uint8 battlegroup)
|
||||
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build)
|
||||
{
|
||||
// Create new if not exist or update existed
|
||||
Realm& realm = m_realms[name];
|
||||
@@ -90,15 +90,11 @@ void RealmList::UpdateRealm(uint32 id, const std::string& name, ip::address cons
|
||||
realm.allowedSecurityLevel = allowedSecurityLevel;
|
||||
realm.populationLevel = population;
|
||||
|
||||
// Append port to IP address.
|
||||
|
||||
realm.ExternalAddress = address;
|
||||
realm.LocalAddress = localAddr;
|
||||
realm.LocalSubnetMask = localSubmask;
|
||||
realm.port = port;
|
||||
realm.gamebuild = build;
|
||||
realm.Region = region;
|
||||
realm.Battlegroup = battlegroup;
|
||||
}
|
||||
|
||||
void RealmList::UpdateIfNeed()
|
||||
@@ -174,11 +170,9 @@ void RealmList::UpdateRealms(bool init)
|
||||
uint8 allowedSecurityLevel = fields[9].GetUInt8();
|
||||
float pop = fields[10].GetFloat();
|
||||
uint32 build = fields[11].GetUInt32();
|
||||
uint8 region = fields[12].GetUInt8();
|
||||
uint8 battlegroup = fields[13].GetUInt8();
|
||||
|
||||
UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
|
||||
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build, region, battlegroup);
|
||||
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build);
|
||||
|
||||
if (init)
|
||||
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port);
|
||||
|
||||
@@ -54,8 +54,6 @@ struct Realm
|
||||
AccountTypes allowedSecurityLevel;
|
||||
float populationLevel;
|
||||
uint32 gamebuild;
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
|
||||
ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
|
||||
};
|
||||
@@ -89,7 +87,7 @@ private:
|
||||
|
||||
void UpdateRealms(bool init = false);
|
||||
void UpdateRealm(uint32 id, 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, uint32 build, uint8 region, uint8 battlegroup);
|
||||
ip::address const& localSubmask, uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population, uint32 build);
|
||||
|
||||
RealmMap m_realms;
|
||||
uint32 m_UpdateInterval;
|
||||
|
||||
@@ -99,14 +99,7 @@ int main(int argc, char** argv)
|
||||
return 1;
|
||||
|
||||
// Get the list of realms for the server
|
||||
sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 20));
|
||||
|
||||
if (sRealmList->size() == 0)
|
||||
{
|
||||
TC_LOG_ERROR("server.bnetserver", "No valid realms specified.");
|
||||
StopDB();
|
||||
return 1;
|
||||
}
|
||||
sRealmList->Initialize(_ioService, sConfigMgr->GetIntDefault("RealmsStateUpdateDelay", 10));
|
||||
|
||||
// Start the listening port (acceptor) for auth connections
|
||||
int32 bnport = sConfigMgr->GetIntDefault("BattlenetPort", 1119);
|
||||
|
||||
@@ -18,23 +18,22 @@
|
||||
#include "Session.h"
|
||||
#include "FriendsPackets.h"
|
||||
|
||||
void Battlenet::Friends::SocialnetworkCheckConnected::Read()
|
||||
void Battlenet::Friends::SocialNetworkCheckConnected::Read()
|
||||
{
|
||||
SocialNetworkId = _stream.Read<uint32>(32);
|
||||
}
|
||||
|
||||
std::string Battlenet::Friends::SocialnetworkCheckConnected::ToString() const
|
||||
std::string Battlenet::Friends::SocialNetworkCheckConnected::ToString() const
|
||||
{
|
||||
return "Battlenet::Friends::SocialnetworkCheckConnected SocialNetworkId " + std::to_string(SocialNetworkId);
|
||||
return "Battlenet::Friends::SocialNetworkCheckConnected SocialNetworkId " + std::to_string(SocialNetworkId);
|
||||
}
|
||||
|
||||
void Battlenet::Friends::SocialnetworkCheckConnected::CallHandler(Session* session) const
|
||||
void Battlenet::Friends::SocialNetworkCheckConnected::CallHandler(Session* session) const
|
||||
{
|
||||
SocialNetworkCheckConnectedResult* result = new SocialNetworkCheckConnectedResult(SocialNetworkId);
|
||||
session->AsyncWrite(result);
|
||||
session->HandleSocialNetworkCheckConnected(*this);
|
||||
}
|
||||
|
||||
void Battlenet::Friends::SocialnetworkConnect::Read()
|
||||
void Battlenet::Friends::SocialNetworkConnect::Read()
|
||||
{
|
||||
int32 unk1 = _stream.Read<int32>(32);
|
||||
uint32 size1 = _stream.Read<uint32>(9);
|
||||
@@ -43,12 +42,12 @@ void Battlenet::Friends::SocialnetworkConnect::Read()
|
||||
auto data2 = _stream.ReadBytes(size2);
|
||||
}
|
||||
|
||||
std::string Battlenet::Friends::SocialnetworkConnect::ToString() const
|
||||
std::string Battlenet::Friends::SocialNetworkConnect::ToString() const
|
||||
{
|
||||
return "Battlenet::Friends::SocialnetworkConnect";
|
||||
return "Battlenet::Friends::SocialNetworkConnect";
|
||||
}
|
||||
|
||||
void Battlenet::Friends::SocialnetworkConnect::CallHandler(Session* session) const
|
||||
void Battlenet::Friends::SocialNetworkConnect::CallHandler(Session* session) const
|
||||
{
|
||||
session->LogUnhandledPacket(*this);
|
||||
}
|
||||
@@ -70,8 +69,7 @@ std::string Battlenet::Friends::SocialNetworkCheckConnectedResult::ToString() co
|
||||
void Battlenet::Friends::SocialNetworkCheckConnectedResult::Write()
|
||||
{
|
||||
_stream.Write(0, 23); // Ignored
|
||||
volatile uint16 res = 0;
|
||||
_stream.Write(res, 16); // Unknown
|
||||
_stream.Write(0, 16); // Unknown
|
||||
_stream.Write(SocialNetworkId, 32);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,10 +54,10 @@ namespace Battlenet
|
||||
SMSG_FRIENDS_LIST_NOTIFY_3 = 0x18 // Not implemented
|
||||
};
|
||||
|
||||
class SocialnetworkConnect final : public ClientPacket
|
||||
class SocialNetworkConnect final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
SocialnetworkConnect(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
SocialNetworkConnect(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
{
|
||||
ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS) && "Invalid packet header for SocialnetworkConnect");
|
||||
}
|
||||
@@ -78,10 +78,10 @@ namespace Battlenet
|
||||
std::string ToString() const override;
|
||||
};
|
||||
|
||||
class SocialnetworkCheckConnected final : public ClientPacket
|
||||
class SocialNetworkCheckConnected final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
SocialnetworkCheckConnected(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
SocialNetworkCheckConnected(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
{
|
||||
ASSERT(header == PacketHeader(CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS) && "Invalid packet header for SocialNetworkCheckConnected");
|
||||
}
|
||||
@@ -96,7 +96,8 @@ namespace Battlenet
|
||||
class SocialNetworkCheckConnectedResult final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
SocialNetworkCheckConnectedResult(uint32 socialNetworkId) : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS)), SocialNetworkId(socialNetworkId)
|
||||
SocialNetworkCheckConnectedResult() : ServerPacket(PacketHeader(SMSG_SOCIAL_NETWORK_CHECK_CONNECTED_RESULT, FRIENDS)),
|
||||
SocialNetworkId(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -57,10 +57,11 @@ namespace Battlenet
|
||||
_creators[PacketHeader(Connection::CMSG_LOGOUT_REQUEST, CONNECTION)] = &New<Connection::LogoutRequest>;
|
||||
|
||||
_creators[PacketHeader(WoWRealm::CMSG_LIST_SUBSCRIBE_REQUEST, WOWREALM)] = &New<WoWRealm::ListSubscribeRequest>;
|
||||
_creators[PacketHeader(WoWRealm::CMSG_LIST_UNSUBSCRIBE, WOWREALM)] = &New<WoWRealm::ListUnsubscribe>;
|
||||
_creators[PacketHeader(WoWRealm::CMSG_JOIN_REQUEST_V2, WOWREALM)] = &New<WoWRealm::JoinRequestV2>;
|
||||
|
||||
_creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS)] = &New<Friends::SocialnetworkCheckConnected>;
|
||||
_creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS)] = &New<Friends::SocialnetworkConnect>;
|
||||
_creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CHECK_CONNECTED, FRIENDS)] = &New<Friends::SocialNetworkCheckConnected>;
|
||||
_creators[PacketHeader(Friends::CMSG_SOCIAL_NETWORK_CONNECT, FRIENDS)] = &New<Friends::SocialNetworkConnect>;
|
||||
_creators[PacketHeader(Friends::CMSG_GET_FRIENDS_OF_FRIEND, FRIENDS)] = &New<Friends::GetFriendsOfFriend>;
|
||||
_creators[PacketHeader(Friends::CMSG_REALID_FRIEND_INVITE, FRIENDS)] = &New<Friends::RealIdFriendInvite>;
|
||||
|
||||
|
||||
@@ -30,6 +30,16 @@ void Battlenet::WoWRealm::ListSubscribeRequest::CallHandler(Session* session) co
|
||||
session->HandleListSubscribeRequest(*this);
|
||||
}
|
||||
|
||||
std::string Battlenet::WoWRealm::ListUnsubscribe::ToString() const
|
||||
{
|
||||
return "Battlenet::WoWRealm::ListUnsubscribe";
|
||||
}
|
||||
|
||||
void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session) const
|
||||
{
|
||||
session->HandleListUnsubscribe(*this);
|
||||
}
|
||||
|
||||
Battlenet::WoWRealm::ListSubscribeResponse::~ListSubscribeResponse()
|
||||
{
|
||||
for (ServerPacket* realmData : RealmData)
|
||||
@@ -95,7 +105,7 @@ void Battlenet::WoWRealm::ListUpdate::Write()
|
||||
if (!Version.empty())
|
||||
{
|
||||
_stream.WriteString(Version, 5);
|
||||
_stream.Write(Build, 32);
|
||||
_stream.Write(Id.Build, 32);
|
||||
|
||||
boost::asio::ip::address_v4::bytes_type ip = Address.address().to_v4().to_bytes();
|
||||
uint16 port = Address.port();
|
||||
@@ -110,16 +120,16 @@ void Battlenet::WoWRealm::ListUpdate::Write()
|
||||
_stream.WriteString(Name, 10);
|
||||
}
|
||||
|
||||
_stream.Write(Battlegroup, 8);
|
||||
_stream.Write(Index, 32);
|
||||
_stream.Write(Region, 8);
|
||||
_stream.Write(Id.Battlegroup, 8);
|
||||
_stream.Write(Id.Index, 32);
|
||||
_stream.Write(Id.Region, 8);
|
||||
}
|
||||
|
||||
std::string Battlenet::WoWRealm::ListUpdate::ToString() const
|
||||
{
|
||||
std::ostringstream stream;
|
||||
stream << "Battlenet::WoWRealm::ListUpdate Timezone " << Timezone << " Population " << Population << " Lock " << uint32(Lock) << " Type " << Type << " Name " << Name
|
||||
<< " Flags " << uint32(Flags) << " Region " << uint32(Region) << " Battlegroup " << uint32(Battlegroup) << " Index " << Index;
|
||||
<< " Flags " << uint32(Flags) << " Region " << uint32(Id.Region) << " Battlegroup " << uint32(Id.Battlegroup) << " Index " << Id.Index;
|
||||
|
||||
if (!Version.empty())
|
||||
stream << " Version " << Version;
|
||||
|
||||
@@ -53,6 +53,19 @@ namespace Battlenet
|
||||
void CallHandler(Session* session) const override;
|
||||
};
|
||||
|
||||
class ListUnsubscribe final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
ListUnsubscribe(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
|
||||
{
|
||||
ASSERT(header == PacketHeader(CMSG_LIST_UNSUBSCRIBE, WOWREALM) && "Invalid packet header for ListUnsubscribe");
|
||||
}
|
||||
|
||||
void Read() override { }
|
||||
std::string ToString() const override;
|
||||
void CallHandler(Session* session) const override;
|
||||
};
|
||||
|
||||
class JoinRequestV2 final : public ClientPacket
|
||||
{
|
||||
public:
|
||||
@@ -110,8 +123,7 @@ namespace Battlenet
|
||||
};
|
||||
|
||||
ListUpdate() : ServerPacket(PacketHeader(SMSG_LIST_UPDATE, WOWREALM)), UpdateState(UPDATE),
|
||||
Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""),
|
||||
Flags(0), Region(0), Battlegroup(0), Index(0), Build(0)
|
||||
Timezone(0), Population(0.0f), Lock(0), Type(0), Name(""), Version(""), Flags(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -127,10 +139,7 @@ namespace Battlenet
|
||||
std::string Version;
|
||||
tcp::endpoint Address;
|
||||
uint8 Flags;
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
uint32 Index;
|
||||
uint32 Build;
|
||||
RealmId Id;
|
||||
};
|
||||
|
||||
class ListComplete final : public ServerPacket
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include "Common.h"
|
||||
#include "RealmList.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
#include "SessionManager.h"
|
||||
#include "Util.h"
|
||||
#include "RealmList.h"
|
||||
|
||||
ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) const
|
||||
{
|
||||
@@ -51,73 +52,71 @@ ip::tcp::endpoint Realm::GetAddressForClient(ip::address const& clientAddr) cons
|
||||
realmIp = ExternalAddress;
|
||||
}
|
||||
|
||||
ip::tcp::endpoint endpoint(realmIp, port);
|
||||
ip::tcp::endpoint endpoint(realmIp, Port);
|
||||
|
||||
// Return external IP
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
RealmList::RealmList() : m_UpdateInterval(0), m_NextUpdateTime(time(NULL)), _resolver(nullptr)
|
||||
RealmList::RealmList() : _updateInterval(0), _updateTimer(nullptr), _resolver(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
RealmList::~RealmList()
|
||||
{
|
||||
delete _updateTimer;
|
||||
delete _resolver;
|
||||
}
|
||||
|
||||
// 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);
|
||||
m_UpdateInterval = updateInterval;
|
||||
|
||||
// Get the content of the realmlist table in the database
|
||||
UpdateRealms(true);
|
||||
UpdateRealms(boost::system::error_code());
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm(uint32 id, 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, uint32 build, uint8 region, uint8 battlegroup)
|
||||
template<typename FieldType>
|
||||
inline void UpdateField(FieldType& out, FieldType const& in, bool& changed)
|
||||
{
|
||||
if (out != in)
|
||||
{
|
||||
out = in;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm(Battlenet::RealmId const& id, 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 = m_realms[name];
|
||||
Realm& realm = _realms[id];
|
||||
|
||||
realm.m_ID = id;
|
||||
realm.name = name;
|
||||
realm.icon = icon;
|
||||
realm.flag = flag;
|
||||
realm.timezone = timezone;
|
||||
realm.allowedSecurityLevel = allowedSecurityLevel;
|
||||
realm.populationLevel = population;
|
||||
realm.Keep = true;
|
||||
realm.Updated = false;
|
||||
|
||||
// Append port to IP address.
|
||||
|
||||
realm.ExternalAddress = address;
|
||||
realm.LocalAddress = localAddr;
|
||||
realm.LocalSubnetMask = localSubmask;
|
||||
realm.port = port;
|
||||
realm.gamebuild = build;
|
||||
realm.Region = region;
|
||||
realm.Battlegroup = battlegroup;
|
||||
realm.Id = id;
|
||||
UpdateField(realm.Name, name, realm.Updated);
|
||||
UpdateField(realm.Type, icon, realm.Updated);
|
||||
UpdateField(realm.Flags, flag, realm.Updated);
|
||||
UpdateField(realm.Timezone, timezone, realm.Updated);
|
||||
UpdateField(realm.AllowedSecurityLevel, allowedSecurityLevel, realm.Updated);
|
||||
UpdateField(realm.PopulationLevel, population, realm.Updated);
|
||||
UpdateField(realm.ExternalAddress, address, realm.Updated);
|
||||
UpdateField(realm.LocalAddress, localAddr, realm.Updated);
|
||||
UpdateField(realm.LocalSubnetMask, localSubmask, realm.Updated);
|
||||
UpdateField(realm.Port, port, realm.Updated);
|
||||
}
|
||||
|
||||
void RealmList::UpdateIfNeed()
|
||||
void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
{
|
||||
// maybe disabled or updated recently
|
||||
if (!m_UpdateInterval || m_NextUpdateTime > time(NULL))
|
||||
if (error)
|
||||
return;
|
||||
|
||||
m_NextUpdateTime = time(NULL) + m_UpdateInterval;
|
||||
|
||||
// Clears Realm list
|
||||
m_realms.clear();
|
||||
|
||||
// Get the content of the realmlist table in the database
|
||||
UpdateRealms();
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealms(bool init)
|
||||
{
|
||||
TC_LOG_INFO("server.authserver", "Updating Realm List...");
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST);
|
||||
@@ -133,7 +132,6 @@ void RealmList::UpdateRealms(bool init)
|
||||
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(), "");
|
||||
|
||||
@@ -142,7 +140,7 @@ void RealmList::UpdateRealms(bool init)
|
||||
if (endPoint == end || ec)
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[2].GetString().c_str());
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
ip::address externalAddress = (*endPoint).endpoint().address();
|
||||
@@ -152,7 +150,7 @@ void RealmList::UpdateRealms(bool init)
|
||||
if (endPoint == end || ec)
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[3].GetString().c_str());
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
ip::address localAddress = (*endPoint).endpoint().address();
|
||||
@@ -162,7 +160,7 @@ void RealmList::UpdateRealms(bool init)
|
||||
if (endPoint == end || ec)
|
||||
{
|
||||
TC_LOG_ERROR("server.authserver", "Could not resolve address %s", fields[4].GetString().c_str());
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
ip::address localSubmask = (*endPoint).endpoint().address();
|
||||
@@ -173,15 +171,17 @@ void RealmList::UpdateRealms(bool init)
|
||||
uint8 timezone = fields[8].GetUInt8();
|
||||
uint8 allowedSecurityLevel = fields[9].GetUInt8();
|
||||
float pop = fields[10].GetFloat();
|
||||
uint32 realmId = fields[0].GetUInt32();
|
||||
uint32 build = fields[11].GetUInt32();
|
||||
uint8 region = fields[12].GetUInt8();
|
||||
uint8 battlegroup = fields[13].GetUInt8();
|
||||
|
||||
UpdateRealm(realmId, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
|
||||
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop, build, region, battlegroup);
|
||||
Battlenet::RealmId id{ region, battlegroup, realmId, build };
|
||||
|
||||
if (init)
|
||||
TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[name].ExternalAddress.to_string().c_str(), port);
|
||||
UpdateRealm(id, name, externalAddress, localAddress, localSubmask, port, icon, flag, timezone,
|
||||
(allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
|
||||
//TC_LOG_INFO("server.authserver", "Added realm \"%s\" at %s:%u.", name.c_str(), m_realms[id].ExternalAddress.to_string().c_str(), port);
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
@@ -191,16 +191,41 @@ void RealmList::UpdateRealms(bool init)
|
||||
}
|
||||
while (result->NextRow());
|
||||
}
|
||||
|
||||
std::vector<Realm const*> updatedRealms;
|
||||
std::vector<Battlenet::RealmId> deletedRealms;
|
||||
|
||||
for (RealmMap::value_type const& pair : _realms)
|
||||
{
|
||||
if (pair.second.Updated)
|
||||
updatedRealms.push_back(&pair.second);
|
||||
if (!pair.second.Keep)
|
||||
deletedRealms.push_back(pair.first);
|
||||
}
|
||||
|
||||
for (Battlenet::RealmId const& deleted : deletedRealms)
|
||||
_realms.erase(deleted);
|
||||
|
||||
if (!updatedRealms.empty() || !deletedRealms.empty())
|
||||
{
|
||||
sSessionMgr.LockedForEach([&updatedRealms, &deletedRealms](Battlenet::Session* session)
|
||||
{
|
||||
if (session->IsSubscribedToRealmListUpdates())
|
||||
session->UpdateRealms(updatedRealms, deletedRealms);
|
||||
});
|
||||
}
|
||||
|
||||
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(Battlenet::RealmId const& id) const
|
||||
{
|
||||
auto itr = std::find_if(m_realms.begin(), m_realms.end(), [id](RealmMap::value_type const& pair)
|
||||
{
|
||||
return pair.second.Region == id.Region && pair.second.Battlegroup == id.Battlegroup && pair.second.m_ID == id.Index;
|
||||
});
|
||||
|
||||
if (itr != m_realms.end())
|
||||
auto itr = _realms.find(id);
|
||||
if (itr != _realms.end())
|
||||
return &itr->second;
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -39,43 +39,55 @@ enum RealmFlags
|
||||
REALM_FLAG_FULL = 0x80
|
||||
};
|
||||
|
||||
// Storage object for a realm
|
||||
struct Realm
|
||||
{
|
||||
ip::address ExternalAddress;
|
||||
ip::address LocalAddress;
|
||||
ip::address LocalSubnetMask;
|
||||
uint16 port;
|
||||
std::string name;
|
||||
uint8 icon;
|
||||
RealmFlags flag;
|
||||
uint8 timezone;
|
||||
uint32 m_ID;
|
||||
AccountTypes allowedSecurityLevel;
|
||||
float populationLevel;
|
||||
uint32 gamebuild;
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
|
||||
ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
|
||||
};
|
||||
#pragma pack(push, 1)
|
||||
|
||||
namespace Battlenet
|
||||
{
|
||||
struct RealmId
|
||||
{
|
||||
RealmId() : Region(0), Battlegroup(0), Index(0), Build(0) { }
|
||||
RealmId(uint8 region, uint8 battlegroup, uint32 index, uint32 build)
|
||||
: Region(region), Battlegroup(battlegroup), Index(index), Build(build) { }
|
||||
|
||||
uint8 Region;
|
||||
uint8 Battlegroup;
|
||||
uint32 Index;
|
||||
uint32 Build;
|
||||
|
||||
bool operator<(RealmId const& r) const
|
||||
{
|
||||
return memcmp(this, &r, sizeof(RealmId) - sizeof(Build)) < 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
// Storage object for a realm
|
||||
struct Realm
|
||||
{
|
||||
Battlenet::RealmId Id;
|
||||
ip::address ExternalAddress;
|
||||
ip::address LocalAddress;
|
||||
ip::address LocalSubnetMask;
|
||||
uint16 Port;
|
||||
std::string Name;
|
||||
uint8 Type;
|
||||
RealmFlags Flags;
|
||||
uint8 Timezone;
|
||||
AccountTypes AllowedSecurityLevel;
|
||||
float PopulationLevel;
|
||||
bool Updated;
|
||||
bool Keep;
|
||||
|
||||
ip::tcp::endpoint GetAddressForClient(ip::address const& clientAddr) const;
|
||||
};
|
||||
|
||||
/// Storage object for the list of realms on the server
|
||||
class RealmList
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, Realm> RealmMap;
|
||||
typedef std::map<Battlenet::RealmId, Realm> RealmMap;
|
||||
|
||||
static RealmList* instance()
|
||||
{
|
||||
@@ -87,25 +99,19 @@ public:
|
||||
|
||||
void Initialize(boost::asio::io_service& ioService, uint32 updateInterval);
|
||||
|
||||
void UpdateIfNeed();
|
||||
|
||||
void AddRealm(const Realm& NewRealm) { m_realms[NewRealm.name] = NewRealm; }
|
||||
|
||||
RealmMap::const_iterator begin() const { return m_realms.begin(); }
|
||||
RealmMap::const_iterator end() const { return m_realms.end(); }
|
||||
uint32 size() const { return m_realms.size(); }
|
||||
RealmMap const& GetRealms() const { return _realms; }
|
||||
Realm const* GetRealm(Battlenet::RealmId const& id) const;
|
||||
|
||||
private:
|
||||
RealmList();
|
||||
|
||||
void UpdateRealms(bool init = false);
|
||||
void UpdateRealm(uint32 id, 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, uint32 build, uint8 region, uint8 battlegroup);
|
||||
void UpdateRealms(boost::system::error_code const& error);
|
||||
void UpdateRealm(Battlenet::RealmId const& id, 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 m_realms;
|
||||
uint32 m_UpdateInterval;
|
||||
time_t m_NextUpdateTime;
|
||||
RealmMap _realms;
|
||||
uint32 _updateInterval;
|
||||
boost::asio::deadline_timer* _updateTimer;
|
||||
boost::asio::ip::tcp::resolver* _resolver;
|
||||
};
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ Battlenet::Session::ModuleHandler const Battlenet::Session::ModuleHandlers[MODUL
|
||||
|
||||
Battlenet::Session::Session(tcp::socket&& socket) : Socket(std::move(socket)), _accountId(0), _accountName(), _locale(),
|
||||
_os(), _build(0), _gameAccountId(0), _gameAccountName(), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(),
|
||||
_reconnectProof(), _crypt(), _authed(false)
|
||||
_reconnectProof(), _crypt(), _authed(false), _subscribedToRealmListUpdates(false)
|
||||
{
|
||||
static uint8 const N_Bytes[] =
|
||||
{
|
||||
@@ -398,8 +398,6 @@ void Battlenet::Session::HandleLogoutRequest(Connection::LogoutRequest const& /*
|
||||
|
||||
void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& /*listSubscribeRequest*/)
|
||||
{
|
||||
sRealmList->UpdateIfNeed();
|
||||
|
||||
WoWRealm::ListSubscribeResponse* listSubscribeResponse = new WoWRealm::ListSubscribeResponse();
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS);
|
||||
@@ -411,58 +409,29 @@ void Battlenet::Session::HandleListSubscribeRequest(WoWRealm::ListSubscribeReque
|
||||
{
|
||||
Field* fields = countResult->Fetch();
|
||||
uint32 build = fields[4].GetUInt32();
|
||||
listSubscribeResponse->CharacterCounts.push_back({ { fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0) }, fields[0].GetUInt8() });
|
||||
listSubscribeResponse->CharacterCounts.push_back({ RealmId(fields[2].GetUInt8(), fields[3].GetUInt8(), fields[1].GetUInt32(), (_build != build ? build : 0)), fields[0].GetUInt8() });
|
||||
} while (countResult->NextRow());
|
||||
}
|
||||
|
||||
for (RealmList::RealmMap::const_iterator i = sRealmList->begin(); i != sRealmList->end(); ++i)
|
||||
{
|
||||
Realm const& realm = i->second;
|
||||
|
||||
uint32 flag = realm.flag & ~REALM_FLAG_SPECIFYBUILD;
|
||||
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm.gamebuild);
|
||||
if (realm.gamebuild != _build)
|
||||
{
|
||||
flag |= REALM_FLAG_INVALID;
|
||||
if (buildInfo)
|
||||
flag |= REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
|
||||
}
|
||||
|
||||
WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate();
|
||||
listUpdate->Timezone = realm.timezone;
|
||||
listUpdate->Population = realm.populationLevel;
|
||||
listUpdate->Lock = (realm.allowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||
listUpdate->Type = realm.icon;
|
||||
listUpdate->Name = realm.name;
|
||||
|
||||
if (flag & REALM_FLAG_SPECIFYBUILD)
|
||||
{
|
||||
std::ostringstream version;
|
||||
version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build;
|
||||
|
||||
listUpdate->Version = version.str();
|
||||
listUpdate->Address = realm.GetAddressForClient(GetRemoteIpAddress());
|
||||
listUpdate->Build = buildInfo->Build;
|
||||
}
|
||||
|
||||
listUpdate->Flags = flag;
|
||||
listUpdate->Region = realm.Region;
|
||||
listUpdate->Battlegroup = realm.Battlegroup;
|
||||
listUpdate->Index = realm.m_ID;
|
||||
|
||||
listSubscribeResponse->RealmData.push_back(listUpdate);
|
||||
}
|
||||
for (RealmList::RealmMap::value_type const& i : sRealmList->GetRealms())
|
||||
listSubscribeResponse->RealmData.push_back(BuildListUpdate(&i.second));
|
||||
|
||||
listSubscribeResponse->RealmData.push_back(new WoWRealm::ListComplete());
|
||||
|
||||
AsyncWrite(listSubscribeResponse);
|
||||
_subscribedToRealmListUpdates = true;
|
||||
}
|
||||
|
||||
void Battlenet::Session::HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& /*listUnsubscribe*/)
|
||||
{
|
||||
_subscribedToRealmListUpdates = false;
|
||||
}
|
||||
|
||||
void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest)
|
||||
{
|
||||
WoWRealm::JoinResponseV2* joinResponse = new WoWRealm::JoinResponseV2();
|
||||
Realm const* realm = sRealmList->GetRealm(joinRequest.Realm);
|
||||
if (!realm || realm->flag & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE))
|
||||
if (!realm || realm->Flags & (REALM_FLAG_INVALID | REALM_FLAG_OFFLINE))
|
||||
{
|
||||
joinResponse->Response = WoWRealm::JoinResponseV2::FAILURE;
|
||||
AsyncWrite(joinResponse);
|
||||
@@ -491,13 +460,20 @@ void Battlenet::Session::HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& join
|
||||
LoginDatabase.DirectPExecute("UPDATE account SET sessionkey = '%s', last_ip = '%s', last_login = NOW(), locale = %u, failed_logins = 0, os = '%s' WHERE id = %u",
|
||||
ByteArrayToHexStr(sessionKey, 40, true).c_str(), GetRemoteIpAddress().to_string().c_str(), GetLocaleByName(_locale), _os.c_str(), _gameAccountId);
|
||||
|
||||
joinResponse->IPv4.emplace_back(realm->ExternalAddress, realm->port);
|
||||
joinResponse->IPv4.emplace_back(realm->ExternalAddress, realm->Port);
|
||||
if (realm->ExternalAddress != realm->LocalAddress)
|
||||
joinResponse->IPv4.emplace_back(realm->LocalAddress, realm->port);
|
||||
joinResponse->IPv4.emplace_back(realm->LocalAddress, realm->Port);
|
||||
|
||||
AsyncWrite(joinResponse);
|
||||
}
|
||||
|
||||
void Battlenet::Session::HandleSocialNetworkCheckConnected(Friends::SocialNetworkCheckConnected const& socialNetworkCheckConnected)
|
||||
{
|
||||
Friends::SocialNetworkCheckConnectedResult* socialNetworkCheckConnectedResult = new Friends::SocialNetworkCheckConnectedResult();
|
||||
socialNetworkCheckConnectedResult->SocialNetworkId = socialNetworkCheckConnected.SocialNetworkId;
|
||||
AsyncWrite(socialNetworkCheckConnectedResult);
|
||||
}
|
||||
|
||||
void Battlenet::Session::ReadHandler()
|
||||
{
|
||||
BitStream stream(std::move(GetReadBuffer()));
|
||||
@@ -998,3 +974,49 @@ bool Battlenet::Session::UnhandledModule(BitStream* /*dataStream*/, ServerPacket
|
||||
ReplaceResponse(response, logonResponse);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Battlenet::Session::UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmId>& deletedRealms)
|
||||
{
|
||||
for (Realm const* realm : realms)
|
||||
AsyncWrite(BuildListUpdate(realm));
|
||||
|
||||
for (RealmId& deleted : deletedRealms)
|
||||
{
|
||||
WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate();
|
||||
listUpdate->UpdateState = WoWRealm::ListUpdate::DELETED;
|
||||
listUpdate->Id = deleted;
|
||||
AsyncWrite(listUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
Battlenet::WoWRealm::ListUpdate* Battlenet::Session::BuildListUpdate(Realm const* realm) const
|
||||
{
|
||||
uint32 flag = realm->Flags & ~REALM_FLAG_SPECIFYBUILD;
|
||||
RealmBuildInfo const* buildInfo = AuthHelper::GetBuildInfo(realm->Id.Build);
|
||||
if (realm->Id.Build != _build)
|
||||
{
|
||||
flag |= REALM_FLAG_INVALID;
|
||||
if (buildInfo)
|
||||
flag |= REALM_FLAG_SPECIFYBUILD; // tell the client what build the realm is for
|
||||
}
|
||||
|
||||
WoWRealm::ListUpdate* listUpdate = new WoWRealm::ListUpdate();
|
||||
listUpdate->Timezone = realm->Timezone;
|
||||
listUpdate->Population = realm->PopulationLevel;
|
||||
listUpdate->Lock = (realm->AllowedSecurityLevel > _accountSecurityLevel) ? 1 : 0;
|
||||
listUpdate->Type = realm->Type;
|
||||
listUpdate->Name = realm->Name;
|
||||
|
||||
if (flag & REALM_FLAG_SPECIFYBUILD)
|
||||
{
|
||||
std::ostringstream version;
|
||||
version << buildInfo->MajorVersion << '.' << buildInfo->MinorVersion << '.' << buildInfo->BugfixVersion << '.' << buildInfo->Build;
|
||||
|
||||
listUpdate->Version = version.str();
|
||||
listUpdate->Address = realm->GetAddressForClient(GetRemoteIpAddress());
|
||||
}
|
||||
|
||||
listUpdate->Flags = flag;
|
||||
listUpdate->Id = realm->Id;
|
||||
return listUpdate;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <memory>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
|
||||
struct Realm;
|
||||
using boost::asio::ip::tcp;
|
||||
|
||||
namespace Battlenet
|
||||
@@ -73,12 +74,23 @@ namespace Battlenet
|
||||
|
||||
// WoWRealm
|
||||
void HandleListSubscribeRequest(WoWRealm::ListSubscribeRequest const& listSubscribeRequest);
|
||||
void HandleListUnsubscribe(WoWRealm::ListUnsubscribe const& listUnsubscribe);
|
||||
void HandleJoinRequestV2(WoWRealm::JoinRequestV2 const& joinRequest);
|
||||
|
||||
// Friends
|
||||
void HandleSocialNetworkCheckConnected(Friends::SocialNetworkCheckConnected const& socialNetworkCheckConnected);
|
||||
|
||||
void Start() override;
|
||||
|
||||
void UpdateRealms(std::vector<Realm const*>& realms, std::vector<RealmId>& deletedRealms);
|
||||
|
||||
void AsyncWrite(ServerPacket* packet);
|
||||
|
||||
uint32 GetAccountId() const { return _accountId; }
|
||||
uint32 GetGameAccountId() const { return _gameAccountId; }
|
||||
|
||||
bool IsSubscribedToRealmListUpdates() const { return _subscribedToRealmListUpdates; }
|
||||
|
||||
protected:
|
||||
void ReadHandler() override;
|
||||
|
||||
@@ -94,6 +106,8 @@ namespace Battlenet
|
||||
bool HandleResumeModule(BitStream* dataStream, ServerPacket** response);
|
||||
bool UnhandledModule(BitStream* dataStream, ServerPacket** response);
|
||||
|
||||
WoWRealm::ListUpdate* BuildListUpdate(Realm const* realm) const;
|
||||
|
||||
uint32 _accountId;
|
||||
std::string _accountName;
|
||||
std::string _locale;
|
||||
@@ -121,6 +135,7 @@ namespace Battlenet
|
||||
|
||||
PacketCrypt _crypt;
|
||||
bool _authed;
|
||||
bool _subscribedToRealmListUpdates;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -35,3 +35,15 @@ void Battlenet::SessionManager::OnSocketAccept(tcp::socket&& sock)
|
||||
{
|
||||
sSessionMgr.OnSocketOpen(std::forward<tcp::socket>(sock));
|
||||
}
|
||||
|
||||
void Battlenet::SessionManager::AddSession(Session* session)
|
||||
{
|
||||
std::unique_lock<boost::shared_mutex> lock(_sessionMutex);
|
||||
_sessions[{ session->GetAccountId(), session->GetGameAccountId() }] = session;
|
||||
}
|
||||
|
||||
void Battlenet::SessionManager::RemoveSession(Session* session)
|
||||
{
|
||||
std::unique_lock<boost::shared_mutex> lock(_sessionMutex);
|
||||
_sessions.erase({ session->GetAccountId(), session->GetGameAccountId() });
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include "Session.h"
|
||||
#include "SocketMgr.h"
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
|
||||
namespace Battlenet
|
||||
{
|
||||
@@ -28,7 +30,7 @@ namespace Battlenet
|
||||
struct SessionInfo
|
||||
{
|
||||
uint32 AccountId;
|
||||
uint32 GameAccountIndex;
|
||||
uint32 GameAccountId;
|
||||
|
||||
bool operator<(SessionInfo const& right) const
|
||||
{
|
||||
@@ -41,6 +43,7 @@ namespace Battlenet
|
||||
class SessionManager : SocketMgr<Session>
|
||||
{
|
||||
typedef SocketMgr<Session> BaseSocketMgr;
|
||||
typedef std::map<SessionInfo, Session*> SessionMap;
|
||||
|
||||
public:
|
||||
static SessionManager& Instance()
|
||||
@@ -52,9 +55,17 @@ namespace Battlenet
|
||||
bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override;
|
||||
|
||||
// noop for now, will be needed later to broadcast realmlist updates for example
|
||||
void AddSession(Session* /*session*/) { }
|
||||
void AddSession(Session* /*session*/);
|
||||
|
||||
void RemoveSession(Session* /*session*/) { }
|
||||
void RemoveSession(Session* /*session*/);
|
||||
|
||||
template<typename Iterator>
|
||||
void LockedForEach(Iterator iterator)
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(_sessionMutex);
|
||||
for (SessionMap::value_type const& pair : _sessions)
|
||||
iterator(pair.second);
|
||||
}
|
||||
|
||||
protected:
|
||||
NetworkThread<Session>* CreateThreads() const override;
|
||||
@@ -62,7 +73,8 @@ namespace Battlenet
|
||||
private:
|
||||
static void OnSocketAccept(tcp::socket&& sock);
|
||||
|
||||
std::map<SessionInfo, Session> _sessions;
|
||||
SessionMap _sessions;
|
||||
boost::shared_mutex _sessionMutex;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -91,10 +91,10 @@ ProcessPriority = 0
|
||||
#
|
||||
# RealmsStateUpdateDelay
|
||||
# Description: Time (in seconds) between realm list updates.
|
||||
# Default: 20 - (Enabled)
|
||||
# Default: 10
|
||||
# 0 - (Disabled)
|
||||
|
||||
RealmsStateUpdateDelay = 20
|
||||
RealmsStateUpdateDelay = 10
|
||||
|
||||
#
|
||||
# WrongPass.MaxCount
|
||||
|
||||
Reference in New Issue
Block a user