mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Realms: Made realmlist threadsafe
This commit is contained in:
@@ -29,10 +29,13 @@
|
||||
#include "RealmList.pb.h"
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/thread/locks.hpp>
|
||||
#include <boost/thread/shared_mutex.hpp>
|
||||
#include <zlib.h>
|
||||
|
||||
RealmList::RealmList() : _updateInterval(0)
|
||||
{
|
||||
_realmsMutex = Trinity::make_unique<boost::shared_mutex>();
|
||||
}
|
||||
|
||||
RealmList::~RealmList()
|
||||
@@ -61,14 +64,11 @@ void RealmList::Close()
|
||||
_updateTimer->cancel();
|
||||
}
|
||||
|
||||
void RealmList::UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
void RealmList::UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel,
|
||||
float population)
|
||||
{
|
||||
// Create new if not exist or update existed
|
||||
Realm& realm = _realms[id];
|
||||
|
||||
realm.Id = id;
|
||||
realm.Build = build;
|
||||
if (realm.Name != name)
|
||||
@@ -101,7 +101,8 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
for (auto const& p : _realms)
|
||||
existingRealms[p.first] = p.second.Name;
|
||||
|
||||
_realms.clear();
|
||||
std::unordered_set<std::string> newSubRegions;
|
||||
RealmMap newRealms;
|
||||
|
||||
// Circle through results and add them to the realm map
|
||||
if (result)
|
||||
@@ -163,10 +164,10 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
|
||||
Battlenet::RealmHandle id{ region, battlegroup, realmId };
|
||||
|
||||
UpdateRealm(id, build, name, externalAddress, localAddress, localSubmask, port, icon, flag,
|
||||
timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
UpdateRealm(newRealms[id], id, build, name, externalAddress, localAddress, localSubmask, port, icon,
|
||||
flag, timezone, (allowedSecurityLevel <= SEC_ADMINISTRATOR ? AccountTypes(allowedSecurityLevel) : SEC_ADMINISTRATOR), pop);
|
||||
|
||||
_subRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString());
|
||||
newSubRegions.insert(Battlenet::RealmHandle{ region, battlegroup, 0 }.GetAddressString());
|
||||
|
||||
if (!existingRealms.count(id))
|
||||
TC_LOG_INFO("realmlist", "Added realm \"%s\" at %s:%u.", name.c_str(), externalAddress.to_string().c_str(), port);
|
||||
@@ -187,6 +188,13 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
for (auto itr = existingRealms.begin(); itr != existingRealms.end(); ++itr)
|
||||
TC_LOG_INFO("realmlist", "Removed realm \"%s\".", itr->second.c_str());
|
||||
|
||||
{
|
||||
std::unique_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
|
||||
_subRegions.swap(newSubRegions);
|
||||
_realms.swap(newRealms);
|
||||
}
|
||||
|
||||
if (_updateInterval)
|
||||
{
|
||||
_updateTimer->expires_from_now(boost::posix_time::seconds(_updateInterval));
|
||||
@@ -196,6 +204,7 @@ void RealmList::UpdateRealms(boost::system::error_code const& error)
|
||||
|
||||
Realm const* RealmList::GetRealm(Battlenet::RealmHandle const& id) const
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
auto itr = _realms.find(id);
|
||||
if (itr != _realms.end())
|
||||
return &itr->second;
|
||||
@@ -237,13 +246,15 @@ RealmBuildInfo const* RealmList::GetBuildInfo(uint32 build) const
|
||||
|
||||
void RealmList::WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const
|
||||
{
|
||||
for (std::string const& subRegion : GetSubRegions())
|
||||
boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
for (std::string const& subRegion : _subRegions)
|
||||
response->add_attribute_value()->set_string_value(subRegion);
|
||||
}
|
||||
|
||||
std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const
|
||||
{
|
||||
std::vector<uint8> compressed;
|
||||
boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
if (Realm const* realm = GetRealm(id))
|
||||
{
|
||||
if (!(realm->Flags & REALM_FLAG_OFFLINE) && realm->Build == build)
|
||||
@@ -276,6 +287,8 @@ std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id
|
||||
realmEntry.set_cfgconfigsid(realm->GetConfigId());
|
||||
realmEntry.set_cfglanguagesid(1);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
std::string json = "JamJSONRealmEntry:" + JSON::Serialize(realmEntry);
|
||||
|
||||
uLong compressedLength = compressBound(uLong(json.length()));
|
||||
@@ -295,44 +308,47 @@ std::vector<uint8> RealmList::GetRealmEntryJSON(Battlenet::RealmHandle const& id
|
||||
std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subRegion) const
|
||||
{
|
||||
JSON::RealmList::RealmListUpdates realmList;
|
||||
for (auto const& realm : _realms)
|
||||
{
|
||||
if (realm.second.Id.GetSubRegionAddress() != subRegion)
|
||||
continue;
|
||||
|
||||
uint32 flag = realm.second.Flags;
|
||||
if (realm.second.Build != build)
|
||||
flag |= REALM_FLAG_VERSION_MISMATCH;
|
||||
|
||||
JSON::RealmList::RealmState* state = realmList.add_updates();
|
||||
state->mutable_update()->set_wowrealmaddress(realm.second.Id.GetAddress());
|
||||
state->mutable_update()->set_cfgtimezonesid(1);
|
||||
state->mutable_update()->set_populationstate((realm.second.Flags & REALM_FLAG_OFFLINE) ? 0u : std::max(uint32(realm.second.PopulationLevel), 1u));
|
||||
state->mutable_update()->set_cfgcategoriesid(realm.second.Timezone);
|
||||
|
||||
JSON::RealmList::ClientVersion* version = state->mutable_update()->mutable_version();
|
||||
if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm.second.Build))
|
||||
boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
for (auto const& realm : _realms)
|
||||
{
|
||||
version->set_versionmajor(buildInfo->MajorVersion);
|
||||
version->set_versionminor(buildInfo->MinorVersion);
|
||||
version->set_versionrevision(buildInfo->BugfixVersion);
|
||||
version->set_versionbuild(buildInfo->Build);
|
||||
}
|
||||
else
|
||||
{
|
||||
version->set_versionmajor(6);
|
||||
version->set_versionminor(2);
|
||||
version->set_versionrevision(4);
|
||||
version->set_versionbuild(realm.second.Build);
|
||||
}
|
||||
if (realm.second.Id.GetSubRegionAddress() != subRegion)
|
||||
continue;
|
||||
|
||||
state->mutable_update()->set_cfgrealmsid(realm.second.Id.Realm);
|
||||
state->mutable_update()->set_flags(flag);
|
||||
state->mutable_update()->set_name(realm.second.Name);
|
||||
state->mutable_update()->set_cfgconfigsid(realm.second.GetConfigId());
|
||||
state->mutable_update()->set_cfglanguagesid(1);
|
||||
uint32 flag = realm.second.Flags;
|
||||
if (realm.second.Build != build)
|
||||
flag |= REALM_FLAG_VERSION_MISMATCH;
|
||||
|
||||
state->set_deleting(false);
|
||||
JSON::RealmList::RealmState* state = realmList.add_updates();
|
||||
state->mutable_update()->set_wowrealmaddress(realm.second.Id.GetAddress());
|
||||
state->mutable_update()->set_cfgtimezonesid(1);
|
||||
state->mutable_update()->set_populationstate((realm.second.Flags & REALM_FLAG_OFFLINE) ? 0u : std::max(uint32(realm.second.PopulationLevel), 1u));
|
||||
state->mutable_update()->set_cfgcategoriesid(realm.second.Timezone);
|
||||
|
||||
JSON::RealmList::ClientVersion* version = state->mutable_update()->mutable_version();
|
||||
if (RealmBuildInfo const* buildInfo = GetBuildInfo(realm.second.Build))
|
||||
{
|
||||
version->set_versionmajor(buildInfo->MajorVersion);
|
||||
version->set_versionminor(buildInfo->MinorVersion);
|
||||
version->set_versionrevision(buildInfo->BugfixVersion);
|
||||
version->set_versionbuild(buildInfo->Build);
|
||||
}
|
||||
else
|
||||
{
|
||||
version->set_versionmajor(6);
|
||||
version->set_versionminor(2);
|
||||
version->set_versionrevision(4);
|
||||
version->set_versionbuild(realm.second.Build);
|
||||
}
|
||||
|
||||
state->mutable_update()->set_cfgrealmsid(realm.second.Id.Realm);
|
||||
state->mutable_update()->set_flags(flag);
|
||||
state->mutable_update()->set_name(realm.second.Name);
|
||||
state->mutable_update()->set_cfgconfigsid(realm.second.GetConfigId());
|
||||
state->mutable_update()->set_cfglanguagesid(1);
|
||||
|
||||
state->set_deleting(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::string json = "JSONRealmListUpdates:" + JSON::Serialize(realmList);
|
||||
@@ -352,6 +368,7 @@ std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subR
|
||||
uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret,
|
||||
LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const
|
||||
{
|
||||
boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
|
||||
if (Realm const* realm = GetRealm(Battlenet::RealmHandle(realmAddress)))
|
||||
{
|
||||
if (realm->Flags & REALM_FLAG_OFFLINE || realm->Build != build)
|
||||
@@ -365,6 +382,8 @@ uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::
|
||||
address->set_ip(realm->GetAddressForClient(clientAddress).to_string());
|
||||
address->set_port(realm->Port);
|
||||
|
||||
lock.unlock();
|
||||
|
||||
std::string json = "JSONRealmListServerIPAddresses:" + JSON::Serialize(serverAddresses);
|
||||
|
||||
uLong compressedLength = compressBound(uLong(json.length()));
|
||||
|
||||
@@ -36,6 +36,8 @@ struct RealmBuildInfo
|
||||
|
||||
namespace boost
|
||||
{
|
||||
class shared_mutex;
|
||||
|
||||
namespace asio
|
||||
{
|
||||
class io_service;
|
||||
@@ -83,11 +85,9 @@ public:
|
||||
void Initialize(boost::asio::io_service& ioService, uint32 updateInterval);
|
||||
void Close();
|
||||
|
||||
RealmMap const& GetRealms() const { return _realms; }
|
||||
Realm const* GetRealm(Battlenet::RealmHandle const& id) const;
|
||||
|
||||
RealmBuildInfo const* GetBuildInfo(uint32 build) const;
|
||||
std::unordered_set<std::string> const& GetSubRegions() const { return _subRegions; }
|
||||
void WriteSubRegions(bgs::protocol::game_utilities::v1::GetAllValuesForAttributeResponse* response) const;
|
||||
std::vector<uint8> GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const;
|
||||
std::vector<uint8> GetRealmList(uint32 build, std::string const& subRegion) const;
|
||||
@@ -98,10 +98,11 @@ private:
|
||||
RealmList();
|
||||
|
||||
void UpdateRealms(boost::system::error_code const& error);
|
||||
void UpdateRealm(Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
void UpdateRealm(Realm& realm, Battlenet::RealmHandle const& id, uint32 build, std::string const& name,
|
||||
boost::asio::ip::address const& address, boost::asio::ip::address const& localAddr, boost::asio::ip::address const& localSubmask,
|
||||
uint16 port, uint8 icon, RealmFlags flag, uint8 timezone, AccountTypes allowedSecurityLevel, float population);
|
||||
|
||||
std::unique_ptr<boost::shared_mutex> _realmsMutex;
|
||||
RealmMap _realms;
|
||||
std::unordered_set<std::string> _subRegions;
|
||||
uint32 _updateInterval;
|
||||
|
||||
Reference in New Issue
Block a user