package proxy import ( "encoding/binary" "time" ) type Packet interface { Marshal(generator MacGenerator) []byte Raw() []byte } type SimplePacket struct { Data []byte timestamp time.Time } // create a packet from the raw data of an IP packet func NewSimplePacket(data []byte) Packet { return SimplePacket{ Data: data, timestamp: time.Now(), } } // rebuild a packet from the wrapped format func UnmarshalPacket(raw []byte, verifier MacVerifier) (Packet, error) { // the MAC is the last N bytes data := raw[:len(raw)-verifier.CodeLength()] sum := raw[len(raw)-verifier.CodeLength():] if err := verifier.Verify(data, sum); err != nil { return SimplePacket{}, err } p := SimplePacket{ Data: data[:len(data)-8], } unixTime := int64(binary.LittleEndian.Uint64(data[len(data)-8:])) p.timestamp = time.Unix(unixTime, 0) return p, nil } // get the raw data of the IP packet func (p SimplePacket) Raw() []byte { return p.Data } // produce the wrapped format of a packet func (p SimplePacket) Marshal(generator MacGenerator) []byte { // length of data + length of timestamp (8 byte) + length of checksum slice := make([]byte, len(p.Data)+8+generator.CodeLength()) copy(slice, p.Data) unixTime := uint64(p.timestamp.Unix()) binary.LittleEndian.PutUint64(slice[len(p.Data):], unixTime) mac := generator.Generate(slice) copy(slice[len(p.Data)+8:], mac) return slice }