aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/shared/Realm/RealmList.cpp101
-rw-r--r--src/server/shared/Realm/RealmList.h7
2 files changed, 64 insertions, 44 deletions
diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp
index 66346614278..2135c1f26b8 100644
--- a/src/server/shared/Realm/RealmList.cpp
+++ b/src/server/shared/Realm/RealmList.cpp
@@ -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;
+ boost::shared_lock<boost::shared_mutex> lock(*_realmsMutex);
+ 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;
+ 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::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);
- }
+ 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->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);
+ 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()));
diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h
index 50609a6a900..855cc4fc428 100644
--- a/src/server/shared/Realm/RealmList.h
+++ b/src/server/shared/Realm/RealmList.h
@@ -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;