diff options
-rw-r--r-- | src/server/game/Server/WorldSession.h | 4 | ||||
-rw-r--r-- | src/server/game/Server/WorldTcpSession.cpp | 68 | ||||
-rw-r--r-- | src/server/game/Server/WorldTcpSession.h | 6 |
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; }; |