mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-19 08:55:32 +01:00
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:
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
75
src/server/game/Server/Packet.h
Normal file
75
src/server/game/Server/Packet.h
Normal 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__
|
||||
21
src/server/game/Server/Packets/AllPackets.h
Normal file
21
src/server/game/Server/Packets/AllPackets.h
Normal 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__
|
||||
231
src/server/game/Server/Packets/PacketUtilities.h
Normal file
231
src/server/game/Server/Packets/PacketUtilities.h
Normal 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
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user