public DataCenter(Stream stream, DataCenterMode mode, DataCenterStringOptions options) { if (stream.Length > 375000000) /// ugly hack since x64 has the same version { x64 = true; AttributeSize = 12; ElementSize = 24; } options.CheckFlagsValidity(nameof(options)); Mode = mode.CheckValidity(nameof(mode)); using var reader = new GameBinaryReader(stream, true); Header = ReadHeader(reader); Extensions = ReadSimpleRegion(reader, false, ExtensionSize); Attributes = ReadSegmentedRegion(reader, AttributeSize); Elements = ReadSegmentedRegion(reader, ElementSize); Values = ReadStringTable(reader, 1024, false, options); Names = ReadStringTable(reader, 512, true, options); Footer = ReadFooter(reader); var diff = stream.Length - stream.Position; if (diff != 0) { throw new InvalidDataException($"{diff} bytes remain unread."); } }
internal static DataCenterAddress ReadAddress(GameBinaryReader reader) { var segment = reader.ReadUInt16(); var element = reader.ReadUInt16(); return(new DataCenterAddress(segment, element)); }
public unsafe DataCenter(string fileName, bool intern) { _intern = intern; using var reader = new GameBinaryReader(File.OpenRead(fileName)); Header = ReadHeader(reader); ReadSimpleRegion(reader, false, Unknown1Size); var attributeRegion = ReadSegmentedRegion(reader, AttributeSize); var elementRegion = ReadSegmentedRegion(reader, ElementSize); _stringRegion = ReadSegmentedRegion(reader, sizeof(char)); ReadSimpleSegmentedRegion(reader, 1024, Unknown2Size); ReadSimpleRegion(reader, true, (uint)sizeof(DataCenterAddress)); var nameRegion = ReadSegmentedRegion(reader, sizeof(char)); ReadSimpleSegmentedRegion(reader, 512, Unknown2Size); var nameAddressRegion = ReadSimpleRegion(reader, true, (uint)sizeof(DataCenterAddress)); Footer = ReadFooter(reader); Attributes = attributeRegion; Elements = elementRegion; Names = ReadAddresses(nameAddressRegion).Select(x => ReadString(nameRegion, x)).ToArray(); Reset(); }
static DataCenterRegion ReadRegion(GameBinaryReader reader, uint elementSize) { var full = reader.ReadUInt32(); var used = reader.ReadUInt32(); var data = reader.ReadBytes((int)(full * elementSize)); return(new DataCenterRegion(elementSize, full, used, data)); }
internal static PacketHeader ReadHeader(byte[] buffer) { using var reader = new GameBinaryReader(buffer); var length = (ushort)(reader.ReadUInt16() - PacketHeader.HeaderSize); var code = reader.ReadUInt16(); return(new PacketHeader(length, code)); }
static PacketHeader ReadHeader(GameBinaryReader reader) { reader.Position = 0; var length = (ushort)(reader.ReadUInt16() - PacketHeader.HeaderSize); var code = reader.ReadUInt16(); return(new PacketHeader(length, code)); }
static unsafe DataCenterStringTable ReadStringTable(GameBinaryReader reader, uint count, bool names, DataCenterStringOptions options) { var data = ReadSegmentedRegion(reader, sizeof(char)); var table = ReadSegmentedSimpleRegion(reader, count, MetadataSize); var addresses = ReadSimpleRegion(reader, true, (uint)sizeof(DataCenterAddress)); return(new DataCenterStringTable(data, table, addresses, names, options)); }
static DataCenterSegmentedRegion ReadSegmentedRegion(GameBinaryReader reader, uint elementSize) { var count = reader.ReadUInt32(); var segments = new List <DataCenterRegion>((int)count); for (var i = 0; i < count; i++) { segments.Add(ReadRegion(reader, elementSize)); } return(new DataCenterSegmentedRegion(elementSize, segments)); }
static DataCenterSegmentedSimpleRegion ReadSegmentedSimpleRegion(GameBinaryReader reader, uint count, uint elementSize) { var segments = new List <DataCenterSimpleRegion>((int)count); for (var i = 0; i < count; i++) { segments.Add(ReadSimpleRegion(reader, false, elementSize)); } return(new DataCenterSegmentedSimpleRegion(elementSize, segments)); }
static DataCenterHeader ReadHeader(GameBinaryReader reader) { var unk1 = reader.ReadInt32(); var unk2 = reader.ReadInt32(); var unk3 = reader.ReadInt32(); var version = reader.ReadUInt32(); var unk4 = reader.ReadInt32(); var unk5 = reader.ReadInt32(); var unk6 = reader.ReadInt32(); var unk7 = reader.ReadInt32(); return(new DataCenterHeader(unk1, unk2, unk3, version, unk4, unk5, unk6, unk7)); }
static DataCenterSimpleRegion ReadSimpleRegion(GameBinaryReader reader, bool offByOne, uint elementSize) { var count = reader.ReadUInt32(); if (offByOne) { count--; } var data = reader.ReadBytes((int)(count * elementSize)); return(new DataCenterSimpleRegion(elementSize, count, data)); }
public void Deserialize(byte[] payload, SerializablePacket packet) { if (payload == null) { throw new ArgumentNullException(nameof(payload)); } if (packet == null) { throw new ArgumentNullException(nameof(packet)); } using var reader = new GameBinaryReader(payload); OnDeserialize(reader, _byType[packet.GetType()], packet); packet.OnDeserialize(this); }
public void Deserialize(byte[] buffer, int index, int count, SerializablePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } if (!_byType.TryGetValue(packet.GetType(), out var info)) { throw new UnmappedMessageException(); } using var reader = new GameBinaryReader(buffer, index, count); OnDeserialize(reader, info, packet); packet.OnDeserialize(this); }
public PacketLogReader(string fileName) { Stream stream = File.OpenRead(fileName); var magic = new byte[PacketLogEntry.Magic.Count]; if (stream.Read(magic, 0, magic.Length) != magic.Length) { throw new EndOfStreamException(); } if (!magic.SequenceEqual(PacketLogEntry.Magic)) { throw new InvalidDataException(); } var level = stream.ReadByte(); if (level == -1) { throw new EndOfStreamException(); } if ((CompressionLevel = (byte)level) != 0) { stream = new DeflateStream(stream, CompressionMode.Decompress); } _reader = new GameBinaryReader(stream); Version = _reader.ReadUInt32(); if (Version != PacketLogEntry.Version) { throw new InvalidDataException(); } Region = (Region)_reader.ReadByte(); if (!Enum.IsDefined(typeof(Region), Region)) { throw new InvalidDataException(); } var clientVersion = _reader.ReadUInt32(); if (!DataCenter.Versions.Values.Contains(clientVersion)) { throw new InvalidDataException(); } GameMessages = new GameMessageTable(clientVersion); SystemMessages = new SystemMessageTable(clientVersion); var serverCount = (int)_reader.ReadUInt32(); if (serverCount < 0) { throw new InvalidDataException(); } var servers = new Dictionary <int, ServerInfo>(serverCount); for (var i = 0; i < serverCount; i++) { var id = _reader.ReadInt32(); if (servers.ContainsKey(id)) { throw new InvalidDataException(); } var name = _reader.ReadString(); var size = _reader.ReadBoolean() ? 16 : 4; var realIPBytes = _reader.ReadBytes(size); var realPort = _reader.ReadUInt16(); var proxyIPBytes = _reader.ReadBytes(size); var proxyPort = _reader.ReadUInt16(); IPEndPoint realEP; IPEndPoint proxyEP; try { realEP = new IPEndPoint(new IPAddress(realIPBytes), realPort); proxyEP = new IPEndPoint(new IPAddress(proxyIPBytes), proxyPort); } catch (ArgumentException) { throw new InvalidDataException(); } servers.Add(id, new ServerInfo(id, name, realEP, proxyEP)); } Servers = servers; }
static DataCenterFooter ReadFooter(GameBinaryReader reader) { var unk1 = reader.ReadInt32(); return(new DataCenterFooter(unk1)); }
public static IEnumerable <PotentialArray> FindArrays(ReadOnlyMemory <byte> payload) { using var reader = new GameBinaryReader(payload.GetArray()); for (var i = 0; i < reader.Length; i++) { reader.Position = i; if (!reader.CanRead(sizeof(ushort) * 2)) { break; } var countPos = reader.Position; var count = reader.ReadUInt16(); var offsetPos = reader.Position; var offset = reader.ReadOffset(); if (count == 0 || (count * (sizeof(ushort) * 2 + sizeof(byte)) + sizeof(ushort) * 2) > reader.Length) { continue; } var positions = new HashSet <int> { countPos, countPos + sizeof(byte), offsetPos, offsetPos + sizeof(byte), }; var elems = new List <PotentialArrayElement>(); var good = true; var last = offsetPos; var next = offset; while (next != -PacketHeader.HeaderSize) { if (!(good = next >= 0 && next > last && next <= reader.Length - sizeof(ushort) * 2 - sizeof(byte))) { break; } last = next + sizeof(ushort) * 2; reader.Position = next; var herePos = reader.Position; var here = reader.ReadOffset(); if (!(good = here == herePos && here == next && positions.Add(herePos) && positions.Add(herePos + sizeof(byte)))) { break; } var nextPos = reader.Position; next = reader.ReadOffset(); if (!(good = positions.Add(nextPos) && positions.Add(nextPos + sizeof(byte)))) { break; } elems.Add(new PotentialArrayElement(here, nextPos, next == -PacketHeader.HeaderSize ? 0 : next)); } if (good && elems.Count == count) { yield return(new PotentialArray(countPos, count, offsetPos, offset, elems)); } } }
void Receive(Direction direction, Memory <byte> headerBuffer, GameBinaryReader headerReader, GameBinaryWriter headerWriter, Memory <byte> payloadBuffer, bool nested) { if (headerBuffer.IsEmpty) { var arr = new byte[PacketHeader.HeaderSize]; headerBuffer = arr; headerReader = new GameBinaryReader(arr); headerWriter = new GameBinaryWriter(arr); } if (payloadBuffer.IsEmpty) { payloadBuffer = new byte[PacketHeader.MaxPayloadSize]; } Socket from; Socket to; GameEncryptionSession fromEnc; GameEncryptionSession toEnc; if (direction == Direction.ClientToServer) { from = _clientSocket; to = _serverSocket; fromEnc = _clientEncryption; toEnc = _serverEncryption; } else { from = _serverSocket; to = _clientSocket; fromEnc = _serverEncryption; toEnc = _clientEncryption; } var toServer = to == _serverSocket; var fromServer = to == _serverSocket; bool DoReceive() { try { ReceiveInternal(headerBuffer, from, fromEnc, fromServer); var header = ReadHeader(headerReader); if (header.Length > PacketHeader.MaxPayloadSize) { DisconnectInternal(); _log.Error("Disconnected client {0} from {1} due to invalid packet length: {2}", EndPoint, Proxy.Info.Name, header.Length); return(false); } var payload = payloadBuffer.Slice(0, header.Length); ReceiveInternal(payload, from, fromEnc, fromServer); var original = payload; var send = Proxy.InvokeReceived(this, direction, header.Code, ref payload); if (send) { // A handler might have created a packet that's too large. if (payload.Length > PacketHeader.MaxPayloadSize) { Proxy.Serializer.GameMessages.CodeToName.TryGetValue(header.Code, out var name); if (name == null) { name = header.Code.ToString(); } _log.Error( "{0}: Packet {1} is too large ({2} bytes) to be sent correctly; sending original", direction.ToDirectionString(), name, payload.Length); payload = original; } header = new PacketHeader((ushort)payload.Length, header.Code); WriteHeader(headerWriter, header); var headerSlice = headerBuffer.Slice(0, PacketHeader.HeaderSize); SendInternal(headerSlice, true, to, toEnc, toServer); SendInternal(payload, true, to, toEnc, toServer); } } catch (SocketDisconnectedException) { // Normal disconnection. Disconnect(); return(false); } catch (Exception e) when(IsSocketException(e)) { // The client is already disconnected. return(false); } return(true); } // If we don't expect a large number of clients, just use dedicated // tasks to receive data instead of spawning a new one per receive. if (!nested && Proxy.MaxClients <= Environment.ProcessorCount) { Task.Factory.StartNew(() => { while (DoReceive()) { } headerReader.Dispose(); headerWriter.Dispose(); }, TaskCreationOptions.LongRunning); } else { Task.Run(() => { if (!DoReceive()) { headerReader.Dispose(); headerWriter.Dispose(); } else { Receive(direction, headerBuffer, headerReader, headerWriter, payloadBuffer, true); } }); } }
protected override void OnDeserialize(GameBinaryReader reader, PacketInfo info, SerializablePacket packet) { _deserializers[info](reader, packet); }
protected abstract void OnDeserialize(GameBinaryReader reader, PacketInfo info, SerializablePacket packet);
void DeserializeObject(GameBinaryReader reader, object target) { foreach (var info in GetPacketInfo(target.GetType()).Fields.Cast <ReflectionPacketFieldInfo>()) { if (info.IsByteArray) { var offset = reader.ReadOffset(); var count = reader.ReadUInt16(); var list = (List <byte>)info.Property.GetValue(target); list.Clear(); if (count == 0) { continue; } reader.Seek(offset, (r, op) => list.AddRange(r.ReadBytes(count))); } else if (info.IsArray) { var count = reader.ReadUInt16(); var offset = reader.ReadOffset(); var list = (IList)info.Property.GetValue(target); list.Clear(); if (count == 0) { continue; } var next = offset; for (var i = 0; i < count; i++) { reader.Seek(next, (r, op) => { r.ReadOffset(); next = r.ReadOffset(); var elem = info.ElementConstructor(); DeserializeObject(r, elem); list.Add(elem); }); } } else if (info.IsString) { var offset = reader.ReadOffset(); info.Property.SetValue(target, reader.Seek(offset, (r, op) => r.ReadString())); } else { var val = info.PrimitiveDeserializer(reader); info.EnumValidator?.Invoke(val); info.Property.SetValue(target, val); } } }
public PacketLogReader(string fileName) { Stream stream = File.OpenRead(fileName); using var reader = new GameBinaryReader(stream, true); if (!reader.ReadBytes(PacketLogEntry.Magic.Count).SequenceEqual(PacketLogEntry.Magic)) { throw new InvalidDataException("Invalid magic number."); } Version = reader.ReadUInt32(); if (Version != PacketLogEntry.Version) { throw new InvalidDataException($"Unknown format version {Version}."); } Region = (Region)reader.ReadByte(); if (!Enum.IsDefined(typeof(Region), Region)) { throw new InvalidDataException($"Unknown region value {Region}."); } var clientVersion = reader.ReadUInt32(); if (!DataCenter.ClientVersions.Values.Contains(clientVersion)) { throw new InvalidDataException($"Unknown client version {clientVersion}."); } GameMessages = new GameMessageTable(clientVersion); SystemMessages = new SystemMessageTable(clientVersion); var serverCount = (int)reader.ReadUInt32(); var servers = new Dictionary <int, ServerInfo>(serverCount); for (var i = 0; i < serverCount; i++) { var id = reader.ReadInt32(); if (servers.ContainsKey(id)) { throw new InvalidDataException($"Duplicate server ID {id}."); } var name = reader.ReadString(); var size = reader.ReadBoolean() ? 16 : 4; var realIPBytes = reader.ReadBytes(size); var realPort = reader.ReadUInt16(); var proxyIPBytes = reader.ReadBytes(size); var proxyPort = reader.ReadUInt16(); IPEndPoint realEP; try { realEP = new IPEndPoint(new IPAddress(realIPBytes), realPort); } catch (ArgumentOutOfRangeException) { throw new InvalidDataException($"Invalid real port {realPort}."); } catch (ArgumentException) { throw new InvalidDataException("Invalid real IP address."); } IPEndPoint proxyEP; try { proxyEP = new IPEndPoint(new IPAddress(proxyIPBytes), proxyPort); } catch (ArgumentOutOfRangeException) { throw new InvalidDataException($"Invalid proxy port {proxyPort}."); } catch (ArgumentException) { throw new InvalidDataException("Invalid proxy IP address."); } servers.Add(id, new ServerInfo(id, name, realEP, proxyEP)); } Servers = servers; CompressionLevel = reader.ReadByte(); _reader = new GameBinaryReader(CompressionLevel != 0 ? new FastDeflateStream(stream, CompressionMode.Decompress) : stream); }
public static IEnumerable <PotentialString> FindStrings(ReadOnlyMemory <byte> payload, bool whiteSpace, bool control, int minLength) { using var reader = new GameBinaryReader(payload.GetArray()); for (var i = 0; i < reader.Length; i++) { reader.Position = i; if (!reader.CanRead(sizeof(ushort))) { break; } var offsetPos = reader.Position; var offset = reader.ReadOffset(); if (offset < 0 || offset < offsetPos + sizeof(ushort) || offset > reader.Length - sizeof(char)) { continue; } reader.Position = offset; string str; try { str = reader.ReadString(); GameBinaryReader.Encoding.GetString(GameBinaryReader.Encoding.GetBytes(str)); } catch (Exception e) when(IsStringException(e)) { continue; } if (!whiteSpace && string.IsNullOrWhiteSpace(str)) { continue; } if (minLength != 0 && str.Length < minLength) { continue; } var hasBadChars = str.Any(c => { var cat = char.GetUnicodeCategory(c); return(cat == UnicodeCategory.Control || cat == UnicodeCategory.Format || cat == UnicodeCategory.OtherNotAssigned || cat == UnicodeCategory.PrivateUse || cat == UnicodeCategory.Surrogate); }); if (!control && hasBadChars) { continue; } yield return(new PotentialString(offsetPos, offset, str)); } }