From 7bb86f94c57f3937766c482749d1c437aa1579ba Mon Sep 17 00:00:00 2001 From: hondacrx Date: Fri, 24 Jul 2020 17:48:02 -0400 Subject: [PATCH] Proper client timeout detection Port From (https://github.com/TrinityCore/TrinityCore/commit/2c3fc47a96baa8a47130befda647bf29d8eacce1) --- Source/Framework/Constants/SharedConst.cs | 3 ++- Source/Game/Networking/WorldSocket.cs | 9 ++++++--- Source/Game/Server/WorldConfig.cs | 3 ++- Source/Game/Server/WorldManager.cs | 2 +- Source/Game/Server/WorldSession.cs | 15 +++++++++++---- Source/WorldServer/WorldServer.conf.dist | 9 +++++++++ 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index 059ced0fd..425317fb8 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -1335,7 +1335,8 @@ namespace Framework.Constants SkillMilling, SkillProspecting, SkipCinematics, - SocketTimeouttime, + SocketTimeoutTime, + SocketTimeoutTimeActive, StartAllExplored, StartAllRep, StartAllSpells, diff --git a/Source/Game/Networking/WorldSocket.cs b/Source/Game/Networking/WorldSocket.cs index 34d524616..a64025973 100644 --- a/Source/Game/Networking/WorldSocket.cs +++ b/Source/Game/Networking/WorldSocket.cs @@ -237,6 +237,10 @@ namespace Game.Networking authContinuedSession.Read(); HandleAuthContinuedSession(authContinuedSession); break; + case ClientOpcodes.KeepAlive: + if (_worldSession != null) + _worldSession.ResetTimeOutTime(true); + break; case ClientOpcodes.LogDisconnect: break; case ClientOpcodes.EnableNagle: @@ -264,9 +268,8 @@ namespace Game.Networking break; } - // Our Idle timer will reset on any non PING opcodes. - // Catches people idling on the login screen and any lingering ingame connections. - _worldSession.ResetTimeOutTime(); + // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling. + _worldSession.ResetTimeOutTime(false); _worldSession.QueuePacket(packet); break; } diff --git a/Source/Game/Server/WorldConfig.cs b/Source/Game/Server/WorldConfig.cs index b57a0a8aa..20d740f6d 100644 --- a/Source/Game/Server/WorldConfig.cs +++ b/Source/Game/Server/WorldConfig.cs @@ -289,7 +289,8 @@ namespace Game Values[WorldCfg.PortInstance] = GetDefaultValue("InstanceServerPort", 8086); } - Values[WorldCfg.SocketTimeouttime] = GetDefaultValue("SocketTimeOutTime", 900000); + Values[WorldCfg.SocketTimeoutTime] = GetDefaultValue("SocketTimeOutTime", 900000); + Values[WorldCfg.SocketTimeoutTimeActive] = GetDefaultValue("SocketTimeOutTimeActive", 60000); Values[WorldCfg.SessionAddDelay] = GetDefaultValue("SessionAddDelay", 10000); Values[WorldCfg.GroupXpDistance] = GetDefaultValue("MaxGroupXPDistance", 74.0f); diff --git a/Source/Game/Server/WorldManager.cs b/Source/Game/Server/WorldManager.cs index d4da4922e..e80fa1d23 100644 --- a/Source/Game/Server/WorldManager.cs +++ b/Source/Game/Server/WorldManager.cs @@ -267,7 +267,7 @@ namespace Game else { sess.SetInQueue(false); - sess.ResetTimeOutTime(); + sess.ResetTimeOutTime(false); m_QueuedPlayer.Remove(iter); found = true; // removing queued session break; diff --git a/Source/Game/Server/WorldSession.cs b/Source/Game/Server/WorldSession.cs index a6cf89e32..f9570ef02 100644 --- a/Source/Game/Server/WorldSession.cs +++ b/Source/Game/Server/WorldSession.cs @@ -60,7 +60,7 @@ namespace Game _collectionMgr = new CollectionMgr(this); m_Address = sock.GetRemoteIpAddress().ToString(); - ResetTimeOutTime(); + ResetTimeOutTime(false); DB.Login.Execute("UPDATE account SET online = 1 WHERE id = {0};", GetAccountId()); // One-time query } @@ -240,7 +240,8 @@ namespace Game UpdateTimeOutTime(diff); // Before we process anything: - // If necessary, kick the player from the character select screen + /// If necessary, kick the player because the client didn't send anything for too long + /// (or they've been idling in character select) if (IsConnectionIdle()) m_Socket[(int)ConnectionType.Realm].CloseSocket(); @@ -737,7 +738,7 @@ namespace Game SendAuthWaitQue(0); SetInQueue(false); - ResetTimeOutTime(); + ResetTimeOutTime(false); SendSetTimeZoneInformation(); SendFeatureSystemStatusGlueScreen(); @@ -815,7 +816,13 @@ namespace Game else m_timeOutTime -= diff; } - public void ResetTimeOutTime() { m_timeOutTime = WorldConfig.GetIntValue(WorldCfg.SocketTimeouttime); } + public void ResetTimeOutTime(bool onlyActive) + { + if (GetPlayer()) + m_timeOutTime = WorldConfig.GetIntValue(WorldCfg.SocketTimeoutTimeActive); + else if (!onlyActive) + m_timeOutTime = WorldConfig.GetIntValue(WorldCfg.SocketTimeoutTime); + } bool IsConnectionIdle() { return (m_timeOutTime <= 0 && !m_inQueue); } public uint GetRecruiterId() { return recruiterId; } diff --git a/Source/WorldServer/WorldServer.conf.dist b/Source/WorldServer/WorldServer.conf.dist index 17c027127..2236dd4b3 100644 --- a/Source/WorldServer/WorldServer.conf.dist +++ b/Source/WorldServer/WorldServer.conf.dist @@ -315,6 +315,15 @@ InstanceMapLoadAllGrids = 0 SocketTimeOutTime = 900000 +# +# SocketTimeOutTimeActive +# Description: Time (in milliseconds) after which an idle connection is dropped while +# logged into the world. +# The client sends keepalive packets every 30 seconds. Values <= 30s are not recommended. +# Default: 60000 - (1 minute) + +SocketTimeOutTimeActive = 60000 + # # SessionAddDelay # Description: Time (in microseconds) that a network thread will sleep after authentication