Core/Packets: Port packet handling rework from 6.x branch (#17777)

* Core/Packets: Port packet handling rework from 6.x branch

Port packet handling reword from 6.x branch. Old handlers are still used at the moment, these changes allow to port old handlers to new packet-specifc ones.
This commit is contained in:
jackpoz
2016-08-19 22:29:00 +02:00
committed by GitHub
parent 628792f960
commit 4073cc510a
14 changed files with 1903 additions and 1381 deletions

View File

@@ -526,8 +526,6 @@ void Trinity::LocalizedPacketDo<Builder>::operator()(Player* p)
i_builder(*data, loc_idx);
ASSERT(data->GetOpcode() != MSG_NULL_ACTION);
i_data_cache[cache_idx] = data;
}
else

View File

@@ -36,10 +36,10 @@
void WorldSession::HandleMoveWorldportAckOpcode(WorldPacket & /*recvData*/)
{
TC_LOG_DEBUG("network", "WORLD: got MSG_MOVE_WORLDPORT_ACK.");
HandleMoveWorldportAckOpcode();
HandleMoveWorldportAck();
}
void WorldSession::HandleMoveWorldportAckOpcode()
void WorldSession::HandleMoveWorldportAck()
{
// ignore unexpected far teleports
if (!GetPlayer()->IsBeingTeleportedFar())

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PacketBaseWorld_h__
#define PacketBaseWorld_h__
#include "WorldPacket.h"
namespace WorldPackets
{
class TC_GAME_API Packet
{
public:
Packet(WorldPacket&& worldPacket) : _worldPacket(std::move(worldPacket)) { }
virtual ~Packet() = default;
Packet(Packet const& right) = delete;
Packet& operator=(Packet const& right) = delete;
virtual WorldPacket const* Write() = 0;
virtual void Read() = 0;
WorldPacket const* GetRawPacket() const { return &_worldPacket; }
size_t GetSize() const { return _worldPacket.size(); }
protected:
WorldPacket _worldPacket;
};
class ServerPacket : public Packet
{
public:
ServerPacket(OpcodeServer opcode, size_t initialSize = 200) : Packet(WorldPacket(opcode, initialSize)) { }
void Read() override final { ASSERT(!"Read not implemented for server packets."); }
void Clear() { _worldPacket.clear(); }
WorldPacket&& Move() { return std::move(_worldPacket); }
OpcodeServer GetOpcode() const { return OpcodeServer(_worldPacket.GetOpcode()); }
};
class ClientPacket : public Packet
{
public:
ClientPacket(WorldPacket&& packet) : Packet(std::move(packet)) { }
ClientPacket(OpcodeClient expectedOpcode, WorldPacket&& packet) : Packet(std::move(packet)) { ASSERT(GetOpcode() == expectedOpcode); }
WorldPacket const* Write() override final
{
ASSERT(!"Write not allowed for client packets.");
// Shut up some compilers
return nullptr;
}
OpcodeClient GetOpcode() const { return OpcodeClient(_worldPacket.GetOpcode()); }
};
}
#endif // PacketBaseWorld_h__

View File

@@ -0,0 +1,21 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AllPackets_h__
#define AllPackets_h__
#endif // AllPackets_h__

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PacketUtilities_h__
#define PacketUtilities_h__
#include "ByteBuffer.h"
#include <G3D/Vector2.h>
#include <G3D/Vector3.h>
#include <sstream>
#include <array>
inline ByteBuffer& operator<<(ByteBuffer& data, G3D::Vector2 const& v)
{
data << v.x << v.y;
return data;
}
inline ByteBuffer& operator>>(ByteBuffer& data, G3D::Vector2& v)
{
data >> v.x >> v.y;
return data;
}
inline ByteBuffer& operator<<(ByteBuffer& data, G3D::Vector3 const& v)
{
data << v.x << v.y << v.z;
return data;
}
inline ByteBuffer& operator>>(ByteBuffer& data, G3D::Vector3& v)
{
data >> v.x >> v.y >> v.z;
return data;
}
namespace WorldPackets
{
class PacketArrayMaxCapacityException : public ByteBufferException
{
public:
PacketArrayMaxCapacityException(std::size_t requestedSize, std::size_t sizeLimit)
{
std::ostringstream builder;
builder << "Attempted to read more array elements from packet " << requestedSize << " than allowed " << sizeLimit;
message().assign(builder.str());
}
};
/**
* Utility class for automated prevention of loop counter spoofing in client packets
*/
template<typename T, std::size_t N = 1000 /*select a sane default limit*/>
class Array
{
typedef std::vector<T> storage_type;
typedef typename storage_type::value_type value_type;
typedef typename storage_type::size_type size_type;
typedef typename storage_type::reference reference;
typedef typename storage_type::const_reference const_reference;
typedef typename storage_type::iterator iterator;
typedef typename storage_type::const_iterator const_iterator;
public:
Array() : _limit(N) { }
Array(size_type limit) : _limit(limit) { }
iterator begin() { return _storage.begin(); }
const_iterator begin() const { return _storage.begin(); }
iterator end() { return _storage.end(); }
const_iterator end() const { return _storage.end(); }
size_type size() const { return _storage.size(); }
bool empty() const { return _storage.empty(); }
reference operator[](size_type i) { return _storage[i]; }
const_reference operator[](size_type i) const { return _storage[i]; }
void resize(size_type newSize)
{
if (newSize > _limit)
throw PacketArrayMaxCapacityException(newSize, _limit);
_storage.resize(newSize);
}
void reserve(size_type newSize)
{
if (newSize > _limit)
throw PacketArrayMaxCapacityException(newSize, _limit);
_storage.reserve(newSize);
}
void push_back(value_type const& value)
{
if (_storage.size() >= _limit)
throw PacketArrayMaxCapacityException(_storage.size() + 1, _limit);
_storage.push_back(value);
}
void push_back(value_type&& value)
{
if (_storage.size() >= _limit)
throw PacketArrayMaxCapacityException(_storage.size() + 1, _limit);
_storage.push_back(std::forward<value_type>(value));
}
private:
storage_type _storage;
size_type _limit;
};
template <typename T>
class CompactArray
{
public:
CompactArray() : _mask(0) { }
CompactArray(CompactArray const& right)
: _mask(right._mask), _contents(right._contents) { }
CompactArray(CompactArray&& right)
: _mask(right._mask), _contents(std::move(right._contents))
{
right._mask = 0;
}
CompactArray& operator= (CompactArray const& right)
{
_mask = right._mask;
_contents = right._contents;
return *this;
}
CompactArray& operator= (CompactArray&& right)
{
_mask = right._mask;
right._mask = 0;
_contents = std::move(right._contents);
return *this;
}
uint32 GetMask() const { return _mask; }
T const& operator[](size_t index) const { return _contents.at(index); }
size_t GetSize() const { return _contents.size(); }
void Insert(size_t index, T const& value)
{
ASSERT(index < 0x20);
_mask |= 1 << index;
if (_contents.size() <= index)
_contents.resize(index + 1);
_contents[index] = value;
}
void Clear()
{
_mask = 0;
_contents.clear();
}
bool operator==(CompactArray const& r) const
{
if (_mask != r._mask)
return false;
return _contents == r._contents;
}
bool operator!=(CompactArray const& r) const { return !(*this == r); }
private:
uint32 _mask;
std::vector<T> _contents;
};
template <typename T>
ByteBuffer& operator<<(ByteBuffer& data, CompactArray<T> const& v)
{
uint32 mask = v.GetMask();
data << uint32(mask);
for (size_t i = 0; i < v.GetSize(); ++i)
{
if (mask & (1 << i))
data << v[i];
}
return data;
}
template <typename T>
ByteBuffer& operator>>(ByteBuffer& data, CompactArray<T>& v)
{
uint32 mask;
data >> mask;
for (size_t index = 0; mask != 0; mask >>= 1, ++index)
{
if ((mask & 1) != 0)
{
T value;
data >> value;
v.Insert(index, value);
}
}
return data;
}
}
#endif // PacketUtilities_h__

File diff suppressed because it is too large Load Diff

View File

@@ -24,11 +24,10 @@
#define _OPCODES_H
#include "Common.h"
#include <iomanip>
/// List of Opcodes
enum Opcodes
enum Opcodes : uint16
{
MSG_NULL_ACTION = 0x000,
CMSG_BOOTME = 0x001,
CMSG_DBLOOKUP = 0x002,
SMSG_DBLOOKUP = 0x003,
@@ -1342,6 +1341,15 @@ enum Opcodes
NUM_MSG_TYPES = 0x51F
};
enum OpcodeMisc : uint16
{
NUM_OPCODE_HANDLERS = NUM_MSG_TYPES,
NULL_OPCODE = 0x0000
};
typedef Opcodes OpcodeClient;
typedef Opcodes OpcodeServer;
/// Player state
enum SessionStatus
{
@@ -1365,30 +1373,92 @@ class WorldPacket;
#pragma pack(push, 1)
struct OpcodeHandler
class OpcodeHandler
{
char const* name;
SessionStatus status;
PacketProcessing packetProcessing;
void (WorldSession::*handler)(WorldPacket& recvPacket);
public:
OpcodeHandler(char const* name, SessionStatus status) : Name(name), Status(status) { }
virtual ~OpcodeHandler() { }
char const* Name;
SessionStatus Status;
};
TC_GAME_API extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
class ClientOpcodeHandler : public OpcodeHandler
{
public:
ClientOpcodeHandler(char const* name, SessionStatus status, PacketProcessing processing)
: OpcodeHandler(name, status), ProcessingPlace(processing) { }
virtual void Call(WorldSession* session, WorldPacket& packet) const = 0;
PacketProcessing ProcessingPlace;
};
class ServerOpcodeHandler : public OpcodeHandler
{
public:
ServerOpcodeHandler(char const* name, SessionStatus status)
: OpcodeHandler(name, status) { }
};
class OpcodeTable
{
public:
OpcodeTable()
{
memset(_internalTableClient, 0, sizeof(_internalTableClient));
}
OpcodeTable(OpcodeTable const&) = delete;
OpcodeTable& operator=(OpcodeTable const&) = delete;
~OpcodeTable()
{
for (uint16 i = 0; i < NUM_OPCODE_HANDLERS; ++i)
{
delete _internalTableClient[i];
}
}
void Initialize();
ClientOpcodeHandler const* operator[](Opcodes index) const
{
return _internalTableClient[index];
}
private:
template<typename Handler, Handler HandlerFunction>
void ValidateAndSetClientOpcode(OpcodeClient opcode, char const* name, SessionStatus status, PacketProcessing processing);
void ValidateAndSetServerOpcode(OpcodeServer opcode, char const* name, SessionStatus status);
ClientOpcodeHandler* _internalTableClient[NUM_OPCODE_HANDLERS];
};
extern OpcodeTable opcodeTable;
#pragma pack(pop)
/// Lookup opcode name for human understandable logging
inline const char* LookupOpcodeName(uint16 id)
{
if (id >= NUM_MSG_TYPES)
return "Received unknown opcode, it's more than max!";
return opcodeTable[id].name;
}
inline std::string GetOpcodeNameForLogging(uint16 opcode)
/// Lookup opcode name for human understandable logging (T = OpcodeClient|OpcodeServer)
template<typename T>
inline std::string GetOpcodeNameForLogging(T id)
{
uint16 opcode = uint16(id);
std::ostringstream ss;
ss << '[' << LookupOpcodeName(opcode) << " 0x" << std::hex << std::uppercase << opcode << std::nouppercase << " (" << std::dec << opcode << ")]";
ss << '[';
if (static_cast<uint16>(id) < NUM_OPCODE_HANDLERS)
{
if (OpcodeHandler const* handler = opcodeTable[id])
ss << handler->Name;
else
ss << "UNKNOWN OPCODE";
}
else
ss << "INVALID OPCODE";
ss << " 0x" << std::hex << std::setw(4) << std::setfill('0') << std::uppercase << opcode << std::nouppercase << std::dec << " (" << opcode << ")]";
return ss.str();
}

View File

@@ -20,17 +20,19 @@
#define TRINITYCORE_WORLDPACKET_H
#include "Common.h"
#include "Opcodes.h"
#include "ByteBuffer.h"
class WorldPacket : public ByteBuffer
{
public:
// just container for later use
WorldPacket() : ByteBuffer(0), m_opcode(0)
WorldPacket() : ByteBuffer(0), m_opcode(NULL_OPCODE)
{
}
explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
WorldPacket(uint16 opcode, size_t res = 200) : ByteBuffer(res),
m_opcode(opcode) { }
WorldPacket(WorldPacket&& packet) : ByteBuffer(std::move(packet)), m_opcode(packet.m_opcode)
{
@@ -51,9 +53,20 @@ class WorldPacket : public ByteBuffer
return *this;
}
WorldPacket& operator=(WorldPacket&& right)
{
if (this != &right)
{
m_opcode = right.m_opcode;
ByteBuffer::operator=(std::move(right));
}
return *this;
}
WorldPacket(uint16 opcode, MessageBuffer&& buffer) : ByteBuffer(std::move(buffer)), m_opcode(opcode) { }
void Initialize(uint16 opcode, size_t newres=200)
void Initialize(uint16 opcode, size_t newres = 200)
{
clear();
_storage.reserve(newres);

View File

@@ -43,6 +43,7 @@
#include "WardenWin.h"
#include "MoveSpline.h"
#include "WardenMac.h"
#include "PacketUtilities.h"
#include "Metric.h"
#include <zlib.h>
@@ -55,14 +56,14 @@ std::string const DefaultPlayerName = "<none>";
bool MapSessionFilter::Process(WorldPacket* packet)
{
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
//let's check if our opcode can be really processed in Map::Update()
if (opHandle.packetProcessing == PROCESS_INPLACE)
if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//we do not process thread-unsafe packets
if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return false;
Player* player = m_pSession->GetPlayer();
@@ -77,13 +78,14 @@ bool MapSessionFilter::Process(WorldPacket* packet)
//OR packet handler is not thread-safe!
bool WorldSessionFilter::Process(WorldPacket* packet)
{
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
//check if packet handler is supposed to be safe
if (opHandle.packetProcessing == PROCESS_INPLACE)
if (opHandle->ProcessingPlace == PROCESS_INPLACE)
return true;
//thread-unsafe packets should be processed in World::UpdateSessions()
if (opHandle.packetProcessing == PROCESS_THREADUNSAFE)
if (opHandle->ProcessingPlace == PROCESS_THREADUNSAFE)
return true;
//no player attached? -> our client! ^^
@@ -190,6 +192,8 @@ ObjectGuid::LowType WorldSession::GetGUIDLow() const
/// Send a packet to the client
void WorldSession::SendPacket(WorldPacket const* packet)
{
ASSERT(packet->GetOpcode() != NULL_OPCODE);
if (!m_Socket)
return;
@@ -229,7 +233,7 @@ void WorldSession::SendPacket(WorldPacket const* packet)
sScriptMgr->OnPacketSend(this, *packet);
TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetPlayerInfo().c_str(), GetOpcodeNameForLogging(packet->GetOpcode()).c_str());
TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetPlayerInfo().c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet->GetOpcode())).c_str());
m_Socket->SendPacket(*packet);
}
@@ -243,7 +247,7 @@ void WorldSession::QueuePacket(WorldPacket* new_packet)
void WorldSession::LogUnexpectedOpcode(WorldPacket* packet, const char* status, const char *reason)
{
TC_LOG_ERROR("network.opcode", "Received unexpected opcode %s Status: %s Reason: %s from %s",
GetOpcodeNameForLogging(packet->GetOpcode()).c_str(), status, reason, GetPlayerInfo().c_str());
GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str(), status, reason, GetPlayerInfo().c_str());
}
/// Logging helper for unexpected opcodes
@@ -253,7 +257,7 @@ void WorldSession::LogUnprocessedTail(WorldPacket* packet)
return;
TC_LOG_TRACE("network.opcode", "Unprocessed tail data (read stop at %u from %u) Opcode %s from %s",
uint32(packet->rpos()), uint32(packet->wpos()), GetOpcodeNameForLogging(packet->GetOpcode()).c_str(), GetPlayerInfo().c_str());
uint32(packet->rpos()), uint32(packet->wpos()), GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str(), GetPlayerInfo().c_str());
packet->print_storage();
}
@@ -279,10 +283,10 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
while (m_Socket && _recvQueue.next(packet, updater))
{
OpcodeHandler const& opHandle = opcodeTable[packet->GetOpcode()];
ClientOpcodeHandler const* opHandle = opcodeTable[static_cast<OpcodeClient>(packet->GetOpcode())];
try
{
switch (opHandle.status)
switch (opHandle->Status)
{
case STATUS_LOGGEDIN:
if (!_player)
@@ -295,13 +299,13 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
requeuePackets.push_back(packet);
deletePacket = false;
TC_LOG_DEBUG("network", "Re-enqueueing packet with opcode %s with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", GetOpcodeNameForLogging(packet->GetOpcode()).c_str());
"Player is currently not in world yet.", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str());
}
}
else if (_player->IsInWorld() && AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
opHandle->Call(this, *packet);
LogUnprocessedTail(packet);
}
// lag can cause STATUS_LOGGEDIN opcodes to arrive after the player started a transfer
@@ -314,7 +318,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
{
// not expected _player or must checked in packet hanlder
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
opHandle->Call(this, *packet);
LogUnprocessedTail(packet);
}
break;
@@ -326,7 +330,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
else if (AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
opHandle->Call(this, *packet);
LogUnprocessedTail(packet);
}
break;
@@ -346,20 +350,25 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (AntiDOS.EvaluateOpcode(*packet, currentTime))
{
sScriptMgr->OnPacketReceive(this, *packet);
(this->*opHandle.handler)(*packet);
opHandle->Call(this, *packet);
LogUnprocessedTail(packet);
}
break;
case STATUS_NEVER:
TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
TC_LOG_ERROR("network.opcode", "Received not allowed opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str()
, GetPlayerInfo().c_str());
break;
case STATUS_UNHANDLED:
TC_LOG_DEBUG("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(packet->GetOpcode()).c_str()
TC_LOG_DEBUG("network.opcode", "Received not handled opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str()
, GetPlayerInfo().c_str());
break;
}
}
catch (WorldPackets::PacketArrayMaxCapacityException const& pamce)
{
TC_LOG_ERROR("network", "PacketArrayMaxCapacityException: %s while parsing %s from %s.",
pamce.what(), GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet->GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
catch (ByteBufferException const&)
{
TC_LOG_ERROR("network", "WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
@@ -424,7 +433,7 @@ void WorldSession::LogoutPlayer(bool save)
{
// finish pending transfers before starting the logout
while (_player && _player->IsBeingTeleportedFar())
HandleMoveWorldportAckOpcode();
HandleMoveWorldportAck();
m_playerLogout = true;
m_playerSave = save;
@@ -487,7 +496,7 @@ void WorldSession::LogoutPlayer(bool save)
// Repop at GraveYard or other player far teleport will prevent saving player because of not present map
// Teleport player immediately for correct player save
while (_player->IsBeingTeleportedFar())
HandleMoveWorldportAckOpcode();
HandleMoveWorldportAck();
///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members
if (Guild* guild = sGuildMgr->GetGuildById(_player->GetGuildId()))
@@ -621,28 +630,27 @@ char const* WorldSession::GetTrinityString(uint32 entry) const
return sObjectMgr->GetTrinityString(entry, GetSessionDbLocaleIndex());
}
void WorldSession::Handle_NULL(WorldPacket& recvPacket)
void WorldSession::Handle_NULL(WorldPacket& null)
{
TC_LOG_ERROR("network.opcode", "Received unhandled opcode %s from %s"
, GetOpcodeNameForLogging(recvPacket.GetOpcode()).c_str(), GetPlayerInfo().c_str());
TC_LOG_ERROR("network.opcode", "Received unhandled opcode %s from %s", GetOpcodeNameForLogging(static_cast<OpcodeClient>(null.GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
void WorldSession::Handle_EarlyProccess(WorldPacket& recvPacket)
{
TC_LOG_ERROR("network.opcode", "Received opcode %s that must be processed in WorldSocket::OnRead from %s"
, GetOpcodeNameForLogging(recvPacket.GetOpcode()).c_str(), GetPlayerInfo().c_str());
, GetOpcodeNameForLogging(static_cast<OpcodeClient>(recvPacket.GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
void WorldSession::Handle_ServerSide(WorldPacket& recvPacket)
{
TC_LOG_ERROR("network.opcode", "Received server-side opcode %s from %s"
, GetOpcodeNameForLogging(recvPacket.GetOpcode()).c_str(), GetPlayerInfo().c_str());
, GetOpcodeNameForLogging(static_cast<OpcodeServer>(recvPacket.GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
void WorldSession::Handle_Deprecated(WorldPacket& recvPacket)
{
TC_LOG_ERROR("network.opcode", "Received deprecated opcode %s from %s"
, GetOpcodeNameForLogging(recvPacket.GetOpcode()).c_str(), GetPlayerInfo().c_str());
, GetOpcodeNameForLogging(static_cast<OpcodeClient>(recvPacket.GetOpcode())).c_str(), GetPlayerInfo().c_str());
}
void WorldSession::SendAuthWaitQue(uint32 position)
@@ -1316,7 +1324,7 @@ bool WorldSession::DosProtection::EvaluateOpcode(WorldPacket& p, time_t time) co
TC_LOG_WARN("network", "AntiDOS: Account %u, IP: %s, Ping: %u, Character: %s, flooding packet (opc: %s (0x%X), count: %u)",
Session->GetAccountId(), Session->GetRemoteAddress().c_str(), Session->GetLatency(), Session->GetPlayerName().c_str(),
opcodeTable[p.GetOpcode()].name, p.GetOpcode(), packetCounter.amountCounter);
opcodeTable[static_cast<OpcodeClient>(p.GetOpcode())]->Name, p.GetOpcode(), packetCounter.amountCounter);
switch (_policy)
{
@@ -1577,7 +1585,6 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
maxPacketCounterAllowed = PLAYER_SLOTS_COUNT;
break;
}
default:
{
maxPacketCounterAllowed = 100;

View File

@@ -28,8 +28,7 @@
#include "AddonMgr.h"
#include "DatabaseEnv.h"
#include "World.h"
#include "Opcodes.h"
#include "WorldPacket.h"
#include "Packet.h"
#include "Cryptography/BigNumber.h"
#include "AccountMgr.h"
#include <unordered_set>
@@ -70,6 +69,9 @@ namespace rbac
class RBACData;
}
namespace WorldPackets
{
}
enum AccountDataType
{
GLOBAL_CONFIG_CACHE = 0, // 0x01 g
@@ -558,7 +560,7 @@ class TC_GAME_API WorldSession
void HandleGameObjectQueryOpcode(WorldPacket& recvPacket);
void HandleMoveWorldportAckOpcode(WorldPacket& recvPacket);
void HandleMoveWorldportAckOpcode(); // for server-side calls
void HandleMoveWorldportAck(); // for server-side calls
void HandleMovementOpcodes(WorldPacket& recvPacket);
void HandleSetActiveMoverOpcode(WorldPacket& recvData);

View File

@@ -311,8 +311,7 @@ struct AccountInfo
WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
{
ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer());
uint16 opcode = uint16(header->cmd);
OpcodeClient opcode = static_cast<OpcodeClient>(header->cmd);
WorldPacket packet(opcode, std::move(_packetBuffer));
@@ -373,6 +372,13 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
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());
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();
@@ -386,7 +392,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
return ReadDataHandlerResult::Ok;
}
void WorldSocket::LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const
void WorldSocket::LogOpcodeText(OpcodeClient opcode, std::unique_lock<std::mutex> const& guard) const
{
if (!guard)
{
@@ -401,7 +407,7 @@ void WorldSocket::LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> cons
void WorldSocket::SendPacketAndLogOpcode(WorldPacket const& packet)
{
TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetRemoteIpAddress().to_string().c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str());
TC_LOG_TRACE("network.opcode", "S->C: %s %s", GetRemoteIpAddress().to_string().c_str(), GetOpcodeNameForLogging(static_cast<OpcodeServer>(packet.GetOpcode())).c_str());
SendPacket(packet);
}

View File

@@ -33,6 +33,10 @@
using boost::asio::ip::tcp;
class EncryptablePacket;
namespace WorldPackets
{
class ServerPacket;
}
#pragma pack(push, 1)
struct ClientPktHeader
@@ -41,7 +45,7 @@ struct ClientPktHeader
uint32 cmd;
bool IsValidSize() const { return size >= 4 && size < 10240; }
bool IsValidOpcode() const { return cmd < NUM_MSG_TYPES; }
bool IsValidOpcode() const { return cmd < NUM_OPCODE_HANDLERS; }
};
#pragma pack(pop)
@@ -82,7 +86,7 @@ private:
/// writes network.opcode log
/// accessing WorldSession is not threadsafe, only do it when holding _worldSessionLock
void LogOpcodeText(uint16 opcode, std::unique_lock<std::mutex> const& guard) const;
void LogOpcodeText(OpcodeClient opcode, std::unique_lock<std::mutex> const& guard) const;
/// sends and logs network.opcode without accessing WorldSession
void SendPacketAndLogOpcode(WorldPacket const& packet);
void HandleSendAuthSession();

View File

@@ -141,7 +141,6 @@ class CreatureTextLocalizer
{
messageTemplate = new WorldPacket();
whisperGUIDpos = _builder(messageTemplate, loc_idx);
ASSERT(messageTemplate->GetOpcode() != MSG_NULL_ACTION);
_packetCache[loc_idx] = new std::pair<WorldPacket*, size_t>(messageTemplate, whisperGUIDpos);
}
else

View File

@@ -1891,6 +1891,9 @@ void World::SetInitialWorldSettings()
// Delete all custom channels which haven't been used for PreserveCustomChannelDuration days.
Channel::CleanOldChannelsInDB();
TC_LOG_INFO("server.loading", "Initializing Opcodes...");
opcodeTable.Initialize();
TC_LOG_INFO("server.loading", "Starting Arena Season...");
sGameEventMgr->StartArenaSeason();