Пример #1
0
        public void TestCustomVarInt()
        {
            {
                var stream = new MemoryStream();
                var bytes  = GetBytes("ff ff ff ff 0f");
                stream.Write(bytes, 0, bytes.Length);
                stream.Position = 0;
                int result = VarInt.ReadInt32(stream);
                Assert.AreEqual(-1, result);

                int t = (int)0x7fffffff;
                t |= 0xff << 1;
                Assert.AreEqual(t | 0x0f << 4 * 7, result);
                Assert.AreEqual(-1, result);

                MemoryStream outstream = new MemoryStream();
                VarInt.WriteInt32(outstream, -1);
                Assert.AreEqual(bytes, outstream.ToArray());
            }
            {
                var stream = new MemoryStream();
                var bytes  = GetBytes("ff ff ff ff ff ff ff ff ff 01");
                stream.Write(bytes, 0, bytes.Length);
                stream.Position = 0;
                long result = VarInt.ReadInt64(stream);
                Assert.AreEqual(-1, result);

                MemoryStream outstream = new MemoryStream();
                VarInt.WriteInt64(outstream, -1);
                Assert.AreEqual(bytes, outstream.ToArray());
            }
        }
Пример #2
0
        public static MetadataDictionary FromStream(BinaryReader reader)
        {
            Stream             stream   = reader.BaseStream;
            MetadataDictionary metadata = new MetadataDictionary();

            {
                var count = VarInt.ReadInt32(stream);

                for (int i = 0; i < count; i++)
                {
                    int index = VarInt.ReadInt32(stream);
                    int type  = VarInt.ReadInt32(stream);
                    var entry = EntryTypes[type]();

                    entry.FromStream(reader);
                    entry.Index = (byte)index;

                    metadata[index] = entry;
                }
            }

            return(metadata);

            return(null);
        }
Пример #3
0
        public override void FromStream(BinaryReader reader)
        {
            try
            {
                var len = VarInt.ReadInt32(reader.BaseStream);

                byte[] bytes = new byte[len];
                reader.BaseStream.Read(bytes, 0, len);
                Value = Encoding.UTF8.GetString(bytes);
            }
            catch (Exception e)
            {
                Log.Error(e);
            }
        }
Пример #4
0
        /// <summary>
        /// Deserialize the <see cref="FilePropertySection"/> from the given stream.
        /// </summary>
        /// <param name="reader">The stream to read from.</param>
        /// <param name="handle">Starting offset and size within the stream for the file properties.</param>
        /// <returns>The deserialized <see cref="FilePropertySection"/> section.</returns>
        public static TProperties Read <TProperties>(BinaryReader reader, BlockHandle handle) where TProperties : FilePropertySection, new()
        {
            var properties = new TProperties();

            if (handle.Offset < 0)
            {
                throw new InvalidDataException(SR.Error_FilePropertySection_Missing);
            }
            if (handle.Size == 0)
            {
                return(properties);
            }

            // The FileProperties start at the given 'offset' within the stream, and contains properties up to 'offset' + 'size'.
            reader.BaseStream.Position = handle.Offset;
            while (reader.BaseStream.Position < handle.EndOffset)
            {
                // Read the property name.
                var property = reader.ReadInt32();

                // Read the size in bytes of the property's value.
                var valueSize = VarInt.ReadInt32(reader);
                if (valueSize < 0)
                {
                    throw new InvalidDataException(string.Format(CultureInfo.CurrentCulture, SR.Error_FilePropertySection_CorruptSizeNegative_OneArgs, valueSize));
                }
                if (reader.BaseStream.Position + valueSize > handle.EndOffset)
                {
                    throw new InvalidDataException(SR.Error_FilePropertySection_CorruptSizeExtend);
                }

                // Read the property's value.
                properties.ReadProperty(reader, property, valueSize);
            }

            // Validate the properties section ended exactly where expected.
            if (reader.BaseStream.Position != handle.EndOffset)
            {
                throw new InvalidDataException(SR.Error_FilePropertySection_CorruptSizeIncorrect);
            }

            return(properties);
        }
Пример #5
0
 public int ReadVarInt()
 {
     return(VarInt.ReadInt32(_buffer));
 }
        public void HandlePacket(Packet message)
        {
            if (message == null)
            {
                throw new NullReferenceException();
            }

            if (message is McpeWrapper wrapper)
            {
                var messages = new List <Packet>();

                // Get bytes to process
                ReadOnlyMemory <byte> payload = wrapper.payload;

                // Decrypt bytes

                if (CryptoContext != null && CryptoContext.UseEncryption)
                {
                    // This call copies the entire buffer, but what can we do? It is kind of compensated by not
                    // creating a new buffer when parsing the packet (only a mem-slice)
                    payload = CryptoUtils.Decrypt(payload, CryptoContext);
                }

                // Decompress bytes

                //var stream = new MemoryStreamReader(payload.Slice(0, payload.Length - 4)); // slice away adler
                //if (stream.ReadByte() != 0x78)
                //{
                //	if (Log.IsDebugEnabled) Log.Error($"Incorrect ZLib header. Expected 0x78 0x9C 0x{wrapper.Id:X2}\n{Packet.HexDump(wrapper.payload)}");
                //	if (Log.IsDebugEnabled) Log.Error($"Incorrect ZLib header. Decrypted 0x{wrapper.Id:X2}\n{Packet.HexDump(payload)}");
                //	throw new InvalidDataException("Incorrect ZLib header. Expected 0x78 0x9C");
                //}
                //stream.ReadByte();
                var stream = new MemoryStreamReader(payload);
                try
                {
                    using (var deflateStream = new DeflateStream(stream, CompressionMode.Decompress, false))
                    {
                        using var s = new MemoryStream();
                        deflateStream.CopyTo(s);
                        s.Position = 0;

                        int count = 0;
                        // Get actual packet out of bytes
                        while (s.Position < s.Length)
                        {
                            count++;

                            uint len = VarInt.ReadUInt32(s);
                            long pos = s.Position;
                            ReadOnlyMemory <byte> internalBuffer = s.GetBuffer().AsMemory((int)s.Position, (int)len);
                            int id = VarInt.ReadInt32(s);
                            try
                            {
                                //if (Log.IsDebugEnabled)
                                //	Log.Debug($"0x{internalBuffer[0]:x2}\n{Packet.HexDump(internalBuffer)}");

                                messages.Add(PacketFactory.Create((byte)id, internalBuffer, "mcpe") ??
                                             new UnknownPacket((byte)id, internalBuffer));
                            }
                            catch (Exception e)
                            {
                                if (Log.IsDebugEnabled)
                                {
                                    Log.Warn($"Error parsing bedrock message #{count} id={id}\n{Packet.HexDump(internalBuffer)}", e);
                                }
                                //throw;
                                return;                                 // Exit, but don't crash.
                            }

                            s.Position = pos + len;
                        }

                        if (s.Length > s.Position)
                        {
                            throw new Exception("Have more data");
                        }
                    }
                }
                catch (Exception e)
                {
                    if (Log.IsDebugEnabled)
                    {
                        Log.Warn($"Error parsing bedrock message \n{Packet.HexDump(payload)}", e);
                    }
                    throw;
                }

                foreach (Packet msg in messages)
                {
                    // Temp fix for performance, take 1.
                    //var interact = msg as McpeInteract;
                    //if (interact?.actionId == 4 && interact.targetRuntimeEntityId == 0) continue;

                    msg.ReliabilityHeader = new ReliabilityHeader()
                    {
                        Reliability           = wrapper.ReliabilityHeader.Reliability,
                        ReliableMessageNumber = wrapper.ReliabilityHeader.ReliableMessageNumber,
                        OrderingChannel       = wrapper.ReliabilityHeader.OrderingChannel,
                        OrderingIndex         = wrapper.ReliabilityHeader.OrderingIndex,
                    };

                    RakOfflineHandler.TraceReceive(Log, msg);
                    try
                    {
                        HandleCustomPacket(msg);
                    }
                    catch (Exception e)
                    {
                        Log.Warn($"Bedrock message handler error", e);
                    }
                }

                wrapper.PutPool();
            }
            else if (message is UnknownPacket unknownPacket)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Warn($"Received unknown packet 0x{unknownPacket.Id:X2}\n{Packet.HexDump(unknownPacket.Message)}");
                }

                unknownPacket.PutPool();
            }
            else
            {
                Log.Error($"Unhandled packet: {message.GetType().Name} 0x{message.Id:X2} for user: {_session.Username}, IP {_session.EndPoint.Address}");
                if (Log.IsDebugEnabled)
                {
                    Log.Warn($"Unknown packet 0x{message.Id:X2}\n{Packet.HexDump(message.Bytes)}");
                }
            }
        }
Пример #7
0
        public static ChunkColumn DecocedChunkColumn(byte[] buffer)
        {
            lock (_chunkRead)
            {
                MemoryStream stream = new MemoryStream(buffer);
                {
                    NbtBinaryReader defStream = new NbtBinaryReader(stream, true);

                    Log.Debug("New chunk column");

                    int count = defStream.ReadByte();
                    if (count < 1)
                    {
                        Log.Warn("Nothing to read");
                        return(null);
                    }

                    Log.Debug($"Reading {count} sections");

                    ChunkColumn chunkColumn = new ChunkColumn();

                    for (int s = 0; s < count; s++)
                    {
                        int idx = defStream.ReadByte();

                        Log.Debug($"New section {s}, index={idx}");
                        Chunk chunk = chunkColumn.chunks[s];

                        int chunkSize = 16 * 16 * 16;
                        defStream.Read(chunk.blocks, 0, chunkSize);
                        //Log.Debug($"Blocks1:\n{Package.HexDump(chunk.blocks)}");

                        if (defStream.Read(chunk.metadata.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: metadata");
                        }

                        //Log.Debug($"metadata:\n{Package.HexDump(chunk.metadata.Data)}");

                        if (defStream.Read(chunk.skylight.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: skylight");
                        }
                        //Log.Debug($"skylight:\n{Package.HexDump(chunk.skylight.Data)}");

                        if (defStream.Read(chunk.blocklight.Data, 0, chunkSize / 2) != chunkSize / 2)
                        {
                            Log.Error($"Out of data: blocklight");
                        }
                        //Log.Debug($"blocklight:\n{Package.HexDump(chunk.blocklight.Data)}");

                        //Log.Debug($"skylight.Data:\n{Package.HexDump(chunk.skylight.Data, 64)}");
                        //Log.Debug($"blocklight.Data:\n{Package.HexDump(chunk.blocklight.Data)}");

                        //byte[] ints = new byte[256*4];
                        //var readLen = defStream.Read(ints, 0, ints.Length);
                        //if (readLen != ints.Length) Log.Error($"Out of data biomeColors, read lenght {readLen}");
                        //Log.Debug($"biomeColor (pre):\n{Package.HexDump(ints)}");

                        //return null;
                        //int j = 0;
                        //for (int i = 0; i < ints.Length; i = i + 4)
                        //{
                        //	chunk.biomeId[j] = ints[i];
                        //	chunk.biomeColor[j++] = BitConverter.ToInt32(new[] {(byte) 0, ints[i + 1], ints[i + 2], ints[i + 3]}, 0);
                        //}
                        //Log.Debug($"biomeId (post):\n{Package.HexDump(chunk.biomeId)}");

                        //if (stream.Position >= stream.Length - 1) return chunk;

                        ////return chunk;

                        //return chunk;
                    }

                    //if (stream.Position >= stream.Length - 1) continue;


                    byte[] ba = new byte[512];
                    if (defStream.Read(ba, 0, 256 * 2) != 256 * 2)
                    {
                        Log.Error($"Out of data height");
                    }

                    Buffer.BlockCopy(ba, 0, chunkColumn.height, 0, 512);
                    //Log.Debug($"Heights:\n{Package.HexDump(ba)}");

                    //if (stream.Position >= stream.Length - 1) continue;

                    if (defStream.Read(chunkColumn.biomeId, 0, 256) != 256)
                    {
                        Log.Error($"Out of data biomeId");
                    }
                    //Log.Debug($"biomeId:\n{Package.HexDump(chunk.biomeId)}");

                    //if (stream.Position >= stream.Length - 1) continue;


                    int borderBlock = VarInt.ReadInt32(stream);
                    if (borderBlock != 0)
                    {
                        byte[] buf = new byte[borderBlock];
                        int    len = defStream.Read(buf, 0, borderBlock);
                        Log.Warn($"??? Got borderblock {borderBlock}. Read {len} bytes");
                        Log.Debug($"{Package.HexDump(buf)}");
                        for (int i = 0; i < borderBlock; i++)
                        {
                            int x = (buf[i] & 0xf0) >> 4;
                            int z = buf[i] & 0x0f;
                            Log.Debug($"x={x}, z={z}");
                        }
                    }

                    int extraCount = VarInt.ReadSInt32(stream);
                    if (extraCount != 0)
                    {
                        //Log.Warn($"Got extradata\n{Package.HexDump(defStream.ReadBytes(extraCount*10))}");
                        for (int i = 0; i < extraCount; i++)
                        {
                            var hash      = VarInt.ReadSInt32(stream);
                            var blockData = defStream.ReadInt16();
                            Log.Warn($"Got extradata: hash=0x{hash:X2}, blockdata=0x{blockData:X2}");
                        }
                    }

                    if (stream.Position < stream.Length - 1)
                    {
                        //Log.Debug($"Got NBT data\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");

                        while (stream.Position < stream.Length)
                        {
                            NbtFile file = new NbtFile()
                            {
                                BigEndian = false, UseVarInt = true
                            };

                            file.LoadFromStream(stream, NbtCompression.None);

                            Log.Debug($"Blockentity: {file.RootTag}");
                        }
                    }
                    if (stream.Position < stream.Length - 1)
                    {
                        Log.Warn($"Still have data to read\n{Package.HexDump(defStream.ReadBytes((int) (stream.Length - stream.Position)))}");
                    }

                    return(chunkColumn);
                }
            }
        }
Пример #8
0
        public void HandlePacket(Packet message)
        {
            if (message is McpeWrapper wrapper)
            {
                var messages = new LinkedList <Packet>();

                // Get bytes to process
                var payload = wrapper.payload.ToArray();

                // Decrypt bytes


                if (CryptoContext != null && CryptoContext.UseEncryption)
                {
                    FirstEncryptedPacketWaitHandle.Set();

                    payload = CryptoUtils.Decrypt(payload, CryptoContext);

                    _hasEncrypted = true;
                }

                //var stream = new MemoryStreamReader(payload);
                using (var deflateStream = new DeflateStream(new MemoryStream(payload), System.IO.Compression.CompressionMode.Decompress, false))
                {
                    using var s = new MemoryStream();
                    deflateStream.CopyTo(s);
                    s.Position = 0;

                    int count = 0;
                    // Get actual packet out of bytes
                    while (s.Position < s.Length)
                    {
                        count++;

                        uint len = VarInt.ReadUInt32(s);
                        long pos = s.Position;
                        ReadOnlyMemory <byte> internalBuffer = s.GetBuffer().AsMemory((int)s.Position, (int)len);
                        int id = VarInt.ReadInt32(s);

                        Packet packet = null;
                        try
                        {
                            packet = PacketFactory.Create((byte)id, internalBuffer, "mcpe")
                                     ?? new UnknownPacket((byte)id, internalBuffer);

                            //Hack for some servers that screw up the order.
                            //	if (packet is McpePlayerList)
                            //	{
                            //		messages.AddFirst(packet);
                            //	}
                            //	else
                            {
                                messages.AddLast(packet);
                            }

                            //var a = 0x91;
                        }
                        catch (Exception e)
                        {
                            Log.Warn(e, $"Error parsing bedrock message #{count} id={id}\n{Packet.HexDump(internalBuffer)}");
                            //throw;
                            return;                             // Exit, but don't crash.
                        }

                        s.Position = pos + len;
                    }

                    if (s.Length > s.Position)
                    {
                        throw new Exception("Have more data");
                    }
                }

                //var msgs = messages.ToArray();
                //messages.Clear();


                foreach (Packet msg in messages)
                {
                    msg.ReliabilityHeader = new ReliabilityHeader()
                    {
                        Reliability           = wrapper.ReliabilityHeader.Reliability,
                        ReliableMessageNumber = wrapper.ReliabilityHeader.ReliableMessageNumber,
                        OrderingChannel       = wrapper.ReliabilityHeader.OrderingChannel,
                        OrderingIndex         = wrapper.ReliabilityHeader.OrderingIndex,
                        SequencingIndex       = wrapper.ReliabilityHeader.SequencingIndex
                    };

                    try
                    {
                        HandleGamePacket(msg);
                    }
                    catch (Exception e)
                    {
                        Log.Warn(e, $"Bedrock message handler error");
                    }
                }

                wrapper.PutPool();
            }
            else if (message is UnknownPacket unknownPacket)
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Warn($"Received unknown packet 0x{unknownPacket.Id:X2}\n{Packet.HexDump(unknownPacket.Message)}");
                }

                unknownPacket.PutPool();
            }
            else
            {
                Log.Error($"Unhandled packet: {message.GetType().Name} 0x{message.Id:X2} for user: {_session.Username}, IP {_session.EndPoint.Address}");
                if (Log.IsDebugEnabled)
                {
                    Log.Warn($"Unknown packet 0x{message.Id:X2}\n{Packet.HexDump(message.Bytes)}");
                }
            }
        }