aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/Utilities/Timer.h19
-rw-r--r--src/server/game/Entities/Player/Player.cpp36
-rw-r--r--src/server/game/Entities/Player/Player.h8
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp20
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp94
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/Server/WorldPacket.h8
-rw-r--r--src/server/game/Server/WorldSession.cpp42
-rw-r--r--src/server/game/Server/WorldSession.h21
-rw-r--r--src/server/game/Server/WorldSocket.cpp53
10 files changed, 199 insertions, 104 deletions
diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h
index be0f28a95ee..11f9cb2accc 100644
--- a/src/common/Utilities/Timer.h
+++ b/src/common/Utilities/Timer.h
@@ -22,13 +22,20 @@
#include "Define.h"
#include <chrono>
-inline uint32 getMSTime()
+inline std::chrono::steady_clock::time_point GetApplicationStartTime()
{
using namespace std::chrono;
static const steady_clock::time_point ApplicationStartTime = steady_clock::now();
- return uint32(duration_cast<milliseconds>(steady_clock::now() - ApplicationStartTime).count());
+ return ApplicationStartTime;
+}
+
+inline uint32 getMSTime()
+{
+ using namespace std::chrono;
+
+ return uint32(duration_cast<milliseconds>(steady_clock::now() - GetApplicationStartTime()).count());
}
inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
@@ -40,6 +47,14 @@ inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
return newMSTime - oldMSTime;
}
+inline uint32 getMSTimeDiff(uint32 oldMSTime, std::chrono::steady_clock::time_point newTime)
+{
+ using namespace std::chrono;
+
+ uint32 newMSTime = uint32(duration_cast<milliseconds>(newTime - GetApplicationStartTime()).count());
+ return getMSTimeDiff(oldMSTime, newMSTime);
+}
+
inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
{
return getMSTimeDiff(oldMSTime, getMSTime());
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a527bf01daf..36474ef67c2 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -380,11 +380,6 @@ Player::Player(WorldSession* session): Unit(true)
m_ChampioningFaction = 0;
- m_timeSyncCounter = 0;
- m_timeSyncTimer = 0;
- m_timeSyncClient = 0;
- m_timeSyncServer = 0;
-
for (uint8 i = 0; i < MAX_POWERS; ++i)
m_powerFraction[i] = 0;
@@ -1233,14 +1228,6 @@ void Player::Update(uint32 p_time)
m_zoneUpdateTimer -= p_time;
}
- if (m_timeSyncTimer > 0)
- {
- if (p_time >= m_timeSyncTimer)
- SendTimeSync();
- else
- m_timeSyncTimer -= p_time;
- }
-
if (IsAlive())
{
m_regenTimer += p_time;
@@ -22563,8 +22550,8 @@ void Player::SendInitialPacketsAfterAddToMap()
GetZoneAndAreaId(newzone, newarea);
UpdateZone(newzone, newarea); // also call SendInitWorldStates();
- ResetTimeSync();
- SendTimeSync();
+ GetSession()->ResetTimeSync();
+ GetSession()->SendTimeSync();
CastSpell(this, 836, true); // LOGINEFFECT
@@ -26028,25 +26015,6 @@ void Player::LoadActions(PreparedQueryResult result)
SendActionButtons(1);
}
-void Player::ResetTimeSync()
-{
- m_timeSyncCounter = 0;
- m_timeSyncTimer = 0;
- m_timeSyncClient = 0;
- m_timeSyncServer = GameTime::GetGameTimeMS();
-}
-
-void Player::SendTimeSync()
-{
- WorldPacket data(SMSG_TIME_SYNC_REQ, 4);
- data << uint32(m_timeSyncCounter++);
- SendDirectMessage(&data);
-
- // Schedule next sync in 10 sec
- m_timeSyncTimer = 10000;
- m_timeSyncServer = GameTime::GetGameTimeMS();
-}
-
void Player::SetReputation(uint32 factionentry, uint32 value)
{
GetReputationMgr().SetReputation(sFactionStore.LookupEntry(factionentry), value);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index f5530c06468..798c1684978 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -2317,9 +2317,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
ItemDurationList m_itemDuration;
GuidUnorderedSet m_itemSoulboundTradeable;
- void ResetTimeSync();
- void SendTimeSync();
-
std::unique_ptr<ResurrectionData> _resurrectionData;
WorldSession* m_session;
@@ -2462,11 +2459,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 m_ChampioningFaction;
- uint32 m_timeSyncCounter;
- uint32 m_timeSyncTimer;
- uint32 m_timeSyncClient;
- uint32 m_timeSyncServer;
-
InstanceTimeMap _instanceResetTimes;
uint32 _pendingBindId;
uint32 _pendingBindTimer;
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index ea24317911c..54be85e6efe 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1222,26 +1222,6 @@ void WorldSession::HandleSetTitleOpcode(WorldPacket& recvData)
GetPlayer()->SetUInt32Value(PLAYER_CHOSEN_TITLE, title);
}
-void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
-{
- TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESP");
-
- uint32 counter, clientTicks;
- recvData >> counter >> clientTicks;
-
- if (counter != _player->m_timeSyncCounter - 1)
- TC_LOG_DEBUG("network", "Wrong time sync counter from player %s (cheater?)", _player->GetName().c_str());
-
- TC_LOG_DEBUG("network", "Time sync received: counter %u, client ticks %u, time since last sync %u", counter, clientTicks, clientTicks - _player->m_timeSyncClient);
-
- uint32 ourTicks = clientTicks + (GameTime::GetGameTimeMS() - _player->m_timeSyncServer);
-
- // diff should be small
- TC_LOG_DEBUG("network", "Our ticks: %u, diff %u, latency %u", ourTicks, ourTicks - clientTicks, GetLatency());
-
- _player->m_timeSyncClient = clientTicks;
-}
-
void WorldSession::HandleResetInstancesOpcode(WorldPacket& /*recvData*/)
{
TC_LOG_DEBUG("network", "WORLD: CMSG_RESET_INSTANCES");
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index c12841d7e0f..b2c5fe4edc2 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -32,8 +32,9 @@
#include "ObjectMgr.h"
#include "Vehicle.h"
#include "GameTime.h"
-
-#define MOVEMENT_PACKET_TIME_DELAY 0
+#include <boost/accumulators/statistics/variance.hpp>
+#include <boost/accumulators/accumulators.hpp>
+#include <boost/accumulators/statistics.hpp>
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/)
{
@@ -362,14 +363,18 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
plrMover->SetInWater(!plrMover->IsInWater() || plrMover->GetBaseMap()->IsUnderWater(movementInfo.pos.GetPositionX(), movementInfo.pos.GetPositionY(), movementInfo.pos.GetPositionZ()));
}
- uint32 mstime = GameTime::GetGameTimeMS();
- /*----------------------*/
- if (m_clientTimeDelay == 0)
- m_clientTimeDelay = mstime - movementInfo.time;
-
/* process position-change */
WorldPacket data(opcode, recvData.size());
- movementInfo.time = movementInfo.time + m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY;
+ int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
+ if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
+ {
+ TC_LOG_WARN("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
+ movementInfo.time = GameTime::GetGameTimeMS();
+ }
+ else
+ {
+ movementInfo.time = (uint32)movementTime;
+ }
movementInfo.guid = mover->GetGUID();
WriteMovementInfo(&data, &movementInfo);
@@ -640,3 +645,76 @@ void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
data << timeSkipped;
GetPlayer()->SendMessageToSet(&data, false);
}
+
+void WorldSession::HandleTimeSyncResp(WorldPacket& recvData)
+{
+ TC_LOG_DEBUG("network", "CMSG_TIME_SYNC_RESP");
+
+ uint32 counter, clientTimestamp;
+ recvData >> counter >> clientTimestamp;
+
+ if (_pendingTimeSyncRequests.count(counter) == 0)
+ return;
+
+ uint32 serverTimeAtSent = _pendingTimeSyncRequests.at(counter);
+ _pendingTimeSyncRequests.erase(counter);
+
+ // time it took for the request to travel to the client, for the client to process it and reply and for response to travel back to the server.
+ // we are going to make 2 assumptions:
+ // 1) we assume that the request processing time equals 0.
+ // 2) we assume that the packet took as much time to travel from server to client than it took to travel from client to server.
+ uint32 roundTripDuration = getMSTimeDiff(serverTimeAtSent, recvData.GetReceivedTime());
+ uint32 lagDelay = roundTripDuration / 2;
+
+ /*
+ clockDelta = serverTime - clientTime
+ where
+ serverTime: time that was displayed on the clock of the SERVER at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
+ clientTime: time that was displayed on the clock of the CLIENT at the moment when the client processed the SMSG_TIME_SYNC_REQUEST packet.
+
+ Once clockDelta has been computed, we can compute the time of an event on server clock when we know the time of that same event on the client clock,
+ using the following relation:
+ serverTime = clockDelta + clientTime
+ */
+ int64 clockDelta = (int64)(serverTimeAtSent + lagDelay) - (int64)clientTimestamp;
+ _timeSyncClockDeltaQueue.push_back(std::pair<int64, uint32>(clockDelta, roundTripDuration));
+ ComputeNewClockDelta();
+}
+
+void WorldSession::ComputeNewClockDelta()
+{
+ // implementation of the technique described here: https://web.archive.org/web/20180430214420/http://www.mine-control.com/zack/timesync/timesync.html
+ // to reduce the skew induced by dropped TCP packets that get resent.
+
+ using namespace boost::accumulators;
+
+ accumulator_set<uint32, features<tag::mean, tag::median, tag::variance(lazy)> > latencyAccumulator;
+
+ for (auto pair : _timeSyncClockDeltaQueue)
+ latencyAccumulator(pair.second);
+
+ uint32 latencyMedian = static_cast<uint32>(std::round(median(latencyAccumulator)));
+ uint32 latencyStandardDeviation = static_cast<uint32>(std::round(sqrt(variance(latencyAccumulator))));
+
+ accumulator_set<int64, features<tag::mean> > clockDeltasAfterFiltering;
+ uint32 sampleSizeAfterFiltering = 0;
+ for (auto pair : _timeSyncClockDeltaQueue)
+ {
+ if (pair.second < latencyStandardDeviation + latencyMedian) {
+ clockDeltasAfterFiltering(pair.first);
+ sampleSizeAfterFiltering++;
+ }
+ }
+
+ if (sampleSizeAfterFiltering != 0)
+ {
+ int64 meanClockDelta = static_cast<int64>(std::round(mean(clockDeltasAfterFiltering)));
+ if (std::abs(meanClockDelta - _timeSyncClockDelta) > 25)
+ _timeSyncClockDelta = meanClockDelta;
+ }
+ else if (_timeSyncClockDelta == 0)
+ {
+ std::pair<int64, uint32> back = _timeSyncClockDeltaQueue.back();
+ _timeSyncClockDelta = back.first;
+ }
+}
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 73c54a4dd29..ce5d8d24945 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1042,7 +1042,7 @@ void OpcodeTable::Initialize()
/*0x38E*/ DEFINE_HANDLER(MSG_PARTY_ASSIGNMENT, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandlePartyAssignmentOpcode );
/*0x38F*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_OFFER_PETITION_ERROR, STATUS_NEVER);
/*0x390*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_TIME_SYNC_REQ, STATUS_NEVER);
- /*0x391*/ DEFINE_HANDLER(CMSG_TIME_SYNC_RESP, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleTimeSyncResp );
+ /*0x391*/ DEFINE_HANDLER(CMSG_TIME_SYNC_RESP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleTimeSyncResp );
/*0x392*/ DEFINE_HANDLER(CMSG_SEND_LOCAL_EVENT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
/*0x393*/ DEFINE_HANDLER(CMSG_SEND_GENERAL_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
/*0x394*/ DEFINE_HANDLER(CMSG_SEND_COMBAT_TRIGGER, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h
index 40da8c65534..4cdb4c06a3f 100644
--- a/src/server/game/Server/WorldPacket.h
+++ b/src/server/game/Server/WorldPacket.h
@@ -22,6 +22,7 @@
#include "Common.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
+#include <chrono>
class WorldPacket : public ByteBuffer
{
@@ -38,6 +39,10 @@ class WorldPacket : public ByteBuffer
{
}
+ WorldPacket(WorldPacket&& packet, std::chrono::steady_clock::time_point receivedTime) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode), m_receivedTime(receivedTime)
+ {
+ }
+
WorldPacket(WorldPacket const& right) : ByteBuffer(right), m_opcode(right.m_opcode)
{
}
@@ -76,8 +81,11 @@ class WorldPacket : public ByteBuffer
uint16 GetOpcode() const { return m_opcode; }
void SetOpcode(uint16 opcode) { m_opcode = opcode; }
+ std::chrono::steady_clock::time_point GetReceivedTime() const { return m_receivedTime; }
+
protected:
uint16 m_opcode;
+ std::chrono::steady_clock::time_point m_receivedTime; // only set for a specific set of opcodes, for performance reasons.
};
#endif
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index ca5fa691375..dafb08bd2ce 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -125,17 +125,22 @@ WorldSession::WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldS
m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
m_sessionDbLocaleIndex(locale),
m_latency(0),
- m_clientTimeDelay(0),
m_TutorialsChanged(TUTORIALS_FLAG_NONE),
recruiterId(recruiter),
isRecruiter(isARecruiter),
_RBACData(nullptr),
expireTime(60000), // 1 min after socket loss, session is deleted
forceExit(false),
- m_currentBankerGUID()
+ m_currentBankerGUID(),
+ _timeSyncClockDeltaQueue(6),
+ _timeSyncClockDelta(0),
+ _pendingTimeSyncRequests()
{
memset(m_Tutorials, 0, sizeof(m_Tutorials));
+ _timeSyncNextCounter = 0;
+ _timeSyncTimer = 0;
+
if (sock)
{
m_Address = sock->GetRemoteIpAddress().to_string();
@@ -400,11 +405,23 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (m_Socket && m_Socket->IsOpen() && _warden)
_warden->Update();
+ if (!updater.ProcessUnsafe()) // <=> updater is of type MapSessionFilter
+ {
+ // Send time sync packet every 10s.
+ if (_timeSyncTimer > 0)
+ {
+ if (diff >= _timeSyncTimer)
+ SendTimeSync();
+ else
+ _timeSyncTimer -= diff;
+ }
+ }
+
ProcessQueryCallbacks();
//check if we are safe to proceed with logout
//logout procedure should happen only in World::UpdateSessions() method!!!
- if (updater.ProcessLogout())
+ if (updater.ProcessUnsafe())
{
///- If necessary, log the player out
if (ShouldLogOut(currentTime) && !m_playerLoading)
@@ -1548,3 +1565,22 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
WorldSession::DosProtection::DosProtection(WorldSession* s) : Session(s), _policy((Policy)sWorld->getIntConfig(CONFIG_PACKET_SPOOF_POLICY))
{
}
+
+void WorldSession::ResetTimeSync()
+{
+ _timeSyncNextCounter = 0;
+ _pendingTimeSyncRequests.clear();
+}
+
+void WorldSession::SendTimeSync()
+{
+ WorldPacket data(SMSG_TIME_SYNC_REQ, 4);
+ data << uint32(_timeSyncNextCounter);
+ SendPacket(&data);
+
+ _pendingTimeSyncRequests[_timeSyncNextCounter] = getMSTime();
+
+ // Schedule next sync in 10 sec (except for the 2 first packets, which are spaced by only 5s)
+ _timeSyncTimer = _timeSyncNextCounter == 0 ? 5000 : 10000;
+ _timeSyncNextCounter++;
+}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 7dc9a1d11c7..27098fc60ce 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -31,7 +31,9 @@
#include "QueryCallbackProcessor.h"
#include "SharedDefines.h"
#include <string>
+#include <map>
#include <unordered_map>
+#include <boost/circular_buffer.hpp>
class BigNumber;
class Creature;
@@ -172,7 +174,7 @@ public:
virtual ~PacketFilter() { }
virtual bool Process(WorldPacket* /*packet*/) { return true; }
- virtual bool ProcessLogout() const { return true; }
+ virtual bool ProcessUnsafe() const { return true; }
protected:
WorldSession* const m_pSession;
@@ -190,7 +192,7 @@ public:
virtual bool Process(WorldPacket* packet) override;
//in Map::Update() we do not process player logout!
- virtual bool ProcessLogout() const override { return false; }
+ virtual bool ProcessUnsafe() const override { return false; }
};
//class used to filer only thread-unsafe packets from queue
@@ -438,7 +440,6 @@ class TC_GAME_API WorldSession
uint32 GetLatency() const { return m_latency; }
void SetLatency(uint32 latency) { m_latency = latency; }
- void ResetClientTimeDelay() { m_clientTimeDelay = 0; }
std::atomic<time_t> m_timeOutTime;
@@ -450,6 +451,10 @@ class TC_GAME_API WorldSession
uint32 GetRecruiterId() const { return recruiterId; }
bool IsARecruiter() const { return isRecruiter; }
+ // Time Synchronisation
+ void ResetTimeSync();
+ void SendTimeSync();
+
public: // opcodes handlers
void Handle_NULL(WorldPacket& recvPacket); // not used
@@ -1066,7 +1071,6 @@ class TC_GAME_API WorldSession
LocaleConstant m_sessionDbcLocale;
LocaleConstant m_sessionDbLocaleIndex;
std::atomic<uint32> m_latency;
- std::atomic<uint32> m_clientTimeDelay;
AccountData m_accountData[NUM_ACCOUNT_DATA_TYPES];
uint32 m_Tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
uint8 m_TutorialsChanged;
@@ -1079,6 +1083,15 @@ class TC_GAME_API WorldSession
bool forceExit;
ObjectGuid m_currentBankerGUID;
+ boost::circular_buffer<std::pair<int64, uint32>> _timeSyncClockDeltaQueue; // first member: clockDelta. Second member: latency of the packet exchange that was used to compute that clockDelta.
+ int64 _timeSyncClockDelta;
+ void ComputeNewClockDelta();
+
+ std::map<uint32, uint32> _pendingTimeSyncRequests; // key: counter. value: server time when packet with that counter was sent.
+ uint32 _timeSyncNextCounter;
+ uint32 _timeSyncTimer;
+
+
WorldSession(WorldSession const& right) = delete;
WorldSession& operator=(WorldSession const& right) = delete;
};
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index d05ec4fdb80..7fc21b64053 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -311,6 +311,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
OpcodeClient opcode = static_cast<OpcodeClient>(header->cmd);
WorldPacket packet(opcode, std::move(_packetBuffer));
+ WorldPacket* packetToQueue;
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort());
@@ -360,34 +361,41 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
if (_worldSession)
_worldSession->ResetTimeOutTime(true);
break;
- default:
- {
- sessionGuard.lock();
- LogOpcodeText(opcode, sessionGuard);
+ // todo: handle this packet in the same way of CMSG_TIME_SYNC_RESP
- if (!_worldSession)
- {
- TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
- return ReadDataHandlerResult::Error;
- }
+ case CMSG_TIME_SYNC_RESP:
+ packetToQueue = new WorldPacket(std::move(packet), std::chrono::steady_clock::now());
+ break;
- OpcodeHandler const* handler = opcodeTable[opcode];
- if (!handler)
- {
- TC_LOG_ERROR("network.opcode", "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())).c_str(), _worldSession->GetPlayerInfo().c_str());
- break;
- }
+ default:
+ packetToQueue = new WorldPacket(std::move(packet));
+ break;
+ }
- // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling.
- _worldSession->ResetTimeOutTime(false);
+ sessionGuard.lock();
- // Copy the packet to the heap before enqueuing
- _worldSession->QueuePacket(new WorldPacket(std::move(packet)));
- break;
- }
+ LogOpcodeText(opcode, sessionGuard);
+
+ if (!_worldSession)
+ {
+ TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
+ return ReadDataHandlerResult::Error;
+ }
+
+ OpcodeHandler const* handler = opcodeTable[opcode];
+ if (!handler)
+ {
+ TC_LOG_ERROR("network.opcode", "No defined handler for opcode %s sent by %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())).c_str(), _worldSession->GetPlayerInfo().c_str());
+ return ReadDataHandlerResult::Error;
}
+ // 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(packetToQueue);
+
return ReadDataHandlerResult::Ok;
}
@@ -674,10 +682,7 @@ bool WorldSocket::HandlePing(WorldPacket& recvPacket)
std::lock_guard<std::mutex> sessionGuard(_worldSessionLock);
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().to_string().c_str());