public void Test_Patching_Payload_Deserializes_To_Correct_Values()
        {
            //arrange
            SerializerService serializer = new SerializerService();

            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadClient, PSOBBPatchPacketPayloadClient_AutoGeneratedTemplateSerializerStrategy>();
            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadServer, PSOBBPatchPacketPayloadServer_AutoGeneratedTemplateSerializerStrategy>();
            Span <byte> buffer = new Span <byte>(new byte[500]);

            PatchingWelcomePayload payload = new PatchingWelcomePayload("Patch Server. Copyright SonicTeam, LTD. 2001", 506953426, 214005626);

            //assert
            int offset = 0;

            serializer.Write(payload, buffer, ref offset);
            int size = offset;

            offset = 0;
            PatchingWelcomePayload deserializedPayload = (PatchingWelcomePayload)serializer.Read <PSOBBPatchPacketPayloadServer>(buffer.Slice(0, size), ref offset);

            //assert
            Assert.AreEqual(payload.PatchCopyrightMessage, deserializedPayload.PatchCopyrightMessage);
            Assert.AreEqual(payload.ClientVector, deserializedPayload.ClientVector);
            Assert.AreEqual(payload.ServerVector, deserializedPayload.ServerVector);
            Assert.AreEqual(0x99, deserializedPayload.OperationCode);
        }
示例#2
0
        public void Can_Deserialize_Captures_To_GamePacketPayloads(PacketCaptureTestEntry entry)
        {
            Console.WriteLine($"Entry Decompressed/Real Size: {entry.BinaryData.Length} OpCode: {entry.OpCode}");

            //arrange
            SerializerService serializer = Serializer;

            GamePacketPayload payload;

            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            //act
            try
            {
                payload = serializer.Read <GamePacketPayload>(new Span <byte>(entry.BinaryData), 0);
            }
            catch (Exception e)
            {
                Assert.Fail($"Critical failure. Cannot deserialize File: {entry.FileName} FileSize: {entry.BinaryData.Length} \n\n Exception: {e.Message} Stack: {e.StackTrace}");
                return;
            }
            finally
            {
                stopwatch.Stop();
            }

            Console.WriteLine($"Serialization time in ms: {stopwatch.ElapsedMilliseconds}");

            //assert
            Assert.NotNull(payload, $"Resulting capture capture deserialization attempt null for File: {entry.FileName}");
            //We should have deserialized it. We want to make sure the opcode matches
            Assert.AreEqual(entry.OpCode, payload.OperationCode, $"Mismatched {nameof(NetworkOperationCode)} on packet capture File: {entry.FileName}. Expected: {entry.OpCode} Was: {payload.OperationCode}");
        }
        public void Test_No_Stack_Overflow_On_Deserializing_PacketHeader()
        {
            //arrange
            SerializerService serializer = new SerializerService();

            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadClient, PSOBBPatchPacketPayloadClient_AutoGeneratedTemplateSerializerStrategy>();
            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadServer, PSOBBPatchPacketPayloadServer_AutoGeneratedTemplateSerializerStrategy>();

            byte[] bytes = new byte[] { 55, 78 };

            serializer.Read <PSOBBPacketHeader>(new Span <byte>(bytes), 0);
        }
示例#4
0
        private static void BenchMarkMethod(SerializerService serializer)
        {
            Stopwatch   watch  = new Stopwatch();
            Span <byte> buffer = new Span <byte>(new byte[10000]);
            int         offset = 0;

            watch.Start();
            for (int i = 0; i < 5000000; i++)
            {
                AuthPacketBaseTest packet = serializer.Read <AuthPacketBaseTest>(realWorldBytes, 0);
                serializer.Write(packet, buffer, ref offset);
                offset = 0;
            }
            watch.Stop();
            Console.WriteLine($"MS: {watch.ElapsedMilliseconds}");
        }
        public void Test_Can_Serialize_Then_Deserialize_Subcommand60Payload()
        {
            //arrange
            SerializerService serializer = new SerializerService();

            serializer.RegisterPolymorphicSerializer <BaseSubCommand60, BaseSubCommand60_Serializer>();
            Span <byte> buffer = new Span <byte>(new byte[1000]);
            int         offset = 0;

            //act
            serializer.Write(new Sub60MovingFastPositionSetCommand(5, new Vector2 <float>(2, 5)), buffer, ref offset);
            Sub60MovingFastPositionSetCommand desserialized = serializer.Read <BaseSubCommand60>(buffer.Slice(0, offset), 0)
                                                              as Sub60MovingFastPositionSetCommand;

            //assert
            Assert.NotNull(desserialized, "Object was null.");
            Assert.NotNull(desserialized.Position);
            Assert.AreEqual(5, desserialized.Identifier);
            Assert.True(Math.Abs(desserialized.Position.X - 2) < float.Epsilon);
        }
        public void Test_Can_Serialize_Payload()
        {
            //arrange
            SerializerService serializer = new SerializerService();

            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadClient, PSOBBPatchPacketPayloadClient_AutoGeneratedTemplateSerializerStrategy>();
            serializer.RegisterPolymorphicSerializer <PSOBBPatchPacketPayloadServer, PSOBBPatchPacketPayloadServer_AutoGeneratedTemplateSerializerStrategy>();
            byte[] bytes = Enumerable.Repeat((byte)55, 200).ToArray();

            //act
            int offset = 0;
            UnknownPatchPacket payload = serializer.Read <PSOBBPatchPacketPayloadServer>(new Span <byte>(bytes), ref offset)
                                         as UnknownPatchPacket;

            Assert.True(payload.UnknownBytes.Length == (200 - 2));

            for (int i = 0; i < bytes.Length - 2; i++)
            {
                Assert.AreEqual(bytes[i], payload.UnknownBytes[i]);
            }
        }
示例#7
0
        static void Main(string[] args)
        {
            realWorldBytes = realWorldBytes
                             .Take(1)
                             .Concat(new byte[5000])
                             .Concat(realWorldBytes.Skip(1))
                             .ToArray();

            Span <byte> buffer = new Span <byte>(new byte[10000]);
            int         offset = 0;

            SerializerService serializer = new SerializerService();

            serializer.RegisterPolymorphicSerializer <AuthPacketBaseTest, AuthPacketBaseTest_AutoGeneratedTemplateSerializerStrategy>();

            //JIT
            AuthPacketBaseTest packet = serializer.Read <AuthPacketBaseTest>(realWorldBytes, 0);

            serializer.Write(packet, buffer, ref offset);

            BenchMarkMethod(serializer);
            Console.ReadKey();
        }
示例#8
0
        public void Can_Serialize_DeserializedDTO_To_Same_Binary_Representation(PacketCaptureTestEntry entry)
        {
            //arrange
            Console.WriteLine($"Entry Size: {entry.BinaryData.Length} OpCode: {entry.OpCode}");
            SerializerService serializer = Serializer;
            GamePacketPayload payload    = serializer.Read <GamePacketPayload>(new Span <byte>(entry.BinaryData), 0);

            //act
            int         offset = 0;
            Span <byte> buffer = new Span <byte>(new byte[62000]);

            try
            {
                serializer.Write(payload, buffer, ref offset);
            }
            catch (KnownIncompleteSerializationException e)
            {
                Assert.Warn($"Incomplete serialization implementation for Type: {e.Message}. Message: {e}");
                return;
            }

            //assert
            try
            {
                Assert.AreEqual(entry.BinaryData.Length, offset, $"Mismatched length on OpCode: {entry.OpCode} Type: {payload.GetType().Name}");
            }
            catch (AssertionException e)
            {
                Assert.Fail($"Failed: {e.Message} {PrintFailureBytes(entry.BinaryData, buffer.Slice(0, offset).ToArray())}");
            }


            for (int i = 0; i < entry.BinaryData.Length; i++)
            {
                Assert.AreEqual(entry.BinaryData[i], buffer[i], $"Mismatched byte value at Index: {i} on OpCode: {entry.OpCode} Type: {payload.GetType().Name}");
            }
        }
        public void Generic_Can_Serialize_DeserializedClientDTO_To_Same_Binary_Representation <TBasePayloadType, TOperationCodeType>(PacketCaptureTestEntry entry)
            where TBasePayloadType : IOperationCodeable <TOperationCodeType>, ITypeSerializerReadingStrategy <TBasePayloadType>, ITypeSerializerWritingStrategy <TBasePayloadType>
            where TOperationCodeType : Enum
        {
            //arrange
            Console.WriteLine($"Entry Size: {entry.BinaryData.Length} OpCode: {entry.OpCode}");
            SerializerService serializer = Serializer;
            TBasePayloadType  payload    = default;
            int readOffset = 0;

            try
            {
                payload = serializer.Read <TBasePayloadType>(entry.BinaryData, ref readOffset);
            }
            catch (IndexOutOfRangeException e)
            {
                Console.WriteLine($"Offset: {readOffset} BinarySize: {entry.BinaryData.Length}");
                throw;
            }
            catch (Exception e)
            {
                Console.WriteLine($"Error: {e}");
                throw;
            }

            if (payload is IUnknownPayloadType)
            {
                Assert.Warn($"Encountered unimplemented OpCode: 0x{payload.OperationCode:X} - {payload.OperationCode.ToString()}.");
                return;
            }

            bool isSub60 = false;
            bool isSub62 = false;

            //Special handling for 0x60 payloads, we don't want to deal with unknown subcommands. Just warn
            if (payload is ISub60CommandContainer sub60)
            {
                isSub60 = true;
                if (sub60.Command is UnknownSubCommand60Command)
                {
                    Assert.Warn($"Encountered unimplemented Sub60 SubCommand: 0x{payload.OperationCode:X} 0x{entry.BinaryData[6]:X}.");
                    return;
                }
            }
            else if (payload is ISub62CommandContainer sub62)
            {
                isSub62 = true;
                if (sub62.Command is UnknownSubCommand62Command)
                {
                    Assert.Warn($"Encountered unimplemented Sub62 SubCommand: 0x{payload.OperationCode:X} 0x{entry.BinaryData[6]:X}.");
                    return;
                }
            }

            //act
            byte[] rentedBuffer = ArrayPool <byte> .Shared.Rent(36000 * 2);

            //Must zero out for cleanest tests.
            for (int i = 0; i < rentedBuffer.Length; i++)
            {
                rentedBuffer[i] = default(byte);
            }

            try
            {
                Span <byte> buffer = new Span <byte>(rentedBuffer);

                int offset = 0;
                serializer.Write(payload, buffer, ref offset);
                buffer = buffer.Slice(0, offset);

                //The plus 2 is from the packet size which is included as calculation in whether it is appropriate for the block
                //size of 8.
                //+2 is also added to the original binary length since it's missing the packet size too.
                int serializedBytesWithBlockSize = ConvertToBlocksizeCount(buffer.Length + 2, 8);
                int entryBytesWithBlockSize      = ConvertToBlocksizeCount(entry.BinaryData.Length + 2, 8);
                //assert
                try
                {
                    if (!isSub60 && !isSub62)
                    {
                        //convert the serialized bytes to block size since Sylverant and the packet captures will include that in the data
                        Assert.AreEqual(entryBytesWithBlockSize, serializedBytesWithBlockSize, $"Mismatched length on OpCode: {(GameNetworkOperationCode)entry.OpCode} - 0x{entry.OpCode:X} Type: {payload.GetType().Name}");
                    }
                    else if (isSub60)
                    {
                        var command = (payload as ISub60CommandContainer).Command;
                        //Similar to the above but we include information about the sub60 command
                        Assert.AreEqual(entryBytesWithBlockSize, serializedBytesWithBlockSize, $"Mismatched length on OpCode: {(GameNetworkOperationCode)entry.OpCode} - 0x{entry.OpCode:X} Type: {payload.GetType().Name} Sub60 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name}");

                        //Command 60s should also check the command size
                        Assert.AreEqual(entry.BinaryData[7], buffer[7], $"Mismatched Sub60 {nameof(BaseSubCommand60.CommandSize)} on OpCode: {(GameNetworkOperationCode)entry.OpCode} - 0x{entry.OpCode:X} Type: {payload.GetType().Name} Sub60 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name}");
                    }
                    else if (isSub62)
                    {
                        var command = (payload as ISub62CommandContainer).Command;
                        //Similar to the above but we include information about the sub60 command
                        Assert.AreEqual(entryBytesWithBlockSize, serializedBytesWithBlockSize, $"Mismatched length on OpCode: {(GameNetworkOperationCode)entry.OpCode} - 0x{entry.OpCode:X} Type: {payload.GetType().Name} Sub62 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name}");
                    }
                }
                catch (AssertionException e)
                {
                    Assert.Fail($"Failed: {e.Message} {PrintFailureBytes(entry.BinaryData, buffer)}");
                }

                //check both lengths since we accept that some packet models won't include the padding.
                for (int i = 0; i < entry.BinaryData.Length && i < buffer.Length; i++)
                {
                    if (!isSub60 && !isSub62)
                    {
                        //This is an optimization to avoid pointless string allocations/building.
                        if (entry.BinaryData[i] != buffer[i])
                        {
                            Assert.AreEqual(entry.BinaryData[i], buffer[i], $"Mismatched byte value at Index: {i} on OpCode: 0x{entry.OpCode:X} Type: {payload.GetType().Name} {PrintFailureBytes(entry.BinaryData, buffer)}");
                        }
                    }
                    else if (isSub60)
                    {
                        var command = (payload as ISub60CommandContainer).Command;

                        //This is an optimization to avoid pointless string allocations/building.
                        if (entry.BinaryData[i] != buffer[i])
                        {
                            Assert.AreEqual(entry.BinaryData[i], buffer[i], $"Mismatched byte value at Index: {i} on OpCode: 0x{entry.OpCode:X} Type: {payload.GetType().Name} Sub60 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name} {PrintFailureBytes(entry.BinaryData, buffer)}");
                        }
                    }
                    else if (isSub62)
                    {
                        var command = (payload as ISub62CommandContainer).Command;

                        //This is an optimization to avoid pointless string allocations/building.
                        if (entry.BinaryData[i] != buffer[i])
                        {
                            Assert.AreEqual(entry.BinaryData[i], buffer[i], $"Mismatched byte value at Index: {i} on OpCode: 0x{entry.OpCode:X} Type: {payload.GetType().Name} Sub62 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name} {PrintFailureBytes(entry.BinaryData, buffer)}");
                        }
                    }
                }

                //Special check for when we have a packet that hasn't failed but has differently lenghts (assumed to be blocksize)
                //we check and make sure that the ending bytes are actually 0. If they aren't it likely NOT padding and additional unhandled data
                if (entry.BinaryData.Length > buffer.Length)
                {
                    for (int i = buffer.Length; i < entry.BinaryData.Length; i++)
                    {
                        if (!isSub60 && !isSub62)
                        {
                            Assert.AreEqual(0, entry.BinaryData[i], $"Encountered assumed padding byte at Index: {i} on OpCode: 0x{entry.OpCode} Type: {payload.GetType().Name} but value was: 0x{entry.BinaryData[i]:X}");
                        }
                        else if (isSub60)
                        {
                            var command = (payload as ISub60CommandContainer).Command;
                            Assert.AreEqual(0, entry.BinaryData[i], $"Encountered assumed padding byte at Index: {i} on OpCode: 0x{entry.OpCode} Type: {payload.GetType().Name} but value was: 0x{entry.BinaryData[i]:X} Sub60 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name}");
                        }
                        else if (isSub62)
                        {
                            var command = (payload as ISub62CommandContainer).Command;
                            Assert.AreEqual(0, entry.BinaryData[i], $"Encountered assumed padding byte at Index: {i} on OpCode: 0x{entry.OpCode} Type: {payload.GetType().Name} but value was: 0x{entry.BinaryData[i]:X} Sub62 OpCode: 0x{entry.BinaryData[6]:X} Type: {command.GetType().Name}");
                        }
                    }
                }
            }
            finally
            {
                ArrayPool <byte> .Shared.Return(rentedBuffer);
            }
        }