From 210c191d41cead76794ab1d698608a8409d48186 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Tue, 10 Feb 2026 21:06:21 +0300 Subject: [PATCH] Added different hash func --- server/server.cpp | 4 ++-- src/Game.cpp | 10 +++++----- src/network/ClientState.cpp | 8 ++++++++ src/network/ClientState.h | 4 +++- src/network/WebSocketClient.cpp | 10 +++++----- src/network/WebSocketClientBase.cpp | 11 +++++++++++ src/network/WebSocketClientBase.h | 2 ++ src/network/WebSocketClientEmscripten.cpp | 4 +++- 8 files changed, 39 insertions(+), 14 deletions(-) diff --git a/server/server.cpp b/server/server.cpp index c9f1d8f..0e8c6b4 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -140,7 +140,7 @@ public: std::string receivedHashStr = fullMessage.substr(hashPos + 6); // 6 — длина "#hash:" // Вычисляем ожидаемый хеш от контента - size_t expectedHash = std::hash{}(originalContent + NET_SECRET); + size_t expectedHash = fnv1a_hash(originalContent + NET_SECRET); std::stringstream ss; ss << std::hex << expectedHash; @@ -323,7 +323,7 @@ private: void process_message(const std::string& msg) { if (!IsMessageValid(msg)) { // Логируем попытку подмены и просто выходим из обработки - std::cout << "[Security] Invalid packet hash. Dropping message." << std::endl; + std::cout << "[Security] Invalid packet hash. Dropping message: " << msg << std::endl; return; } std::string cleanMessage = msg.substr(0, msg.find("#hash:")); diff --git a/src/Game.cpp b/src/Game.cpp index 760545c..ee766d6 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -839,8 +839,8 @@ namespace ZL // Берем удаленных игроков //latestRemotePlayers = networkClient->getRemotePlayers(); - auto now = std::chrono::system_clock::now(); - now -= std::chrono::milliseconds(CLIENT_DELAY); + //auto now = std::chrono::system_clock::now(); + //now -= std::chrono::milliseconds(CLIENT_DELAY); for (auto const& [id, remotePlayer] : remotePlayerStates) { @@ -1000,17 +1000,17 @@ namespace ZL auto latestRemotePlayers = networkClient->getRemotePlayers(); - std::chrono::system_clock::time_point nowRounded{ std::chrono::milliseconds(newTickCount) }; + std::chrono::system_clock::time_point nowRoundedWithDelay{ std::chrono::milliseconds(newTickCount-CLIENT_DELAY) }; for (auto const& [id, remotePlayer] : latestRemotePlayers) { - if (!remotePlayer.canFetchClientStateAtTime(nowRounded)) + if (!remotePlayer.canFetchClientStateAtTime(nowRoundedWithDelay)) { continue; } - ClientState playerState = remotePlayer.fetchClientStateAtTime(nowRounded); + ClientState playerState = remotePlayer.fetchClientStateAtTime(nowRoundedWithDelay); remotePlayerStates[id] = playerState; diff --git a/src/network/ClientState.cpp b/src/network/ClientState.cpp index 8f52c0e..578f536 100644 --- a/src/network/ClientState.cpp +++ b/src/network/ClientState.cpp @@ -1,5 +1,13 @@ #include "ClientState.h" +uint32_t fnv1a_hash(const std::string& data) { + uint32_t hash = 0x811c9dc5; + for (unsigned char c : data) { + hash ^= c; + hash *= 0x01000193; + } + return hash; +} void ClientState::simulate_physics(size_t delta) { if (discreteMag > 0.01f) diff --git a/src/network/ClientState.h b/src/network/ClientState.h index 8dd52ba..7e48953 100644 --- a/src/network/ClientState.h +++ b/src/network/ClientState.h @@ -23,9 +23,11 @@ constexpr float PLANET_MAX_ANGULAR_VELOCITY = 10.f; constexpr float PITCH_LIMIT = static_cast(M_PI) / 9.f;//18.0f; constexpr long long SERVER_DELAY = 0; //ms -constexpr long long CLIENT_DELAY = 1000; //ms +constexpr long long CLIENT_DELAY = 500; //ms constexpr long long CUTOFF_TIME = 5000; //ms +uint32_t fnv1a_hash(const std::string& data); + struct ClientState { int id = 0; Eigen::Vector3f position = { 0, 0, 45000.0f }; diff --git a/src/network/WebSocketClient.cpp b/src/network/WebSocketClient.cpp index be31377..b661890 100644 --- a/src/network/WebSocketClient.cpp +++ b/src/network/WebSocketClient.cpp @@ -57,7 +57,7 @@ namespace ZL { std::lock_guard lock(queueMutex); while (!messageQueue.empty()) { - + /* auto nowTime = std::chrono::system_clock::now(); //Apply server delay: @@ -65,7 +65,7 @@ namespace ZL { auto now_ms = std::chrono::duration_cast( nowTime.time_since_epoch() - ).count(); + ).count();*/ std::string msg = messageQueue.front(); messageQueue.pop(); @@ -78,8 +78,8 @@ namespace ZL { void WebSocketClient::Send(const std::string& message) { if (!connected) return; - std::string finalMessage = message; - + std::string finalMessage = SignMessage(message); + /* #ifdef ENABLE_NETWORK_CHECKSUM // Вычисляем хеш. Для примера используем std::hash, // но в продакшене лучше взять быструю реализацию типа MurmurHash3. @@ -93,7 +93,7 @@ namespace ZL { // Например: "UPD:12345:pos...#hash:a1b2c3d4" finalMessage += "#hash:" + ss_hash.str(); #endif - +*/ auto ss = std::make_shared(finalMessage); std::lock_guard lock(writeMutex_); diff --git a/src/network/WebSocketClientBase.cpp b/src/network/WebSocketClientBase.cpp index 47f6241..de4f03b 100644 --- a/src/network/WebSocketClientBase.cpp +++ b/src/network/WebSocketClientBase.cpp @@ -251,6 +251,17 @@ namespace ZL { } } + std::string WebSocketClientBase::SignMessage(const std::string& msg) { +#ifdef ENABLE_NETWORK_CHECKSUM + size_t hashValue = fnv1a_hash(msg + NET_SECRET); + std::stringstream ss; + ss << msg << "#hash:" << std::hex << hashValue; + return ss.str(); +#else + return msg; +#endif + } + std::vector WebSocketClientBase::getPendingProjectiles() { std::lock_guard lock(projMutex_); auto copy = pendingProjectiles_; diff --git a/src/network/WebSocketClientBase.h b/src/network/WebSocketClientBase.h index ed9639f..75480c1 100644 --- a/src/network/WebSocketClientBase.h +++ b/src/network/WebSocketClientBase.h @@ -39,6 +39,8 @@ namespace ZL { void HandlePollMessage(const std::string& msg); + std::string SignMessage(const std::string& msg); + std::unordered_map getRemotePlayers() override { std::lock_guard lock(playersMutex); return remotePlayers; diff --git a/src/network/WebSocketClientEmscripten.cpp b/src/network/WebSocketClientEmscripten.cpp index a3418fa..b85f3bf 100644 --- a/src/network/WebSocketClientEmscripten.cpp +++ b/src/network/WebSocketClientEmscripten.cpp @@ -25,7 +25,9 @@ namespace ZL { void WebSocketClientEmscripten::Send(const std::string& message) { if (connected && socket_ > 0) { - emscripten_websocket_send_utf8_text(socket_, message.c_str()); + auto signedMsg = SignMessage(message); + std::cout << "[WebWS] Sending message: " << signedMsg << std::endl; + emscripten_websocket_send_utf8_text(socket_, signedMsg.c_str()); } }