package node import ( "errors" "net/netip" ) var ( errMalformedPacket = errors.New("malformed packet") errUnknownPacketType = errors.New("unknown packet type") ) const ( packetTypeSyn = iota + 1 packetTypeSynAck packetTypeAck packetTypeProbe packetTypeAddrDiscovery ) // ---------------------------------------------------------------------------- type controlPacket struct { SrcIP byte SrcAddr netip.AddrPort Payload any } func (p *controlPacket) ParsePayload(buf []byte) (err error) { switch buf[0] { case packetTypeSyn: p.Payload, err = parseSynPacket(buf) case packetTypeSynAck: p.Payload, err = parseSynAckPacket(buf) case packetTypeProbe: p.Payload, err = parseProbePacket(buf) case packetTypeAddrDiscovery: p.Payload, err = parseAddrDiscoveryPacket(buf) default: return errUnknownPacketType } return err } // ---------------------------------------------------------------------------- type synPacket struct { TraceID uint64 // TraceID to match response w/ request. SharedKey [32]byte // Our shared key. Direct bool FromAddr netip.AddrPort // The client's sending address. } func (p synPacket) Marshal(buf []byte) []byte { return newBinWriter(buf). Byte(packetTypeSyn). Uint64(p.TraceID). SharedKey(p.SharedKey). Bool(p.Direct). AddrPort(p.FromAddr). Build() } func parseSynPacket(buf []byte) (p synPacket, err error) { err = newBinReader(buf[1:]). Uint64(&p.TraceID). SharedKey(&p.SharedKey). Bool(&p.Direct). AddrPort(&p.FromAddr). Error() return } // ---------------------------------------------------------------------------- type synAckPacket struct { TraceID uint64 FromAddr netip.AddrPort } func (p synAckPacket) Marshal(buf []byte) []byte { return newBinWriter(buf). Byte(packetTypeSynAck). Uint64(p.TraceID). AddrPort(p.FromAddr). Build() } func parseSynAckPacket(buf []byte) (p synAckPacket, err error) { err = newBinReader(buf[1:]). Uint64(&p.TraceID). AddrPort(&p.FromAddr). Error() return } // ---------------------------------------------------------------------------- type addrDiscoveryPacket struct { TraceID uint64 ToAddr netip.AddrPort } func (p addrDiscoveryPacket) Marshal(buf []byte) []byte { return newBinWriter(buf). Byte(packetTypeAddrDiscovery). Uint64(p.TraceID). AddrPort(p.ToAddr). Build() } func parseAddrDiscoveryPacket(buf []byte) (p addrDiscoveryPacket, err error) { err = newBinReader(buf[1:]). Uint64(&p.TraceID). AddrPort(&p.ToAddr). Error() return } // ---------------------------------------------------------------------------- // A probeReqPacket is sent from a client to a server to determine if direct // UDP communication can be used. type probePacket struct { TraceID uint64 } func (p probePacket) Marshal(buf []byte) []byte { return newBinWriter(buf). Byte(packetTypeProbe). Uint64(p.TraceID). Build() } func parseProbePacket(buf []byte) (p probePacket, err error) { err = newBinReader(buf[1:]). Uint64(&p.TraceID). Error() return }