From a0bafa9bf771a9ea0b4aff77c85ee7859d414d64 Mon Sep 17 00:00:00 2001 From: Mark Sturgill Date: Mon, 7 Oct 2013 15:27:16 -0700 Subject: [PATCH] add crash report packet handler begin packet processing parallelization --- Server/Network/MessagePump.cs | 187 ++++++++++++++----------------- Server/Network/PacketHandlers.cs | 36 +++++- 2 files changed, 120 insertions(+), 103 deletions(-) diff --git a/Server/Network/MessagePump.cs b/Server/Network/MessagePump.cs index de211e0ba..8a3b7e6f3 100644 --- a/Server/Network/MessagePump.cs +++ b/Server/Network/MessagePump.cs @@ -37,7 +37,6 @@ namespace Server.Network private Queue m_Queue; private Queue m_WorkingQueue; private Queue m_Throttled; - private byte[] m_Peek; public MessagePump() { @@ -64,7 +63,6 @@ namespace Server.Network m_Queue = new Queue(); m_WorkingQueue = new Queue(); m_Throttled = new Queue(); - m_Peek = new byte[4]; } public Listener[] Listeners @@ -139,151 +137,136 @@ namespace Server.Network private const int BufferSize = 4096; private BufferPool m_Buffers = new BufferPool( "Processor", 4, BufferSize ); - public bool HandleReceive( NetState ns ) + private bool HandleSeed(NetState ns, ByteQueue buffer) { + if (buffer.GetPacketID() == 0xEF) { + // new packet in client 6.0.5.0 replaces the traditional seed method with a seed packet + // 0xEF = 239 = multicast IP, so this should never appear in a normal seed. So this is backwards compatible with older clients. + ns.Seeded = true; + return true; + } else if (buffer.Length >= 4) { + byte[] m_Peek = new byte[4]; + + buffer.Dequeue(m_Peek, 0, 4); + + int seed = (m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]; + + if (seed == 0) { + Console.WriteLine("Login: {0}: Invalid client detected, disconnecting", ns); + ns.Dispose(); + return false; + } + + ns.m_Seed = seed; + ns.Seeded = true; + return true; + } else { + return false; + } + } + + private bool CheckEncrypted(NetState ns, int packetID) { + if (!ns.SentFirstPacket && packetID != 0xF0 && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 && packetID != 0x91 && packetID != 0xA4 && packetID != 0xEF) { + Console.WriteLine("Client: {0}: Encrypted client detected, disconnecting", ns); + ns.Dispose(); + return true; + } + return false; + } + + public void HandleReceive( NetState ns ) { ByteQueue buffer = ns.Buffer; if ( buffer == null || buffer.Length <= 0 ) - return true; + return; lock ( buffer ) { - int length = buffer.Length; - - if ( !ns.Seeded ) - { - if ( buffer.GetPacketID() == 0xEF ) - { - // new packet in client 6.0.5.0 replaces the traditional seed method with a seed packet - // 0xEF = 239 = multicast IP, so this should never appear in a normal seed. So this is backwards compatible with older clients. - ns.Seeded = true; - } - else if ( buffer.Length >= 4 ) - { - buffer.Dequeue( m_Peek, 0, 4 ); - - int seed = (m_Peek[0] << 24) | (m_Peek[1] << 16) | (m_Peek[2] << 8) | m_Peek[3]; - - if ( seed == 0 ) - { - Console.WriteLine( "Login: {0}: Invalid client detected, disconnecting", ns ); - ns.Dispose(); - return false; - } - - ns.m_Seed = seed; - ns.Seeded = true; - - length = buffer.Length; - } - else - { - return true; - } + if ( !ns.Seeded ) { + if (!HandleSeed(ns, buffer)) + return; } - while ( length > 0 && ns.Running ) - { + int length = buffer.Length; + + while ( length > 0 && ns.Running ) { int packetID = buffer.GetPacketID(); - if ( !ns.SentFirstPacket && packetID != 0xF0 && packetID != 0xF1 && packetID != 0xCF && packetID != 0x80 && packetID != 0x91 && packetID != 0xA4 && packetID != 0xEF ) - { - Console.WriteLine( "Client: {0}: Encrypted client detected, disconnecting", ns ); - ns.Dispose(); + if (CheckEncrypted(ns, packetID)) break; - } PacketHandler handler = ns.GetHandler( packetID ); - if ( handler == null ) - { + if ( handler == null ) { byte[] data = new byte[length]; length = buffer.Dequeue( data, 0, length ); - new PacketReader( data, length, false ).Trace( ns ); - break; } int packetLength = handler.Length; - if ( packetLength <= 0 ) - { - if ( length >= 3 ) - { + if ( packetLength <= 0 ) { + if ( length >= 3 ) { packetLength = buffer.GetPacketLength(); - if ( packetLength < 3 ) - { + if ( packetLength < 3 ) { ns.Dispose(); break; } - } - else - { + } else { break; } } - if ( length >= packetLength ) - { - if ( handler.Ingame && ns.Mobile == null ) - { + if ( length >= packetLength ) { + if ( handler.Ingame && ns.Mobile == null ) { Console.WriteLine( "Client: {0}: Sent ingame packet (0x{1:X2}) before having been attached to a mobile", ns, packetID ); ns.Dispose(); break; - } - else if ( handler.Ingame && ns.Mobile.Deleted ) - { + } else if ( handler.Ingame && ns.Mobile.Deleted ) { ns.Dispose(); break; } - else - { - ThrottlePacketCallback throttler = handler.ThrottleCallback; - if ( throttler != null && !throttler( ns ) ) - { - m_Throttled.Enqueue( ns ); - return false; - } + ThrottlePacketCallback throttler = handler.ThrottleCallback; - PacketReceiveProfile prof = PacketReceiveProfile.Acquire( packetID ); - - if ( prof != null ) { - prof.Start(); - } - - byte[] packetBuffer; - - if ( BufferSize >= packetLength ) - packetBuffer = m_Buffers.AcquireBuffer(); - else - packetBuffer = new byte[packetLength]; - - packetLength = buffer.Dequeue( packetBuffer, 0, packetLength ); - - PacketReader r = new PacketReader( packetBuffer, packetLength, handler.Length != 0 ); - - handler.OnReceive( ns, r ); - length = buffer.Length; - - if ( BufferSize >= packetLength ) - m_Buffers.ReleaseBuffer( packetBuffer ); - - if ( prof != null ) { - prof.Finish( packetLength ); - } + if ( throttler != null && !throttler( ns ) ) { + m_Throttled.Enqueue( ns ); + return; } - } - else - { + + PacketReceiveProfile prof = PacketReceiveProfile.Acquire( packetID ); + + if ( prof != null ) { + prof.Start(); + } + + byte[] packetBuffer; + + if ( BufferSize >= packetLength ) + packetBuffer = m_Buffers.AcquireBuffer(); + else + packetBuffer = new byte[packetLength]; + + packetLength = buffer.Dequeue( packetBuffer, 0, packetLength ); + + PacketReader r = new PacketReader( packetBuffer, packetLength, handler.Length != 0 ); + + handler.OnReceive( ns, r ); + length = buffer.Length; + + if ( BufferSize >= packetLength ) + m_Buffers.ReleaseBuffer( packetBuffer ); + + if ( prof != null ) { + prof.Finish( packetLength ); + } + } else { break; } } } - - return true; } } } \ No newline at end of file diff --git a/Server/Network/PacketHandlers.cs b/Server/Network/PacketHandlers.cs index 665f0c277..1f2e87846 100644 --- a/Server/Network/PacketHandlers.cs +++ b/Server/Network/PacketHandlers.cs @@ -149,6 +149,7 @@ namespace Server.Network Register( 0xD7, 0, true, new OnPacketReceive( EncodedCommand ) ); Register( 0xE1, 0, false, new OnPacketReceive( ClientType ) ); Register( 0xEF, 21, false, new OnPacketReceive( LoginServerSeed ) ); + Register( 0xF4, 0, false, new OnPacketReceive( CrashReport ) ); Register( 0xF8, 106, false, new OnPacketReceive( CreateCharacter70160 ) ); Register6017( 0x08, 15, true, new OnPacketReceive( DropReq6017 ) ); @@ -2566,7 +2567,40 @@ namespace Server.Network state.Version = new ClientVersion( clientMaj, clientMin, clientRev, clientPat ); } - public static void AccountLogin( NetState state, PacketReader pvSrc ) + public static void CrashReport(NetState state, PacketReader pvSrc) + { + byte clientMaj = pvSrc.ReadByte(); + byte clientMin = pvSrc.ReadByte(); + byte clientRev = pvSrc.ReadByte(); + byte clientPat = pvSrc.ReadByte(); + + ushort x = pvSrc.ReadUInt16(); + ushort y = pvSrc.ReadUInt16(); + sbyte z = pvSrc.ReadSByte(); + byte map = pvSrc.ReadByte(); + + string account = pvSrc.ReadString(32); + string character = pvSrc.ReadString(32); + string ip = pvSrc.ReadString(15); + + int unk1 = pvSrc.ReadInt32(); + int exception = pvSrc.ReadInt32(); + + string process = pvSrc.ReadString(100); + string report = pvSrc.ReadString(100); + + pvSrc.ReadByte(); // 0x00 + + int offset = pvSrc.ReadInt32(); + + int count = (int)pvSrc.ReadByte(); + + for (int i = 0; i < count; i++) { + int address = pvSrc.ReadInt32(); + } + } + + public static void AccountLogin(NetState state, PacketReader pvSrc) { if ( state.SentFirstPacket ) {