feat(net): extract GameMessage opcodes from live fragment stream (Phase 4.6f)
Reassembles the fragments arriving from the live handshake into full
game message bodies, reads the opcode from the first 4 bytes, and
identifies them by name. On the live wire we now see exactly the
sequence ACE sends right after HandleConnectResponse:
GameMessage assembled: opcode=0xF7E5 (DDDInterrogation), body=28 bytes
GameMessage assembled: opcode=0xF658 (CharacterList), body=80 bytes
GameMessage assembled: opcode=0xF7E1 (ServerName), body=20 bytes
summary: 5 packets received, 5 decoded OK, 0 checksum failures,
3 GameMessages assembled
Every layer of the net stack is now proven live:
* NetClient send/receive on both ports 9000 and 9001
* PacketCodec.Encode building LoginRequest + ConnectResponse with
correct unencrypted CRC
* IsaacRandom byte-compatible with ACE's ISAAC (3 EncryptedChecksum
packets decoded, zero mismatches)
* PacketHeaderOptional parsing ConnectRequest, TimeSync, AckSequence
* MessageFragment.TryParse walking a body tail of back-to-back
fragments (the 152-byte packet had TWO messages: CharacterList
and ServerName packed into one datagram)
* FragmentAssembler reassembling by index
The CharacterList body has our test character +Acdream inside it but
we're not decoding its fields yet — that's Phase 4.7 where we actually
pick a character and send CharacterLogin to enter the game world.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a961d842d4
commit
0aea24c78e
1 changed files with 28 additions and 4 deletions
|
|
@ -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<uint>();
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue