Example #1
0
        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);
            }
        }
Example #3
0
        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;
            }
        }
Example #4
0
        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);
        }