aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2020-08-26 21:30:38 +0200
committerGitHub <noreply@github.com>2020-08-26 21:30:38 +0200
commit7cc027401e4a2837872db54c835a4ed1a98e4a03 (patch)
treee997cf8a91c7c500ca3aad7336577d10dba61cbf /src
parentf59d6c1306c2a2e3548ca5a9b48cb60996fab581 (diff)
Core/Warden: Ensure Warden packets do not exceed 512 bytes. This should rectify random Warden timeouts.
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Warden/WardenWin.cpp103
1 files changed, 77 insertions, 26 deletions
diff --git a/src/server/game/Warden/WardenWin.cpp b/src/server/game/Warden/WardenWin.cpp
index 41ba180d381..fccf8ecaaff 100644
--- a/src/server/game/Warden/WardenWin.cpp
+++ b/src/server/game/Warden/WardenWin.cpp
@@ -186,11 +186,36 @@ void WardenWin::HandleHashResult(ByteBuffer &buff)
_initialized = true;
}
+static constexpr uint8 GetCheckPacketBaseSize(WardenCheckType type)
+{
+ switch (type)
+ {
+ case DRIVER_CHECK: return 1;
+ case LUA_EVAL_CHECK: return 1 + sizeof(_luaEvalPrefix)-1 + sizeof(_luaEvalMidfix)-1 + 4 + sizeof(_luaEvalPostfix)-1;
+ case MPQ_CHECK: return 1;
+ case PAGE_CHECK_A: return (4 + 1);
+ case PAGE_CHECK_B: return (4 + 1);
+ case MODULE_CHECK: return (4 + Trinity::Crypto::HMAC_SHA1::DIGEST_LENGTH);
+ case MEM_CHECK: return (1 + 4 + 1);
+ default: return 0;
+ }
+}
+
+static uint16 GetCheckPacketSize(WardenCheck const& check)
+{
+ uint16 size = 1 + GetCheckPacketBaseSize(check.Type); // 1 byte check type
+ if (!check.Str.empty())
+ size += (check.Str.length() + 1); // 1 byte string length
+ if (!check.Data.empty())
+ size += check.Data.size();
+ return size;
+}
+
void WardenWin::RequestChecks()
{
- TC_LOG_DEBUG("warden", "Request data");
+ TC_LOG_DEBUG("warden", "Request data from %s (account %u) - loaded: %u", _session->GetPlayerName().c_str(), _session->GetAccountId(), _session->GetPlayer() && !_session->PlayerLoading());
- // If all checks were done, fill the todo list again
+ // If all checks for a category are done, fill its todo list again
for (WardenCheckCategory category : EnumUtils::Iterate<WardenCheckCategory>())
{
auto& [checks, checksIt] = _checks[category];
@@ -216,26 +241,40 @@ void WardenWin::RequestChecks()
{
if (checksIt == checks.end()) // all checks were already sent, list will be re-filled on next Update() run
break;
+ _currentChecks.push_back(*(checksIt++));
+ }
+ }
- uint16 const id = *(checksIt++);
+ Trinity::Containers::RandomShuffle(_currentChecks);
- WardenCheck const& check = sWardenCheckMgr->GetCheckData(id);
- if (check.Type == LUA_EVAL_CHECK)
- {
- buff << uint8(sizeof(_luaEvalPrefix)-1 + check.Str.size() + sizeof(_luaEvalMidfix)-1 + check.IdStr.size() + sizeof(_luaEvalPostfix)-1);
- buff.append(_luaEvalPrefix, sizeof(_luaEvalPrefix)-1);
- buff.append(check.Str.data(), check.Str.size());
- buff.append(_luaEvalMidfix, sizeof(_luaEvalMidfix)-1);
- buff.append(check.IdStr.data(), check.IdStr.size());
- buff.append(_luaEvalPostfix, sizeof(_luaEvalPostfix)-1);
- }
- else if (!check.Str.empty())
- {
- buff << uint8(check.Str.size());
- buff.append(check.Str.data(), check.Str.size());
- }
+ uint16 expectedSize = 4;
+ Trinity::Containers::EraseIf(_currentChecks,
+ [&expectedSize](uint16 id)
+ {
+ uint8 const thisSize = GetCheckPacketSize(sWardenCheckMgr->GetCheckData(id));
+ if ((expectedSize + thisSize) > 512) // warden packets are truncated to 512 bytes clientside
+ return true;
+ expectedSize += thisSize;
+ return false;
+ }
+ );
- _currentChecks.push_back(id);
+ for (uint16 const id : _currentChecks)
+ {
+ WardenCheck const& check = sWardenCheckMgr->GetCheckData(id);
+ if (check.Type == LUA_EVAL_CHECK)
+ {
+ buff << uint8(sizeof(_luaEvalPrefix) - 1 + check.Str.size() + sizeof(_luaEvalMidfix) - 1 + check.IdStr.size() + sizeof(_luaEvalPostfix) - 1);
+ buff.append(_luaEvalPrefix, sizeof(_luaEvalPrefix) - 1);
+ buff.append(check.Str.data(), check.Str.size());
+ buff.append(_luaEvalMidfix, sizeof(_luaEvalMidfix) - 1);
+ buff.append(check.IdStr.data(), check.IdStr.size());
+ buff.append(_luaEvalPostfix, sizeof(_luaEvalPostfix) - 1);
+ }
+ else if (!check.Str.empty())
+ {
+ buff << uint8(check.Str.size());
+ buff.append(check.Str.data(), check.Str.size());
}
}
@@ -305,6 +344,25 @@ void WardenWin::RequestChecks()
buff << uint8(xorByte);
buff.hexlike();
+ auto idstring = [this]() -> std::string
+ {
+ std::stringstream stream;
+ for (uint16 const id : _currentChecks)
+ stream << id << " ";
+ return stream.str();
+ };
+
+ if (buff.size() == expectedSize)
+ {
+ TC_LOG_DEBUG("warden", "Finished building warden packet, size is %zu bytes", buff.size());
+ TC_LOG_DEBUG("warden", "Sent checks: %s", idstring().c_str());
+ }
+ else
+ {
+ TC_LOG_WARN("warden", "Finished building warden packet, size is %zu bytes, but expected %u bytes!", buff.size(), expectedSize);
+ TC_LOG_WARN("warden", "Sent checks: %s", idstring().c_str());
+ }
+
// Encrypt with warden RC4 key
EncryptData(buff.contents(), buff.size());
@@ -313,13 +371,6 @@ void WardenWin::RequestChecks()
_session->SendPacket(&pkt);
_dataSent = true;
-
- std::stringstream stream;
- stream << "Sent check id's: ";
- for (uint16 const id : _currentChecks)
- stream << id << " ";
-
- TC_LOG_DEBUG("warden", "%s", stream.str().c_str());
}
void WardenWin::HandleCheckResult(ByteBuffer &buff)