Core/Network: Move parsing of EarlyProcessClientPacket from WorldSocket::ReadDataHandlerResult to their handler functions

This commit is contained in:
Shauren
2026-01-18 17:00:29 +01:00
parent b384c2bc8b
commit 345091244c
6 changed files with 178 additions and 157 deletions

View File

@@ -60,6 +60,11 @@ WorldPacket const* Pong::Write()
return &_worldPacket;
}
void LogDisconnect::Read()
{
_worldPacket >> Reason;
}
WorldPacket const* AuthChallenge::Write()
{
_worldPacket.append(DosChallenge.data(), DosChallenge.size());

View File

@@ -73,6 +73,18 @@ namespace WorldPackets
uint32 Serial = 0;
};
class LogDisconnect final : public EarlyProcessClientPacket<LogDisconnect>
{
public:
explicit LogDisconnect(WorldPacket&& packet) : EarlyProcessClientPacket(CMSG_LOG_DISCONNECT, std::move(packet)) { }
uint32 Reason = 0;
private:
friend EarlyProcessClientPacket;
void Read() override;
};
class AuthChallenge final : public ServerPacket
{
public:

View File

@@ -325,9 +325,9 @@ void WorldSession::AddInstanceConnection(WorldSession* session, std::weak_ptr<Wo
}
/// Add an incoming packet to the queue
void WorldSession::QueuePacket(WorldPacket* new_packet)
void WorldSession::QueuePacket(WorldPacket&& new_packet)
{
_recvQueue.add(new_packet);
_recvQueue.add(new WorldPacket(std::move(new_packet)));
}
/// Logging helper for unexpected opcodes

View File

@@ -1053,7 +1053,7 @@ class TC_GAME_API WorldSession
// May kick player on false depending on world config (handler should abort)
bool DisallowHyperlinksAndMaybeKick(std::string const& str);
void QueuePacket(WorldPacket* new_packet);
void QueuePacket(WorldPacket&& new_packet);
bool Update(uint32 diff, PacketFilter& updater);
/// Handle the authentication waiting queue (to be completed)

View File

@@ -63,7 +63,7 @@ std::array<uint8, 32> const WorldSocket::EncryptionKeySeed = { 0x71, 0xC9, 0xED,
0x5D, 0xA1, 0x48, 0xC8, 0x30, 0x47, 0x4A, 0xDE, 0xF6, 0x0D, 0x6C, 0xBE, 0x6F, 0xE4, 0x55, 0x73 };
WorldSocket::WorldSocket(Trinity::Net::IoContextTcpSocket&& socket) : BaseSocket(std::move(socket)),
_type(CONNECTION_TYPE_REALM), _key(0), _serverChallenge(), _sessionKey(), _encryptKey(), _OverSpeedPings(0),
_type(CONNECTION_TYPE_REALM), _key(0), _serverChallenge(), _sessionKey(), _encryptKey(), _overSpeedPings(0),
_worldSession(nullptr), _authed(false), _canRequestHotfixes(true), _headerBuffer(sizeof(IncomingPacketHeader)), _sendBufferSize(4096), _compressionStream(nullptr)
{
}
@@ -379,129 +379,53 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
if (sPacketLog->CanLogPacket())
sPacketLog->LogPacket(packet, CLIENT_TO_SERVER, GetRemoteIpAddress(), GetRemotePort(), GetConnectionType());
std::unique_lock<std::mutex> sessionGuard(_worldSessionLock, std::defer_lock);
switch (opcode)
{
case CMSG_PING:
{
LogOpcodeText(opcode, sessionGuard);
WorldPackets::Auth::Ping ping(std::move(packet));
if (!ping.ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_PING", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
if (!HandlePing(ping))
return ReadDataHandlerResult::Error;
break;
}
return HandlePing(std::move(packet));
case CMSG_AUTH_SESSION:
{
LogOpcodeText(opcode, sessionGuard);
if (_authed)
{
// locking just to safely log offending user is probably overkill but we are disconnecting him anyway
if (sessionGuard.try_lock())
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from {}", _worldSession->GetPlayerInfo());
return ReadDataHandlerResult::Error;
}
std::shared_ptr<WorldPackets::Auth::AuthSession> authSession = std::make_shared<WorldPackets::Auth::AuthSession>(std::move(packet));
if (!authSession->ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_AUTH_SESSION", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
HandleAuthSession(authSession);
return ReadDataHandlerResult::WaitingForQuery;
}
return HandleAuthSession(std::move(packet));
case CMSG_AUTH_CONTINUED_SESSION:
{
LogOpcodeText(opcode, sessionGuard);
if (_authed)
{
// locking just to safely log offending user is probably overkill but we are disconnecting him anyway
if (sessionGuard.try_lock())
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from {}", _worldSession->GetPlayerInfo());
return ReadDataHandlerResult::Error;
}
std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet));
if (!authSession->ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_AUTH_CONTINUED_SESSION", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
HandleAuthContinuedSession(authSession);
return ReadDataHandlerResult::WaitingForQuery;
}
return HandleAuthContinuedSession(std::move(packet));
case CMSG_KEEP_ALIVE:
sessionGuard.lock();
LogOpcodeText(opcode, sessionGuard);
if (_worldSession)
{
_worldSession->ResetTimeOutTime(true);
return ReadDataHandlerResult::Ok;
}
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_KEEP_ALIVE without being authenticated", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
return HandleKeepAlive();
case CMSG_LOG_DISCONNECT:
LogOpcodeText(opcode, sessionGuard);
TC_LOG_DEBUG("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_LOG_DISCONNECT reason {}", GetRemoteIpAddress(), packet.read<uint32>());
break;
return HandleLogDisconnect(std::move(packet));
case CMSG_ENABLE_NAGLE:
LogOpcodeText(opcode, sessionGuard);
LogOpcodeText(CMSG_ENABLE_NAGLE);
SetNoDelay(false);
break;
case CMSG_CONNECT_TO_FAILED:
{
sessionGuard.lock();
LogOpcodeText(opcode, sessionGuard);
WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet));
if (!connectToFailed.ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_CONNECT_TO_FAILED", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
HandleConnectToFailed(connectToFailed);
break;
}
return HandleConnectToFailed(std::move(packet));
case CMSG_ENTER_ENCRYPTED_MODE_ACK:
LogOpcodeText(opcode, sessionGuard);
HandleEnterEncryptedModeAck();
break;
case CMSG_HOTFIX_REQUEST:
_canRequestHotfixes = false;
[[fallthrough]];
return HandleEnterEncryptedModeAck();
default:
{
if (opcode == CMSG_TIME_SYNC_RESPONSE || opcode == CMSG_MOVE_INIT_ACTIVE_MOVER_COMPLETE || opcode == CMSG_QUEUED_MESSAGES_END)
packet.SetReceiveTime(std::chrono::steady_clock::now());
else if (opcode == CMSG_HOTFIX_REQUEST)
_canRequestHotfixes = false;
sessionGuard.lock();
std::scoped_lock sessionGuard(_worldSessionLock);
LogOpcodeText(opcode, sessionGuard);
if (!_worldSession)
{
TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = {}", uint32(opcode));
TC_LOG_ERROR("network.opcode", "WorldSocket::ReadDataHandler: Client not authed opcode {}", GetOpcodeNameForLogging(opcode));
return ReadDataHandlerResult::Error;
}
ClientOpcodeHandler const* handler = opcodeTable[opcode];
if (!handler)
if (!opcodeTable[opcode])
{
TC_LOG_ERROR("network.opcode", "No defined handler for opcode {} sent by {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())), _worldSession->GetPlayerInfo());
TC_LOG_ERROR("network.opcode", "WorldSocket::ReadDataHandler: No defined handler for opcode {} sent by {}", GetOpcodeNameForLogging(opcode), _worldSession->GetPlayerInfo());
break;
}
// 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)));
_worldSession->QueuePacket(std::move(packet));
break;
}
}
@@ -509,9 +433,14 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
return ReadDataHandlerResult::Ok;
}
void WorldSocket::LogOpcodeText(OpcodeClient opcode, std::unique_lock<std::mutex> const& guard) const
void WorldSocket::LogOpcodeText(OpcodeClient opcode) const
{
if (!guard || !_worldSession)
TC_LOG_TRACE("network.opcode", "C->S: {} {}", GetRemoteIpAddress(), GetOpcodeNameForLogging(opcode));
}
void WorldSocket::LogOpcodeText(OpcodeClient opcode, std::scoped_lock<std::mutex> const& /*guard*/) const
{
if (!_worldSession)
{
TC_LOG_TRACE("network.opcode", "C->S: {} {}", GetRemoteIpAddress(), GetOpcodeNameForLogging(opcode));
}
@@ -677,29 +606,45 @@ struct AccountInfo
}
};
void WorldSocket::HandleAuthSession(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession)
WorldSocket::ReadDataHandlerResult WorldSocket::HandleAuthSession(WorldPacket&& packet)
{
std::shared_ptr<JSON::RealmList::RealmJoinTicket> joinTicket = std::make_shared<JSON::RealmList::RealmJoinTicket>();
if (!JSON::Deserialize(authSession->RealmJoinTicket, joinTicket.get()))
LogOpcodeText(CMSG_AUTH_SESSION);
if (_authed)
{
std::scoped_lock guard(_worldSessionLock);
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_SESSION from {}", _worldSession->GetPlayerInfo());
return ReadDataHandlerResult::Error;
}
std::shared_ptr callbackData = std::make_shared<std::pair<WorldPackets::Auth::AuthSession, JSON::RealmList::RealmJoinTicket>>(
std::piecewise_construct, std::forward_as_tuple(std::move(packet)), std::forward_as_tuple());
if (!callbackData->first.ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_AUTH_SESSION", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
if (!JSON::Deserialize(callbackData->first.RealmJoinTicket, &callbackData->second))
{
SendAuthResponseError(ERROR_WOW_SERVICES_INVALID_JOIN_TICKET);
DelayedCloseSocket();
return;
return ReadDataHandlerResult::Error;
}
// Get the account information from the auth database
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
stmt->setInt32(0, int32(sRealmList->GetCurrentRealmId().Realm));
stmt->setString(1, joinTicket->gameaccount());
stmt->setString(1, callbackData->second.gameaccount());
QueueQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([this, authSession = std::move(authSession), joinTicket = std::move(joinTicket)](PreparedQueryResult result) mutable
QueueQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([this, callbackData = std::move(callbackData)](PreparedQueryResult const& result) mutable
{
HandleAuthSessionCallback(std::move(authSession), std::move(joinTicket), std::move(result));
HandleAuthSessionCallback(&callbackData->first, &callbackData->second, result.get());
}));
return ReadDataHandlerResult::WaitingForQuery;
}
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession,
std::shared_ptr<JSON::RealmList::RealmJoinTicket> joinTicket, PreparedQueryResult result)
void WorldSocket::HandleAuthSessionCallback(WorldPackets::Auth::AuthSession const* authSession, JSON::RealmList::RealmJoinTicket* joinTicket, PreparedResultSet const* result)
{
// Stop if the account is not found
if (!result)
@@ -712,7 +657,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
std::string address = GetRemoteIpAddress().to_string();
AccountInfo account(result.get());
AccountInfo account(result);
ClientBuild::Info const* buildInfo = ClientBuild::GetBuildInfo(account.Game.Build);
if (!buildInfo)
@@ -906,13 +851,29 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
void WorldSocket::LoadSessionPermissionsCallback(PreparedQueryResult result)
{
// RBAC must be loaded before adding session to check for skip queue permission
_worldSession->GetRBACData()->LoadFromDBCallback(result);
_worldSession->GetRBACData()->LoadFromDBCallback(std::move(result));
SendPacketAndLogOpcode(*WorldPackets::Auth::EnterEncryptedMode(_encryptKey, true).Write());
}
void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession)
WorldSocket::ReadDataHandlerResult WorldSocket::HandleAuthContinuedSession(WorldPacket&& packet)
{
LogOpcodeText(CMSG_AUTH_CONTINUED_SESSION);
if (_authed)
{
std::scoped_lock guard(_worldSessionLock);
TC_LOG_ERROR("network", "WorldSocket::ProcessIncoming: received duplicate CMSG_AUTH_CONTINUED_SESSION from {}", _worldSession->GetPlayerInfo());
return ReadDataHandlerResult::Error;
}
std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet));
if (!authSession->ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_AUTH_CONTINUED_SESSION", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
WorldSession::ConnectToKey key;
key.Raw = authSession->Key;
@@ -921,20 +882,21 @@ void WorldSocket::HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth:
{
SendAuthResponseError(ERROR_DENIED);
DelayedCloseSocket();
return;
return ReadDataHandlerResult::Error;
}
uint32 accountId = uint32(key.Fields.AccountId);
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION);
stmt->setUInt32(0, accountId);
QueueQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([this, authSession = std::move(authSession)](PreparedQueryResult result) mutable
QueueQuery(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([this, authSession = std::move(authSession)](PreparedQueryResult const& result) mutable
{
HandleAuthContinuedSessionCallback(std::move(authSession), std::move(result));
HandleAuthContinuedSessionCallback(authSession.get(), result.get());
}));
return ReadDataHandlerResult::WaitingForQuery;
}
void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession, PreparedQueryResult result)
void WorldSocket::HandleAuthContinuedSessionCallback(WorldPackets::Auth::AuthContinuedSession const* authSession, PreparedResultSet const* result)
{
if (!result)
{
@@ -978,8 +940,50 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket
AsyncRead(Trinity::Net::InvokeReadHandlerCallback<WorldSocket>{ .Socket = this });
}
void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed)
WorldSocket::ReadDataHandlerResult WorldSocket::HandleKeepAlive()
{
std::scoped_lock sessionGuard(_worldSessionLock);
LogOpcodeText(CMSG_KEEP_ALIVE, sessionGuard);
if (!_worldSession)
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_KEEP_ALIVE without being authenticated", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
_worldSession->ResetTimeOutTime(true);
return ReadDataHandlerResult::Ok;
}
WorldSocket::ReadDataHandlerResult WorldSocket::HandleLogDisconnect(WorldPacket&& packet) const
{
LogOpcodeText(CMSG_LOG_DISCONNECT);
WorldPackets::Auth::LogDisconnect logDisconnect(std::move(packet));
if (!logDisconnect.ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_LOG_DISCONNECT", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
TC_LOG_DEBUG("network", "WorldSocket::ReadDataHandler: client {} sent CMSG_LOG_DISCONNECT reason {}", GetRemoteIpAddress(), logDisconnect.Reason);
return ReadDataHandlerResult::Ok;
}
WorldSocket::ReadDataHandlerResult WorldSocket::HandleConnectToFailed(WorldPacket&& packet)
{
std::scoped_lock sessionGuard(_worldSessionLock);
LogOpcodeText(CMSG_CONNECT_TO_FAILED, sessionGuard);
WorldPackets::Auth::ConnectToFailed connectToFailed(std::move(packet));
if (!connectToFailed.ReadNoThrow())
{
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_CONNECT_TO_FAILED", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
if (_worldSession)
{
if (_worldSession->PlayerLoading())
@@ -1005,7 +1009,7 @@ void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& con
break;
}
default:
return;
break;
}
}
//else
@@ -1014,15 +1018,21 @@ void WorldSocket::HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& con
// SendPacketAndLogOpcode(*WorldPackets::Auth::ResumeComms().Write());
//}
}
return ReadDataHandlerResult::Ok;
}
void WorldSocket::HandleEnterEncryptedModeAck()
WorldSocket::ReadDataHandlerResult WorldSocket::HandleEnterEncryptedModeAck()
{
LogOpcodeText(CMSG_ENTER_ENCRYPTED_MODE_ACK);
_authCrypt.Init(_encryptKey);
if (_type == CONNECTION_TYPE_REALM)
sWorld->AddSession(_worldSession);
else
sWorld->AddInstanceSocket(static_pointer_cast<WorldSocket>(shared_from_this()), _key);
return ReadDataHandlerResult::Ok;
}
void WorldSocket::SendAuthResponseError(uint32 code)
@@ -1032,29 +1042,30 @@ void WorldSocket::SendAuthResponseError(uint32 code)
SendPacketAndLogOpcode(*response.Write());
}
bool WorldSocket::HandlePing(WorldPackets::Auth::Ping& ping)
WorldSocket::ReadDataHandlerResult WorldSocket::HandlePing(WorldPacket&& packet)
{
using namespace std::chrono;
LogOpcodeText(CMSG_PING);
if (_LastPingTime == steady_clock::time_point())
WorldPackets::Auth::Ping ping(std::move(packet));
if (!ping.ReadNoThrow())
{
_LastPingTime = steady_clock::now();
TC_LOG_ERROR("network", "WorldSocket::ReadDataHandler(): client {} sent malformed CMSG_PING", GetRemoteIpAddress());
return ReadDataHandlerResult::Error;
}
else
TimePoint lastPingTime = std::exchange(_lastPingTime, TimePoint::clock::now());
if (lastPingTime != TimePoint())
{
steady_clock::time_point now = steady_clock::now();
steady_clock::duration diff = now - _LastPingTime;
_LastPingTime = now;
TimePoint::duration diff = _lastPingTime - lastPingTime;
if (diff < 27s)
{
++_OverSpeedPings;
++_overSpeedPings;
uint32 maxAllowed = sWorld->getIntConfig(CONFIG_MAX_OVERSPEED_PINGS);
if (maxAllowed && _OverSpeedPings > maxAllowed)
if (maxAllowed && _overSpeedPings > maxAllowed)
{
bool ignoresOverspeedPingsLimit = [&]
{
@@ -1067,12 +1078,12 @@ bool WorldSocket::HandlePing(WorldPackets::Auth::Ping& ping)
TC_LOG_ERROR("network", "WorldSocket::HandlePing: {} kicked for over-speed pings (address: {})",
_worldSession->GetPlayerInfo(), GetRemoteIpAddress());
return false;
return ReadDataHandlerResult::Error;
}
}
}
else
_OverSpeedPings = 0;
_overSpeedPings = 0;
}
bool success = [&]
@@ -1089,10 +1100,9 @@ bool WorldSocket::HandlePing(WorldPackets::Auth::Ping& ping)
if (!success)
{
TC_LOG_ERROR("network", "WorldSocket::HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = {}", GetRemoteIpAddress());
return false;
return ReadDataHandlerResult::Error;
}
SendPacketAndLogOpcode(*WorldPackets::Auth::Pong(ping.Serial).Write());
return true;
return ReadDataHandlerResult::Ok;
}

View File

@@ -21,13 +21,12 @@
#include "AsyncCallbackProcessor.h"
#include "AuthDefines.h"
#include "DatabaseEnvFwd.h"
#include "MPSCQueue.h"
#include "MessageBuffer.h"
#include "Socket.h"
#include "WorldPacket.h"
#include "WorldPacketCrypt.h"
#include "MPSCQueue.h"
#include <array>
#include <boost/asio/ip/tcp.hpp>
#include <mutex>
namespace JSON::RealmList
@@ -58,16 +57,10 @@ private:
bool _encrypt;
};
namespace WorldPackets
namespace WorldPackets::Auth
{
class ServerPacket;
namespace Auth
{
class AuthSession;
class AuthContinuedSession;
class ConnectToFailed;
class Ping;
}
class AuthSession;
class AuthContinuedSession;
}
#pragma pack(push, 1)
@@ -99,7 +92,7 @@ class TC_GAME_API WorldSocket final : public Trinity::Net::Socket<>
using BaseSocket = Socket;
public:
WorldSocket(Trinity::Net::IoContextTcpSocket&& socket);
explicit WorldSocket(Trinity::Net::IoContextTcpSocket&& socket);
~WorldSocket();
WorldSocket(WorldSocket const& right) = delete;
@@ -139,22 +132,23 @@ protected:
ReadDataHandlerResult ReadDataHandler();
private:
/// writes network.opcode log
/// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock
void LogOpcodeText(OpcodeClient opcode, std::unique_lock<std::mutex> const& guard) const;
void LogOpcodeText(OpcodeClient opcode) const;
void LogOpcodeText(OpcodeClient opcode, std::scoped_lock<std::mutex> const& guard) const;
/// sends and logs network.opcode without accessing WorldSession
void SendPacketAndLogOpcode(WorldPacket const& packet);
void WritePacketToBuffer(EncryptablePacket const& packet, MessageBuffer& buffer);
uint32 CompressPacket(uint8* buffer, WorldPacket const& packet);
void HandleAuthSession(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession);
void HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession,
std::shared_ptr<JSON::RealmList::RealmJoinTicket> joinTicket, PreparedQueryResult result);
void HandleAuthContinuedSession(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession);
void HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession, PreparedQueryResult result);
ReadDataHandlerResult HandleAuthSession(WorldPacket&& packet);
void HandleAuthSessionCallback(WorldPackets::Auth::AuthSession const* authSession, JSON::RealmList::RealmJoinTicket* joinTicket, PreparedResultSet const* result);
ReadDataHandlerResult HandleAuthContinuedSession(WorldPacket&& packet);
void HandleAuthContinuedSessionCallback(WorldPackets::Auth::AuthContinuedSession const* authSession, PreparedResultSet const* result);
void LoadSessionPermissionsCallback(PreparedQueryResult result);
void HandleConnectToFailed(WorldPackets::Auth::ConnectToFailed& connectToFailed);
bool HandlePing(WorldPackets::Auth::Ping& ping);
void HandleEnterEncryptedModeAck();
ReadDataHandlerResult HandleKeepAlive();
ReadDataHandlerResult HandleLogDisconnect(WorldPacket&& packet) const;
ReadDataHandlerResult HandleConnectToFailed(WorldPacket&& packet);
ReadDataHandlerResult HandlePing(WorldPacket&& packet);
ReadDataHandlerResult HandleEnterEncryptedModeAck();
ConnectionType _type;
uint64 _key;
@@ -164,8 +158,8 @@ private:
SessionKey _sessionKey;
std::array<uint8, 32> _encryptKey;
TimePoint _LastPingTime;
uint32 _OverSpeedPings;
TimePoint _lastPingTime;
uint32 _overSpeedPings;
std::mutex _worldSessionLock;
WorldSession* _worldSession;