aboutsummaryrefslogtreecommitdiff
path: root/src/server
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2020-07-30 17:41:20 +0200
committerShauren <shauren.trinity@gmail.com>2022-01-24 13:38:40 +0100
commit54a6e603ffc8b4913669cf0f189a966d25b620d8 (patch)
tree3b0f83d7e12a899113715cb018c4c2b9315141ed /src/server
parent1977d26050d1b0c6f2d21fe3316147ae0df9fc64 (diff)
Core/Misc: Replace database query in WorldSession::HandleAddFriendOpcode with async version
(cherry picked from commit 2f0893d279ddab86ae7c3e4fd1d7a47b15e938f7)
Diffstat (limited to 'src/server')
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp3
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h1
-rw-r--r--src/server/game/Accounts/AccountMgr.cpp16
-rw-r--r--src/server/game/Accounts/AccountMgr.h2
-rw-r--r--src/server/game/Entities/Player/SocialMgr.cpp2
-rw-r--r--src/server/game/Entities/Player/SocialMgr.h2
-rw-r--r--src/server/game/Handlers/SocialHandler.cpp93
-rw-r--r--src/server/worldserver/TCSoap/TCSoap.cpp3
8 files changed, 80 insertions, 42 deletions
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index b26b4565bad..199c298576a 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -77,8 +77,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM, "DELETE FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_INS_ACCOUNT_ACCESS, "INSERT INTO account_access (AccountID, SecurityLevel, RealmID) VALUES (?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_GET_ACCOUNT_ID_BY_USERNAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL, "SELECT SecurityLevel FROM account_access WHERE AccountID = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1)", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_GET_GMLEVEL_BY_REALMID, "SELECT SecurityLevel FROM account_access WHERE AccountID = ? AND (RealmID = ? OR RealmID = -1) ORDER BY RealmID DESC", CONNECTION_BOTH);
PrepareStatement(LOGIN_GET_USERNAME_BY_ID, "SELECT username FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD, "SELECT salt, verifier FROM account WHERE id = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_CHECK_PASSWORD_BY_NAME, "SELECT salt, verifier FROM account WHERE username = ? AND salt IS NOT NULL AND verifier IS NOT NULL", CONNECTION_SYNCH);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index 1f0d9ff6e52..e83675bd394 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -77,7 +77,6 @@ enum LoginDatabaseStatements : uint32
LOGIN_DEL_ACCOUNT_ACCESS_BY_REALM,
LOGIN_INS_ACCOUNT_ACCESS,
LOGIN_GET_ACCOUNT_ID_BY_USERNAME,
- LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL,
LOGIN_GET_GMLEVEL_BY_REALMID,
LOGIN_GET_USERNAME_BY_ID,
LOGIN_SEL_CHECK_PASSWORD,
diff --git a/src/server/game/Accounts/AccountMgr.cpp b/src/server/game/Accounts/AccountMgr.cpp
index 7fc2a303926..2875a08179c 100644
--- a/src/server/game/Accounts/AccountMgr.cpp
+++ b/src/server/game/Accounts/AccountMgr.cpp
@@ -314,23 +314,25 @@ uint32 AccountMgr::GetId(std::string const& username)
return (result) ? (*result)[0].GetUInt32() : 0;
}
-uint32 AccountMgr::GetSecurity(uint32 accountId)
+uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId)
{
- LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_ACCOUNT_ACCESS_GMLEVEL);
+ LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
stmt->setUInt32(0, accountId);
+ stmt->setInt32(1, realmId);
PreparedQueryResult result = LoginDatabase.Query(stmt);
return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
}
-uint32 AccountMgr::GetSecurity(uint32 accountId, int32 realmId)
+QueryCallback AccountMgr::GetSecurityAsync(uint32 accountId, int32 realmId, std::function<void(uint32)> callback)
{
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_GET_GMLEVEL_BY_REALMID);
stmt->setUInt32(0, accountId);
stmt->setInt32(1, realmId);
- PreparedQueryResult result = LoginDatabase.Query(stmt);
-
- return (result) ? (*result)[0].GetUInt8() : uint32(SEC_PLAYER);
+ return LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([callback = std::move(callback)](PreparedQueryResult result)
+ {
+ callback(result ? uint32((*result)[0].GetUInt8()) : uint32(SEC_PLAYER));
+ });
}
bool AccountMgr::GetName(uint32 accountId, std::string& name)
@@ -580,7 +582,7 @@ bool AccountMgr::HasPermission(uint32 accountId, uint32 permissionId, uint32 rea
return false;
}
- rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId));
+ rbac::RBACData rbac(accountId, "", realmId, GetSecurity(accountId, realmId));
rbac.LoadFromDB();
bool hasPermission = rbac.HasPermission(permissionId);
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index 45d8b8cf7ee..41a1948fdd4 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -68,8 +68,8 @@ class TC_GAME_API AccountMgr
static bool CheckEmail(uint32 accountId, std::string newEmail);
static uint32 GetId(std::string const& username);
- static uint32 GetSecurity(uint32 accountId);
static uint32 GetSecurity(uint32 accountId, int32 realmId);
+ [[nodiscard]] static QueryCallback GetSecurityAsync(uint32 accountId, int32 realmId, std::function<void(uint32)> callback);
static bool GetName(uint32 accountId, std::string& name);
static bool GetEmail(uint32 accountId, std::string& email);
static uint32 GetCharactersCount(uint32 accountId);
diff --git a/src/server/game/Entities/Player/SocialMgr.cpp b/src/server/game/Entities/Player/SocialMgr.cpp
index ecf60f20302..b00b3a2c9c5 100644
--- a/src/server/game/Entities/Player/SocialMgr.cpp
+++ b/src/server/game/Entities/Player/SocialMgr.cpp
@@ -164,7 +164,7 @@ void PlayerSocial::SendSocialList(Player* player, uint32 flags)
if (++ignoredCount > SOCIALMGR_IGNORE_LIMIT)
continue;
- sSocialMgr->GetFriendInfo(player, v.first, v.second);
+ SocialMgr::GetFriendInfo(player, v.first, v.second);
contactList.Contacts.emplace_back(v.first, v.second);
}
diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h
index af8590d07aa..f2db116aae7 100644
--- a/src/server/game/Entities/Player/SocialMgr.h
+++ b/src/server/game/Entities/Player/SocialMgr.h
@@ -144,7 +144,7 @@ class SocialMgr
// Misc
void RemovePlayerSocial(ObjectGuid const& guid) { _socialMap.erase(guid); }
- void GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo);
+ static void GetFriendInfo(Player* player, ObjectGuid const& friendGUID, FriendInfo& friendInfo);
// Packet send's
void SendFriendStatus(Player* player, FriendsResult result, ObjectGuid const& friendGuid, bool broadcast = false);
diff --git a/src/server/game/Handlers/SocialHandler.cpp b/src/server/game/Handlers/SocialHandler.cpp
index 98fddfb491f..e84c64ab1f0 100644
--- a/src/server/game/Handlers/SocialHandler.cpp
+++ b/src/server/game/Handlers/SocialHandler.cpp
@@ -23,6 +23,7 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "QueryCallback.h"
#include "RBAC.h"
#include "Realm.h"
#include "SocialMgr.h"
@@ -43,41 +44,77 @@ void WorldSession::HandleAddFriendOpcode(WorldPackets::Social::AddFriend& packet
TC_LOG_DEBUG("network", "WorldSession::HandleAddFriendOpcode: %s asked to add friend: %s",
GetPlayerInfo().c_str(), packet.Name.c_str());
- FriendsResult friendResult = FRIEND_NOT_FOUND;
- ObjectGuid friendGuid;
-
- if (CharacterCacheEntry const* characterInfo = sCharacterCache->GetCharacterCacheByName(packet.Name))
+ CharacterCacheEntry const* friendCharacterInfo = sCharacterCache->GetCharacterCacheByName(packet.Name);
+ if (!friendCharacterInfo)
{
- friendGuid = characterInfo->Guid;
- ObjectGuid friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(characterInfo->AccountId);
- uint32 team = Player::TeamForRace(characterInfo->Race);
- uint32 friendAccountId = characterInfo->AccountId;
+ sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty);
+ return;
+ }
- if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND) || AccountMgr::IsPlayerAccount(AccountMgr::GetSecurity(friendAccountId, realm.Id.Realm)))
+ auto processFriendRequest = [this,
+ playerGuid = _player->GetGUID(),
+ friendGuid = friendCharacterInfo->Guid,
+ friendAccountGuid = ObjectGuid::Create<HighGuid::WowAccount>(friendCharacterInfo->AccountId),
+ team = Player::TeamForRace(friendCharacterInfo->Race),
+ friendNote = std::move(packet.Notes)]()
+ {
+ if (playerGuid.GetCounter() != m_GUIDLow)
+ return; // not the player initiating request, do nothing
+
+ FriendsResult friendResult = FRIEND_NOT_FOUND;
+ if (friendGuid == GetPlayer()->GetGUID())
+ friendResult = FRIEND_SELF;
+ else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
+ friendResult = FRIEND_ENEMY;
+ else if (GetPlayer()->GetSocial()->HasFriend(friendGuid))
+ friendResult = FRIEND_ALREADY;
+ else
{
- if (friendGuid == GetPlayer()->GetGUID())
- friendResult = FRIEND_SELF;
- else if (GetPlayer()->GetTeam() != team && !HasPermission(rbac::RBAC_PERM_TWO_SIDE_ADD_FRIEND))
- friendResult = FRIEND_ENEMY;
- else if (GetPlayer()->GetSocial()->HasFriend(friendGuid))
- friendResult = FRIEND_ALREADY;
+ Player* pFriend = ObjectAccessor::FindPlayer(friendGuid);
+ if (pFriend && pFriend->IsVisibleGloballyFor(GetPlayer()))
+ friendResult = FRIEND_ADDED_ONLINE;
else
- {
- Player* playerFriend = ObjectAccessor::FindPlayer(friendGuid);
- if (playerFriend && playerFriend->IsVisibleGloballyFor(GetPlayer()))
- friendResult = FRIEND_ADDED_ONLINE;
- else
- friendResult = FRIEND_ADDED_OFFLINE;
-
- if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, friendAccountGuid, SOCIAL_FLAG_FRIEND))
- GetPlayer()->GetSocial()->SetFriendNote(friendGuid, packet.Notes);
- else
- friendResult = FRIEND_LIST_FULL;
- }
+ friendResult = FRIEND_ADDED_OFFLINE;
+ if (GetPlayer()->GetSocial()->AddToSocialList(friendGuid, friendAccountGuid, SOCIAL_FLAG_FRIEND))
+ GetPlayer()->GetSocial()->SetFriendNote(friendGuid, friendNote);
+ else
+ friendResult = FRIEND_LIST_FULL;
+ }
+
+ sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid);
+ };
+
+ if (HasPermission(rbac::RBAC_PERM_ALLOW_GM_FRIEND))
+ {
+ processFriendRequest();
+ return;
+ }
+
+ // First try looking up friend candidate security from online object
+ if (Player* friendPlayer = ObjectAccessor::FindPlayer(friendCharacterInfo->Guid))
+ {
+ if (!AccountMgr::IsPlayerAccount(friendPlayer->GetSession()->GetSecurity()))
+ {
+ sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty);
+ return;
}
+
+ processFriendRequest();
+ return;
}
- sSocialMgr->SendFriendStatus(GetPlayer(), friendResult, friendGuid);
+ // When not found, consult database
+ GetQueryProcessor().AddCallback(AccountMgr::GetSecurityAsync(friendCharacterInfo->AccountId, realm.Id.Realm,
+ [this, continuation = std::move(processFriendRequest)](uint32 friendSecurity)
+ {
+ if (!AccountMgr::IsPlayerAccount(friendSecurity))
+ {
+ sSocialMgr->SendFriendStatus(GetPlayer(), FRIEND_NOT_FOUND, ObjectGuid::Empty);
+ return;
+ }
+
+ continuation();
+ }));
}
void WorldSession::HandleDelFriendOpcode(WorldPackets::Social::DelFriend& packet)
diff --git a/src/server/worldserver/TCSoap/TCSoap.cpp b/src/server/worldserver/TCSoap/TCSoap.cpp
index 996e9d5e82e..868c649e0e8 100644
--- a/src/server/worldserver/TCSoap/TCSoap.cpp
+++ b/src/server/worldserver/TCSoap/TCSoap.cpp
@@ -18,6 +18,7 @@
#include "TCSoap.h"
#include "soapH.h"
#include "soapStub.h"
+#include "Realm.h"
#include "World.h"
#include "AccountMgr.h"
#include "Log.h"
@@ -95,7 +96,7 @@ int ns1__executeCommand(soap* soap, char* command, char** result)
return 401;
}
- if (AccountMgr::GetSecurity(accountId) < SEC_ADMINISTRATOR)
+ if (AccountMgr::GetSecurity(accountId, realm.Id.Realm) < SEC_ADMINISTRATOR)
{
TC_LOG_INFO("network.soap", "%s's gmlevel is too low", soap->userid);
return 403;