mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
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
80 lines
2.1 KiB
Go
80 lines
2.1 KiB
Go
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
|
|
}
|