aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2025-07-12 18:55:51 +0200
committerShauren <shauren.trinity@gmail.com>2025-07-12 18:55:51 +0200
commit359258cb074a60a2e95a354d2d19d4a20b9ffcd7 (patch)
treec8995fdcbc36d24e40dd2549e0dbfa006550ce61
parent7760b8e4ed5f9b2a44eba50adf1dc1d14d0dd953 (diff)
Core/Authserver: Optimize auth packet handler lookup
-rw-r--r--src/server/authserver/Server/AuthSession.cpp67
-rw-r--r--src/server/authserver/Server/AuthSession.h8
2 files changed, 55 insertions, 20 deletions
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index f19fb843902..c523130e08b 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -35,7 +35,7 @@
using boost::asio::ip::tcp;
-enum eAuthCmd
+enum eAuthCmd : uint8
{
AUTH_LOGON_CHALLENGE = 0x00,
AUTH_LOGON_PROOF = 0x01,
@@ -49,6 +49,12 @@ enum eAuthCmd
XFER_CANCEL = 0x34
};
+// perfect hash function for all valid values of eAuthCmd
+inline constexpr std::size_t GetOpcodeArrayIndex(eAuthCmd c)
+{
+ return (c & 0x7) + ((c & 0x10) >> 2) + ((c & 0x20) >> 5);
+}
+
#pragma pack(push, 1)
typedef struct AUTH_LOGON_CHALLENGE_C
@@ -120,20 +126,50 @@ std::array<uint8, 16> VersionChallenge = { { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B,
#define AUTH_LOGON_CHALLENGE_INITIAL_SIZE 4
#define REALM_LIST_PACKET_SIZE 5
-std::unordered_map<uint8, AuthHandler> AuthSession::InitHandlers()
+consteval std::array<AuthHandler, 10> AuthSession::InitHandlers()
{
- std::unordered_map<uint8, AuthHandler> handlers;
+ std::array<AuthHandler, 10> handlers = { };
- handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge };
- handlers[AUTH_LOGON_PROOF] = { STATUS_LOGON_PROOF, sizeof(AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof };
- handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge };
- handlers[AUTH_RECONNECT_PROOF] = { STATUS_RECONNECT_PROOF, sizeof(AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof };
- handlers[REALM_LIST] = { STATUS_AUTHED, REALM_LIST_PACKET_SIZE, &AuthSession::HandleRealmList };
+ handlers[GetOpcodeArrayIndex(AUTH_LOGON_CHALLENGE)] =
+ {
+ .cmd = AUTH_LOGON_CHALLENGE,
+ .status = STATUS_CHALLENGE,
+ .packetSize = AUTH_LOGON_CHALLENGE_INITIAL_SIZE,
+ .handler = &AuthSession::HandleLogonChallenge
+ };
+ handlers[GetOpcodeArrayIndex(AUTH_LOGON_PROOF)] =
+ {
+ .cmd = AUTH_LOGON_PROOF,
+ .status = STATUS_LOGON_PROOF,
+ .packetSize = sizeof(AUTH_LOGON_PROOF_C),
+ .handler = &AuthSession::HandleLogonProof
+ };
+ handlers[GetOpcodeArrayIndex(AUTH_RECONNECT_CHALLENGE)] =
+ {
+ .cmd = AUTH_RECONNECT_CHALLENGE,
+ .status = STATUS_CHALLENGE,
+ .packetSize = AUTH_LOGON_CHALLENGE_INITIAL_SIZE,
+ .handler = &AuthSession::HandleReconnectChallenge
+ };
+ handlers[GetOpcodeArrayIndex(AUTH_RECONNECT_PROOF)] =
+ {
+ .cmd = AUTH_RECONNECT_PROOF,
+ .status = STATUS_RECONNECT_PROOF,
+ .packetSize = sizeof(AUTH_RECONNECT_PROOF_C),
+ .handler = &AuthSession::HandleReconnectProof
+ };
+ handlers[GetOpcodeArrayIndex(REALM_LIST)] =
+ {
+ .cmd = REALM_LIST,
+ .status = STATUS_AUTHED,
+ .packetSize = REALM_LIST_PACKET_SIZE,
+ .handler = &AuthSession::HandleRealmList
+ };
return handlers;
}
-std::unordered_map<uint8, AuthHandler> const Handlers = AuthSession::InitHandlers();
+constexpr std::array<AuthHandler, 10> Handlers = AuthSession::InitHandlers();
void AccountInfo::LoadResult(Field* fields)
{
@@ -216,22 +252,23 @@ void AuthSession::ReadHandler()
MessageBuffer& packet = GetReadBuffer();
while (packet.GetActiveSize())
{
- uint8 cmd = packet.GetReadPointer()[0];
- auto itr = Handlers.find(cmd);
- if (itr == Handlers.end())
+ eAuthCmd cmd = eAuthCmd(packet.GetReadPointer()[0]);
+ std::size_t index = GetOpcodeArrayIndex(cmd);
+ if (index >= Handlers.size() || Handlers[index].cmd != cmd)
{
// well we dont handle this, lets just ignore it
packet.Reset();
break;
}
- if (_status != itr->second.status)
+ AuthHandler const* itr = &Handlers[index];
+ if (_status != itr->status)
{
CloseSocket();
return;
}
- uint16 size = uint16(itr->second.packetSize);
+ std::size_t size = itr->packetSize;
if (packet.GetActiveSize() < size)
break;
@@ -249,7 +286,7 @@ void AuthSession::ReadHandler()
if (packet.GetActiveSize() < size)
break;
- if (!(*this.*itr->second.handler)())
+ if (!(this->*itr->handler)())
{
CloseSocket();
return;
diff --git a/src/server/authserver/Server/AuthSession.h b/src/server/authserver/Server/AuthSession.h
index 844de0ed787..06c1b79bf3e 100644
--- a/src/server/authserver/Server/AuthSession.h
+++ b/src/server/authserver/Server/AuthSession.h
@@ -32,6 +32,7 @@ using boost::asio::ip::tcp;
class ByteBuffer;
struct AuthHandler;
+enum eAuthCmd : uint8;
enum AuthStatus
{
@@ -63,7 +64,7 @@ class AuthSession : public Socket<AuthSession>
typedef Socket<AuthSession> AuthSocket;
public:
- static std::unordered_map<uint8, AuthHandler> InitHandlers();
+ static consteval std::array<AuthHandler, 10> InitHandlers();
AuthSession(tcp::socket&& socket);
@@ -106,15 +107,12 @@ private:
QueryCallbackProcessor _queryProcessor;
};
-#pragma pack(push, 1)
-
struct AuthHandler
{
+ eAuthCmd cmd;
AuthStatus status;
size_t packetSize;
bool (AuthSession::*handler)();
};
-#pragma pack(pop)
-
#endif