mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Proper client timeout detection (#19906)
- Properly detect client timeout when logged into a character after a configurable time (default 60s) has passed without the client sending any packets. - Fixes issues with crashed clients leaving characters in the world for a very long time (default 15 minutes), as well as edge case exploits involving intentionally pausing client execution for some amount of time.
This commit is contained in:
@@ -137,7 +137,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
|
||||
if (sock)
|
||||
{
|
||||
m_Address = sock->GetRemoteIpAddress().to_string();
|
||||
ResetTimeOutTime();
|
||||
ResetTimeOutTime(false);
|
||||
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
|
||||
}
|
||||
|
||||
@@ -271,7 +271,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
||||
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->CloseSocket();
|
||||
|
||||
@@ -633,9 +634,12 @@ char const* WorldSession::GetTrinityString(uint32 entry) const
|
||||
return sObjectMgr->GetTrinityString(entry, GetSessionDbLocaleIndex());
|
||||
}
|
||||
|
||||
void WorldSession::ResetTimeOutTime()
|
||||
void WorldSession::ResetTimeOutTime(bool onlyActive)
|
||||
{
|
||||
m_timeOutTime = int32(sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME));
|
||||
if (GetPlayer())
|
||||
m_timeOutTime = int32(sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME_ACTIVE));
|
||||
else if (!onlyActive)
|
||||
m_timeOutTime = int32(sWorld->getIntConfig(CONFIG_SOCKET_TIMEOUTTIME));
|
||||
}
|
||||
|
||||
void WorldSession::Handle_NULL(WorldPacket& null)
|
||||
@@ -1198,7 +1202,7 @@ void WorldSession::InitializeSessionCallback(SQLQueryHolder* realmHolder)
|
||||
SendAuthWaitQue(0);
|
||||
|
||||
SetInQueue(false);
|
||||
ResetTimeOutTime();
|
||||
ResetTimeOutTime(false);
|
||||
|
||||
SendAddonsInfo();
|
||||
SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
|
||||
|
||||
@@ -439,7 +439,7 @@ class TC_GAME_API WorldSession
|
||||
m_timeOutTime -= int32(diff);
|
||||
}
|
||||
|
||||
void ResetTimeOutTime();
|
||||
void ResetTimeOutTime(bool onlyActive);
|
||||
|
||||
bool IsConnectionIdle() const
|
||||
{
|
||||
|
||||
@@ -357,7 +357,10 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
|
||||
return ReadDataHandlerResult::Error;
|
||||
}
|
||||
case CMSG_KEEP_ALIVE:
|
||||
sessionGuard.lock();
|
||||
LogOpcodeText(opcode, sessionGuard);
|
||||
if (_worldSession)
|
||||
_worldSession->ResetTimeOutTime(true);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
@@ -378,9 +381,8 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
|
||||
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);
|
||||
|
||||
// Copy the packet to the heap before enqueuing
|
||||
_worldSession->QueuePacket(new WorldPacket(std::move(packet)));
|
||||
|
||||
@@ -353,7 +353,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
|
||||
if (*iter == sess)
|
||||
{
|
||||
sess->SetInQueue(false);
|
||||
sess->ResetTimeOutTime();
|
||||
sess->ResetTimeOutTime(false);
|
||||
iter = m_QueuedPlayer.erase(iter);
|
||||
found = true; // removing queued session
|
||||
break;
|
||||
@@ -664,6 +664,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
|
||||
|
||||
m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetIntDefault("SocketTimeOutTime", 900000);
|
||||
m_int_configs[CONFIG_SOCKET_TIMEOUTTIME_ACTIVE] = sConfigMgr->GetIntDefault("SocketTimeOutTimeActive", 60000);
|
||||
m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetIntDefault("SessionAddDelay", 10000);
|
||||
|
||||
m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f);
|
||||
|
||||
@@ -389,6 +389,7 @@ enum WorldIntConfigs
|
||||
CONFIG_RESPAWN_DYNAMICMINIMUM_CREATURE,
|
||||
CONFIG_RESPAWN_DYNAMICMINIMUM_GAMEOBJECT,
|
||||
CONFIG_RESPAWN_GUIDWARNING_FREQUENCY,
|
||||
CONFIG_SOCKET_TIMEOUTTIME_ACTIVE,
|
||||
INT_CONFIG_VALUE_COUNT
|
||||
};
|
||||
|
||||
|
||||
@@ -304,6 +304,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
|
||||
|
||||
Reference in New Issue
Block a user