mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
feat(network): add protocol packet capture and replay system
Add a recording and replay foundation for the MHF network protocol. A RecordingConn decorator wraps network.Conn to transparently capture all decrypted packets to binary .mhfr files, with zero handler changes and zero overhead when disabled. - network/pcap: binary capture format (writer, reader, filters) - RecordingConn: thread-safe Conn decorator with direction tracking - CaptureOptions in config (disabled by default) - Capture wired into all three server types (sign, entrance, channel) - cmd/replay: CLI tool with dump, json, stats, and compare modes - 19 new tests, all passing with -race
This commit is contained in:
79
cmd/replay/compare.go
Normal file
79
cmd/replay/compare.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/pcap"
|
||||
)
|
||||
|
||||
// PacketDiff describes a difference between an expected and actual packet.
|
||||
type PacketDiff struct {
|
||||
Index int
|
||||
Expected pcap.PacketRecord
|
||||
Actual *pcap.PacketRecord // nil if no response received
|
||||
OpcodeMismatch bool
|
||||
SizeDelta int
|
||||
}
|
||||
|
||||
func (d PacketDiff) String() string {
|
||||
if d.Actual == nil {
|
||||
return fmt.Sprintf("#%d: expected 0x%04X (%s), got no response",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode))
|
||||
}
|
||||
if d.OpcodeMismatch {
|
||||
return fmt.Sprintf("#%d: opcode mismatch: expected 0x%04X (%s), got 0x%04X (%s)",
|
||||
d.Index,
|
||||
d.Expected.Opcode, network.PacketID(d.Expected.Opcode),
|
||||
d.Actual.Opcode, network.PacketID(d.Actual.Opcode))
|
||||
}
|
||||
return fmt.Sprintf("#%d: 0x%04X (%s) size delta %+d bytes",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode), d.SizeDelta)
|
||||
}
|
||||
|
||||
// ComparePackets compares expected server responses against actual responses.
|
||||
// Only compares S→C packets (server responses).
|
||||
func ComparePackets(expected, actual []pcap.PacketRecord) []PacketDiff {
|
||||
expectedS2C := pcap.FilterByDirection(expected, pcap.DirServerToClient)
|
||||
actualS2C := pcap.FilterByDirection(actual, pcap.DirServerToClient)
|
||||
|
||||
var diffs []PacketDiff
|
||||
for i, exp := range expectedS2C {
|
||||
if i >= len(actualS2C) {
|
||||
diffs = append(diffs, PacketDiff{
|
||||
Index: i,
|
||||
Expected: exp,
|
||||
Actual: nil,
|
||||
})
|
||||
continue
|
||||
}
|
||||
act := actualS2C[i]
|
||||
if exp.Opcode != act.Opcode {
|
||||
diffs = append(diffs, PacketDiff{
|
||||
Index: i,
|
||||
Expected: exp,
|
||||
Actual: &act,
|
||||
OpcodeMismatch: true,
|
||||
})
|
||||
} else if len(exp.Payload) != len(act.Payload) {
|
||||
diffs = append(diffs, PacketDiff{
|
||||
Index: i,
|
||||
Expected: exp,
|
||||
Actual: &act,
|
||||
SizeDelta: len(act.Payload) - len(exp.Payload),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Extra actual packets beyond expected.
|
||||
for i := len(expectedS2C); i < len(actualS2C); i++ {
|
||||
act := actualS2C[i]
|
||||
diffs = append(diffs, PacketDiff{
|
||||
Index: i,
|
||||
Expected: pcap.PacketRecord{},
|
||||
Actual: &act,
|
||||
})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
Reference in New Issue
Block a user