aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Server/WorldSession.h4
-rw-r--r--src/server/game/Server/WorldTcpSession.cpp68
-rw-r--r--src/server/game/Server/WorldTcpSession.h6
3 files changed, 72 insertions, 6 deletions
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index d864a2ca76d..d7b2b9ca4d4 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -1002,8 +1002,8 @@ class WorldSession
bool m_playerSave;
LocaleConstant m_sessionDbcLocale;
LocaleConstant m_sessionDbLocaleIndex;
- uint32 m_latency;
- uint32 m_clientTimeDelay;
+ std::atomic_uint32_t m_latency;
+ std::atomic_uint32_t m_clientTimeDelay;
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
bool m_TutorialsChanged;
diff --git a/src/server/game/Server/WorldTcpSession.cpp b/src/server/game/Server/WorldTcpSession.cpp
index 4a485dec20d..89ecb31ae68 100644
--- a/src/server/game/Server/WorldTcpSession.cpp
+++ b/src/server/game/Server/WorldTcpSession.cpp
@@ -30,7 +30,7 @@ using boost::asio::ip::tcp;
using boost::asio::streambuf;
WorldTcpSession::WorldTcpSession(tcp::socket socket)
- : _socket(std::move(socket)), _authSeed(static_cast<uint32>(rand32())), _worldSession(nullptr)
+ : _socket(std::move(socket)), _authSeed(static_cast<uint32>(rand32())), _worldSession(nullptr), _OverSpeedPings(0)
{
}
@@ -109,7 +109,7 @@ void WorldTcpSession::AsyncReadData(size_t dataSize)
switch (opcode)
{
case CMSG_PING:
- //return HandlePing(*new_pct);
+ HandlePing(packet);
break;
case CMSG_AUTH_SESSION:
if (_worldSession)
@@ -127,8 +127,6 @@ void WorldTcpSession::AsyncReadData(size_t dataSize)
break;
default:
{
- //ACE_GUARD_RETURN(LockType, Guard, m_SessionLock, -1);
-
if (!_worldSession)
{
TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
@@ -413,3 +411,65 @@ void WorldTcpSession::SendAuthResponseError(uint8 code)
AsyncWrite(packet);
}
+
+void WorldTcpSession::HandlePing(WorldPacket& recvPacket)
+{
+ uint32 ping;
+ uint32 latency;
+
+ // Get the ping packet content
+ recvPacket >> ping;
+ recvPacket >> latency;
+
+ if (_LastPingTime == steady_clock::time_point())
+ {
+ _LastPingTime = steady_clock::now();
+ }
+ else
+ {
+ steady_clock::time_point now = steady_clock::now();
+
+ steady_clock::duration diff = now - _LastPingTime;
+
+ _LastPingTime = now;
+
+ if (diff < seconds(27))
+ {
+ ++_OverSpeedPings;
+
+ uint32 maxAllowed = sWorld->getIntConfig(CONFIG_MAX_OVERSPEED_PINGS);
+
+ if (maxAllowed && _OverSpeedPings > maxAllowed)
+ {
+ if (_worldSession && !_worldSession->HasPermission(rbac::RBAC_PERM_SKIP_CHECK_OVERSPEED_PING))
+ {
+ TC_LOG_ERROR("network", "WorldSocket::HandlePing: %s kicked for over-speed pings (address: %s)",
+ _worldSession->GetPlayerInfo().c_str(), GetRemoteIpAddress().c_str());
+
+ _socket.close();
+ return;
+ }
+ }
+ }
+ else
+ _OverSpeedPings = 0;
+ }
+
+ if (_worldSession)
+ {
+ _worldSession->SetLatency(latency);
+ _worldSession->ResetClientTimeDelay();
+ }
+ else
+ {
+ TC_LOG_ERROR("network", "WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = %s",
+ GetRemoteIpAddress().c_str());
+
+ _socket.close();
+ return;
+ }
+
+ WorldPacket packet(SMSG_PONG, 4);
+ packet << ping;
+ return AsyncWrite(packet);
+}
diff --git a/src/server/game/Server/WorldTcpSession.h b/src/server/game/Server/WorldTcpSession.h
index 6663b879480..387768bfbef 100644
--- a/src/server/game/Server/WorldTcpSession.h
+++ b/src/server/game/Server/WorldTcpSession.h
@@ -20,6 +20,7 @@
#define __WORLDTCPSESSION_H__
#include <memory>
+#include <chrono>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/streambuf.hpp>
#include "Common.h"
@@ -63,6 +64,8 @@ private:
void HandleAuthSession(WorldPacket& recvPacket);
void SendAuthResponseError(uint8 code);
+ void HandlePing(WorldPacket& recvPacket);
+
void AsyncReadHeader();
void AsyncReadData(size_t dataSize);
@@ -73,6 +76,9 @@ private:
uint32 _authSeed;
AuthCrypt _authCrypt;
+ std::chrono::steady_clock::time_point _LastPingTime;
+ uint32 _OverSpeedPings;
+
WorldSession* _worldSession;
};