internal void HandlePackage(Package message, PlayerNetworkSession playerSession) { try { if (message == null) { return; } if (typeof(UnknownPackage) == message.GetType()) { UnknownPackage packet = (UnknownPackage)message; if (Log.IsDebugEnabled) { Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}"); } message.PutPool(); return; } if (typeof(McpeWrapper) == message.GetType()) { McpeWrapper batch = (McpeWrapper)message; var messages = new List <Package>(); // Get bytes byte[] payload = batch.payload; if (playerSession.CryptoContext != null && playerSession.CryptoContext.UseEncryption) { payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext); } // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual package out of bytes using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream()) { defStream2.CopyTo(destination); destination.Position = 0; NbtBinaryReader reader = new NbtBinaryReader(destination, true); while (destination.Position < destination.Length) { //int len = reader.ReadInt32(); int len = BatchUtils.ReadLength(destination); byte[] internalBuffer = reader.ReadBytes(len); //if (Log.IsDebugEnabled) // Log.Debug($"0x{internalBuffer[0]:x2}\n{Package.HexDump(internalBuffer)}"); messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ?? new UnknownPackage(internalBuffer[0], internalBuffer)); } if (destination.Length > destination.Position) { throw new Exception("Have more data"); } } } foreach (var msg in messages) { msg.DatagramSequenceNumber = batch.DatagramSequenceNumber; msg.Reliability = batch.Reliability; msg.ReliableMessageNumber = batch.ReliableMessageNumber; msg.OrderingChannel = batch.OrderingChannel; msg.OrderingIndex = batch.OrderingIndex; HandlePackage(msg, playerSession); } message.PutPool(); return; } MiNetServer.TraceReceive(message); if (CryptoContext != null && CryptoContext.UseEncryption) { MiNetServer.FastThreadPool.QueueUserWorkItem(delegate() { HandlePackage(MessageHandler, message as Package); message.PutPool(); }); } else { HandlePackage(MessageHandler, message); message.PutPool(); } } catch (Exception e) { Log.Error("Package handling", e); throw; } }
internal void HandlePackage(Package message, PlayerNetworkSession playerSession) { Player player = playerSession.Player; if (message == null) { return; } if (typeof(McpeWrapper) == message.GetType()) { McpeWrapper batch = (McpeWrapper)message; // Get bytes byte[] payload = batch.payload; if (playerSession.CryptoContext != null && Config.GetProperty("UseEncryption", true)) { payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext); } //if (Log.IsDebugEnabled) // Log.Debug($"0x{payload[0]:x2}\n{Package.HexDump(payload)}"); var msg = PackageFactory.CreatePackage(payload[0], payload, "mcpe") ?? new UnknownPackage(payload[0], payload); HandlePackage(msg, playerSession); msg.PutPool(); return; } if (typeof(UnknownPackage) == message.GetType()) { UnknownPackage packet = (UnknownPackage)message; Log.Warn($"Received unknown package 0x{message.Id:X2}\n{Package.HexDump(packet.Message)}"); return; } if (typeof(McpeBatch) == message.GetType()) { Log.Debug("Handle MCPE batch message"); McpeBatch batch = (McpeBatch)message; var messages = new List <Package>(); // Get bytes byte[] payload = batch.payload; // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var defStream2 = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual package out of bytes MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream(); defStream2.CopyTo(destination); destination.Position = 0; NbtBinaryReader reader = new NbtBinaryReader(destination, true); while (destination.Position < destination.Length) { int len = reader.ReadInt32(); byte[] internalBuffer = reader.ReadBytes(len); //if (Log.IsDebugEnabled) // Log.Debug($"0x{internalBuffer[0]:x2}\n{Package.HexDump(internalBuffer)}"); messages.Add(PackageFactory.CreatePackage(internalBuffer[0], internalBuffer, "mcpe") ?? new UnknownPackage(internalBuffer[0], internalBuffer)); } if (destination.Length > destination.Position) { throw new Exception("Have more data"); } } foreach (var msg in messages) { msg.DatagramSequenceNumber = batch.DatagramSequenceNumber; msg.OrderingChannel = batch.OrderingChannel; msg.OrderingIndex = batch.OrderingIndex; HandlePackage(msg, playerSession); msg.PutPool(); } return; } if (player != null) { player.HandlePackage(message); } }
internal void HandlePacket(Packet message, PlayerNetworkSession playerSession) { //SignalTick(); try { if (message == null) { return; } if (typeof(UnknownPacket) == message.GetType()) { UnknownPacket packet = (UnknownPacket)message; if (Log.IsDebugEnabled) { Log.Warn($"Received unknown packet 0x{message.Id:X2}\n{Packet.HexDump(packet.Message)}"); } message.PutPool(); return; } if (typeof(McpeWrapper) == message.GetType()) { McpeWrapper batch = (McpeWrapper)message; var messages = new List <Packet>(); // Get bytes byte[] payload = batch.payload; if (playerSession.CryptoContext != null && playerSession.CryptoContext.UseEncryption) { payload = CryptoUtils.Decrypt(payload, playerSession.CryptoContext); } // Decompress bytes MemoryStream stream = new MemoryStream(payload); if (stream.ReadByte() != 0x78) { if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Expected 0x78 0x9C 0x{message.Id:X2}\n{Packet.HexDump(batch.payload)}"); } if (Log.IsDebugEnabled) { Log.Error($"Incorrect ZLib header. Decrypted 0x{message.Id:X2}\n{Packet.HexDump(payload)}"); } throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C"); } stream.ReadByte(); using (var deflateStream = new DeflateStream(stream, CompressionMode.Decompress, false)) { // Get actual packet out of bytes using (MemoryStream destination = MiNetServer.MemoryStreamManager.GetStream()) { deflateStream.CopyTo(destination); destination.Position = 0; while (destination.Position < destination.Length) { int len = (int)VarInt.ReadUInt32(destination); long pos = destination.Position; int id = (int)VarInt.ReadUInt32(destination); len = (int)(len - (destination.Position - pos)); // calculate len of buffer after varint byte[] internalBuffer = new byte[len]; destination.Read(internalBuffer, 0, len); //if (Log.IsDebugEnabled) // Log.Debug($"0x{internalBuffer[0]:x2}\n{Packet.HexDump(internalBuffer)}"); try { messages.Add(PacketFactory.Create((byte)id, internalBuffer, "mcpe") ?? new UnknownPacket((byte)id, internalBuffer)); } catch (Exception e) { if (Log.IsDebugEnabled) { Log.Warn($"Error parsing packet 0x{message.Id:X2}\n{Packet.HexDump(internalBuffer)}"); } throw; } } if (destination.Length > destination.Position) { throw new Exception("Have more data"); } } } foreach (var msg in messages) { // Temp fix for performance, take 1. var interact = msg as McpeInteract; if (interact?.actionId == 4 && interact.targetRuntimeEntityId == 0) { continue; } msg.DatagramSequenceNumber = batch.DatagramSequenceNumber; msg.Reliability = batch.Reliability; msg.ReliableMessageNumber = batch.ReliableMessageNumber; msg.OrderingChannel = batch.OrderingChannel; msg.OrderingIndex = batch.OrderingIndex; HandlePacket(msg, playerSession); } message.PutPool(); return; } MiNetServer.TraceReceive(message); if (CryptoContext != null && CryptoContext.UseEncryption) { MiNetServer.FastThreadPool.QueueUserWorkItem(() => { HandlePacket(MessageHandler, message as Packet); message.PutPool(); }); } else { HandlePacket(MessageHandler, message); message.PutPool(); } } catch (Exception e) { Log.Error("Packet handling", e); throw; } }
private static List <MessagePart> CreateMessageParts(Packet message, int mtuSize, Reliability reliability, RakSession session) { Memory <byte> encodedMessage = message.Encode(); if (encodedMessage.IsEmpty) { return(new List <MessagePart>(0)); } // All MCPE messages goes into a compressed (and possible encrypted) wrapper. // Note that McpeWrapper itself is a RakNet level message. bool isWrapper = message is McpeWrapper; if (message.IsMcpe) { var wrapper = McpeWrapper.CreateObject(); wrapper.payload = Compression.Compress(encodedMessage, true, encodedMessage.Length > 1000 ? CompressionLevel.Fastest : CompressionLevel.NoCompression); encodedMessage = wrapper.Encode(); wrapper.PutPool(); isWrapper = true; } // Should probably only force for McpeWrapper, not the other messages (RakNet) if (!(message is ConnectedPong) && !(message is DetectLostConnections)) { reliability = Reliability.ReliableOrdered; } int orderingIndex = 0; lock (session.EncodeSync) { CryptoContext cryptoContext = session.CryptoContext; if (!message.ForceClear && cryptoContext != null && session.CryptoContext.UseEncryption && isWrapper) { var wrapper = McpeWrapper.CreateObject(); wrapper.payload = CryptoUtils.Encrypt(encodedMessage.Slice(1), cryptoContext); encodedMessage = wrapper.Encode(); wrapper.PutPool(); } if (reliability == Reliability.ReliableOrdered) { orderingIndex = Interlocked.Increment(ref session.OrderingIndex); } } List <(int @from, int length)> splits = ArraySplit(encodedMessage.Length, mtuSize - 100); int count = splits.Count; if (count == 0) { Log.Warn("Got zero parts back from split"); } if (count <= 1) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = orderingIndex; messagePart.ReliabilityHeader.HasSplit = false; messagePart.Buffer = encodedMessage; return(new List <MessagePart>(1) { messagePart }); } // Stupid but scared to change it .. remove the -100 when i feel "safe" if (session.SplitPartId > short.MaxValue - 100) { Interlocked.CompareExchange(ref session.SplitPartId, 0, short.MaxValue); } int index = 0; short splitId = (short)Interlocked.Increment(ref session.SplitPartId); var messageParts = new List <MessagePart>(count); foreach ((int from, int length)span in splits) { var messagePart = MessagePart.CreateObject(); messagePart.ReliabilityHeader.Reliability = reliability; messagePart.ReliabilityHeader.ReliableMessageNumber = Interlocked.Increment(ref session.ReliableMessageNumber); messagePart.ReliabilityHeader.OrderingChannel = 0; messagePart.ReliabilityHeader.OrderingIndex = orderingIndex; messagePart.ReliabilityHeader.HasSplit = count > 1; messagePart.ReliabilityHeader.PartCount = count; messagePart.ReliabilityHeader.PartId = splitId; messagePart.ReliabilityHeader.PartIndex = index++; messagePart.Buffer = encodedMessage.Slice(span.@from, span.length); messageParts.Add(messagePart); } return(messageParts); }