Core/Session: proper client timeout detection (#1232)
* Core/Session: proper client timeout detection - 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:
@@ -125,7 +125,7 @@ WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8
|
|||||||
{
|
{
|
||||||
m_Address = sock->GetRemoteAddress();
|
m_Address = sock->GetRemoteAddress();
|
||||||
sock->AddReference();
|
sock->AddReference();
|
||||||
ResetTimeOutTime();
|
ResetTimeOutTime(false);
|
||||||
LoginDatabase.PExecute("UPDATE account SET online = online | (1<<(%u-1)) WHERE id = %u;", realmID, GetAccountId());
|
LoginDatabase.PExecute("UPDATE account SET online = online | (1<<(%u-1)) WHERE id = %u;", realmID, GetAccountId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,6 +251,9 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
|
|||||||
if (updater.ProcessLogout())
|
if (updater.ProcessLogout())
|
||||||
{
|
{
|
||||||
UpdateTimeOutTime(diff);
|
UpdateTimeOutTime(diff);
|
||||||
|
|
||||||
|
/// 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())
|
if (IsConnectionIdle())
|
||||||
m_Socket->CloseSocket();
|
m_Socket->CloseSocket();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -355,9 +355,12 @@ class WorldSession
|
|||||||
else
|
else
|
||||||
m_timeOutTime -= diff;
|
m_timeOutTime -= diff;
|
||||||
}
|
}
|
||||||
void ResetTimeOutTime()
|
void ResetTimeOutTime(bool onlyActive)
|
||||||
{
|
{
|
||||||
m_timeOutTime = 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));
|
||||||
}
|
}
|
||||||
bool IsConnectionIdle() const
|
bool IsConnectionIdle() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -681,8 +681,10 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return HandleAuthSession (*new_pct);
|
return HandleAuthSession (*new_pct);
|
||||||
case CMSG_KEEP_ALIVE:
|
case CMSG_KEEP_ALIVE:
|
||||||
return 0;
|
if (m_Session)
|
||||||
|
m_Session->ResetTimeOutTime(true);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
|
ACE_GUARD_RETURN (LockType, Guard, m_SessionLock, -1);
|
||||||
@@ -691,7 +693,7 @@ int WorldSocket::ProcessIncoming(WorldPacket* new_pct)
|
|||||||
{
|
{
|
||||||
// Our Idle timer will reset on any non PING opcodes.
|
// Our Idle timer will reset on any non PING opcodes.
|
||||||
// Catches people idling on the login screen and any lingering ingame connections.
|
// Catches people idling on the login screen and any lingering ingame connections.
|
||||||
m_Session->ResetTimeOutTime();
|
m_Session->ResetTimeOutTime(false);
|
||||||
|
|
||||||
// OK, give the packet to WorldSession
|
// OK, give the packet to WorldSession
|
||||||
aptr.release();
|
aptr.release();
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
|
|||||||
if (*iter == sess)
|
if (*iter == sess)
|
||||||
{
|
{
|
||||||
sess->SetInQueue(false);
|
sess->SetInQueue(false);
|
||||||
sess->ResetTimeOutTime();
|
sess->ResetTimeOutTime(false);
|
||||||
iter = m_QueuedPlayer.erase(iter);
|
iter = m_QueuedPlayer.erase(iter);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
@@ -394,7 +394,7 @@ bool World::RemoveQueuedPlayer(WorldSession* sess)
|
|||||||
{
|
{
|
||||||
WorldSession* pop_sess = m_QueuedPlayer.front();
|
WorldSession* pop_sess = m_QueuedPlayer.front();
|
||||||
pop_sess->SetInQueue(false);
|
pop_sess->SetInQueue(false);
|
||||||
pop_sess->ResetTimeOutTime();
|
pop_sess->ResetTimeOutTime(false);
|
||||||
pop_sess->SendAuthWaitQue(0);
|
pop_sess->SendAuthWaitQue(0);
|
||||||
pop_sess->SendAddonsInfo();
|
pop_sess->SendAddonsInfo();
|
||||||
|
|
||||||
@@ -690,6 +690,7 @@ void World::LoadConfigSettings(bool reload)
|
|||||||
m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
|
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] = 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_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetIntDefault("SessionAddDelay", 10000);
|
||||||
|
|
||||||
m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f);
|
m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f);
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ enum WorldIntConfigs
|
|||||||
CONFIG_WARDEN_NUM_MEM_CHECKS,
|
CONFIG_WARDEN_NUM_MEM_CHECKS,
|
||||||
CONFIG_WARDEN_NUM_OTHER_CHECKS,
|
CONFIG_WARDEN_NUM_OTHER_CHECKS,
|
||||||
CONFIG_BIRTHDAY_TIME,
|
CONFIG_BIRTHDAY_TIME,
|
||||||
|
CONFIG_SOCKET_TIMEOUTTIME_ACTIVE,
|
||||||
INT_CONFIG_VALUE_COUNT
|
INT_CONFIG_VALUE_COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -220,6 +220,15 @@ GridUnload = 1
|
|||||||
|
|
||||||
SocketTimeOutTime = 900000
|
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
|
# SessionAddDelay
|
||||||
# Description: Time (in microseconds) that a network thread will sleep after authentication
|
# Description: Time (in microseconds) that a network thread will sleep after authentication
|
||||||
|
|||||||
Reference in New Issue
Block a user