aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/authserver/Realms/RealmList.cpp10
-rw-r--r--src/server/authserver/Realms/RealmList.h4
-rw-r--r--src/server/bnetserver/Main.cpp9
-rw-r--r--src/server/bnetserver/Packets/FriendsPackets.cpp22
-rw-r--r--src/server/bnetserver/Packets/FriendsPackets.h11
-rw-r--r--src/server/bnetserver/Packets/PacketFactory.h5
-rw-r--r--src/server/bnetserver/Packets/WoWRealmPackets.cpp20
-rw-r--r--src/server/bnetserver/Packets/WoWRealmPackets.h21
-rw-r--r--src/server/bnetserver/Realms/RealmList.cpp133
-rw-r--r--src/server/bnetserver/Realms/RealmList.h74
-rw-r--r--src/server/bnetserver/Server/Session.cpp110
-rw-r--r--src/server/bnetserver/Server/Session.h15
-rw-r--r--src/server/bnetserver/Server/SessionManager.cpp12
-rw-r--r--src/server/bnetserver/Server/SessionManager.h20
-rw-r--r--src/server/bnetserver/bnetserver.conf.dist4
15 files changed, 283 insertions, 187 deletions
diff --git a/src/server/authserver/Realms/RealmList.cpp b/src/server/authserver/Realms/RealmList.cpp
index 662a015dc65..15302c74ac6 100644
--- a/src/server/authserver/Realms/RealmList.cpp
+++ b/src/server/authserver/Realms/RealmList.cpp
@@ -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);
diff --git a/src/server/authserver/Realms/RealmList.h b/src/server/authserver/Realms/RealmList.h
index f7a98cda686..9d5771144a9 100644
--- a/src/server/authserver/Realms/RealmList.h
+++ b/src/server/authserver/Realms/RealmList.h
@@ -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;
diff --git a/src/server/bnetserver/Main.cpp b/src/server/bnetserver/Main.cpp
index e208f3cd1d9..5e0d728d724 100644
--- a/src/server/bnetserver/Main.cpp
+++ b/src/server/bnetserver/Main.cpp
@@ -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);
diff --git a/src/server/bnetserver/Packets/FriendsPackets.cpp b/src/server/bnetserver/Packets/FriendsPackets.cpp
index 784d6980777..cd920e91c9c 100644
--- a/src/server/bnetserver/Packets/FriendsPackets.cpp
+++ b/src/server/bnetserver/Packets/FriendsPackets.cpp
@@ -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);
}
diff --git a/src/server/bnetserver/Packets/FriendsPackets.h b/src/server/bnetserver/Packets/FriendsPackets.h
index a0ef6f4a63f..ec20f202098 100644
--- a/src/server/bnetserver/Packets/FriendsPackets.h
+++ b/src/server/bnetserver/Packets/FriendsPackets.h
@@ -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)
{
}
diff --git a/src/server/bnetserver/Packets/PacketFactory.h b/src/server/bnetserver/Packets/PacketFactory.h
index 4ae6338cfd7..418e56abea4 100644
--- a/src/server/bnetserver/Packets/PacketFactory.h
+++ b/src/server/bnetserver/Packets/PacketFactory.h
@@ -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>;
diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
index 6845fc914b1..95176963c18 100644
--- a/src/server/bnetserver/Packets/WoWRealmPackets.cpp
+++ b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
@@ -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;
diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.h b/src/server/bnetserver/Packets/WoWRealmPackets.h
index 4ce5ea68835..a27601f7478 100644
--- a/src/server/bnetserver/Packets/WoWRealmPackets.h
+++ b/src/server/bnetserver/Packets/WoWRealmPackets.h
@@ -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
diff --git a/src/server/bnetserver/Realms/RealmList.cpp b/src/server/bnetserver/Realms/RealmList.cpp
index 60d40f98edf..6e2c1e99e56 100644
--- a/src/server/bnetserver/Realms/RealmList.cpp
+++ b/src/server/bnetserver/Realms/RealmList.cpp
@@ -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)
{
- // Create new if not exist or update existed
- Realm& realm = m_realms[name];
-
- realm.m_ID = id;
- realm.name = name;
- realm.icon = icon;
- realm.flag = flag;
- realm.timezone = timezone;
- 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;
+ if (out != in)
+ {
+ out = in;
+ changed = true;
+ }
}
-void RealmList::UpdateIfNeed()
+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)
{
- // maybe disabled or updated recently
- if (!m_UpdateInterval || m_NextUpdateTime > time(NULL))
- return;
-
- m_NextUpdateTime = time(NULL) + m_UpdateInterval;
-
- // Clears Realm list
- m_realms.clear();
-
- // Get the content of the realmlist table in the database
- UpdateRealms();
+ // Create new if not exist or update existed
+ Realm& realm = _realms[id];
+
+ realm.Keep = true;
+ realm.Updated = false;
+
+ 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::UpdateRealms(bool init)
+void RealmList::UpdateRealms(boost::system::error_code const& error)
{
+ if (error)
+ return;
+
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;
diff --git a/src/server/bnetserver/Realms/RealmList.h b/src/server/bnetserver/Realms/RealmList.h
index 502fef80ee7..c7108101056 100644
--- a/src/server/bnetserver/Realms/RealmList.h
+++ b/src/server/bnetserver/Realms/RealmList.h
@@ -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;
};
diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp
index 1d8e0136af3..301a6b9bae1 100644
--- a/src/server/bnetserver/Server/Session.cpp
+++ b/src/server/bnetserver/Server/Session.cpp
@@ -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;
+}
diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h
index 41caadbab3f..7def3c70460 100644
--- a/src/server/bnetserver/Server/Session.h
+++ b/src/server/bnetserver/Server/Session.h
@@ -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;
};
}
diff --git a/src/server/bnetserver/Server/SessionManager.cpp b/src/server/bnetserver/Server/SessionManager.cpp
index d8b6bfca8d1..caa17364038 100644
--- a/src/server/bnetserver/Server/SessionManager.cpp
+++ b/src/server/bnetserver/Server/SessionManager.cpp
@@ -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() });
+}
diff --git a/src/server/bnetserver/Server/SessionManager.h b/src/server/bnetserver/Server/SessionManager.h
index 10e7196e4d8..4f8e0d9fa97 100644
--- a/src/server/bnetserver/Server/SessionManager.h
+++ b/src/server/bnetserver/Server/SessionManager.h
@@ -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;
};
}
diff --git a/src/server/bnetserver/bnetserver.conf.dist b/src/server/bnetserver/bnetserver.conf.dist
index 2ca57cea20c..ac02a06c918 100644
--- a/src/server/bnetserver/bnetserver.conf.dist
+++ b/src/server/bnetserver/bnetserver.conf.dist
@@ -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