3535
3636using boost::asio::ip::tcp;
3737
38- enum eAuthCmd
38+ enum eAuthCmd : uint8
3939{
4040 AUTH_LOGON_CHALLENGE = 0x00 ,
4141 AUTH_LOGON_PROOF = 0x01 ,
@@ -49,6 +49,12 @@ enum eAuthCmd
4949 XFER_CANCEL = 0x34
5050};
5151
52+ // perfect hash function for all valid values of eAuthCmd
53+ inline constexpr std::size_t GetOpcodeArrayIndex (eAuthCmd c)
54+ {
55+ return (c & 0x7 ) + ((c & 0x10 ) >> 2 ) + ((c & 0x20 ) >> 5 );
56+ }
57+
5258#pragma pack(push, 1)
5359
5460typedef struct AUTH_LOGON_CHALLENGE_C
@@ -120,20 +126,50 @@ std::array<uint8, 16> VersionChallenge = { { 0xBA, 0xA3, 0x1E, 0x99, 0xA0, 0x0B,
120126#define AUTH_LOGON_CHALLENGE_INITIAL_SIZE 4
121127#define REALM_LIST_PACKET_SIZE 5
122128
123- std::unordered_map<uint8, AuthHandler > AuthSession::InitHandlers ()
129+ consteval std::array<AuthHandler, 10 > AuthSession::InitHandlers ()
124130{
125- std::unordered_map<uint8, AuthHandler > handlers;
131+ std::array<AuthHandler, 10 > handlers = { } ;
126132
127- handlers[AUTH_LOGON_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleLogonChallenge };
128- handlers[AUTH_LOGON_PROOF] = { STATUS_LOGON_PROOF, sizeof (AUTH_LOGON_PROOF_C), &AuthSession::HandleLogonProof };
129- handlers[AUTH_RECONNECT_CHALLENGE] = { STATUS_CHALLENGE, AUTH_LOGON_CHALLENGE_INITIAL_SIZE, &AuthSession::HandleReconnectChallenge };
130- handlers[AUTH_RECONNECT_PROOF] = { STATUS_RECONNECT_PROOF, sizeof (AUTH_RECONNECT_PROOF_C), &AuthSession::HandleReconnectProof };
131- handlers[REALM_LIST] = { STATUS_AUTHED, REALM_LIST_PACKET_SIZE, &AuthSession::HandleRealmList };
133+ handlers[GetOpcodeArrayIndex (AUTH_LOGON_CHALLENGE)] =
134+ {
135+ .cmd = AUTH_LOGON_CHALLENGE,
136+ .status = STATUS_CHALLENGE,
137+ .packetSize = AUTH_LOGON_CHALLENGE_INITIAL_SIZE,
138+ .handler = &AuthSession::HandleLogonChallenge
139+ };
140+ handlers[GetOpcodeArrayIndex (AUTH_LOGON_PROOF)] =
141+ {
142+ .cmd = AUTH_LOGON_PROOF,
143+ .status = STATUS_LOGON_PROOF,
144+ .packetSize = sizeof (AUTH_LOGON_PROOF_C),
145+ .handler = &AuthSession::HandleLogonProof
146+ };
147+ handlers[GetOpcodeArrayIndex (AUTH_RECONNECT_CHALLENGE)] =
148+ {
149+ .cmd = AUTH_RECONNECT_CHALLENGE,
150+ .status = STATUS_CHALLENGE,
151+ .packetSize = AUTH_LOGON_CHALLENGE_INITIAL_SIZE,
152+ .handler = &AuthSession::HandleReconnectChallenge
153+ };
154+ handlers[GetOpcodeArrayIndex (AUTH_RECONNECT_PROOF)] =
155+ {
156+ .cmd = AUTH_RECONNECT_PROOF,
157+ .status = STATUS_RECONNECT_PROOF,
158+ .packetSize = sizeof (AUTH_RECONNECT_PROOF_C),
159+ .handler = &AuthSession::HandleReconnectProof
160+ };
161+ handlers[GetOpcodeArrayIndex (REALM_LIST)] =
162+ {
163+ .cmd = REALM_LIST,
164+ .status = STATUS_AUTHED,
165+ .packetSize = REALM_LIST_PACKET_SIZE,
166+ .handler = &AuthSession::HandleRealmList
167+ };
132168
133169 return handlers;
134170}
135171
136- std::unordered_map<uint8, AuthHandler> const Handlers = AuthSession::InitHandlers();
172+ constexpr std::array<AuthHandler, 10 > Handlers = AuthSession::InitHandlers();
137173
138174void AccountInfo::LoadResult (Field* fields)
139175{
@@ -216,22 +252,23 @@ void AuthSession::ReadHandler()
216252 MessageBuffer& packet = GetReadBuffer ();
217253 while (packet.GetActiveSize ())
218254 {
219- uint8 cmd = packet.GetReadPointer ()[0 ];
220- auto itr = Handlers. find (cmd);
221- if (itr == Handlers.end () )
255+ eAuthCmd cmd = eAuthCmd ( packet.GetReadPointer ()[0 ]) ;
256+ std:: size_t index = GetOpcodeArrayIndex (cmd);
257+ if (index >= Handlers.size () || Handlers[index]. cmd != cmd )
222258 {
223259 // well we dont handle this, lets just ignore it
224260 packet.Reset ();
225261 break ;
226262 }
227263
228- if (_status != itr->second .status )
264+ AuthHandler const * itr = &Handlers[index];
265+ if (_status != itr->status )
229266 {
230267 CloseSocket ();
231268 return ;
232269 }
233270
234- uint16 size = uint16 ( itr->second . packetSize ) ;
271+ std:: size_t size = itr->packetSize ;
235272 if (packet.GetActiveSize () < size)
236273 break ;
237274
@@ -249,7 +286,7 @@ void AuthSession::ReadHandler()
249286 if (packet.GetActiveSize () < size)
250287 break ;
251288
252- if (!(* this . *itr->second . handler )())
289+ if (!(this -> *itr->handler )())
253290 {
254291 CloseSocket ();
255292 return ;
0 commit comments