Beispiel #1
0
        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.");
            }
        }
Beispiel #2
0
        internal static DataCenterAddress ReadAddress(GameBinaryReader reader)
        {
            var segment = reader.ReadUInt16();
            var element = reader.ReadUInt16();

            return(new DataCenterAddress(segment, element));
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
        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));
        }
Beispiel #6
0
        static PacketHeader ReadHeader(GameBinaryReader reader)
        {
            reader.Position = 0;

            var length = (ushort)(reader.ReadUInt16() - PacketHeader.HeaderSize);
            var code   = reader.ReadUInt16();

            return(new PacketHeader(length, code));
        }
Beispiel #7
0
        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));
        }
Beispiel #8
0
        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));
        }
Beispiel #9
0
        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));
        }
Beispiel #10
0
        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));
        }
Beispiel #11
0
        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));
        }
Beispiel #12
0
        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;
        }
Beispiel #15
0
        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));
                }
            }
        }
Beispiel #17
0
        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);
 }
Beispiel #19
0
 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));
            }
        }