aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Server
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2017-06-27 00:22:33 +0200
committerGitHub <noreply@github.com>2017-06-27 00:22:33 +0200
commit7dfd472f8dff6ce067572e2887c2beb56d9ba9de (patch)
treedb9a92f5e30f5f6783a8c5a43d56f5953070a35d /src/server/game/Server
parent19fefbb72b0a4a413e86d57a13fb0fd040c2a78a (diff)
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.
Diffstat (limited to 'src/server/game/Server')
-rw-r--r--src/server/game/Server/WorldSession.cpp14
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Server/WorldSocket.cpp8
3 files changed, 15 insertions, 9 deletions
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index a7a959bd0ea..05f69568507 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -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));
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 9271fb06e06..237fa991456 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -439,7 +439,7 @@ class TC_GAME_API WorldSession
m_timeOutTime -= int32(diff);
}
- void ResetTimeOutTime();
+ void ResetTimeOutTime(bool onlyActive);
bool IsConnectionIdle() const
{
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 699c5a38a92..f759e2d27dd 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -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)));