diff options
author | Shauren <shauren.trinity@gmail.com> | 2025-07-12 18:55:51 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2025-07-12 18:55:51 +0200 |
commit | 359258cb074a60a2e95a354d2d19d4a20b9ffcd7 (patch) | |
tree | c8995fdcbc36d24e40dd2549e0dbfa006550ce61 | |
parent | 7760b8e4ed5f9b2a44eba50adf1dc1d14d0dd953 (diff) |
Core/Authserver: Optimize auth packet handler lookup
-rw-r--r-- | src/server/authserver/Server/AuthSession.cpp | 67 | ||||
-rw-r--r-- | src/server/authserver/Server/AuthSession.h | 8 |
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 |