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