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()); } }
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); }
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); } }
/// <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); }
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)}"); } } }
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); } } }
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)}"); } } }