From 24d30a05bf336c8528cb69c4f9557091dd4d9421 Mon Sep 17 00:00:00 2001 From: CPunch Date: Tue, 18 Aug 2020 20:34:39 -0500 Subject: [PATCH] added heartbeat support --- Makefile | 2 +- src/CNProtocol.cpp | 17 ++++++++++++++--- src/CNProtocol.hpp | 4 +++- src/CNShardServer.cpp | 17 +++++++++++++++++ src/CNShardServer.hpp | 3 +++ src/CNStructs.hpp | 9 ++++++++- src/PlayerManager.cpp | 6 ++++++ src/PlayerManager.hpp | 3 ++- src/main.cpp | 4 ++-- src/settings.cpp | 2 +- 10 files changed, 57 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index 64075cf..e046f02 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ CC = clang++ # using GNU C++ compiler WIN_CC = x86_64-w64-mingw32-g++ # using GNU C++ compiler # -w suppresses all warnings (the part that's commented out helps me find memory leaks, it ruins performance though!) -COMPILER_FLAGS = -std=c++17 -o3 -static #-g3 -fsanitize=address +COMPILER_FLAGS = -std=c++17 -o3 -g3 -fsanitize=address WIN_COMPILER_FLAGS = -std=c++17 -o3 -static #-g3 -fsanitize=address #LINKER_FLAGS specifies the libraries we're linking against (NONE, this is a single header library.) diff --git a/src/CNProtocol.cpp b/src/CNProtocol.cpp index 40d1e56..c81d64a 100644 --- a/src/CNProtocol.cpp +++ b/src/CNProtocol.cpp @@ -1,4 +1,5 @@ #include "CNProtocol.hpp" +#include "CNStructs.hpp" // ========================================================[[ CNSocketEncryption ]]======================================================== @@ -228,8 +229,12 @@ void CNServer::init() { } } -CNServer::CNServer() {}; -CNServer::CNServer(uint16_t p): port(p) {} +CNServer::CNServer() { + lastTimer = getTime(); +}; +CNServer::CNServer(uint16_t p): port(p) { + lastTimer = getTime(); +} void CNServer::start() { std::cout << "Starting server at *:" << port << std::endl; @@ -274,6 +279,11 @@ void CNServer::start() { } } + if (getTime() - lastTimer > 2000) { // every 2 seconds call the onTimer method + onTimer(); + lastTimer = getTime(); + } + #ifdef _WIN32 Sleep(0); #else @@ -302,4 +312,5 @@ void CNServer::kill() { connections.clear(); } -void CNServer::killConnection(CNSocket* cns) {} // stubbed lol \ No newline at end of file +void CNServer::killConnection(CNSocket* cns) {} // stubbed lol +void CNServer::onTimer() {} // stubbed lol diff --git a/src/CNProtocol.hpp b/src/CNProtocol.hpp index 6f0041e..af33ed1 100644 --- a/src/CNProtocol.hpp +++ b/src/CNProtocol.hpp @@ -124,6 +124,7 @@ public: class CNServer { protected: std::list connections; + std::mutex activeCrit; SOCKET sock; uint16_t port; @@ -132,7 +133,7 @@ protected: void init(); bool active = true; - std::mutex activeCrit; + long int lastTimer; public: PacketHandler pHandler; @@ -143,6 +144,7 @@ public: void start(); void kill(); virtual void killConnection(CNSocket* cns); + virtual void onTimer(); // called every 2 seconds }; #endif \ No newline at end of file diff --git a/src/CNShardServer.cpp b/src/CNShardServer.cpp index 8165dcf..7fa9aeb 100644 --- a/src/CNShardServer.cpp +++ b/src/CNShardServer.cpp @@ -29,4 +29,21 @@ void CNShardServer::killConnection(CNSocket* cns) { PlayerManager::removePlayer(cns); CNSharedData::erasePlayer(cachedPlr.SerialKey); +} + +void CNShardServer::onTimer() { + long int currTime = getTime(); + + auto cachedPlayers = PlayerManager::players; + + for (auto pair : cachedPlayers) { + if (pair.second.lastHeartbeat != 0 && currTime - pair.second.lastHeartbeat > 4000) { // if the client hadn't responded in 4 seconds, its a dead connection so throw it out + pair.first->kill(); + continue; + } + + // passed the heartbeat, send another + sP_FE2CL_REQ_LIVE_CHECK* data = (sP_FE2CL_REQ_LIVE_CHECK*)xmalloc(sizeof(sP_FE2CL_REQ_LIVE_CHECK)); + pair.first->sendPacket(new CNPacketData((void*)data, P_FE2CL_REQ_LIVE_CHECK, sizeof(sP_FE2CL_REQ_LIVE_CHECK), pair.first->getFEKey())); + } } \ No newline at end of file diff --git a/src/CNShardServer.hpp b/src/CNShardServer.hpp index 09b01f3..7b1c005 100644 --- a/src/CNShardServer.hpp +++ b/src/CNShardServer.hpp @@ -9,6 +9,7 @@ enum SHARDPACKETID { // client 2 shard P_CL2FE_REQ_PC_ENTER = 318767105, P_CL2FE_REQ_PC_LOADING_COMPLETE = 318767245, + P_CL2FE_REP_LIVE_CHECK = 318767221, P_CL2FE_REQ_PC_MOVE = 318767107, P_CL2FE_REQ_PC_STOP = 318767108, P_CL2FE_REQ_PC_JUMP = 318767109, @@ -21,6 +22,7 @@ enum SHARDPACKETID { // shard 2 client P_FE2CL_REP_PC_ENTER_SUCC = 822083586, P_FE2CL_REP_PC_LOADING_COMPLETE_SUCC = 822083833, + P_FE2CL_REQ_LIVE_CHECK = 822083792, P_FE2CL_PC_NEW = 822083587, P_FE2CL_PC_MOVE = 822083592, P_FE2CL_PC_STOP = 822083593, @@ -44,6 +46,7 @@ public: CNShardServer(uint16_t p); void killConnection(CNSocket* cns); + void onTimer(); }; #endif \ No newline at end of file diff --git a/src/CNStructs.hpp b/src/CNStructs.hpp index 4ee3f60..a59afe3 100644 --- a/src/CNStructs.hpp +++ b/src/CNStructs.hpp @@ -336,11 +336,14 @@ struct sP_CL2FE_REQ_PC_ENTER { int64_t iEnterSerialKey; }; - struct sP_CL2FE_REQ_PC_LOADING_COMPLETE { int32_t iPC_ID; }; +struct sP_CL2FE_REP_LIVE_CHECK { + int32_t iTempValue; +}; + struct sP_CL2FE_REQ_PC_MOVE { uint64_t iCliTime; int32_t iX; @@ -429,6 +432,10 @@ struct sP_FE2CL_REP_PC_LOADING_COMPLETE_SUCC { int32_t iPC_ID; }; +struct sP_FE2CL_REQ_LIVE_CHECK { + int32_t iTempValue; +}; + // literally just a wrapper for a sPCAppearanceData struct :/ struct sP_FE2CL_PC_NEW { sPCAppearanceData PCAppearanceData; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 96e03d4..406f44c 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -21,12 +21,14 @@ void PlayerManager::init() { REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_MOVEPLATFORM, PlayerManager::movePlatformPlayer); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GOTO, PlayerManager::gotoPlayer); REGISTER_SHARD_PACKET(P_CL2FE_GM_REQ_PC_SET_VALUE, PlayerManager::setSpecialPlayer); + REGISTER_SHARD_PACKET(P_CL2FE_REP_LIVE_CHECK, PlayerManager::heartbeatPlayer); } void PlayerManager::addPlayer(CNSocket* key, Player plr) { players[key] = PlayerView(); players[key].viewable = std::list(); players[key].plr = plr; + players[key].lastHeartbeat = 0; std::cout << U16toU8(plr.PCStyle.szFirstName) << U16toU8(plr.PCStyle.szLastName) << " has joined!" << std::endl; std::cout << players.size() << " players" << std::endl; @@ -384,4 +386,8 @@ void PlayerManager::setSpecialPlayer(CNSocket* sock, CNPacketData* data) { response->iSetValueType = setData->iSetValueType; sock->sendPacket(new CNPacketData((void*)response, P_FE2CL_GM_REP_PC_SET_VALUE, sizeof(sP_FE2CL_GM_REP_PC_SET_VALUE), sock->getFEKey())); +} + +void PlayerManager::heartbeatPlayer(CNSocket* sock, CNPacketData* data) { + players[sock].lastHeartbeat = getTime(); } \ No newline at end of file diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index 532142b..a36b2bf 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -12,6 +12,7 @@ struct PlayerView { std::list viewable; Player plr; + int long lastHeartbeat; }; @@ -33,7 +34,7 @@ namespace PlayerManager { void movePlatformPlayer(CNSocket* sock, CNPacketData* data); void gotoPlayer(CNSocket* sock, CNPacketData* data); void setSpecialPlayer(CNSocket* sock, CNPacketData* data); - + void heartbeatPlayer(CNSocket* sock, CNPacketData* data); } #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 67a155e..ec6460d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,8 +30,8 @@ int main() { ChatManager::init(); std::cout << "[INFO] Starting Server Threads..." << std::endl; - CNShardServer loginServer(settings::LOGINPORT); - CNLoginServer shardServer(settings::SHARDPORT); + CNLoginServer loginServer(settings::LOGINPORT); + CNShardServer shardServer(settings::SHARDPORT); std::thread shardThread(startShard, (CNShardServer*)&shardServer); diff --git a/src/settings.cpp b/src/settings.cpp index a3870be..40bc8e5 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -8,7 +8,7 @@ bool settings::LOGINRANDCHARACTERS = false; int settings::SHARDPORT = 8002; std::string settings::SHARDSERVERIP = "127.0.0.1"; -int settings::VIEWDISTANCE = 25000; +int settings::VIEWDISTANCE = 20000; // default spawn point is city hall int settings::SPAWN_X = 179213;