mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-26 09:33:02 +01:00
feat(pcap): complete replay system with filtering, metadata, and live replay
Wire ExcludeOpcodes config into RecordingConn so configured opcodes (e.g. ping, nop, position) are filtered at record time. Add padded metadata with in-place PatchMetadata to populate CharID/UserID after login. Implement --mode replay using protbot's encrypted connection with timing-aware packet sending, auto-ping response, concurrent S→C collection, and byte-level payload diff reporting.
This commit is contained in:
@@ -2,11 +2,22 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"erupe-ce/network"
|
||||
"erupe-ce/network/pcap"
|
||||
)
|
||||
|
||||
// maxPayloadDiffs is the maximum number of byte-level diffs to report per packet.
|
||||
const maxPayloadDiffs = 16
|
||||
|
||||
// ByteDiff describes a single byte difference between expected and actual payloads.
|
||||
type ByteDiff struct {
|
||||
Offset int
|
||||
Expected byte
|
||||
Actual byte
|
||||
}
|
||||
|
||||
// PacketDiff describes a difference between an expected and actual packet.
|
||||
type PacketDiff struct {
|
||||
Index int
|
||||
@@ -14,10 +25,15 @@ type PacketDiff struct {
|
||||
Actual *pcap.PacketRecord // nil if no response received
|
||||
OpcodeMismatch bool
|
||||
SizeDelta int
|
||||
PayloadDiffs []ByteDiff // byte-level diffs (when opcodes match and sizes match)
|
||||
}
|
||||
|
||||
func (d PacketDiff) String() string {
|
||||
if d.Actual == nil {
|
||||
if d.Expected.Opcode == 0 {
|
||||
return fmt.Sprintf("#%d: unexpected extra response 0x%04X (%s)",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode))
|
||||
}
|
||||
return fmt.Sprintf("#%d: expected 0x%04X (%s), got no response",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode))
|
||||
}
|
||||
@@ -27,8 +43,21 @@ func (d PacketDiff) String() string {
|
||||
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)
|
||||
if d.SizeDelta != 0 {
|
||||
return fmt.Sprintf("#%d: 0x%04X (%s) size delta %+d bytes",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode), d.SizeDelta)
|
||||
}
|
||||
if len(d.PayloadDiffs) > 0 {
|
||||
var sb strings.Builder
|
||||
fmt.Fprintf(&sb, "#%d: 0x%04X (%s) %d byte diff(s):",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode), len(d.PayloadDiffs))
|
||||
for _, bd := range d.PayloadDiffs {
|
||||
fmt.Fprintf(&sb, " [0x%04X: %02X→%02X]", bd.Offset, bd.Expected, bd.Actual)
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
return fmt.Sprintf("#%d: 0x%04X (%s) unknown diff",
|
||||
d.Index, d.Expected.Opcode, network.PacketID(d.Expected.Opcode))
|
||||
}
|
||||
|
||||
// ComparePackets compares expected server responses against actual responses.
|
||||
@@ -62,6 +91,17 @@ func ComparePackets(expected, actual []pcap.PacketRecord) []PacketDiff {
|
||||
Actual: &act,
|
||||
SizeDelta: len(act.Payload) - len(exp.Payload),
|
||||
})
|
||||
} else {
|
||||
// Same opcode and size — check for byte-level diffs.
|
||||
byteDiffs := comparePayloads(exp.Payload, act.Payload)
|
||||
if len(byteDiffs) > 0 {
|
||||
diffs = append(diffs, PacketDiff{
|
||||
Index: i,
|
||||
Expected: exp,
|
||||
Actual: &act,
|
||||
PayloadDiffs: byteDiffs,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,3 +117,19 @@ func ComparePackets(expected, actual []pcap.PacketRecord) []PacketDiff {
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// comparePayloads returns byte-level diffs between two equal-length payloads.
|
||||
// Returns at most maxPayloadDiffs entries.
|
||||
func comparePayloads(expected, actual []byte) []ByteDiff {
|
||||
var diffs []ByteDiff
|
||||
for i := 0; i < len(expected) && len(diffs) < maxPayloadDiffs; i++ {
|
||||
if expected[i] != actual[i] {
|
||||
diffs = append(diffs, ByteDiff{
|
||||
Offset: i,
|
||||
Expected: expected[i],
|
||||
Actual: actual[i],
|
||||
})
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user