Pārlūkot izejas kodu

Update to capture unhandled packets that can desync client (orig credit: theFoof)

Based on DM conversation, extracted GetProtocolPacket -> IsProtocolPacket

https://github.com/Jabantiz/EQ2Emulator-Rewrite/blob/master/trunk/source/common/Packets/ProtocolPacket.cpp

ProtocolPacket* subPacket = ProtocolPacket::GetProtocolPacket(p->buffer + processed + offset, subpacket_length, false);
if (subPacket) {
     //I've seen some garbage packets get sent with wrong protocol opcodes but the rest of the combine is still correct
     //So don't break if GetProtocolPacket fails
     ProcessPacket(subPacket);
     delete subPacket;
}
else if (ntohs(*reinterpret_cast<uint16_t*>(p->buffer + processed + offset)) > 0x1e) {
    //Garbage packet?
    crypto.RC4Decrypt(p->buffer + processed + offset, subpacket_length);
    LogError(LOG_PACKET, 0, "Garbage packet?!:");
    DumpBytes(p->buffer + processed + offset, subpacket_length);
}
Image 4 gadi atpakaļ
vecāks
revīzija
ae6f55fd12

+ 25 - 0
EQ2/source/common/EQPacket.cpp

@@ -555,6 +555,31 @@ void EQProtocolPacket::ChatEncode(unsigned char *buffer, int size, int EncodeKey
 	}
 }
 
+bool EQProtocolPacket::IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC) {
+	bool ret = false;
+	uint16_t opcode = ntohs(*(uint16_t*)in_buff);
+	uint32_t offset = 2;
+
+	switch (opcode) {
+	case OP_SessionRequest:
+	case OP_SessionDisconnect:
+	case OP_KeepAlive:
+	case OP_SessionStatResponse:
+	case OP_Packet:
+	case OP_Combined:
+	case OP_Fragment:
+	case OP_Ack:
+	case OP_OutOfOrderAck:
+	case OP_OutOfSession:
+		{
+			ret = true;
+			break;
+		}
+	}
+
+	return ret;
+}
+
 
 
 void DumpPacketHex(const EQApplicationPacket* app)

+ 2 - 0
EQ2/source/common/EQPacket.h

@@ -104,6 +104,8 @@ public:
 	static uint32 Compress(const unsigned char *buffer, const uint32 length, unsigned char *newbuf, uint32 newbufsize);
 	static void ChatDecode(unsigned char *buffer, int size, int DecodeKey);
 	static void ChatEncode(unsigned char *buffer, int size, int EncodeKey);
+	static bool IsProtocolPacket(const unsigned char* in_buff, uint32_t len, bool bTrimCRC);
+
 	EQProtocolPacket *Copy() { 
 		EQProtocolPacket* new_packet = new EQProtocolPacket(opcode,pBuffer,size);
 		new_packet->eq2_compressed = this->eq2_compressed;

+ 18 - 7
EQ2/source/common/EQStream.cpp

@@ -239,17 +239,28 @@ void EQStream::ProcessPacket(EQProtocolPacket *p)
 #ifdef LE_DEBUG
 					LogWrite(PACKET__DEBUG, 0, "Packet", "OP_Combined Packet %i (%u) (%u): ", count, subpacket_length, processed);
 #endif
-					EQProtocolPacket *subp=new EQProtocolPacket(p->pBuffer+processed+offset,subpacket_length);
-					subp->copyInfo(p);
+					bool isSubPacket = EQProtocolPacket::IsProtocolPacket(p->pBuffer + processed + offset, subpacket_length, false);
+					if (isSubPacket) {
+						EQProtocolPacket* subp = new EQProtocolPacket(p->pBuffer + processed + offset, subpacket_length);
+						subp->copyInfo(p);
+						//I've seen some garbage packets get sent with wrong protocol opcodes but the rest of the combine is still correct
+						//So don't break if GetProtocolPacket fails
 #ifdef LE_DEBUG
-					LogWrite(PACKET__DEBUG, 0, "Packet", "Opcode %i:", subp->opcode);
-					DumpPacket(subp);
+						LogWrite(PACKET__DEBUG, 0, "Packet", "Opcode %i:", subp->opcode);
+						DumpPacket(subp);
 #endif
-					ProcessPacket(subp);
+						ProcessPacket(subp);
 #ifdef LE_DEBUG
-					DumpPacket(subp);
+						DumpPacket(subp);
 #endif
-					delete subp;
+						delete subp;
+					}
+					else if (ntohs(*reinterpret_cast<uint16_t*>(p->pBuffer + processed + offset)) > 0x1e) {
+						//Garbage packet?
+						crypto->RC4Decrypt(p->pBuffer + processed + offset, subpacket_length);
+						LogWrite(PACKET__ERROR, 0, "Packet", "Garbage packet?!:");
+						DumpPacket(p->pBuffer + processed + offset, subpacket_length);
+					}
 					processed+=subpacket_length+offset;
 				}
 				break;