Files
2022-10-26 12:25:11 +08:00

317 lines
10 KiB
C++

#pragma once
#ifndef PROGRAMCOMMON_KBMOVECHECK_MANAGER_H
#define PROGRAMCOMMON_KBMOVECHECK_MANAGER_H
#include <ITimeout.h>
#include "PacketStruct_CG.h"
//==================================================================================================
//==================================================================================================
// the reason of 'TAllocMalloc' and 'TAllocFree'
// to support other memory acquisition
namespace nsSync {
;
struct MSGSUB_SYNC_SERVER_TIMER_SYNCHRONIZE_BRD;
//
class KBMoveCheckManager
{
public:
KBMoveCheckManager();
virtual ~KBMoveCheckManager();
//
bool ReceiveOrders(const MSG_CG_MAP_KBMOVE_SERIAL_CHECK_CMD& command,
MSG_CG_MAP_KBMOVE_SERIAL_CHECK_ACK* const reply_msg);
bool IssueNextSerial(ulong* const next_serial_key);
bool IssueNextStopSerial(ulong* const next_stop_serial_key);
//
bool StartLocalTickTest();
template<size_t LineNo>
bool CheckLocalTestRequest(MSG_CG_CONNECTION_CLIENT_TICK_TEST_SYN* const msg_syn);
//
ulong GetClientSendTick() const;
bool CheckReceivedLocalTest(const MSG_CG_CONNECTION_CLIENT_TICK_TEST_ACK& reply_msg);
virtual bool ReceiveReplyFromServer(const MSG_CG_CONNECTION_CLIENT_TICK_TEST_ACK& reply_msg) = 0;
private:
//
util::ITimerBase local_test_interval_;
nsSync::KBMoveSerialNode kbmove_node_;
ulong* client_send_tick_id_;
ulong* client_send_tick_;
ulong* server_timer_selected_index_;
ulong* server_timer_;
//
__DISABLE_COPY(KBMoveCheckManager);
};
class InorderValue
{
public:
InorderValue();
~InorderValue();
ulong Set(ulong value);
ulong Set(const InorderValue& rhs);
ulong Get();
void Realloc();
bool Move(InorderValue* inorder_value);
void Swap(InorderValue* inorder_value);
private:
typedef mpl::if_c<sizeof(void*) == sizeof(ulong), ulong,
mpl::if_c<sizeof(void*) == sizeof(int64), int64,
void>::type >::type cast_type;
typedef STLX_LIST<void*> InorderArray;
void Init();
//
InorderArray* inorder_array_;
//
__DISABLE_COPY(InorderValue);
};
class ServerTimerSynchronier
{
public:
static const ulong kServerTimerCrc = ulong( ((PROTOCOL_GENERATOR_CHARINFO_041 << 24))
| ((PROTOCOL_GENERATOR_MAP_008 << 16))
| ((PROTOCOL_GENERATOR_SYNC_018 << 8))
| ((PROTOCOL_GENERATOR_SYNC_099)) );
static ServerTimerSynchronier* Instance();
void EnterField(); // client
void LeaveField(); // client
// contorller for MSGSUB_SYNC_SERVER_TIMER_SYNCHRONIZE_BRD
static bool CheckServerTimerSynchronizationTest(
const nsSync::MSGSUB_SYNC_SERVER_TIMER_SYNCHRONIZE_BRD& msg_brd);
private:
//
ServerTimerSynchronier();
~ServerTimerSynchronier();
static ServerTimerSynchronier* CreateInstance();
// fields...
InorderValue milestone_counter_;
InorderValue timestamp_;
// last order...
static ServerTimerSynchronier* instance_static_;
__DISABLE_COPY(ServerTimerSynchronier);
};
class MemoryHackMonitor
{
public:
static MemoryHackMonitor* Instance();
void EnterField(); // client
ulong GetNextClientTestSerial();
ulong GetCurrentClientTestSerial();
void ForceIncreaseClientTestSerial();
private:
MemoryHackMonitor();
~MemoryHackMonitor();
static MemoryHackMonitor* CreateInstance();
#pragma pack(push, 1)
uint16_t __dummy0;
struct BattleSerial {
uint16_t __dummy0;
ulong serial_counter;
uint16_t __dummy1;
} battle_serial_;
uint16_t __dummy1;
#pragma pack(pop)
// last order...
static MemoryHackMonitor* instance_static_;
__DISABLE_COPY(MemoryHackMonitor);
};
#ifdef _SERVER
struct KBMoveCheckManagerInServer
{
enum eKBMoveKey {
eKBMoveKey_None = 0,
eKBMoveKey_Issued,
eKBMoveKey_Used,
};
static void Initialize(KBMoveCheckManagerInServer* manager);
//
void EnterField(MSG_CG_MAP_KBMOVE_SERIAL_CHECK_CMD* const msg_cmd);
bool ReceiveReply(const MSG_CG_MAP_KBMOVE_SERIAL_CHECK_ACK& reply_msg);
bool EnabledMoving(ulong received_serial_key) const;
bool EnabledStopping(ulong received_stop_serial_key) const;
// NOTE: f110801.2L, abusing check routine in client
bool CheckClientBattleSerial(ulong client_battle_serial);
bool UpdateKBMoveCheckRefresh(MSG_CG_MAP_KBMOVE_SERIAL_CHECK_CMD* const msg_cmd);
//
bool ReceiveClientLocalTest(const MSG_CG_CONNECTION_CLIENT_TICK_TEST_SYN& test_msg);
bool UpdateClientLocatTestRefresh(MSG_CG_CONNECTION_CLIENT_TICK_TEST_ACK* const reply_msg);
//
util::ITimerBase serial_issue_timer; // change type
util::ITimerBase client_local_test_timer; // change type
eKBMoveKey kbmove_state;
KBMoveSerialNode* active_node;
KBMoveSerialNode kbmove_nodes[2];
bool client_battle_serial_failed;
ulong client_battle_serial_counter;
util::ITimerBase client_battle_serial_failed_pending_timer;
ulong received_tick_in_server;
ulong received_client_local_tick_id;
ulong received_client_local_tick;
};
#endif
}; //end of namespace
//==================================================================================================
// code spreading for hack prevention
__forceinline nsSync::KBMoveCheckManager::KBMoveCheckManager()
{
ZeroMemory(&kbmove_node_, sizeof(kbmove_node_));
client_send_tick_id_ = static_cast<ulong*>(TAllocMalloc(sizeof(ulong)));
client_send_tick_ = static_cast<ulong*>(TAllocMalloc(sizeof(ulong)));
*client_send_tick_ = 0;
}
__forceinline bool nsSync::KBMoveCheckManager::ReceiveOrders(
const MSG_CG_MAP_KBMOVE_SERIAL_CHECK_CMD& command,
MSG_CG_MAP_KBMOVE_SERIAL_CHECK_ACK* const reply_msg)
{
kbmove_node_ = command.serial_block;
reply_msg->serial_guid = kbmove_node_.serial_guid;
return true;
}
__forceinline bool nsSync::KBMoveCheckManager::IssueNextSerial(ulong* const next_serial_key)
{
if (kbmove_node_.process_index >= kbmove_node_.kNumberOfMoveKeys) {
return false;
};
*next_serial_key = kbmove_node_.serial_key_begin + kbmove_node_.process_index;
++kbmove_node_.process_index;
return true;
}
__forceinline bool nsSync::KBMoveCheckManager::IssueNextStopSerial(
ulong* const next_stop_serial_key)
{
if (kbmove_node_.process_stop_index >= kbmove_node_.kNumberOfStopKeys) {
return false;
};
*next_stop_serial_key = kbmove_node_.stop_serial_key_begin + kbmove_node_.process_stop_index;
++kbmove_node_.process_stop_index;
return true;
}
inline ulong nsSync::KBMoveCheckManager::GetClientSendTick() const
{
return (*client_send_tick_) ^ (*client_send_tick_id_);
}
__forceinline bool nsSync::KBMoveCheckManager::CheckReceivedLocalTest(
const MSG_CG_CONNECTION_CLIENT_TICK_TEST_ACK& reply_msg)
{
if (client_send_tick_id_ == NULL || client_send_tick_ == NULL) {
return false;
};
if (*client_send_tick_id_ != reply_msg.client_send_tick_id) {
return false;
};
return true;
}
template<size_t LineNo>
__forceinline bool nsSync::KBMoveCheckManager::CheckLocalTestRequest(
MSG_CG_CONNECTION_CLIENT_TICK_TEST_SYN* const msg_syn)
{
if (local_test_interval_.IsExpired() == false) {
return false;
};
#pragma warning(push)
#pragma warning(disable : 4307 4308)
const ulong kBuildSeed = ulong( ((PROTOCOL_GENERATOR_CHARINFO_040 << 24) + LineNo)
| ((PROTOCOL_GENERATOR_MAP_004 << 16) + LineNo)
| ((PROTOCOL_GENERATOR_SYNC_008 << 8) + LineNo)
| ((PROTOCOL_GENERATOR_SYNC_083) + LineNo) );
const ulong kIncSeed = ulong( ((PROTOCOL_GENERATOR_BATTLE_002 << 8) + LineNo)
| ((PROTOCOL_GENERATOR_STYLE_011) + LineNo) ) + 199;
#pragma warning(pop)
TAllocFree(client_send_tick_id_);
TAllocFree(client_send_tick_);
client_send_tick_id_ = static_cast<ulong*>(TAllocMalloc(sizeof(ulong)));
client_send_tick_ = static_cast<ulong*>(TAllocMalloc(sizeof(ulong)));
//
const ulong cur_tick = GetTickCount();
*client_send_tick_id_ = ((ulong(__int64(client_send_tick_id_)) >> 2) ^ kBuildSeed);
*client_send_tick_id_ += RandomNumberGenerator::GetRandomNumberRange(1, kIncSeed);
*client_send_tick_ = cur_tick ^ *client_send_tick_id_;
msg_syn->client_send_tick_id = *client_send_tick_id_;
msg_syn->client_send_tick = *client_send_tick_;
return true;
}
//==================================================================================================
inline nsSync::ServerTimerSynchronier* nsSync::ServerTimerSynchronier::Instance()
{
if (instance_static_ != NULL) {
return instance_static_;
}
return CreateInstance();
}
__forceinline nsSync::ServerTimerSynchronier::ServerTimerSynchronier()
{
}
__forceinline nsSync::ServerTimerSynchronier::~ServerTimerSynchronier()
{
}
//==================================================================================================
__forceinline nsSync::MemoryHackMonitor::MemoryHackMonitor()
{
battle_serial_.serial_counter = 0;
}
__forceinline nsSync::MemoryHackMonitor::~MemoryHackMonitor()
{
}
inline void nsSync::MemoryHackMonitor::EnterField() // client
{
battle_serial_.serial_counter = 0;
}
inline ulong nsSync::MemoryHackMonitor::GetNextClientTestSerial()
{
return ++battle_serial_.serial_counter;
}
inline ulong nsSync::MemoryHackMonitor::GetCurrentClientTestSerial()
{
return battle_serial_.serial_counter;
}
__forceinline void nsSync::MemoryHackMonitor::ForceIncreaseClientTestSerial()
{
int64_t copied = *(int64_t*)&battle_serial_;
BattleSerial copied2 = *(BattleSerial*)&copied;
++copied2.serial_counter;
battle_serial_ = copied2;
}
//==================================================================================================
#ifdef _SERVER
inline void nsSync::KBMoveCheckManagerInServer::Initialize(
nsSync::KBMoveCheckManagerInServer* manager)
{
ZeroMemory(manager, sizeof(*manager));
}
#endif //_SERVER
//==================================================================================================
#endif //PROGRAMCOMMON_KBMOVECHECK_MANAGER_H