Core/Netcode: Re-enqueue packets with STATUS_LOGGEDIN requirement that are sent before the server recognizes the player as logged in. They will be processed later.

Fixes #208
Fixes #1434
Fixes #2338
This commit is contained in:
Machiavelli
2011-12-16 15:36:03 +01:00
parent db8c10c7bf
commit 829be0b82b
2 changed files with 20 additions and 5 deletions

View File

@@ -791,7 +791,7 @@ void WorldSession::HandlePlayerLoginOpcode(WorldPacket & recv_data)
_charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder); _charLoginCallback = CharacterDatabase.DelayQueryHolder((SQLQueryHolder*)holder);
} }
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
{ {
uint64 playerGuid = holder->GetGuid(); uint64 playerGuid = holder->GetGuid();

View File

@@ -222,6 +222,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
///- Retrieve packets from the receive queue and call the appropriate handlers ///- Retrieve packets from the receive queue and call the appropriate handlers
/// not process packets if socket already closed /// not process packets if socket already closed
WorldPacket* packet = NULL; WorldPacket* packet = NULL;
//! Delete packet after processing by default
bool deletePacket = true;
while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater)) while (m_Socket && !m_Socket->IsClosed() && _recvQueue.next(packet, updater))
{ {
if (packet->GetOpcode() >= NUM_MSG_TYPES) if (packet->GetOpcode() >= NUM_MSG_TYPES)
@@ -240,8 +242,19 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!_player) if (!_player)
{ {
// skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets // skip STATUS_LOGGEDIN opcode unexpected errors if player logout sometime ago - this can be network lag delayed packets
//! If player didn't log out a while ago, it means packets are being sent while the server does not recognize
//! the client to be in world yet. We will re-add the packets to the bottom of the queue and process them later.
if (!m_playerRecentlyLogout) if (!m_playerRecentlyLogout)
LogUnexpectedOpcode(packet, "STATUS_LOGGEDIN", "the player has not logged in yet"); {
//! Because checking a bool is faster than reallocating memory
deletePacket = false;
//! Re-enqueue
QueuePacket(packet);
//! Log
sLog->outDebug(LOG_FILTER_NETWORKIO, "Re-enqueueing packet with opcode %s (0x%.4X) with with status STATUS_LOGGEDIN. "
"Player is currently not in world yet.", opHandle.name, packet->GetOpcode());
}
} }
else if (_player->IsInWorld()) else if (_player->IsInWorld())
{ {
@@ -258,7 +271,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
"the player has not logged in yet and not recently logout"); "the player has not logged in yet and not recently logout");
else else
{ {
// not expected _player or must checked in packet hanlder // not expected _player or must checked in packet handler
sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet)); sScriptMgr->OnPacketReceive(m_Socket, WorldPacket(*packet));
(this->*opHandle.handler)(*packet); (this->*opHandle.handler)(*packet);
if (sLog->IsOutDebug() && packet->rpos() < packet->wpos()) if (sLog->IsOutDebug() && packet->rpos() < packet->wpos())
@@ -308,7 +321,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
break; break;
} }
} }
catch(ByteBufferException &) catch (ByteBufferException &)
{ {
sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.", sLog->outError("WorldSession::Update ByteBufferException occured while parsing a packet (opcode: %u) from client %s, accountid=%i. Skipped packet.",
packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId()); packet->GetOpcode(), GetRemoteAddress().c_str(), GetAccountId());
@@ -320,7 +333,8 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
} }
} }
delete packet; if (deletePacket)
delete packet;
} }
ProcessQueryCallbacks(); ProcessQueryCallbacks();
@@ -344,6 +358,7 @@ bool WorldSession::Update(uint32 diff, PacketFilter& updater)
if (!m_Socket) if (!m_Socket)
return false; //Will remove this session from the world session map return false; //Will remove this session from the world session map
} }
return true; return true;
} }