initial: ZeroTier-like P2P mesh VPN server with multi-tenant Web UI
This commit is contained in:
117
internal/vl1/packet.go
Normal file
117
internal/vl1/packet.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package vl1
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
Version = 1
|
||||
MaxPacketSize = 65535
|
||||
HeaderSize = 8
|
||||
MaxFrameSize = 65535
|
||||
MinFrameSize = 14
|
||||
|
||||
PacketTypeHandshake = byte(1)
|
||||
PacketTypeData = byte(2)
|
||||
PacketTypeKeepalive = byte(3)
|
||||
)
|
||||
|
||||
type Header struct {
|
||||
Version byte
|
||||
Type byte
|
||||
NetworkID uint32
|
||||
Length uint16
|
||||
}
|
||||
|
||||
func (h *Header) Encode(buf []byte) {
|
||||
buf[0] = h.Version
|
||||
buf[1] = h.Type
|
||||
binary.BigEndian.PutUint32(buf[2:6], h.NetworkID)
|
||||
binary.BigEndian.PutUint16(buf[6:8], h.Length)
|
||||
}
|
||||
|
||||
func (h *Header) Decode(buf []byte) error {
|
||||
if len(buf) < HeaderSize {
|
||||
return fmt.Errorf("header too short: %d < %d", len(buf), HeaderSize)
|
||||
}
|
||||
h.Version = buf[0]
|
||||
h.Type = buf[1]
|
||||
h.NetworkID = binary.BigEndian.Uint32(buf[2:6])
|
||||
h.Length = binary.BigEndian.Uint16(buf[6:8])
|
||||
return nil
|
||||
}
|
||||
|
||||
type Packet struct {
|
||||
Header Header
|
||||
Payload []byte
|
||||
}
|
||||
|
||||
func NewHandshakePacket(payload []byte) Packet {
|
||||
return Packet{
|
||||
Header: Header{
|
||||
Version: Version,
|
||||
Type: PacketTypeHandshake,
|
||||
Length: uint16(len(payload)),
|
||||
},
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDataPacket(networkID uint32, payload []byte) Packet {
|
||||
return Packet{
|
||||
Header: Header{
|
||||
Version: Version,
|
||||
Type: PacketTypeData,
|
||||
NetworkID: networkID,
|
||||
Length: uint16(len(payload)),
|
||||
},
|
||||
Payload: payload,
|
||||
}
|
||||
}
|
||||
|
||||
func NewKeepalivePacket() Packet {
|
||||
return Packet{
|
||||
Header: Header{
|
||||
Version: Version,
|
||||
Type: PacketTypeKeepalive,
|
||||
Length: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Packet) Encode() []byte {
|
||||
total := HeaderSize + len(p.Payload)
|
||||
buf := make([]byte, total)
|
||||
p.Header.Length = uint16(len(p.Payload))
|
||||
p.Header.Encode(buf[:HeaderSize])
|
||||
copy(buf[HeaderSize:], p.Payload)
|
||||
return buf
|
||||
}
|
||||
|
||||
func DecodePacket(data []byte) (*Packet, error) {
|
||||
var p Packet
|
||||
if err := p.Header.Decode(data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payloadLen := int(p.Header.Length)
|
||||
if HeaderSize+payloadLen > len(data) {
|
||||
return nil, fmt.Errorf("packet truncated: header claims %d + %d > %d", HeaderSize, payloadLen, len(data))
|
||||
}
|
||||
p.Payload = make([]byte, payloadLen)
|
||||
copy(p.Payload, data[HeaderSize:HeaderSize+payloadLen])
|
||||
return &p, nil
|
||||
}
|
||||
|
||||
func DecodePacketInto(p *Packet, data []byte) error {
|
||||
if err := p.Header.Decode(data); err != nil {
|
||||
return err
|
||||
}
|
||||
payloadLen := int(p.Header.Length)
|
||||
if HeaderSize+payloadLen > len(data) {
|
||||
return fmt.Errorf("packet truncated")
|
||||
}
|
||||
p.Payload = make([]byte, payloadLen)
|
||||
copy(p.Payload, data[HeaderSize:HeaderSize+payloadLen])
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user