1
0

Handle incomplete packets in cProtocolRecognizer

This commit is contained in:
peterbell10 2017-07-17 00:19:09 +01:00 committed by Tiger Wang
parent 87af95b67c
commit e0a44fb3bc
2 changed files with 61 additions and 47 deletions

View File

@ -83,46 +83,58 @@ void cProtocolRecognizer::DataReceived(const char * a_Data, size_t a_Size)
return; return;
} }
if (m_InPingForUnrecognizedVersion) if (!m_InPingForUnrecognizedVersion)
{
if (TryRecognizeProtocol())
{
// The protocol has just been recognized, dump the whole m_Buffer contents into it for parsing:
AString Dump;
m_Buffer.ResetRead();
m_Buffer.ReadAll(Dump);
m_Protocol->DataReceived(Dump.data(), Dump.size());
return;
}
else
{
m_Buffer.ResetRead();
}
}
if (!m_InPingForUnrecognizedVersion)
{
return;
}
// Handle server list ping packets
for (;;)
{ {
// We already know the verison; handle it here.
UInt32 PacketLen; UInt32 PacketLen;
UInt32 PacketID; UInt32 PacketID;
if (!m_Buffer.ReadVarInt32(PacketLen)) if (
!m_Buffer.ReadVarInt32(PacketLen) ||
!m_Buffer.CanReadBytes(PacketLen) ||
!m_Buffer.ReadVarInt32(PacketID)
)
{ {
return; // Not enough data
} m_Buffer.ResetRead();
if (!m_Buffer.ReadVarInt32(PacketID)) break;
{
return;
}
if ((PacketID != 0x01) || (PacketLen != 9))
{
// Not a Ping packet
return;
} }
Int64 Data; if ((PacketID == 0x00) && (PacketLen == 1)) // Request packet
if (!m_Buffer.ReadBEInt64(Data))
{ {
HandlePacketStatusRequest();
}
else if ((PacketID == 0x01) && (PacketLen == 9)) // Ping packet
{
HandlePacketStatusPing();
}
else
{
m_Client->Kick("Server list ping failed, unrecognized packet");
return; return;
} }
cPacketizer Pkt(*this, 0x01); // Pong packet
Pkt.WriteBEInt64(Data);
return;
} }
if (!TryRecognizeProtocol())
{
return;
}
// The protocol has just been recognized, dump the whole m_Buffer contents into it for parsing:
AString Dump;
m_Buffer.ResetRead();
m_Buffer.ReadAll(Dump);
m_Protocol->DataReceived(Dump.data(), Dump.size());
} }
@ -1108,20 +1120,6 @@ bool cProtocolRecognizer::TryRecognizeLengthedProtocol(UInt32 a_PacketLengthRema
else else
{ {
m_InPingForUnrecognizedVersion = true; m_InPingForUnrecognizedVersion = true;
UInt32 PacketLen;
UInt32 PacketID;
if (!m_Buffer.ReadVarInt32(PacketLen))
{
return false;
}
if (!m_Buffer.ReadVarInt32(PacketID))
{
return false;
}
ASSERT(PacketID == 0x00); // Request packet
ASSERT(PacketLen == 1); // No payload except for packet ID
SendPingStatusResponse();
} }
return false; return false;
} }
@ -1155,7 +1153,7 @@ void cProtocolRecognizer::SendPacket(cPacketizer & a_Pkt)
void cProtocolRecognizer::SendPingStatusResponse(void) void cProtocolRecognizer::HandlePacketStatusRequest(void)
{ {
cServer * Server = cRoot::Get()->GetServer(); cServer * Server = cRoot::Get()->GetServer();
AString ServerDescription = Server->GetDescription(); AString ServerDescription = Server->GetDescription();
@ -1200,3 +1198,18 @@ void cProtocolRecognizer::SendPingStatusResponse(void)
void cProtocolRecognizer::HandlePacketStatusPing()
{
Int64 Timestamp;
if (!m_Buffer.ReadBEInt64(Timestamp))
{
return;
}
cPacketizer Pkt(*this, 0x01); // Pong packet
Pkt.WriteBEInt64(Timestamp);
}

View File

@ -143,8 +143,6 @@ public:
virtual void SendData(const char * a_Data, size_t a_Size) override; virtual void SendData(const char * a_Data, size_t a_Size) override;
void SendPingStatusResponse(void);
protected: protected:
/** The recognized protocol */ /** The recognized protocol */
cProtocol * m_Protocol; cProtocol * m_Protocol;
@ -155,6 +153,9 @@ protected:
/** Is a server list ping for an unrecognized version currently occuring? */ /** Is a server list ping for an unrecognized version currently occuring? */
bool m_InPingForUnrecognizedVersion; bool m_InPingForUnrecognizedVersion;
// Packet handlers while in status state (m_InPingForUnrecognizedVersion == true)
void HandlePacketStatusRequest();
void HandlePacketStatusPing();
/** Tries to recognize protocol based on m_Buffer contents; returns true if recognized */ /** Tries to recognize protocol based on m_Buffer contents; returns true if recognized */
bool TryRecognizeProtocol(void); bool TryRecognizeProtocol(void);