Core/Warden: Ensure Warden packets do not exceed 512 bytes. This should rectify random Warden timeouts.

(cherry picked from commit 7cc027401e)
This commit is contained in:
Treeston
2020-08-26 21:30:38 +02:00
committed by Shauren
parent e419d7536a
commit 7b88fd607e

View File

@@ -187,11 +187,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];
@@ -217,26 +242,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());
}
}
@@ -306,6 +345,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());
@@ -314,13 +372,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)