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
66 lines
1.5 KiB
Go
66 lines
1.5 KiB
Go
package pcap
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"erupe-ce/network"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
// RecordingConn wraps a network.Conn and records all packets to a Writer.
|
|
// It is safe for concurrent use from separate send/recv goroutines.
|
|
type RecordingConn struct {
|
|
inner network.Conn
|
|
writer *Writer
|
|
startNs int64
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// NewRecordingConn wraps inner, recording all packets to w.
|
|
// startNs is the session start time in nanoseconds (used as the time base).
|
|
func NewRecordingConn(inner network.Conn, w *Writer, startNs int64) *RecordingConn {
|
|
return &RecordingConn{
|
|
inner: inner,
|
|
writer: w,
|
|
startNs: startNs,
|
|
}
|
|
}
|
|
|
|
// ReadPacket reads from the inner connection and records the packet as client-to-server.
|
|
func (rc *RecordingConn) ReadPacket() ([]byte, error) {
|
|
data, err := rc.inner.ReadPacket()
|
|
if err != nil {
|
|
return data, err
|
|
}
|
|
rc.record(DirClientToServer, data)
|
|
return data, nil
|
|
}
|
|
|
|
// SendPacket sends via the inner connection and records the packet as server-to-client.
|
|
func (rc *RecordingConn) SendPacket(data []byte) error {
|
|
err := rc.inner.SendPacket(data)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
rc.record(DirServerToClient, data)
|
|
return nil
|
|
}
|
|
|
|
func (rc *RecordingConn) record(dir Direction, data []byte) {
|
|
var opcode uint16
|
|
if len(data) >= 2 {
|
|
opcode = binary.BigEndian.Uint16(data[:2])
|
|
}
|
|
|
|
rec := PacketRecord{
|
|
TimestampNs: time.Now().UnixNano(),
|
|
Direction: dir,
|
|
Opcode: opcode,
|
|
Payload: data,
|
|
}
|
|
|
|
rc.mu.Lock()
|
|
_ = rc.writer.WritePacket(rec)
|
|
rc.mu.Unlock()
|
|
}
|