diff --git a/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs b/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs index c5d3f66..44f4258 100644 --- a/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs +++ b/tests/AcDream.Core.Net.Tests/LiveHandshakeTests.cs @@ -197,12 +197,15 @@ public class LiveHandshakeTests $"inbound.next=0x{new IsaacRandom(serverSeedBytes).Next():X8}, " + $"outbound.next=0x{new IsaacRandom(clientSeedBytes).Next():X8}"); - // Step 4: receive post-handshake traffic. We expect EncryptedChecksum - // packets containing CharacterList and friends. If our ISAAC seed is - // wrong or our CRC math is off, TryDecode will return ChecksumMismatch. + // Step 4: receive post-handshake traffic. Run fragments through a + // FragmentAssembler so multi-packet game messages reassemble, then + // read the opcode (first 4 bytes of the assembled body) to prove + // we're looking at real GameMessage opcodes. + var assembler = new FragmentAssembler(); int postHandshakePackets = 0; int successfullyDecoded = 0; int checksumFailures = 0; + var seenOpcodes = new List(); var postDeadline = DateTime.UtcNow + TimeSpan.FromSeconds(5); while (DateTime.UtcNow < postDeadline) { @@ -214,13 +217,34 @@ public class LiveHandshakeTests $"decode={decoded.Error}, flags={decoded.Packet?.Header.Flags}, " + $"seq={decoded.Packet?.Header.Sequence}"); if (decoded.IsOk) + { successfullyDecoded++; + foreach (var frag in decoded.Packet!.Fragments) + { + var completeBody = assembler.Ingest(frag, out _); + if (completeBody is not null && completeBody.Length >= 4) + { + uint opcode = BinaryPrimitives.ReadUInt32LittleEndian(completeBody); + seenOpcodes.Add(opcode); + string name = opcode switch + { + 0xF658 => "CharacterList", + 0xF7E1 => "ServerName", + 0xF7E5 => "DDDInterrogation", + _ => "unknown", + }; + Console.WriteLine($"[live] GameMessage assembled: opcode=0x{opcode:X8} ({name}), " + + $"body={completeBody.Length} bytes"); + } + } + } else if (decoded.Error == PacketCodec.DecodeError.ChecksumMismatch) checksumFailures++; } Console.WriteLine($"[live] step 4 summary: {postHandshakePackets} packets received, " + - $"{successfullyDecoded} decoded OK, {checksumFailures} checksum failures"); + $"{successfullyDecoded} decoded OK, {checksumFailures} checksum failures, " + + $"{seenOpcodes.Count} GameMessages assembled"); // The contract of Phase 4.6e is "server accepted our ConnectResponse // and started streaming". Any post-handshake traffic at all proves