protocol

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package protocol implements the versioned WireHop wire protocol.

Index

Constants

View Source
const (

	// MaxProbePayloadSize bounds opaque probe traffic in one frame.
	MaxProbePayloadSize = 1200
	// ProbeFrameOverhead is the complete per-probe frame overhead excluding opaque padding.
	ProbeFrameOverhead = frameHeaderSize + 8
)
View Source
const (

	// DataFrameOverhead is the complete per-datagram frame overhead excluding the WireGuard payload.
	DataFrameOverhead = frameHeaderSize + dataHeaderSize
	// MaxPacketSize is the largest UDP datagram carried by WireHop.
	MaxPacketSize = 65_535
	// MaxPacketLifetimeMicros is the absolute wire-protocol packet lifetime limit.
	MaxPacketLifetimeMicros = 5 * 60 * 1_000_000
)
View Source
const (
	// Version is the current WireHop wire protocol version.
	Version uint16 = 1

	// MaxFrameContentSize is the largest valid type-specific frame content.
	MaxFrameContentSize = dataHeaderSize + MaxPacketSize
	// MaxEncodedFrameSize is the largest valid frame including its common header.
	MaxEncodedFrameSize = frameHeaderSize + MaxFrameContentSize
)
View Source
const (

	// MaxClientHelloSize bounds a creation hello containing the longest canonical target.
	MaxClientHelloSize = clientHelloMinimumSize + target.MaxTextSize

	// MaxDiagnosticSize bounds a peer-controlled handshake diagnostic.
	MaxDiagnosticSize = 512
)
View Source
const (
	// SessionIDSize is the encoded size of a session identifier.
	SessionIDSize = 16
	// SessionSecretSize is the encoded size of an ephemeral session secret.
	SessionSecretSize = 32
	// LaneIDSize is the encoded size of a stable lane identifier.
	LaneIDSize = 16
	// PathGroupIDSize is the encoded size of a session-scoped path group identifier.
	PathGroupIDSize = 16
	// NonceSize is the encoded size of a handshake nonce.
	NonceSize = 12
)

Variables

View Source
var (
	// ErrInvalidControlFrame indicates malformed control-frame fields or length.
	ErrInvalidControlFrame = errors.New("invalid control frame")
	// ErrProbeTooLarge indicates probe padding above its absolute protocol limit.
	ErrProbeTooLarge = errors.New("probe too large")
)
View Source
var (
	// ErrInvalidFrameType indicates an unknown or unset frame type.
	ErrInvalidFrameType = errors.New("invalid frame type")
	// ErrFrameTooLarge indicates a frame above the absolute protocol limit.
	ErrFrameTooLarge = errors.New("frame too large")
	// ErrTrailingFrameData indicates bytes remaining after a complete frame sequence.
	ErrTrailingFrameData = errors.New("trailing frame data")
)
View Source
var (
	// ErrInvalidMagic indicates input that does not carry a WireHop protocol preface.
	ErrInvalidMagic = errors.New("invalid protocol magic")
	// ErrUnsupportedVersion indicates an incompatible WireHop protocol version.
	ErrUnsupportedVersion = errors.New("unsupported protocol version")
	// ErrInvalidClientHello indicates inconsistent client hello fields.
	ErrInvalidClientHello = errors.New("invalid client hello")
	// ErrInvalidServerHello indicates inconsistent server hello fields.
	ErrInvalidServerHello = errors.New("invalid server hello")
	// ErrMissingAuthKey indicates an empty long-term token or session secret.
	ErrMissingAuthKey = errors.New("missing authentication key")
	// ErrAuthenticationFailed indicates a mismatched handshake authentication tag.
	ErrAuthenticationFailed = errors.New("authentication failed")
	// ErrDiagnosticTooLarge indicates a handshake diagnostic above its protocol limit.
	ErrDiagnosticTooLarge = errors.New("diagnostic too large")
)
View Source
var (
	// ErrInvalidDataFrame indicates malformed data-frame fields or packet length.
	ErrInvalidDataFrame = errors.New("invalid data frame")
)

Functions

func AppendDataFrame

func AppendDataFrame(destination []byte, data Data) ([]byte, error)

AppendDataFrame appends one complete data frame to destination.

func AppendFrame

func AppendFrame(destination []byte, frame Frame) ([]byte, error)

AppendFrame appends the typed and length-prefixed binary encoding of frame to destination.

func DataFrameSize

func DataFrameSize(data Data) (int, error)

DataFrameSize validates data and returns its complete encoded wire size.

func MarshalClientHello

func MarshalClientHello(hello ClientHello) ([]byte, error)

MarshalClientHello returns the canonical variable-width encoding of hello.

func MarshalDataFrame

func MarshalDataFrame(data Data) ([]byte, error)

MarshalDataFrame returns one complete data-frame encoding without an intermediate payload copy.

func MarshalFrame

func MarshalFrame(frame Frame) ([]byte, error)

MarshalFrame returns the typed and length-prefixed binary encoding of frame.

func MarshalServerHello

func MarshalServerHello(hello ServerHello) ([]byte, error)

MarshalServerHello returns the variable-width canonical encoding of hello.

func SignClientHello

func SignClientHello(hello *ClientHello, key []byte) error

SignClientHello validates hello and authenticates its canonical encoding with key.

func SignServerHello

func SignServerHello(hello *ServerHello, key []byte) error

SignServerHello validates hello and authenticates its canonical encoding with key.

func VerifyClientHello

func VerifyClientHello(hello ClientHello, key []byte) error

VerifyClientHello verifies hello against key without modifying it.

func VerifyServerHello

func VerifyServerHello(hello ServerHello, key []byte) error

VerifyServerHello verifies hello against key without modifying it.

func WriteClientHello

func WriteClientHello(writer io.Writer, hello ClientHello) error

WriteClientHello writes one complete client hello to writer.

func WriteServerHello

func WriteServerHello(writer io.Writer, hello ServerHello) error

WriteServerHello writes one complete server hello to writer.

Types

type AuthTag

type AuthTag [sha256.Size]byte

AuthTag is an HMAC-SHA256 authentication tag.

type ClientHello

type ClientHello struct {
	Mode            HelloMode
	UnixSeconds     int64
	MonotonicMicros uint64
	Nonce           Nonce
	LaneID          LaneID
	Generation      uint64
	PathGroupID     PathGroupID
	SessionID       SessionID
	Target          target.Endpoint
	AuthTag         AuthTag
}

ClientHello authenticates session creation or a lane connection generation.

func ParseClientHello

func ParseClientHello(encoded []byte) (ClientHello, error)

ParseClientHello parses and validates a canonical variable-width client hello.

func ReadClientHello

func ReadClientHello(reader io.Reader) (ClientHello, error)

ReadClientHello reads one complete variable-width client hello from reader.

type ClockSync

type ClockSync struct {
	ClientSendMicros    uint64
	ServerReceiveMicros uint64
	ServerSendMicros    uint64
	ClientReceiveMicros uint64
}

ClockSync carries one complete four-timestamp clock sample.

func ParseClockSync

func ParseClockSync(frame Frame) (ClockSync, error)

ParseClockSync parses a clock synchronization frame.

type CloseReason

type CloseReason uint8

CloseReason identifies an intentional session-close cause.

const (
	// CloseClientShutdown identifies an intentional client process shutdown.
	CloseClientShutdown CloseReason = 1
)

func ParseSessionClose

func ParseSessionClose(frame Frame) (CloseReason, error)

ParseSessionClose parses an explicit session-close control frame.

func (CloseReason) Valid

func (r CloseReason) Valid() bool

Valid reports whether the close reason is defined by this protocol version.

type Data

type Data struct {
	PacketID       uint64
	DeadlineMicros uint64
	Payload        []byte
}

Data is one WireGuard datagram and its cross-lane delivery metadata.

func ParseData

func ParseData(frame Frame) (Data, error)

ParseData parses and validates one generic data frame.

type DeliveryReport

type DeliveryReport struct {
	LaneID       LaneID
	Generation   uint64
	DataBytes    uint64
	DataPackets  uint64
	ProbeBytes   uint64
	ProbePackets uint64
}

DeliveryReport reports cumulative parsing progress for one lane generation and direction.

func ParseDeliveryReport

func ParseDeliveryReport(frame Frame) (DeliveryReport, error)

ParseDeliveryReport parses a cumulative delivery report frame.

type ErrorClass

type ErrorClass uint8

ErrorClass determines client retry and process-lifecycle behavior.

const (
	// ErrorRetryable identifies a temporary transport or capacity failure.
	ErrorRetryable ErrorClass = iota + 1
	// ErrorLaneRejected identifies a terminal rejection scoped to one lane candidate.
	ErrorLaneRejected
	// ErrorSessionGone identifies a session that no longer exists on the server.
	ErrorSessionGone
	// ErrorSessionRejected identifies a terminal rejection of the authenticated session.
	ErrorSessionRejected
)

func (ErrorClass) Valid

func (c ErrorClass) Valid() bool

Valid reports whether the error class is defined by this protocol version.

type ErrorCode

type ErrorCode uint16

ErrorCode identifies one machine-readable protocol, policy, or capacity failure.

const (
	// ErrorMalformed identifies malformed handshake or frame input.
	ErrorMalformed ErrorCode = iota + 1
	// ErrorUnsupportedVersion identifies an incompatible wire protocol version.
	ErrorUnsupportedVersion
	// ErrorAuthentication identifies invalid authentication material.
	ErrorAuthentication
	// ErrorReplay identifies a reused authenticated handshake nonce.
	ErrorReplay
	// ErrorTargetDenied identifies a target outside server policy.
	ErrorTargetDenied
	// ErrorSessionNotFound identifies an unknown or expired session.
	ErrorSessionNotFound
	// ErrorStaleGeneration identifies a non-increasing lane connection generation.
	ErrorStaleGeneration
	// ErrorLaneLimit identifies a per-session lane limit.
	ErrorLaneLimit
	// ErrorSessionLimit identifies a server session limit.
	ErrorSessionLimit
	// ErrorProtocolViolation identifies invalid in-session behavior.
	ErrorProtocolViolation
	// ErrorUnavailable identifies a temporary server or target failure.
	ErrorUnavailable
	// ErrorRateLimited identifies a temporary admission or reconnect rate limit.
	ErrorRateLimited
	// ErrorInternal identifies an unexpected server failure.
	ErrorInternal
	// ErrorClockSkew identifies an authenticated timestamp outside the server's acceptance window.
	ErrorClockSkew
)

func (ErrorCode) Valid

func (c ErrorCode) Valid() bool

Valid reports whether the error code is defined by this protocol version.

type ErrorFrame

type ErrorFrame struct {
	Code       ErrorCode
	Class      ErrorClass
	Scope      ErrorScope
	LaneID     LaneID
	Generation uint64
	Diagnostic string
}

ErrorFrame carries a stable in-session error and bounded diagnostic.

func ParseErrorFrame

func ParseErrorFrame(frame Frame) (ErrorFrame, error)

ParseErrorFrame parses an in-session error frame.

type ErrorScope

type ErrorScope uint8

ErrorScope identifies the state affected by a protocol error.

const (
	// ErrorScopeLane limits an error to one lane generation.
	ErrorScopeLane ErrorScope = iota + 1
	// ErrorScopeSession applies an error to the complete session.
	ErrorScopeSession
)

func (ErrorScope) Valid

func (s ErrorScope) Valid() bool

Valid reports whether the error scope is defined by this protocol version.

type Frame

type Frame struct {
	Type    FrameType
	Payload []byte
}

Frame is one decoded WireHop frame. Callers must treat Payload as read-only and honor the lifetime documented by the decoder that returned it.

func AppendFrames

func AppendFrames(destination []Frame, message []byte) ([]Frame, error)

AppendFrames appends complete frames whose payloads alias message. On error, it returns destination at its original length.

func MarshalClockSync

func MarshalClockSync(sync ClockSync) (Frame, error)

MarshalClockSync returns a clock synchronization frame.

func MarshalData

func MarshalData(data Data) (Frame, error)

MarshalData returns a generic frame containing data.

func MarshalDeliveryReport

func MarshalDeliveryReport(report DeliveryReport) (Frame, error)

MarshalDeliveryReport returns a cumulative delivery report frame.

func MarshalErrorFrame

func MarshalErrorFrame(value ErrorFrame) (Frame, error)

MarshalErrorFrame returns an in-session error frame.

func MarshalLaneAbandon

func MarshalLaneAbandon(lane LaneGeneration) (Frame, error)

MarshalLaneAbandon returns a generation-specific lane-abandon frame.

func MarshalLaneAccepted

func MarshalLaneAccepted(accepted LaneAccepted) (Frame, error)

MarshalLaneAccepted returns a lane-accepted control frame.

func MarshalProbe

func MarshalProbe(probe Probe) (Frame, error)

MarshalProbe returns a bounded probe frame.

func MarshalSessionClose

func MarshalSessionClose(reason CloseReason) (Frame, error)

MarshalSessionClose returns an explicit session-close control frame.

func MarshalSessionCreated

func MarshalSessionCreated(created SessionCreated) (Frame, error)

MarshalSessionCreated returns a session-created control frame.

func MarshalTimingPing

func MarshalTimingPing(ping TimingPing) (Frame, error)

MarshalTimingPing returns a timing ping frame.

func MarshalTimingPong

func MarshalTimingPong(pong TimingPong) (Frame, error)

MarshalTimingPong returns a timing pong frame.

func ParseFrames

func ParseFrames(message []byte) ([]Frame, error)

ParseFrames parses complete frames whose payloads alias message.

func ReadFrame

func ReadFrame(reader io.Reader) (Frame, error)

ReadFrame reads one complete typed and length-prefixed frame from reader.

type FrameReader

type FrameReader struct {
	// contains filtered or unexported fields
}

FrameReader incrementally decodes stream frames with connection-local reusable storage.

func (*FrameReader) Read

func (r *FrameReader) Read(reader io.Reader) (Frame, error)

Read reads one frame whose payload remains valid until the next Read call.

type FrameSequence

type FrameSequence struct {
	// contains filtered or unexported fields
}

FrameSequence iterates over one completely validated frame sequence without allocating per-frame metadata. The source message must remain unchanged while the sequence or any returned frame is in use.

func ParseFrameSequence

func ParseFrameSequence(message []byte) (FrameSequence, error)

ParseFrameSequence validates one complete frame sequence and returns an allocation-free iterator whose frame payloads alias message.

func (*FrameSequence) Next

func (s *FrameSequence) Next() (Frame, bool)

Next returns the next frame whose payload aliases the validated message.

type FrameType

type FrameType uint8

FrameType identifies one data-plane or control-plane frame.

const (
	// FrameData carries one WireGuard UDP datagram.
	FrameData FrameType = iota + 1
	// FramePing requests a lane timing response.
	FramePing
	// FramePong responds to a lane timing request.
	FramePong
	// FrameClockSync updates the shared session clock mapping.
	FrameClockSync
	// FrameProbe measures lane delivery behavior without reaching the UDP target.
	FrameProbe
	// FrameDeliveryReport reports cumulative peer parsing progress.
	FrameDeliveryReport
	// FrameSessionCreated accepts a newly created session.
	FrameSessionCreated
	// FrameLaneAccepted accepts a lane joined to an existing session.
	FrameLaneAccepted
	// FrameSessionClose explicitly closes a session.
	FrameSessionClose
	// FrameLaneAbandon coordinates generation-specific connection abandonment.
	FrameLaneAbandon
	// FrameError reports an in-session protocol or policy error.
	FrameError
)

func (FrameType) Valid

func (t FrameType) Valid() bool

Valid reports whether the frame type is defined by this protocol version.

type HelloMode

type HelloMode uint8

HelloMode distinguishes session creation from lane join.

const (
	// HelloCreate creates a new authenticated session and its first lane.
	HelloCreate HelloMode = iota + 1
	// HelloJoin joins a new connection generation to an existing session.
	HelloJoin
)

func (HelloMode) Valid

func (m HelloMode) Valid() bool

Valid reports whether the hello mode is defined by this protocol version.

type LaneAccepted

type LaneAccepted struct {
	SessionID     SessionID
	PathGroupID   PathGroupID
	ReceiveMicros uint64
	SendMicros    uint64
}

LaneAccepted carries the effective path group and clock-bootstrap timestamps for a joined lane.

func ParseLaneAccepted

func ParseLaneAccepted(frame Frame) (LaneAccepted, error)

ParseLaneAccepted parses a lane-accepted control frame.

type LaneGeneration

type LaneGeneration struct {
	LaneID     LaneID
	Generation uint64
}

LaneGeneration identifies one stable lane and exact connection generation.

func ParseLaneAbandon

func ParseLaneAbandon(frame Frame) (LaneGeneration, error)

ParseLaneAbandon parses a generation-specific lane-abandon frame.

type LaneID

type LaneID [LaneIDSize]byte

LaneID identifies one stable lane across connection generations.

func NewLaneID

func NewLaneID() LaneID

NewLaneID returns a cryptographically random stable lane identifier.

func ParseLaneID

func ParseLaneID(value string) (LaneID, error)

ParseLaneID parses a lowercase or uppercase hexadecimal lane identifier.

func (LaneID) IsZero

func (id LaneID) IsZero() bool

IsZero reports whether the lane identifier is unset.

func (LaneID) String

func (id LaneID) String() string

String returns the lowercase hexadecimal lane identifier.

type Nonce

type Nonce [NonceSize]byte

Nonce prevents replay of one authenticated handshake.

func NewNonce

func NewNonce() Nonce

NewNonce returns a cryptographically random handshake nonce.

func ParseNonce

func ParseNonce(value string) (Nonce, error)

ParseNonce parses a lowercase or uppercase hexadecimal handshake nonce.

func (Nonce) String

func (nonce Nonce) String() string

String returns the lowercase hexadecimal handshake nonce.

type PathGroupID

type PathGroupID [PathGroupIDSize]byte

PathGroupID identifies one session-scoped scheduling path group.

func NewPathGroupID

func NewPathGroupID() PathGroupID

NewPathGroupID returns a cryptographically random path group identifier.

func ParsePathGroupID

func ParsePathGroupID(value string) (PathGroupID, error)

ParsePathGroupID parses a lowercase or uppercase hexadecimal path group identifier.

func (PathGroupID) IsZero

func (id PathGroupID) IsZero() bool

IsZero reports whether the path group identifier is unset.

func (PathGroupID) String

func (id PathGroupID) String() string

String returns the lowercase hexadecimal path group identifier.

type Probe

type Probe struct {
	ID      uint64
	Payload []byte
}

Probe carries bounded opaque bytes for lane delivery measurement.

func ParseProbe

func ParseProbe(frame Frame) (Probe, error)

ParseProbe parses a bounded probe frame.

type ServerHello

type ServerHello struct {
	Result            ServerHelloResult
	RequestNonce      Nonce
	ServerUnixSeconds int64
	SessionID         SessionID
	SessionSecret     SessionSecret
	PathGroupID       PathGroupID
	ReceiveMicros     uint64
	SendMicros        uint64
	ErrorCode         ErrorCode
	ErrorClass        ErrorClass
	ErrorScope        ErrorScope
	Diagnostic        string
	AuthTag           AuthTag
}

ServerHello authenticates an admission result or a pre-upgrade rejection.

func ParseServerHello

func ParseServerHello(encoded []byte) (ServerHello, error)

ParseServerHello parses and validates a canonical server hello.

func ReadServerHello

func ReadServerHello(reader io.Reader) (ServerHello, error)

ReadServerHello reads one variable-width server hello from reader.

type ServerHelloResult

type ServerHelloResult uint8

ServerHelloResult distinguishes successful creation, lane acceptance, and rejection.

const (
	// ServerSessionCreated accepts a newly created session.
	ServerSessionCreated ServerHelloResult = iota + 1
	// ServerLaneAccepted accepts a joined lane connection generation.
	ServerLaneAccepted
	// ServerRejected rejects the client hello with a stable protocol error.
	ServerRejected
)

func (ServerHelloResult) Valid

func (r ServerHelloResult) Valid() bool

Valid reports whether the server hello result is defined by this protocol version.

type SessionCreated

type SessionCreated struct {
	SessionID     SessionID
	SessionSecret SessionSecret
	PathGroupID   PathGroupID
	ReceiveMicros uint64
	SendMicros    uint64
}

SessionCreated carries session credentials and clock-bootstrap timestamps.

func ParseSessionCreated

func ParseSessionCreated(frame Frame) (SessionCreated, error)

ParseSessionCreated parses a session-created control frame.

type SessionID

type SessionID [SessionIDSize]byte

SessionID identifies one authenticated WireHop session.

func NewSessionID

func NewSessionID() SessionID

NewSessionID returns a cryptographically random session identifier.

func ParseSessionID

func ParseSessionID(value string) (SessionID, error)

ParseSessionID parses a lowercase or uppercase hexadecimal session identifier.

func (SessionID) IsZero

func (id SessionID) IsZero() bool

IsZero reports whether the session identifier is unset.

func (SessionID) String

func (id SessionID) String() string

String returns the lowercase hexadecimal session identifier.

type SessionSecret

type SessionSecret [SessionSecretSize]byte

SessionSecret authorizes lane joins to an established session.

func NewSessionSecret

func NewSessionSecret() SessionSecret

NewSessionSecret returns a cryptographically random ephemeral session secret.

type TimingPing

type TimingPing struct {
	ID         uint64
	SendMicros uint64
}

TimingPing requests one lane-local timing observation.

func ParseTimingPing

func ParseTimingPing(frame Frame) (TimingPing, error)

ParseTimingPing parses a timing ping frame.

type TimingPong

type TimingPong struct {
	ID             uint64
	PingSendMicros uint64
	ReceiveMicros  uint64
	SendMicros     uint64
}

TimingPong responds with receiver timing for a prior ping.

func ParseTimingPong

func ParseTimingPong(frame Frame) (TimingPong, error)

ParseTimingPong parses a timing pong frame.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL