vppn/node/packets.go
2024-12-20 15:55:46 +01:00

89 lines
2.0 KiB
Go

package node
import (
"errors"
"net/netip"
"time"
"unsafe"
)
var errMalformedPacket = errors.New("malformed packet")
const (
packetTypePing = iota + 1
packetTypePong
)
// ----------------------------------------------------------------------------
type controlPacket struct {
SrcIP byte
RemoteAddr netip.AddrPort
Payload any
}
// ----------------------------------------------------------------------------
// A pingPacket is sent from a node acting as a client, to a node acting
// as a server. It always contains the shared key the client is expecting
// to use for data encryption with the server.
type pingPacket struct {
SentAt int64 // UnixMilli.
SharedKey [32]byte
}
func newPingPacket(sharedKey []byte) (pp pingPacket) {
pp.SentAt = time.Now().UnixMilli()
copy(pp.SharedKey[:], sharedKey)
return
}
func (p pingPacket) Marshal(buf []byte) []byte {
buf = buf[:41]
buf[0] = packetTypePing
*(*uint64)(unsafe.Pointer(&buf[1])) = uint64(p.SentAt)
copy(buf[9:41], p.SharedKey[:])
return buf
}
func parsePingPacket(buf []byte) (p pingPacket, err error) {
if len(buf) != 41 {
return p, errMalformedPacket
}
p.SentAt = *(*int64)(unsafe.Pointer(&buf[1]))
copy(p.SharedKey[:], buf[9:41])
return
}
// ----------------------------------------------------------------------------
// A pongPacket is sent by a node in a server role in response to a pingPacket.
type pongPacket struct {
SentAt int64 // UnixMilli.
RecvdAt int64 // UnixMilli.
}
func newPongPacket(sentAt int64) (pp pongPacket) {
pp.SentAt = sentAt
pp.RecvdAt = time.Now().UnixMilli()
return
}
func (p pongPacket) Marshal(buf []byte) []byte {
buf = buf[:17]
buf[0] = packetTypePong
*(*uint64)(unsafe.Pointer(&buf[1])) = uint64(p.SentAt)
*(*uint64)(unsafe.Pointer(&buf[9])) = uint64(p.RecvdAt)
return buf
}
func parsePongPacket(buf []byte) (p pongPacket, err error) {
if len(buf) != 17 {
return p, errMalformedPacket
}
p.SentAt = *(*int64)(unsafe.Pointer(&buf[1]))
p.RecvdAt = *(*int64)(unsafe.Pointer(&buf[9]))
return
}