diff --git a/src/CNProtocol.cpp b/src/CNProtocol.cpp index d1e4a2a..3b1d5f8 100644 --- a/src/CNProtocol.cpp +++ b/src/CNProtocol.cpp @@ -268,12 +268,8 @@ void CNServer::init() { } } -CNServer::CNServer() { - lastTimer = getTime(); -}; -CNServer::CNServer(uint16_t p): port(p) { - lastTimer = getTime(); -} +CNServer::CNServer() {}; +CNServer::CNServer(uint16_t p): port(p) {} void CNServer::start() { std::cout << "Starting server at *:" << port << std::endl; @@ -326,10 +322,7 @@ void CNServer::start() { } } - if (getTime() - lastTimer > 2000) { // every 2 seconds call the onTimer method - onTimer(); - lastTimer = getTime(); - } + onStep(); #ifdef _WIN32 Sleep(0); @@ -383,4 +376,4 @@ void CNServer::printPacket(CNPacketData *data, int type) { void CNServer::newConnection(CNSocket* cns) {} // stubbed void CNServer::killConnection(CNSocket* cns) {} // stubbed -void CNServer::onTimer() {} // stubbed +void CNServer::onStep() {} // stubbed diff --git a/src/CNProtocol.hpp b/src/CNProtocol.hpp index a260901..3cb7ef0 100644 --- a/src/CNProtocol.hpp +++ b/src/CNProtocol.hpp @@ -132,6 +132,20 @@ public: bool isAlive(); }; +class CNServer; +typedef void (*TimerHandler)(CNServer* serv, uint64_t time); + +// timer struct +struct TimerEvent { + TimerHandler handlr; + uint64_t delta; // time to be added to the current time on reset + uint64_t scheduledEvent; // time to call handlr() + + TimerEvent(TimerHandler h, uint64_t d): handlr(h), delta(d) { + scheduledEvent = 0; + } +}; + // in charge of accepting new connections and making sure each connection is kept alive class CNServer { protected: @@ -145,7 +159,6 @@ protected: void init(); bool active = true; - uint64_t lastTimer; public: PacketHandler pHandler; @@ -158,5 +171,5 @@ public: static void printPacket(CNPacketData *data, int type); virtual void newConnection(CNSocket* cns); virtual void killConnection(CNSocket* cns); - virtual void onTimer(); // called every 2 seconds + virtual void onStep(); // called every 2 seconds }; diff --git a/src/CNShardServer.cpp b/src/CNShardServer.cpp index accd53a..76199d9 100644 --- a/src/CNShardServer.cpp +++ b/src/CNShardServer.cpp @@ -10,10 +10,12 @@ #include std::map CNShardServer::ShardPackets; +std::list CNShardServer::Timers; CNShardServer::CNShardServer(uint16_t p) { port = p; pHandler = &CNShardServer::handlePacket; + REGISTER_SHARD_TIMER(keepAliveTimer, 2000); init(); } @@ -26,6 +28,22 @@ void CNShardServer::handlePacket(CNSocket* sock, CNPacketData* data) { std::cerr << "OpenFusion: SHARD UNIMPLM ERR. PacketType: " << Defines::p2str(CL2FE, data->type) << " (" << data->type << ")" << std::endl; } +void CNShardServer::keepAliveTimer(CNServer* serv, uint64_t currTime) { + std::cout << "keep alive called! " << currTime << std::endl; + 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 + INITSTRUCT(sP_FE2CL_REQ_LIVE_CHECK, data); + pair.first->sendPacket((void*)&data, P_FE2CL_REQ_LIVE_CHECK, sizeof(sP_FE2CL_REQ_LIVE_CHECK)); + } +} + void CNShardServer::newConnection(CNSocket* cns) { cns->setActiveKey(SOCKETKEY_E); // by default they accept keys encrypted with the default key } @@ -38,19 +56,20 @@ void CNShardServer::killConnection(CNSocket* cns) { CNSharedData::erasePlayer(cachedPlr.SerialKey); } -void CNShardServer::onTimer() { +void CNShardServer::onStep() { uint64_t 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(); + for (TimerEvent& event : Timers) { + if (event.scheduledEvent == 0) { + // event hasn't been queued yet, go ahead and do that + event.scheduledEvent = currTime + event.delta; continue; } - // passed the heartbeat, send another - INITSTRUCT(sP_FE2CL_REQ_LIVE_CHECK, data); - pair.first->sendPacket((void*)&data, P_FE2CL_REQ_LIVE_CHECK, sizeof(sP_FE2CL_REQ_LIVE_CHECK)); + if (event.scheduledEvent < currTime) { + // timer needs to be called + event.handlr(this, currTime); + event.scheduledEvent = currTime + event.delta; + } } } diff --git a/src/CNShardServer.hpp b/src/CNShardServer.hpp index 4d5ca31..56f6303 100644 --- a/src/CNShardServer.hpp +++ b/src/CNShardServer.hpp @@ -6,17 +6,21 @@ #include #define REGISTER_SHARD_PACKET(pactype, handlr) CNShardServer::ShardPackets[pactype] = handlr; +#define REGISTER_SHARD_TIMER(handlr, delta) CNShardServer::Timers.push_back(TimerEvent(handlr, delta)); class CNShardServer : public CNServer { private: static void handlePacket(CNSocket* sock, CNPacketData* data); + static void keepAliveTimer(CNServer*, uint64_t); + public: static std::map ShardPackets; + static std::list Timers; CNShardServer(uint16_t p); void newConnection(CNSocket* cns); void killConnection(CNSocket* cns); - void onTimer(); + void onStep(); };