diff --git a/config.ini b/config.ini index 2d3471b..de43a05 100644 --- a/config.ini +++ b/config.ini @@ -9,9 +9,6 @@ verbosity=1 [login] # must be kept in sync with loginInfo.php port=8001 -# enables two randomly generated characters in the -# character selection menu for convenience -randomcharacters=true # will all custom names be approved instantly? acceptallcustomnames=true # how often should everything be flushed to the database? @@ -25,6 +22,9 @@ ip=127.0.0.1 # distance at which other players and NPCs become visible playerdistance=20000 npcdistance=16000 +# time, in milliseconds, to wait before kicking a non-responsive client +# default is 1 minute +timeout=60000 # little message players see when they enter the game motd=Welcome to OpenFusion! # NPC json data diff --git a/src/CNProtocol.hpp b/src/CNProtocol.hpp index 36f024e..62b94f6 100644 --- a/src/CNProtocol.hpp +++ b/src/CNProtocol.hpp @@ -172,15 +172,15 @@ public: }; class CNServer; -typedef void (*TimerHandler)(CNServer* serv, uint64_t time); +typedef void (*TimerHandler)(CNServer* serv, time_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() + time_t delta; // time to be added to the current time on reset + time_t scheduledEvent; // time to call handlr() - TimerEvent(TimerHandler h, uint64_t d): handlr(h), delta(d) { + TimerEvent(TimerHandler h, time_t d): handlr(h), delta(d) { scheduledEvent = 0; } }; diff --git a/src/CNShardServer.cpp b/src/CNShardServer.cpp index af568b7..f87a987 100644 --- a/src/CNShardServer.cpp +++ b/src/CNShardServer.cpp @@ -16,7 +16,7 @@ std::list CNShardServer::Timers; CNShardServer::CNShardServer(uint16_t p) { port = p; pHandler = &CNShardServer::handlePacket; - REGISTER_SHARD_TIMER(keepAliveTimer, 2000); + REGISTER_SHARD_TIMER(keepAliveTimer, 4000); REGISTER_SHARD_TIMER(periodicSaveTimer, settings::DBSAVEINTERVAL*1000); init(); } @@ -28,24 +28,26 @@ void CNShardServer::handlePacket(CNSocket* sock, CNPacketData* data) { ShardPackets[data->type](sock, data); else if (settings::VERBOSITY > 0) std::cerr << "OpenFusion: SHARD UNIMPLM ERR. PacketType: " << Defines::p2str(CL2FE, data->type) << " (" << data->type << ")" << std::endl; + + PlayerManager::players[sock].lastHeartbeat = getTime(); } -void CNShardServer::keepAliveTimer(CNServer* serv, uint64_t currTime) { +void CNShardServer::keepAliveTimer(CNServer* serv, time_t currTime) { auto cachedPlayers = PlayerManager::players; for (auto& pair : cachedPlayers) { - if (pair.second.lastHeartbeat != 0 && currTime - pair.second.lastHeartbeat > 60000) { // if the client hadn't responded in 60 seconds, its a dead connection so throw it out + if (pair.second.lastHeartbeat != 0 && currTime - pair.second.lastHeartbeat > settings::TIMEOUT) { + // if the client hasn't responded in 60 seconds, its a dead connection so throw it out pair.first->kill(); - continue; + } else if (pair.second.lastHeartbeat != 0 && currTime - pair.second.lastHeartbeat > settings::TIMEOUT/2) { + // if the player hasn't responded in 30 seconds, send a live check + INITSTRUCT(sP_FE2CL_REQ_LIVE_CHECK, data); + pair.first->sendPacket((void*)&data, P_FE2CL_REQ_LIVE_CHECK, sizeof(sP_FE2CL_REQ_LIVE_CHECK)); } - - // 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::periodicSaveTimer(CNServer* serv, uint64_t currTime) { +void CNShardServer::periodicSaveTimer(CNServer* serv, time_t currTime) { auto cachedPlayers = PlayerManager::players; for (auto& pair : cachedPlayers) { @@ -73,7 +75,7 @@ void CNShardServer::killConnection(CNSocket* cns) { } void CNShardServer::onStep() { - uint64_t currTime = getTime(); + time_t currTime = getTime(); for (TimerEvent& event : Timers) { if (event.scheduledEvent == 0) { diff --git a/src/CNShardServer.hpp b/src/CNShardServer.hpp index 3ced4fd..c03e30d 100644 --- a/src/CNShardServer.hpp +++ b/src/CNShardServer.hpp @@ -12,8 +12,8 @@ class CNShardServer : public CNServer { private: static void handlePacket(CNSocket* sock, CNPacketData* data); - static void keepAliveTimer(CNServer*, uint64_t); - static void periodicSaveTimer(CNServer* serv, uint64_t currTime); + static void keepAliveTimer(CNServer*, time_t); + static void periodicSaveTimer(CNServer* serv, time_t currTime); public: static std::map ShardPackets; diff --git a/src/PlayerManager.hpp b/src/PlayerManager.hpp index 263036b..9da42f9 100644 --- a/src/PlayerManager.hpp +++ b/src/PlayerManager.hpp @@ -14,7 +14,7 @@ struct PlayerView { std::list viewable; std::list viewableNPCs; Player *plr; - uint64_t lastHeartbeat; + time_t lastHeartbeat; }; diff --git a/src/settings.cpp b/src/settings.cpp index 9fb3b22..a71fd76 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -11,6 +11,7 @@ int settings::DBSAVEINTERVAL = 240; int settings::SHARDPORT = 8002; std::string settings::SHARDSERVERIP = "127.0.0.1"; +time_t settings::TIMEOUT = 60000; int settings::PLAYERDISTANCE = 20000; int settings::NPCDISTANCE = 16000; @@ -43,6 +44,7 @@ void settings::init() { SHARDPORT = reader.GetInteger("shard", "port", SHARDPORT); SHARDSERVERIP = reader.Get("shard", "ip", "127.0.0.1"); DBSAVEINTERVAL = reader.GetInteger("login", "dbsaveinterval", DBSAVEINTERVAL); + TIMEOUT = reader.GetInteger("shard", "timeout", TIMEOUT); PLAYERDISTANCE = reader.GetInteger("shard", "playerdistance", PLAYERDISTANCE); NPCDISTANCE = reader.GetInteger("shard", "npcdistance", NPCDISTANCE); SPAWN_X = reader.GetInteger("shard", "spawnx", SPAWN_X); diff --git a/src/settings.hpp b/src/settings.hpp index ae04f54..6700ab6 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -7,6 +7,7 @@ namespace settings { extern int DBSAVEINTERVAL; extern int SHARDPORT; extern std::string SHARDSERVERIP; + extern time_t TIMEOUT; extern int PLAYERDISTANCE; extern int NPCDISTANCE; extern int SPAWN_X;