aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-05-05 18:19:36 +0200
committerShauren <shauren.trinity@gmail.com>2024-05-05 18:19:36 +0200
commite7c0ea904823934a436a1b97780b19069cd09e3c (patch)
treee299485d3d25b3e636c798fbd719093d4478aed0 /src
parentef63bbe4927f04fa7bb19d530ce082a4d849c989 (diff)
Core/Misc: Refactor OpcodeTable reducing its size and modernize array/pointer storage
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp107
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h90
-rw-r--r--src/server/game/Server/WorldSession.cpp11
-rw-r--r--src/server/game/Server/WorldSocket.cpp4
4 files changed, 102 insertions, 110 deletions
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index 054cf392d94..10c07c3a7ec 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -20,20 +20,17 @@
#include "WorldSession.h"
#include "Packets/AllPackets.h"
-template<class PacketClass, void(WorldSession::*HandlerFunction)(PacketClass&)>
-class PacketHandler : public ClientOpcodeHandler
+namespace
{
-public:
- PacketHandler(char const* name, SessionStatus status, PacketProcessing processing) : ClientOpcodeHandler(name, status, processing) { }
-
- void Call(WorldSession* session, WorldPacket& packet) const override
- {
- std::remove_cv_t<PacketClass> nicePacket(std::move(packet));
- nicePacket.Read();
- (session->*HandlerFunction)(nicePacket);
- session->LogUnprocessedTail(nicePacket.GetRawPacket());
- }
-};
+template<class PacketClass, void(WorldSession::* HandlerFunction)(PacketClass&)>
+void CallHandlerWrapper(WorldSession* session, WorldPacket& packet)
+{
+ std::remove_cv_t<PacketClass> nicePacket(std::move(packet));
+ nicePacket.Read();
+ (session->*HandlerFunction)(nicePacket);
+ session->LogUnprocessedTail(nicePacket.GetRawPacket());
+}
+}
OpcodeTable opcodeTable;
@@ -48,93 +45,100 @@ struct get_packet_class<void(WorldSession::*)(PacketClass&)>
using type = PacketClass;
};
-OpcodeTable::OpcodeTable()
-{
- memset(_internalTableClient, 0, sizeof(_internalTableClient));
- memset(_internalTableServer, 0, sizeof(_internalTableServer));
-}
+OpcodeTable::OpcodeTable() = default;
-OpcodeTable::~OpcodeTable()
-{
- for (uint16 i = 0; i < NUM_OPCODE_HANDLERS; ++i)
- {
- delete _internalTableClient[i];
- delete _internalTableServer[i];
- }
-}
+OpcodeTable::~OpcodeTable() = default;
bool OpcodeTable::ValidateClientOpcode(OpcodeClient opcode, char const* name) const
{
- if (uint32(opcode) == NULL_OPCODE)
+ if (opcode == UNKNOWN_OPCODE)
{
TC_LOG_ERROR("network", "Opcode {} does not have a value", name);
return false;
}
- if (uint32(opcode) >= NUM_OPCODE_HANDLERS)
+ if (opcode < MIN_CMSG_OPCODE_NUMBER || opcode > MAX_CMSG_OPCODE_NUMBER)
{
TC_LOG_ERROR("network", "Tried to set handler for an invalid opcode {}", opcode);
return false;
}
- if (_internalTableClient[opcode] != nullptr)
+ if ((*this)[opcode] != nullptr)
{
- TC_LOG_ERROR("network", "Tried to override client handler of {} with {} (opcode {})", _internalTableClient[opcode]->Name, name, opcode);
+ TC_LOG_ERROR("network", "Tried to override client handler of {} with {} (opcode {})", (*this)[opcode]->Name, name, opcode);
return false;
}
return true;
}
-template<typename Handler, Handler HandlerFunction>
-void OpcodeTable::ValidateAndSetClientOpcode(OpcodeClient opcode, char const* name, SessionStatus status, PacketProcessing processing)
+void OpcodeTable::ValidateAndSetClientOpcode(OpcodeClient opcode, char const* name, SessionStatus status, ClientOpcodeHandler::HandlerFunction call, PacketProcessing processing)
{
if (!ValidateClientOpcode(opcode, name))
return;
- _internalTableClient[opcode] = new PacketHandler<typename get_packet_class<Handler>::type, HandlerFunction>(name, status, processing);
+ _internalTableClient[opcode - MIN_CMSG_OPCODE_NUMBER].reset(new ClientOpcodeHandler{
+ .Name = name,
+ .Status = status,
+ .Call = call,
+ .ProcessingPlace = processing
+ });
}
-void OpcodeTable::ValidateAndSetServerOpcode(OpcodeServer opcode, char const* name, SessionStatus status, ConnectionType conIdx)
+bool OpcodeTable::ValidateServerOpcode(OpcodeServer opcode, char const* name, ConnectionType conIdx) const
{
- if (uint32(opcode) == NULL_OPCODE)
+ if (opcode == UNKNOWN_OPCODE)
{
TC_LOG_ERROR("network", "Opcode {} does not have a value", name);
- return;
+ return false;
}
- if (uint32(opcode) >= NUM_OPCODE_HANDLERS)
+ if (opcode < MIN_SMSG_OPCODE_NUMBER || opcode > MAX_SMSG_OPCODE_NUMBER)
{
TC_LOG_ERROR("network", "Tried to set handler for an invalid opcode {}", opcode);
- return;
+ return false;
}
if (conIdx >= MAX_CONNECTION_TYPES)
{
TC_LOG_ERROR("network", "Tried to set invalid connection type {} for opcode {}", conIdx, name);
- return;
+ return false;
}
if (IsInstanceOnlyOpcode(opcode) && conIdx != CONNECTION_TYPE_INSTANCE)
{
TC_LOG_ERROR("network", "Tried to set invalid connection type {} for instance only opcode {}", conIdx, name);
- return;
+ return false;
}
- if (_internalTableServer[opcode] != nullptr)
+ if ((*this)[opcode] != nullptr)
{
- TC_LOG_ERROR("network", "Tried to override server handler of {} with {} (opcode {})", opcodeTable[opcode]->Name, name, opcode);
- return;
+ TC_LOG_ERROR("network", "Tried to override server handler of {} with {} (opcode {})", (*this)[opcode]->Name, name, opcode);
+ return false;
}
- _internalTableServer[opcode] = new ServerOpcodeHandler(name, status, conIdx);
+ return true;
+}
+
+void OpcodeTable::ValidateAndSetServerOpcode(OpcodeServer opcode, char const* name, SessionStatus status, ConnectionType conIdx)
+{
+ if (!ValidateServerOpcode(opcode, name, conIdx))
+ return;
+
+ _internalTableServer[opcode - MIN_SMSG_OPCODE_NUMBER].reset(new ServerOpcodeHandler{ .Name = name, .Status = status, .ConnectionIndex = conIdx });
}
/// Correspondence between opcodes and their names
void OpcodeTable::Initialize()
{
+ InitializeClientOpcodes();
+ InitializeServerOpcodes();
+}
+
+void OpcodeTable::InitializeClientOpcodes()
+{
#define DEFINE_HANDLER(opcode, status, processing, handler) \
- ValidateAndSetClientOpcode<decltype(handler), handler>(opcode, #opcode, status, processing)
+ ValidateAndSetClientOpcode(opcode, #opcode, status, &CallHandlerWrapper<typename get_packet_class<decltype(handler)>::type, handler>, processing)
DEFINE_HANDLER(CMSG_ABANDON_NPE_RESPONSE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL);
DEFINE_HANDLER(CMSG_ACCEPT_GUILD_INVITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleGuildAcceptInvite);
@@ -1002,7 +1006,10 @@ void OpcodeTable::Initialize()
DEFINE_HANDLER(CMSG_WRAP_ITEM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleWrapItem);
#undef DEFINE_HANDLER
+}
+void OpcodeTable::InitializeServerOpcodes()
+{
#define DEFINE_SERVER_OPCODE_HANDLER(opcode, status, con) \
static_assert((status) == STATUS_NEVER || (status) == STATUS_UNHANDLED, "Invalid status for server opcode"); \
ValidateAndSetServerOpcode(opcode, #opcode, status, con)
@@ -2203,15 +2210,15 @@ void OpcodeTable::Initialize()
#undef DEFINE_SERVER_OPCODE_HANDLER
}
-template<typename T>
+template<std::size_t MIN_OPCODE, std::size_t MAX_OPCODE, typename T>
inline std::string GetOpcodeNameForLoggingImpl(T id)
{
uint32 opcode = uint32(id);
char const* name = nullptr;
- if (opcode < NUM_OPCODE_HANDLERS)
+ if (opcode >= MIN_OPCODE && opcode <= MAX_OPCODE)
{
- if (OpcodeHandler const* handler = opcodeTable[id])
+ if (auto const* handler = opcodeTable[id])
name = handler->Name;
else
name = "UNKNOWN OPCODE";
@@ -2224,10 +2231,10 @@ inline std::string GetOpcodeNameForLoggingImpl(T id)
std::string GetOpcodeNameForLogging(OpcodeClient opcode)
{
- return GetOpcodeNameForLoggingImpl(opcode);
+ return GetOpcodeNameForLoggingImpl<MIN_CMSG_OPCODE_NUMBER, MAX_CMSG_OPCODE_NUMBER>(opcode);
}
std::string GetOpcodeNameForLogging(OpcodeServer opcode)
{
- return GetOpcodeNameForLoggingImpl(opcode);
+ return GetOpcodeNameForLoggingImpl<MIN_SMSG_OPCODE_NUMBER, MAX_SMSG_OPCODE_NUMBER>(opcode);
}
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index b6436a5dd03..84b20b9e458 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -23,6 +23,8 @@
#define _OPCODES_H
#include "Define.h"
+#include <array>
+#include <memory>
#include <string>
enum ConnectionType : int8
@@ -34,13 +36,15 @@ enum ConnectionType : int8
CONNECTION_TYPE_DEFAULT = -1
};
-enum OpcodeMisc : uint16
-{
- MAX_OPCODE = 0x3FFF,
- NUM_OPCODE_HANDLERS = (MAX_OPCODE + 1),
- UNKNOWN_OPCODE = 0xFFFF,
- NULL_OPCODE = 0xBADD
-};
+constexpr std::size_t MIN_CMSG_OPCODE_NUMBER = 0x305C;
+constexpr std::size_t MAX_CMSG_OPCODE_NUMBER = 0x3A63;
+constexpr std::size_t NUM_CMSG_OPCODES = MAX_CMSG_OPCODE_NUMBER - MIN_CMSG_OPCODE_NUMBER + 1;
+
+constexpr std::size_t MIN_SMSG_OPCODE_NUMBER = 0x256C;
+constexpr std::size_t MAX_SMSG_OPCODE_NUMBER = 0x3052;
+constexpr std::size_t NUM_SMSG_OPCODES = MAX_SMSG_OPCODE_NUMBER - MIN_SMSG_OPCODE_NUMBER + 1;
+
+constexpr uint16 UNKNOWN_OPCODE = 0xBADD; // special marker value for uninitialized WorldPackets
enum OpcodeClient : uint16
{
@@ -2107,10 +2111,10 @@ enum OpcodeServer : uint16
SMSG_MULTIPLE_PACKETS = 0x3051,
// Deleted opcodes, here only to allow compile
- SMSG_ARENA_TEAM_STATS = 0xBADD,
+ SMSG_ARENA_TEAM_STATS = UNKNOWN_OPCODE,
};
-inline bool IsInstanceOnlyOpcode(uint32 opcode)
+constexpr bool IsInstanceOnlyOpcode(uint32 opcode)
{
switch (opcode)
{
@@ -2151,67 +2155,53 @@ enum PacketProcessing
class WorldPacket;
class WorldSession;
-class OpcodeHandler
+struct ClientOpcodeHandler final
{
-public:
- OpcodeHandler(char const* name, SessionStatus status) : Name(name), Status(status) { }
- virtual ~OpcodeHandler() { }
+ using HandlerFunction = void (*)(WorldSession* session, WorldPacket& packet);
char const* Name;
SessionStatus Status;
-};
-
-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;
-
+ HandlerFunction Call;
PacketProcessing ProcessingPlace;
};
-class ServerOpcodeHandler : public OpcodeHandler
+struct ServerOpcodeHandler final
{
-public:
- ServerOpcodeHandler(char const* name, SessionStatus status, ConnectionType conIdx)
- : OpcodeHandler(name, status), ConnectionIndex(conIdx) { }
-
+ char const* Name;
+ SessionStatus Status;
ConnectionType ConnectionIndex;
};
class OpcodeTable
{
- public:
- OpcodeTable();
-
- OpcodeTable(OpcodeTable const&) = delete;
- OpcodeTable& operator=(OpcodeTable const&) = delete;
+public:
+ OpcodeTable();
+ ~OpcodeTable();
- ~OpcodeTable();
+ void Initialize();
- void Initialize();
+ ClientOpcodeHandler const* operator[](OpcodeClient index) const
+ {
+ return _internalTableClient[index - MIN_CMSG_OPCODE_NUMBER].get();
+ }
- ClientOpcodeHandler const* operator[](OpcodeClient index) const
- {
- return _internalTableClient[index];
- }
+ ServerOpcodeHandler const* operator[](OpcodeServer index) const
+ {
+ return _internalTableServer[index - MIN_SMSG_OPCODE_NUMBER].get();
+ }
- ServerOpcodeHandler const* operator[](OpcodeServer index) const
- {
- return _internalTableServer[index];
- }
+private:
+ bool ValidateClientOpcode(OpcodeClient opcode, char const* name) const;
+ void ValidateAndSetClientOpcode(OpcodeClient opcode, char const* name, SessionStatus status, ClientOpcodeHandler::HandlerFunction call, PacketProcessing processing);
- private:
- bool ValidateClientOpcode(OpcodeClient opcode, char const* name) const;
- template<typename Handler, Handler HandlerFunction>
- void ValidateAndSetClientOpcode(OpcodeClient opcode, char const* name, SessionStatus status, PacketProcessing processing);
+ bool ValidateServerOpcode(OpcodeServer opcode, char const* name, ConnectionType conIdx) const;
+ void ValidateAndSetServerOpcode(OpcodeServer opcode, char const* name, SessionStatus status, ConnectionType conIdx);
- void ValidateAndSetServerOpcode(OpcodeServer opcode, char const* name, SessionStatus status, ConnectionType conIdx);
+ void InitializeClientOpcodes();
+ void InitializeServerOpcodes();
- ClientOpcodeHandler* _internalTableClient[NUM_OPCODE_HANDLERS];
- ServerOpcodeHandler* _internalTableServer[NUM_OPCODE_HANDLERS];
+ std::array<std::unique_ptr<ClientOpcodeHandler>, NUM_CMSG_OPCODES> _internalTableClient;
+ std::array<std::unique_ptr<ServerOpcodeHandler>, NUM_SMSG_OPCODES> _internalTableServer;
};
extern OpcodeTable opcodeTable;
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index ccf7846371f..47beaad053a 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -210,19 +210,14 @@ std::string WorldSession::GetPlayerInfo() const
/// Send a packet to the client
void WorldSession::SendPacket(WorldPacket const* packet, bool forced /*= false*/)
{
- if (packet->GetOpcode() == NULL_OPCODE)
+ if (packet->GetOpcode() < MIN_SMSG_OPCODE_NUMBER || packet->GetOpcode() > MAX_SMSG_OPCODE_NUMBER)
{
- TC_LOG_ERROR("network.opcode", "Prevented sending of NULL_OPCODE to {}", GetPlayerInfo());
- return;
- }
- else if (packet->GetOpcode() == UNKNOWN_OPCODE)
- {
- TC_LOG_ERROR("network.opcode", "Prevented sending of UNKNOWN_OPCODE to {}", GetPlayerInfo());
+ char const* specialName = packet->GetOpcode() == UNKNOWN_OPCODE ? "UNKNOWN_OPCODE" : "INVALID_OPCODE";
+ TC_LOG_ERROR("network.opcode", "Prevented sending of {} (0x{:04X}) to {}", specialName, packet->GetOpcode(), GetPlayerInfo());
return;
}
ServerOpcodeHandler const* handler = opcodeTable[static_cast<OpcodeServer>(packet->GetOpcode())];
-
if (!handler)
{
TC_LOG_ERROR("network.opcode", "Prevented sending of opcode {} with non existing handler to {}", packet->GetOpcode(), GetPlayerInfo());
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 7a3a1841853..6aa746ebef7 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -362,7 +362,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
WorldPacket packet(std::move(_packetBuffer), GetConnectionType());
OpcodeClient opcode = packet.read<OpcodeClient>();
- if (uint32(opcode) >= uint32(NUM_OPCODE_HANDLERS))
+ if (opcode < MIN_CMSG_OPCODE_NUMBER || opcode > MAX_CMSG_OPCODE_NUMBER)
{
TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client {} sent wrong opcode (opcode: {})",
GetRemoteIpAddress().to_string(), uint32(opcode));
@@ -485,7 +485,7 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
return ReadDataHandlerResult::Error;
}
- OpcodeHandler const* handler = opcodeTable[opcode];
+ ClientOpcodeHandler const* handler = opcodeTable[opcode];
if (!handler)
{
TC_LOG_ERROR("network.opcode", "No defined handler for opcode {} sent by {}", GetOpcodeNameForLogging(static_cast<OpcodeClient>(packet.GetOpcode())), _worldSession->GetPlayerInfo());