transport

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2026 License: Apache-2.0 Imports: 23 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrDialerClosed = errors.New("iceDialer explicitly closed")

ErrDialerClosed is returned by Dial when the iceDialer is explicitly closed (e.g. ICE reached Failed state or a SYN arrived on an active agent). It signals that onClose already triggered probe.restart(), so onFailure should NOT schedule a second restart.

View Source
var UpgradeDisabled = false

UpgradeDisabled turns the periodic relay→direct upgrade retry off entirely. The retry is break-before-make (ADR-0007): every attempt tears down a working relayed session. While the direct path is unusable anyway (e.g. the macOS NE self-capture problem), the retries only buy outage windows.

Functions

func GenerateSessionID

func GenerateSessionID() (uint64, error)

func NewIceDialer

func NewIceDialer(cfg *ICEDialerConfig) infra.Dialer

func NewRelayDialer

func NewRelayDialer(cfg *RelayDialerConfig) infra.Dialer

func NewWGConfigurator

func NewWGConfigurator(peerOps PeerOps, routeOps RouteOps) *wgConfigurator

NewWGConfigurator creates a configurator. peerOps and routeOps may be nil (operations become no-ops, useful for testing).

Types

type ConnectionConfigurator

type ConnectionConfigurator interface {
	// RegisterPeer adds a peer entry to WireGuard (called on first SYN/ACK).
	RegisterPeer(publicKey, allowedIPs string) error

	// SetEndpoint updates the WireGuard peer endpoint (called on every connect).
	SetEndpoint(publicKey, endpoint string, persistentKeepalive int) error

	// RemovePeer removes a peer entry from WireGuard (called on Failed/Closed).
	RemovePeer(publicKey string) error

	// ApplyRoute adds or removes a kernel route for the peer's VPN address.
	ApplyRoute(address, iface string) error

	// SetupNAT configures NAT rules for the WireGuard interface.
	SetupNAT(iface string) error
}

ConnectionConfigurator defines the WireGuard configuration actions triggered by connection state transitions.

type ConnectionState

type ConnectionState int

ConnectionState is an enum showing the state of a ICE Connection

const (
	ConnectionStateUnknown ConnectionState = iota

	// ConnectionStateNew probe the remote peer.
	ConnectionStateNew

	ConnectionStateChecking

	ConnectionStateConnected

	ConnectionStateCompleted

	ConnectionStateFailed

	ConnectionStateDisconnected

	ConnectionStateClosed
)

List of supported States

func (ConnectionState) String

func (c ConnectionState) String() string

type ICEDialerConfig

type ICEDialerConfig struct {
	Sender        func(ctx context.Context, peerId infra.PeerID, data []byte) error
	LocalId       infra.PeerIdentity
	RemoteId      infra.PeerIdentity
	FilteringMux  *infra.FilteringUDPMux
	FilteringMux6 *infra.FilteringUDPMux // nil when IPv6 unavailable
	Configurer    provision.Provisioner
	// GetLocalPeer is called at send time so late-arriving ApplyFullConfig
	// updates (Address, AllowedIPs) are always reflected in SYN/ACK peer info.
	GetLocalPeer   func() *infra.Peer
	OnPeerReceived func(peer infra.Peer)
	ShowLog        bool
	// OnRestart is called when a SYN arrives on an already-closed dialer,
	// indicating the remote peer restarted. Mirrors the Relay dialer pattern.
	OnRestart func()
}

type ICETransport

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

func (*ICETransport) Close

func (i *ICETransport) Close() error

func (*ICETransport) Priority

func (i *ICETransport) Priority() uint8

func (*ICETransport) Read

func (i *ICETransport) Read(buff []byte) (int, error)

func (*ICETransport) RemoteAddr

func (i *ICETransport) RemoteAddr() string

func (*ICETransport) Type

func (i *ICETransport) Type() infra.TransportType

func (*ICETransport) Write

func (i *ICETransport) Write(data []byte) error

type PeerOps

type PeerOps interface {
	AddPeer(publicKey, allowedIPs string) error
	SetEndpoint(publicKey, endpoint string, persistentKeepalive int) error
	RemovePeer(publicKey string) error
}

PeerOps is the minimal interface for WireGuard peer management.

type PeerState

type PeerState string

PeerState represents the lifecycle stage of a peer connection.

const (
	StateCreated    PeerState = "created"
	StateProbing    PeerState = "probing"
	StateICEReady   PeerState = "ice-ready"
	StateRelayReady PeerState = "relay-ready"
	StateFailed     PeerState = "failed"
	StateClosed     PeerState = "closed"
)

func (PeerState) String

func (s PeerState) String() string

type PeerStats

type PeerStats struct {
	LastHandshake time.Time
	RxBytes       uint64
	// Endpoint is where WireGuard currently sends this peer's packets. It
	// follows the source of the last authenticated packet received, so it can
	// differ from the transport the probe chose.
	Endpoint *net.UDPAddr
}

PeerStats is the WireGuard-side view of a peer used for liveness checks.

type Probe

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

Probe manages the connection lifecycle to a single remote peer.

func (*Probe) Close

func (p *Probe) Close()

Close permanently stops this probe.

func (*Probe) Handle

func (p *Probe) Handle(ctx context.Context, remoteId infra.PeerIdentity, packet *signal.SignalPacket) error

func (*Probe) OnConnectionStateChange

func (p *Probe) OnConnectionStateChange(state ice.ConnectionState)

func (*Probe) Ping

func (p *Probe) Ping(ctx context.Context) error

func (*Probe) RTT

func (p *Probe) RTT() time.Duration

RTT returns the latest measured direct-path RTT, 0 if none.

func (*Probe) RemoteAppID

func (p *Probe) RemoteAppID() string

RemoteAppID returns the remote peer's AppID.

func (*Probe) SetRTT

func (p *Probe) SetRTT(d time.Duration)

SetRTT records the latest direct-path echo RTT (d<=0 clears it).

func (*Probe) Start

func (p *Probe) Start(ctx context.Context, remoteId infra.PeerIdentity) error

func (*Probe) State

func (p *Probe) State() PeerState

State returns the peer's current connection lifecycle state (probing / ice-ready / relay-ready / failed / closed).

func (*Probe) SyncAllowedIPs

func (p *Probe) SyncAllowedIPs(allowedIPs string) error

SyncAllowedIPs re-applies this peer's WireGuard AllowedIPs from a locally computed value — e.g. the server-side netmap widened it to 0.0.0.0/0 after this node selected the peer as an exit-node route provider. This is independent of P2P signaling: the signaling handshake only ever carries the remote peer's self-description, which has no notion of "who selected me as their exit route" (that's a consumer-side, per-viewer decision), so it can never carry this value. The configurator is idempotent per (publicKey, allowedIPs), so calling this with an unchanged value is a cheap no-op — safe to call on every netmap application.

type ProbeFactory

type ProbeFactory struct {
	FilteringMux  *infra.FilteringUDPMux
	FilteringMux6 *infra.FilteringUDPMux
	// contains filtered or unexported fields
}

func NewProbeFactory

func NewProbeFactory(cfg *ProbeFactoryConfig) *ProbeFactory

func (*ProbeFactory) Allows

func (p *ProbeFactory) Allows(remoteId string) bool

TODO

func (*ProbeFactory) Get

func (f *ProbeFactory) Get(remoteId infra.PeerIdentity) (*Probe, error)

func (*ProbeFactory) Handle

func (p *ProbeFactory) Handle(ctx context.Context, remoteId infra.PeerID, packet *signal.SignalPacket) error

Handle is the NATS SignalHandler boundary: remoteId is PeerID from packet.SenderId. It resolves to a full PeerIdentity via PeerManager before passing down.

func (*ProbeFactory) NewProbe

func (p *ProbeFactory) NewProbe(remoteId infra.PeerIdentity) (*Probe, error)

func (*ProbeFactory) OnReceive

func (p *ProbeFactory) OnReceive(sessionId [28]byte, data []byte) error

func (*ProbeFactory) PeerConnectionStates

func (p *ProbeFactory) PeerConnectionStates() map[string]string

PeerConnectionStates snapshots each tracked peer's connection lifecycle state (probing / ice-ready / relay-ready / failed / closed), keyed by remote AppID. Embedded-engine clients (Apple Network Extension) surface this as connection quality: ice-ready = direct, relay-ready = relayed.

func (*ProbeFactory) PeerRTTs

func (p *ProbeFactory) PeerRTTs() map[string]int64

PeerRTTs snapshots each tracked peer's latest direct-path echo RTT in milliseconds, keyed by remote AppID. 0 = not measured (older agent, relayed path, or no echo yet).

func (*ProbeFactory) Register

func (f *ProbeFactory) Register(remoteId infra.PeerIdentity, probe *Probe)

func (*ProbeFactory) Remove

func (f *ProbeFactory) Remove(appId string)

func (*ProbeFactory) StartReconciler

func (f *ProbeFactory) StartReconciler(ctx context.Context, interval time.Duration)

StartReconciler periodically revives probes that reached StateClosed.

Probes close permanently after 60 s of failed discovery (Probe.onFailure), and the netmap pipeline cannot be relied on to recreate them: the poll loop skips re-applying an unchanged ConfigVersion, so a node whose first probe window overlapped a peer outage or a control-plane incident stayed dark until process restart even though every dependency had recovered (observed live: Mac initiator probes closed during the STUN outage and never restarted, 2026-09-19). This reconciler replaces every closed probe with a fresh one (Get swaps StateClosed entries) and starts it, restoring the initiate/answer role it had before.

type ProbeFactoryConfig

type ProbeFactoryConfig struct {
	LocalId        infra.PeerIdentity
	Signal         infra.SignalService
	GetOnMessage   func() func(context.Context, *infra.Message) error
	PeerManager    *infra.PeerManager
	GetRelay       func() infra.RelayChannel
	FilteringMux   *infra.FilteringUDPMux
	FilteringMux6  *infra.FilteringUDPMux
	GetProvisioner func() provision.Provisioner
	// GetPeerStats returns the WireGuard handshake time and received-byte
	// counter for the given peer public key. Used by the liveness ticker to
	// detect silent peer failures. May be nil (liveness monitoring is disabled).
	GetPeerStats func(pubKey string) (PeerStats, error)
	ShowLog      bool
}

type RelayDialerConfig

type RelayDialerConfig struct {
	LocalId   infra.PeerIdentity
	RemoteId  infra.PeerIdentity
	Relay     infra.RelayChannel
	SM        *SessionManager
	SessionId uint64
	// GetLocalPeer is called at send time so late-arriving ApplyFullConfig
	// updates (Address, AllowedIPs) are always reflected in SYN/ACK peer info.
	GetLocalPeer   func() *infra.Peer
	OnPeerReceived func(peer infra.Peer)
	Sender         func(ctx context.Context, peerId infra.PeerID, data []byte) error
	// OnRestart is called when a HANDSHAKE_SYN arrives while the session is
	// already active, signalling that the remote peer restarted.  The callback
	// should trigger probe.restart() to re-run discovery with fresh dialers.
	OnRestart func()
}

type RelayTransport

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

func (RelayTransport) Close

func (w RelayTransport) Close() error

func (RelayTransport) Priority

func (w RelayTransport) Priority() uint8

func (RelayTransport) Read

func (w RelayTransport) Read(buff []byte) (int, error)

func (RelayTransport) RemoteAddr

func (w RelayTransport) RemoteAddr() string

func (RelayTransport) Type

func (RelayTransport) Write

func (w RelayTransport) Write(data []byte) error

type RouteOps

type RouteOps interface {
	ApplyRoute(address, iface string) error
	SetupNAT(iface string) error
}

RouteOps is the minimal interface for routing and NAT.

type SessionManager

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

func (*SessionManager) Add

func (m *SessionManager) Add(pubKey [32]byte, sid uint64)

Add registers a new session (typically called after NATS negotiation completes)

func (*SessionManager) Remove

func (m *SessionManager) Remove(pubKey [32]byte, sid uint64)

Remove deletes a session

type StateMachine

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

StateMachine guards connection lifecycle transitions. It does NOT handle side effects — callers register callbacks via OnTransition.

func NewStateMachine

func NewStateMachine(initial PeerState) *StateMachine

NewStateMachine creates a state machine in the given initial state.

func (*StateMachine) Current

func (sm *StateMachine) Current() PeerState

Current returns the current state (thread-safe).

func (*StateMachine) OnTransition

func (sm *StateMachine) OnTransition(cb func(from, to PeerState))

OnTransition registers a callback that fires on every successful transition.

func (*StateMachine) Transition

func (sm *StateMachine) Transition(target PeerState) error

Transition attempts to move from the current state to target. Returns an error if the transition is not allowed. On success, fires all registered OnTransition callbacks.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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