[Warden] Refactor to match other cores

This commit is contained in:
Antz 2020-01-09 22:33:56 +00:00 committed by Antz
parent 5e1e9ae18a
commit 377686f881
9 changed files with 262 additions and 245 deletions

View file

@ -4001,7 +4001,7 @@ void ObjectMgr::LoadQuests()
// 80 81 82 83
"`ReqCurrencyCount1`, `ReqCurrencyCount1`, `ReqCurrencyCount1`, `ReqCurrencyCount1`,"
// 84 85 86 87 88
"`ReqSpellCast1`, `ReqSpellCast2`, `ReqSpellCast3`, `ReqSpellCast4`, `ReqSpellLearnedv`,"
"`ReqSpellCast1`, `ReqSpellCast2`, `ReqSpellCast3`, `ReqSpellCast4`, `ReqSpellLearned`,"
// 89 90 91 92 93 94
"`RewChoiceItemId1`, `RewChoiceItemId2`, `RewChoiceItemId3`, `RewChoiceItemId4`, `RewChoiceItemId5`, `RewChoiceItemId6`,"
// 95 96 97 98 99 100

View file

@ -841,21 +841,30 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
// NOTE: ATM the socket is singlethread, have this in mind ...
uint8 digest[20];
uint16 clientBuild, security;
uint32 id, m_addonSize, clientSeed, expansion;
std::string accountName;
uint32 clientSeed, id, security;
uint32 m_addonSize;
uint16 BuiltNumberClient;
uint8 expansion = 0;
LocaleConstant locale;
std::string account;
Sha1Hash sha1;
BigNumber v, s, g, N, K;
std::string os;
WorldPacket packet;
bool wardenActive = (sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) || sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED));
// Read the content of the packet
recvPacket.read_skip<uint32>();
recvPacket.read_skip<uint32>();
recvPacket >> digest[18];
recvPacket >> digest[14];
recvPacket >> digest[3];
recvPacket >> digest[4];
recvPacket >> BuiltNumberClient;
recvPacket >> digest[8];
recvPacket.read_skip<uint32>();
recvPacket.read_skip<uint8>();
recvPacket >> digest[17];
recvPacket >> digest[6];
recvPacket >> digest[0];
recvPacket.read_skip<uint32>();
recvPacket >> digest[11];
@ -886,15 +895,21 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
addonsData.resize(m_addonSize);
recvPacket.read((uint8*)addonsData.contents(), m_addonSize);
accountName = recvPacket.ReadString(recvPacket.ReadBits(11));
uint8 nameLenLow, nameLenHigh;
recvPacket >> nameLenHigh;
recvPacket >> nameLenLow;
uint8 accNameLen = (nameLenHigh << 5) | (nameLenLow >> 3);
account = recvPacket.ReadString(accNameLen);
DEBUG_LOG("WorldSocket::HandleAuthSession: client build %u, account %s, clientseed %X",
clientBuild,
accountName.c_str(),
clientSeed);
BuiltNumberClient,
account.c_str(),
clientSeed);
// Check the version of client trying to connect
if(!IsAcceptableClientBuild(clientBuild))
if (!IsAcceptableClientBuild(BuiltNumberClient))
{
SendAuthResponseError(AUTH_VERSION_MISMATCH);
sLog.outError ("WorldSocket::HandleAuthSession: Sent Auth Response (version mismatch).");
@ -902,7 +917,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
}
// Get the account information from the realmd database
std::string safe_account = accountName; // Duplicate, else will screw the SHA hash verification below
std::string safe_account = account; // Duplicate, else will screw the SHA hash verification below
LoginDatabase.escape_string (safe_account);
// No SQL injection, username escaped.
@ -917,7 +932,8 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
"`s`, " // 6
"`expansion`, " // 7
"`mutetime`, " // 8
"`locale` " // 9
"`locale`, " // 9
"`os` " // 10
"FROM `account` "
"WHERE `username` = '%s'",
safe_account.c_str());
@ -1017,7 +1033,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 t = 0;
uint32 seed = m_Seed;
sha.UpdateData (accountName);
sha.UpdateData (account);
sha.UpdateData((uint8*) & t, 4);
sha.UpdateData((uint8*) & clientSeed, 4);
sha.UpdateData((uint8*) & seed, 4);
@ -1042,7 +1058,7 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
static SqlStatementID updAccount;
SqlStatement stmt = LoginDatabase.CreateStatement(updAccount, "UPDATE `account` SET `last_ip` = ? WHERE `username` = ?");
stmt.PExecute(address.c_str(), accountName.c_str());
stmt.PExecute(address.c_str(), account.c_str());
// NOTE ATM the socket is single-threaded, have this in mind ...
ACE_NEW_RETURN(m_Session, WorldSession(id, this, AccountTypes(security), expansion, mutetime, locale), -1);
@ -1054,7 +1070,11 @@ int WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
m_Session->ReadAddonsInfo(addonsData);
// In case needed sometime the second arg is in microseconds 1 000 000 = 1 sec
ACE_OS::sleep (ACE_Time_Value (0, 10000));
ACE_OS::sleep(ACE_Time_Value(0, 10000));
// Warden: Initialize Warden system only if it is enabled by config
if (wardenActive)
m_Session->InitWarden(uint16(BuiltNumberClient), &K, os);
sWorld.AddSession(m_Session);

View file

@ -36,11 +36,12 @@
#include "AccountMgr.h"
Warden::Warden() : _session(NULL), _inputCrypto(16), _outputCrypto(16), _checkTimer(10000/*10 sec*/), _clientResponseTimer(0),
_dataSent(false), _previousTimestamp(0), _module(NULL), _initialized(false)
_module(NULL), _state(WardenState::STATE_INITIAL)
{
memset(_inputKey, 0, sizeof(_inputKey));
memset(_outputKey, 0, sizeof(_outputKey));
memset(_seed, 0, sizeof(_seed));
_previousTimestamp = WorldTimer::getMSTime();
}
Warden::~Warden()
@ -48,7 +49,11 @@ Warden::~Warden()
delete[] _module->CompressedData;
delete _module;
_module = NULL;
_initialized = false;
}
void Warden::InitializeModule()
{
SetNewState(WardenState::STATE_INITIALIZE_MODULE);
}
void Warden::RequestHash()
@ -66,6 +71,8 @@ void Warden::RequestHash()
WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenHashRequest));
pkt.append((uint8*)&Request, sizeof(WardenHashRequest));
_session->SendPacket(&pkt);
SetNewState(WardenState::STATE_REQUESTED_HASH);
}
void Warden::SendModuleToClient()
@ -92,6 +99,8 @@ void Warden::SendModuleToClient()
pkt1.append((uint8*)&packet, burstSize + 3);
_session->SendPacket(&pkt1);
}
SetNewState(WardenState::STATE_SENT_MODULE);
}
void Warden::RequestModule()
@ -112,17 +121,24 @@ void Warden::RequestModule()
WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenModuleUse));
pkt.append((uint8*)&request, sizeof(WardenModuleUse));
_session->SendPacket(&pkt);
SetNewState(WardenState::STATE_REQUESTED_MODULE);
}
void Warden::Update()
{
if (_initialized)
{
uint32 currentTimestamp = WorldTimer::getMSTime();
uint32 diff = currentTimestamp - _previousTimestamp;
_previousTimestamp = currentTimestamp;
uint32 currentTimestamp = WorldTimer::getMSTime();
uint32 diff = currentTimestamp - _previousTimestamp;
_previousTimestamp = currentTimestamp;
if (_dataSent)
switch (_state)
{
case WardenState::STATE_INITIAL:
break;
case WardenState::STATE_REQUESTED_MODULE:
case WardenState::STATE_SENT_MODULE:
case WardenState::STATE_REQUESTED_HASH:
case WardenState::STATE_REQUESTED_DATA:
{
uint32 maxClientResponseDelay = sWorld.getConfig(CONFIG_UINT32_WARDEN_CLIENT_RESPONSE_DELAY);
@ -131,23 +147,34 @@ void Warden::Update()
// Kick player if client response delays more than set in config
if (_clientResponseTimer > maxClientResponseDelay * IN_MILLISECONDS)
{
sLog.outWarden("%s (latency: %u, IP: %s) exceeded Warden module response delay for more than %s - disconnecting client",
_session->GetPlayerName(), _session->GetLatency(), _session->GetRemoteAddress().c_str(), secsToTimeString(maxClientResponseDelay, true).c_str());
sLog.outWarden("%s (latency: %u, IP: %s) exceeded Warden module response delay on state %s for more than %s - disconnecting client",
_session->GetPlayerName(), _session->GetLatency(), _session->GetRemoteAddress().c_str(), WardenState::to_string(_state), secsToTimeString(maxClientResponseDelay, true).c_str());
_session->KickPlayer();
}
else
{
_clientResponseTimer += diff;
}
}
}
else
break;
case WardenState::STATE_INITIALIZE_MODULE:
case WardenState::STATE_RESTING:
{
if (diff >= _checkTimer)
{
RequestData();
}
else
{
_checkTimer -= diff;
}
}
break;
default:
sLog.outWarden("Unimplemented warden state!");
break;
}
}
@ -161,6 +188,28 @@ void Warden::EncryptData(uint8* buffer, uint32 length)
_outputCrypto.UpdateData(length, buffer);
}
void Warden::SetNewState(WardenState::Value state)
{
//if we pass all initial checks, allow change
if (state < WardenState::STATE_REQUESTED_DATA)
{
if (state < _state)
{
sLog.outWarden("Warden Error: jump from %s to %s which is lower by initialization routine", WardenState::to_string(_state), WardenState::to_string(state));
return;
}
}
_state = state;
//Reset timers
// Set hold off timer, minimum timer should at least be 1 second
uint32 holdOff = sWorld.getConfig(CONFIG_UINT32_WARDEN_CLIENT_CHECK_HOLDOFF);
_checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS;
_clientResponseTimer = 0;
}
bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 length)
{
uint32 newChecksum = BuildChecksum(data, length);
@ -284,11 +333,14 @@ void WorldSession::HandleWardenDataOpcode(WorldPacket& recvData)
}
}
void Warden::RequestData()
{
SetNewState(WardenState::STATE_REQUESTED_DATA);
}
void Warden::HandleData(ByteBuffer& /*buff*/)
{
// Set hold off timer, minimum timer should at least be 1 second
uint32 holdOff = sWorld.getConfig(CONFIG_UINT32_WARDEN_CLIENT_CHECK_HOLDOFF);
_checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS;
SetNewState(WardenState::STATE_RESTING);
}
void Warden::LogPositiveToDB(WardenCheck* check)

View file

@ -34,7 +34,7 @@
#include "Database/DatabaseEnv.h"
// the default client version with info in warden_checks; for other version checks, see warden_build_specific
#define DEFAULT_CLIENT_BUILD 5875
#define DEFAULT_CLIENT_BUILD 12340
enum WardenOpcodes
{
@ -95,6 +95,42 @@ struct WardenHashRequest
uint8 Seed[16];
};
namespace WardenState
{
enum Value
{
STATE_INITIAL,
STATE_REQUESTED_MODULE,
STATE_SENT_MODULE,
STATE_REQUESTED_HASH,
STATE_INITIALIZE_MODULE,
STATE_REQUESTED_DATA,
STATE_RESTING
};
inline const char* to_string(WardenState::Value value)
{
switch (value)
{
case WardenState::STATE_INITIAL:
return "STATE_INITIAL";
case WardenState::STATE_REQUESTED_MODULE:
return "STATE_REQUESTED_MODULE";
case WardenState::STATE_SENT_MODULE:
return "STATE_SENT_MODULE";
case WardenState::STATE_REQUESTED_HASH:
return "STATE_REQUESTED_HASH";
case WardenState::STATE_INITIALIZE_MODULE:
return "STATE_INITIALIZE_MODULE";
case WardenState::STATE_REQUESTED_DATA:
return "STATE_REQUESTED_DATA";
case WardenState::STATE_RESTING:
return "STATE_RESTING";
}
return "UNDEFINED STATE";
}
};
#if defined(__GNUC__)
#pragma pack()
#else
@ -119,10 +155,10 @@ class Warden
virtual void Init(WorldSession* session, BigNumber* k) = 0;
virtual ClientWardenModule* GetModuleForClient() = 0;
virtual void InitializeModule() = 0;
virtual void InitializeModule();
virtual void RequestHash();
virtual void HandleHashResult(ByteBuffer &buff) = 0;
virtual void RequestData() = 0;
virtual void RequestData();
virtual void HandleData(ByteBuffer &buff);
void SendModuleToClient();
@ -131,6 +167,8 @@ class Warden
void DecryptData(uint8* buffer, uint32 length);
void EncryptData(uint8* buffer, uint32 length);
void SetNewState(WardenState::Value state);
static bool IsValidCheckSum(uint32 checksum, const uint8 *data, const uint16 length);
static uint32 BuildChecksum(const uint8 *data, uint32 length);
@ -148,10 +186,9 @@ class Warden
ARC4 _outputCrypto;
uint32 _checkTimer; // Timer for sending check requests
uint32 _clientResponseTimer; // Timer for client response delay
bool _dataSent;
uint32 _previousTimestamp;
ClientWardenModule* _module;
bool _initialized;
WardenState::Value _state;
};
#endif

View file

@ -32,19 +32,18 @@
#include "WardenCheckMgr.h"
#include "Warden.h"
WardenCheckMgr::WardenCheckMgr() { }
WardenCheckMgr::WardenCheckMgr() : m_lock(0), CheckStore(), CheckResultStore() { }
WardenCheckMgr::~WardenCheckMgr()
{
for (uint16 i = 0; i < CheckStore.size(); ++i)
{
delete CheckStore[i];
}
for (CheckMap::iterator it = CheckStore.begin(); it != CheckStore.end(); ++it)
delete it->second;
for (CheckResultContainer::iterator itr = CheckResultStore.begin(); itr != CheckResultStore.end(); ++itr)
{
delete itr->second;
}
for (CheckResultMap::iterator it = CheckResultStore.begin(); it != CheckResultStore.end(); ++it)
delete it->second;
CheckStore.clear();
CheckResultStore.clear();
}
void WardenCheckMgr::LoadWardenChecks()
@ -52,48 +51,34 @@ void WardenCheckMgr::LoadWardenChecks()
// Check if Warden is enabled by config before loading anything
if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) && !sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED))
{
sLog.outWarden(">> Warden disabled, loading checks skipped.");
sLog.outString(">> Warden disabled, loading checks skipped.");
return;
}
QueryResult *result = WorldDatabase.Query("SELECT MAX(`id`) FROM `warden_checks`");
// 0 1 2 3 4 5 6 7 8
QueryResult *result = WorldDatabase.Query("SELECT id, build, type, data, result, address, length, str, comment FROM warden ORDER BY build ASC, id ASC");
if (!result)
{
sLog.outWarden(">> Loaded 0 Warden checks. DB table `warden_checks` is empty!");
sLog.outString("[Warden]: >> Loaded 0 warden data and results");
return;
}
Field* fields = result->Fetch();
uint16 maxCheckId = fields[0].GetUInt16();
CheckStore.resize(maxCheckId + 1);
delete result;
// 0 1 2 3 4 5 6 7
result = WorldDatabase.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC");
uint32 count = 0;
if (!result)
{
sLog.outString("[Warden]: >> Loaded %u warden data and results", count);
return;
}
Field* fields;
do
{
fields = result->Fetch();
uint16 id = fields[0].GetUInt16();
uint8 checkType = fields[1].GetUInt8();
std::string data = fields[2].GetString();
std::string checkResult = fields[3].GetString();
uint32 address = fields[4].GetUInt32();
uint8 length = fields[5].GetUInt8();
std::string str = fields[6].GetString();
std::string comment = fields[7].GetString();
uint16 id = fields[0].GetUInt16();
uint16 build = fields[1].GetUInt16();
uint8 checkType = fields[2].GetUInt8();
std::string data = fields[3].GetString();
std::string checkResult = fields[4].GetString();
uint32 address = fields[5].GetUInt32();
uint8 length = fields[6].GetUInt8();
std::string str = fields[7].GetString();
std::string comment = fields[8].GetString();
WardenCheck* wardenCheck = new WardenCheck();
wardenCheck->Type = checkType;
@ -117,11 +102,6 @@ void WardenCheckMgr::LoadWardenChecks()
}
}
if (checkType == MEM_CHECK || checkType == MODULE_CHECK)
MemChecksIdPool.push_back(id);
else
OtherChecksIdPool.push_back(id);
if (checkType == MEM_CHECK || checkType == PAGE_CHECK_A || checkType == PAGE_CHECK_B || checkType == PROC_CHECK)
{
wardenCheck->Address = address;
@ -132,11 +112,12 @@ void WardenCheckMgr::LoadWardenChecks()
if (checkType == MEM_CHECK || checkType == MPQ_CHECK || checkType == LUA_STR_CHECK || checkType == DRIVER_CHECK || checkType == MODULE_CHECK)
wardenCheck->Str = str;
CheckStore[id] = wardenCheck;
CheckStore.insert(std::pair<uint16, WardenCheck*>(build, wardenCheck));
if (checkType == MPQ_CHECK || checkType == MEM_CHECK)
{
WardenCheckResult* wr = new WardenCheckResult();
wr->Id = id;
wr->Result.SetHexStr(checkResult.c_str());
int len = checkResult.size() / 2;
if (wr->Result.GetNumBytes() < len)
@ -148,7 +129,7 @@ void WardenCheckMgr::LoadWardenChecks()
wr->Result.SetBinary((uint8*)temp, len);
delete[] temp;
}
CheckResultStore[id] = wr;
CheckResultStore.insert(std::pair<uint16, WardenCheckResult*>(build, wr));
}
if (comment.empty())
@ -159,82 +140,9 @@ void WardenCheckMgr::LoadWardenChecks()
++count;
} while (result->NextRow());
sLog.outWarden(">> Loaded %u warden checks.", count);
sLog.outString(">> Loaded %u warden checks.", count);
delete result;
// 0 1 2 3 4 5 6
result = WorldDatabase.Query("SELECT id, build, data, result, address, length, str FROM warden_build_specific ORDER BY id ASC");
if (!result)
{
sLog.outString("[Warden]: >> Loaded 0 warden client build-specific data.");
return;
}
count = 0;
do
{
fields = result->Fetch();
uint16 id = fields[0].GetUInt16();
if (id >= CheckStore.size())
{
sLog.outWarden("ERROR: Build-specific, check is missing in warden_checks, skipping id %u.", id);
continue;
}
uint16 build = fields[1].GetUInt16();
if (build == DEFAULT_CLIENT_BUILD)
{
sLog.outWarden("ERROR: Build-specific table may not contain checks for default %u build, skipping id %u.", DEFAULT_CLIENT_BUILD, id);
continue;
}
//std::string data = fields[2].GetString(); //unused for now
std::string checkResult = fields[3].GetString();
uint32 address = fields[4].GetUInt32();
uint8 length = fields[5].GetUInt8();
std::string str = fields[6].GetString();
WardenCheck* wardenCheck = new WardenCheck();
wardenCheck->CheckId = id;
wardenCheck->Type = CheckStore[id]->Type;
WardenCheckResult* wr = new WardenCheckResult();
switch (wardenCheck->Type)
{
case MEM_CHECK:
wardenCheck->Address = address;
wardenCheck->Length = length;
wardenCheck->Str = str;
wr->Result.SetHexStr(checkResult.c_str());
{
int len = checkResult.size() / 2;
if (wr->Result.GetNumBytes() < len)
{
uint8 *temp = new uint8[len];
memset(temp, 0, len);
memcpy(temp, wr->Result.AsByteArray(), wr->Result.GetNumBytes());
std::reverse(temp, temp + len);
wr->Result.SetBinary((uint8*)temp, len);
delete[] temp;
}
}
break;
default:
sLog.outWarden("The check type %u is considered as build-independent, skipping id %u.", wardenCheck->Type, id);
delete wr;
delete wardenCheck;
continue;
}
MCheckStore[ComposeMultiCheckKey(build, id)] = wardenCheck;
MCheckResultStore[ComposeMultiCheckKey(build, id)] = wr;
++count;
} while (result->NextRow());
sLog.outString(">> Loaded %u warden client build-specific check overrides.", count);
}
void WardenCheckMgr::LoadWardenOverrides()
@ -242,22 +150,22 @@ void WardenCheckMgr::LoadWardenOverrides()
// Check if Warden is enabled by config before loading anything
if (!sWorld.getConfig(CONFIG_BOOL_WARDEN_WIN_ENABLED) && !sWorld.getConfig(CONFIG_BOOL_WARDEN_OSX_ENABLED))
{
sLog.outWarden(">> Warden disabled, loading check overrides skipped.");
sLog.outString(">> Warden disabled, loading check overrides skipped.");
return;
}
// 0 1
QueryResult* result = CharacterDatabase.Query("SELECT `wardenId`, `action` FROM `warden_action`");
QueryResult* result = CharacterDatabase.Query("SELECT wardenId, action FROM warden_action");
if (!result)
{
sLog.outWarden(">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!");
sLog.outString(">> Loaded 0 Warden action overrides. DB table `warden_action` is empty!");
return;
}
uint32 count = 0;
ACE_WRITE_GUARD(ACE_RW_Mutex, g, _checkStoreLock);
ACE_WRITE_GUARD(LOCK, g, m_lock)
do
{
@ -269,54 +177,68 @@ void WardenCheckMgr::LoadWardenOverrides()
// Check if action value is in range (0-2, see WardenActions enum)
if (action > WARDEN_ACTION_BAN)
sLog.outWarden("Warden check override action out of range (ID: %u, action: %u)", checkId, action);
// Check if check actually exists before accessing the CheckStore vector
else if (checkId > CheckStore.size())
sLog.outWarden("Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action);
else
{
CheckStore[checkId]->Action = WardenActions(action);
++count;
bool found = false;
for (CheckMap::iterator it = CheckStore.begin(); it != CheckStore.end(); ++it)
{
if (it->second->CheckId == checkId)
{
it->second->Action = WardenActions(action);
++count;
found = true;
}
}
if (!found)
sLog.outWarden("Warden check action override for non-existing check (ID: %u, action: %u), skipped", checkId, action);
}
}
while (result->NextRow());
sLog.outWarden(">> Loaded %u warden action overrides.", count);
sLog.outString(">> Loaded %u warden action overrides.", count);
}
WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 build, uint16 Id)
WardenCheck* WardenCheckMgr::GetWardenDataById(uint16 build, uint16 id)
{
if (Id < CheckStore.size())
WardenCheck* result = NULL;
ACE_READ_GUARD_RETURN(LOCK, g, m_lock, result)
for (CheckMap::iterator it = CheckStore.lower_bound(build); it != CheckStore.upper_bound(build); ++it)
{
if (build != DEFAULT_CLIENT_BUILD)
{
MultiCheckContainer::const_iterator it = MCheckStore.find(ComposeMultiCheckKey(build, Id));
if (it != MCheckStore.end())
{
return it->second;
}
}
return CheckStore[Id];
if (it->second->CheckId == id)
result = it->second;
}
return NULL;
return result;
}
WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 build, uint16 Id)
WardenCheckResult* WardenCheckMgr::GetWardenResultById(uint16 build, uint16 id)
{
if (build != DEFAULT_CLIENT_BUILD)
WardenCheckResult* result = NULL;
ACE_READ_GUARD_RETURN(LOCK, g, m_lock, result)
for (CheckResultMap::iterator it = CheckResultStore.lower_bound(build); it != CheckResultStore.upper_bound(build); ++it)
{
MultiResultContainer::const_iterator it = MCheckResultStore.find(ComposeMultiCheckKey(build, Id));
if (it != MCheckResultStore.end())
{
return it->second;
}
if (it->second->Id == id)
result = it->second;
}
CheckResultContainer::const_iterator itr = CheckResultStore.find(Id);
if (itr != CheckResultStore.end())
{
return itr->second;
}
return NULL;
return result;
}
void WardenCheckMgr::GetWardenCheckIds(bool isMemCheck, uint16 build, std::list<uint16>& idl)
{
idl.clear(); //just to be sure
ACE_READ_GUARD(LOCK, g, m_lock)
for (CheckMap::iterator it = CheckStore.lower_bound(build); it != CheckStore.upper_bound(build); ++it)
{
if (isMemCheck)
{
if ((it->second->Type == MEM_CHECK) || (it->second->Type == MODULE_CHECK))
idl.push_back(it->second->CheckId);
}
else
idl.push_back(it->second->CheckId);
}
}

View file

@ -50,6 +50,7 @@ struct WardenCheck
struct WardenCheckResult
{
uint16 Id;
BigNumber Result; // MEM_CHECK
};
@ -66,33 +67,22 @@ class WardenCheckMgr
return &instance;
}
WardenCheck* GetWardenDataById(uint16 build, uint16 Id);
WardenCheckResult* GetWardenResultById(uint16 build, uint16 Id);
std::vector<uint16> MemChecksIdPool;
std::vector<uint16> OtherChecksIdPool;
WardenCheck* GetWardenDataById(uint16 /*build*/, uint16 /*id*/);
WardenCheckResult* GetWardenResultById(uint16 /*build*/, uint16 /*id*/);
void GetWardenCheckIds(bool isMemCheck /* true = MEM */, uint16 build, std::list<uint16>& list);
void LoadWardenChecks();
void LoadWardenOverrides();
ACE_RW_Mutex _checkStoreLock;
private:
uint32 inline ComposeMultiCheckKey(uint16 clientBuild, uint16 checkID) { return (uint32(checkID) << 16) | clientBuild; }
typedef ACE_RW_Thread_Mutex LOCK;
typedef std::multimap< uint16, WardenCheck* > CheckMap;
typedef std::multimap< uint16, WardenCheckResult* > CheckResultMap;
// We have a linear key without any gaps, so we use vector for fast access
typedef std::vector<WardenCheck*> CheckContainer;
typedef std::map<uint32, WardenCheckResult*> CheckResultContainer;
LOCK m_lock;
CheckMap CheckStore;
CheckResultMap CheckResultStore;
CheckContainer CheckStore;
CheckResultContainer CheckResultStore;
// here we have just few checks, vector is not appropriate; key is from ComposeMultiCheckKey
typedef std::map<uint32 /*MultiCheckKey*/, WardenCheck*> MultiCheckContainer;
typedef std::map<uint32 /*MultiCheckKey*/, WardenCheckResult*> MultiResultContainer;
MultiCheckContainer MCheckStore;
MultiResultContainer MCheckResultStore;
};
#define sWardenCheckMgr WardenCheckMgr::instance()

View file

@ -98,6 +98,7 @@ ClientWardenModule* WardenMac::GetModuleForClient()
void WardenMac::InitializeModule()
{
sLog.outWarden("Initialize module");
Warden::InitializeModule();
}
struct keyData {
@ -174,8 +175,6 @@ void WardenMac::HandleHashResult(ByteBuffer &buff)
_inputCrypto.Init(_inputKey);
_outputCrypto.Init(_outputKey);
_initialized = true;
_previousTimestamp = WorldTimer::getMSTime();
}
@ -200,16 +199,13 @@ void WardenMac::RequestData()
pkt.append(buff);
_session->SendPacket(&pkt);
_dataSent = true;
Warden::RequestData();
}
void WardenMac::HandleData(ByteBuffer &buff)
{
sLog.outWarden("Handle data");
_dataSent = false;
_clientResponseTimer = 0;
//uint16 Length;
//buff >> Length;
//uint32 Checksum;

View file

@ -132,6 +132,8 @@ void WardenWin::InitializeModule()
WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenInitModuleRequest));
pkt.append((uint8*)&Request, sizeof(WardenInitModuleRequest));
_session->SendPacket(&pkt);
Warden::InitializeModule();
}
void WardenWin::HandleHashResult(ByteBuffer &buff)
@ -154,8 +156,6 @@ void WardenWin::HandleHashResult(ByteBuffer &buff)
_inputCrypto.Init(_inputKey);
_outputCrypto.Init(_outputKey);
_initialized = true;
_previousTimestamp = WorldTimer::getMSTime();
}
@ -163,18 +163,20 @@ void WardenWin::RequestData()
{
sLog.outWarden("Request data");
uint16 build = _session->GetClientBuild();
uint16 id = 0;
uint8 type = 0;
WardenCheck* wd = NULL;
// If all checks were done, fill the todo list again
if (_memChecksTodo.empty())
_memChecksTodo.assign(sWardenCheckMgr->MemChecksIdPool.begin(), sWardenCheckMgr->MemChecksIdPool.end());
sWardenCheckMgr->GetWardenCheckIds(true, build, _memChecksTodo);
if (_otherChecksTodo.empty())
_otherChecksTodo.assign(sWardenCheckMgr->OtherChecksIdPool.begin(), sWardenCheckMgr->OtherChecksIdPool.end());
sWardenCheckMgr->GetWardenCheckIds(false, build, _otherChecksTodo);
_serverTicks = WorldTimer::getMSTime();
uint16 id;
uint8 type;
WardenCheck* wd;
_currentChecks.clear();
// Build check request
@ -195,8 +197,6 @@ void WardenWin::RequestData()
ByteBuffer buff;
buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST);
ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock);
for (uint16 i = 0; i < sWorld.getConfig(CONFIG_UINT32_WARDEN_NUM_OTHER_CHECKS); ++i)
{
// If todo list is done break loop (will be filled on next Update() run)
@ -210,18 +210,22 @@ void WardenWin::RequestData()
// Add the id to the list sent in this cycle
_currentChecks.push_back(id);
wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), id);
switch (wd->Type)
// if we are here, the function is guaranteed to not return NULL
// but ... who knows
wd = sWardenCheckMgr->GetWardenDataById(build, id);
if (wd)
{
case MPQ_CHECK:
case LUA_STR_CHECK:
case DRIVER_CHECK:
buff << uint8(wd->Str.size());
buff.append(wd->Str.c_str(), wd->Str.size());
break;
default:
break;
switch (wd->Type)
{
case MPQ_CHECK:
case LUA_STR_CHECK:
case DRIVER_CHECK:
buff << uint8(wd->Str.size());
buff.append(wd->Str.c_str(), wd->Str.size());
break;
default:
break;
}
}
}
@ -235,7 +239,7 @@ void WardenWin::RequestData()
for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr)
{
wd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr);
wd = sWardenCheckMgr->GetWardenDataById(build, *itr);
type = wd->Type;
buff << uint8(type ^ xorByte);
@ -301,8 +305,6 @@ void WardenWin::RequestData()
pkt.append(buff);
_session->SendPacket(&pkt);
_dataSent = true;
std::stringstream stream;
stream << "Sent check id's: ";
for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr)
@ -311,15 +313,14 @@ void WardenWin::RequestData()
}
sLog.outWarden("%s", stream.str().c_str());
Warden::RequestData();
}
void WardenWin::HandleData(ByteBuffer &buff)
{
sLog.outWarden("Handle data");
_dataSent = false;
_clientResponseTimer = 0;
uint16 Length;
buff >> Length;
uint32 Checksum;
@ -349,8 +350,9 @@ void WardenWin::HandleData(ByteBuffer &buff)
uint32 ticksNow = WorldTimer::getMSTime();
uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks);
sLog.outWarden("ServerTicks %u, RequestTicks %u, CLientTicks %u", ticksNow, _serverTicks, newClientTicks); // Now, At request, At response
sLog.outWarden("ServerTicks %u, RequestTicks %u, ClientTicks %u", ticksNow, _serverTicks, newClientTicks); // Now, At request, At response
sLog.outWarden("Waittime %u", ourTicks - newClientTicks);
}
WardenCheckResult* rs;
@ -358,8 +360,6 @@ void WardenWin::HandleData(ByteBuffer &buff)
uint8 type;
uint16 checkFailed = 0;
ACE_READ_GUARD(ACE_RW_Mutex, g, sWardenCheckMgr->_checkStoreLock);
for (std::list<uint16>::iterator itr = _currentChecks.begin(); itr != _currentChecks.end(); ++itr)
{
rd = sWardenCheckMgr->GetWardenDataById(_session->GetClientBuild(), *itr);

View file

@ -39,5 +39,5 @@
#define WORLD_DB_VERSION_NR 21
#define WORLD_DB_STRUCTURE_NR 12
#define WORLD_DB_CONTENT_NR 001
#define WORLD_DB_UPDATE_DESCRIPTION "GM_Commands_localization"
#define WORLD_DB_UPDATE_DESCRIPTION "warden_refactor"
#endif // __REVISION_H__