Help us shape the future of Go! Take the 2026 Go Developer Survey

routing

package
v1.3.104 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: AGPL-3.0 Imports: 12 Imported by: 4

Documentation

Overview

Package routing pkg/routing/addr.go c1-net-routing

Package routing pkg/routing/batch_route.go c1-net-routing

The BATCHED half of the route-setup protocol.

A multiplexed dial wants N routes to ONE destination at once: a standby-pool fill, `--tunnels N`, and every aux mux leg are all "give me N disjoint routes to the same exit". Until now each of those was its own BidirectionalRoute in its own SetupRPCGateway.DialRouteGroup request, so the setup node re-dialed the source and the destination once PER ROUTE, reserved route IDs from each of them once PER ROUTE, and the initiator paid the full setup latency (p50 0.6-2.1 s, max 7.8 s on the live deployment) N times.

BidirectionalRouteBatch carries all N in one message. The setup node can then coalesce the per-hop work — one id-reservation RPC per DISTINCT hop covering every route that traverses it, one intermediary-rule install per distinct hop carrying that hop's rules for every route — and answer with one result per route. Partial success is first class: a batch where one route's intermediate is unreachable still returns the other N-1 installed.

The batch form is NOT a flag: a client sends it only when the setup node has advertised CapBatchRouteSetup (see the setup gateway's Capabilities RPC and HealthCheck reply). A setup node that predates this message never sees one.

Package routing pkg/routing/cascade.go c1-net-routing

CascadeSetup and CascadeAck define the wire format for the cascade route setup protocol. Messages are nested (Russian-doll style) so that each hop only sees its own layer.

Package routing pkg/routing/failure.go c1-net-routing

Package routing pkg/routing/leg_control_frame.go c2-net-routing

The IN-BAND leg control frame: the re-home / split request, ack, refusal and commit (leg_rehome.go, leg_split.go) carried inside an ordinary DataPacket instead of as a LegRehomePacket of its own.

Why. An intermediary relay forwards a LegRehomePacket only if its build knows the type; one that does not drops it, and the fleet is heterogeneous and stays so — a re-home routed through an unknown relay is never acked, while the same request on a leg whose transport reaches the exit directly is acked every time. A relay forwards a DataPacket by route ID WITHOUT looking at the payload, so a control message carried inside one reaches the exit through any relay, old or new. Relays need no change at all.

The frame is the plaintext body of a mux frame; the mux wraps it exactly like a data frame (per-frame AEAD when negotiated, CRC32C otherwise — see router/mux_control_frame.go) and gives it a sequence number from a RESERVED band, so it never enters the data sequence space: the receiver dispatches it before the reorder buffer, so it cannot advance the frontier, appear in a SACK, or be counted as a reorder drop.

Body layout (LegControlFrameSize bytes):

[0:2]   magic   0x4C43 ("LC")
[2]     version 1
[3]     kind    LegControlKind*
[4:12]  nonce   uint64 BE   — ties request, ack and commit together
[12]    flags   LegRehome*  — the SAME flag byte the packet type carries
[13:15] srcPort uint16 BE   — the sender's ports for the TARGET group
[15:17] dstPort uint16 BE

The fields are the LegRehomePacket payload's, in the same order, so both dialects feed one state machine.

Package routing pkg/routing/packet.go c1-net-routing

Package routing pkg/routing/route.go c1-net-routing operations.

Package routing pkg/routing/route_descriptor.go c1-net-routing

Package routing pkg/routing/rule.go c1-net-routing

Package routing pkg/routing/table.go c1-net-routing

Index

Constants

View Source
const (
	CascadePhaseReserve uint8 = 0
	CascadePhaseInstall uint8 = 1
)

Cascade protocol phases.

View Source
const (
	// PacketHeaderSize represents the base size of a packet.
	// All rules should have at-least this size.
	PacketHeaderSize        = 7
	PacketTypeOffset        = 0
	PacketRouteIDOffset     = 1
	PacketPayloadSizeOffset = 5
	PacketPayloadOffset     = PacketHeaderSize
)

Packet sizes and offsets.

View Source
const (
	// LegRehomeAck marks the exit's acceptance of a re-home request: its own
	// consume rule has been rewritten and the chain now belongs to the target
	// group on that side.
	LegRehomeAck byte = 0x01
	// LegRehomeCommit marks the initiator's third message, sent through the
	// TARGET group's rules once its own rewrite is done: the exit may promote
	// the adopted leg out of standby and start striping onto it.
	LegRehomeCommit byte = 0x02
	// LegRehomeRefused marks a refusal (no such target group, a different peer,
	// mux not enabled). Carried with LegRehomeAck cleared; both groups are left
	// exactly as they were.
	LegRehomeRefused byte = 0x04
	// LegRehomeSplit marks the REVERSE direction (router/leg_split.go): the
	// ports name a NEW standalone standby group of the INITIATOR, and the chain
	// the packet arrives on is to leave the group it belongs to and become that
	// group's only leg. Echoed on the ack and on a refusal, so an answer is
	// never mistaken for a forward re-home's.
	LegRehomeSplit byte = 0x08
	// LegRehomeAdopt marks a request to turn a LEG RESERVE (a split's group)
	// back into a stream-level tunnel (router/leg_adopt.go): the ports name the
	// INITIATOR's new tunnel descriptor, and the chain the packet arrives on
	// leaves its reserve group and becomes that tunnel's primary leg, to be
	// handshaked and accepted like a freshly set-up route group. Echoed on the
	// ack and on a refusal. A peer that predates it reads it as a forward
	// re-home naming a group that does not exist, and refuses.
	LegRehomeAdopt byte = 0x10
)

LegRehomePacket payload flags.

View Source
const (
	CapMux     uint16 = 1 << 0 // Supports route multiplexing (sequenced DataPackets)
	CapSACK    uint16 = 1 << 1 // Supports SACK retransmission
	CapCascade uint16 = 1 << 2 // Supports cascade route setup protocol
	// CapPerFrameNoise: the peer supports per-frame AEAD inside the mux (each
	// sequenced DATA frame independently sealed with its sequence as the nonce),
	// so noise is no longer a stateful stream wrapper and the reorder buffer may
	// deliver out of order. When BOTH edges advertise it, the route-group
	// handshake also carries a piggybacked noise KK message (after the 3-byte
	// enc+caps prefix), and network.EncryptConn is bypassed.
	CapPerFrameNoise uint16 = 1 << 3
	// CapHOLRetx: the peer supports PROACTIVE head-of-line retransmit inside the
	// mux. When BOTH edges advertise it (and CapSACK, which it reuses), a receiver
	// whose reorder frontier has been gap-blocked for ~one fastest-live-leg RTT
	// prompts the sender with a SACK, and the sender immediately retransmits the
	// stuck frontier seq on its fastest live leg — bypassing the reactive
	// retxMinAge/reorderTimeout waits — so a single multi-leg download's stall is
	// bounded by a fast-leg RTT instead of collapsing below single-leg rate. It
	// adds NO new wire message (the existing SACK carries the frontier); a peer
	// without this bit cleanly falls back to the reactive SACK behavior.
	CapHOLRetx uint16 = 1 << 4
	// CapFEC: the peer supports forward-error-correction inside the mux. When BOTH
	// edges advertise it (and CapMux, which it requires), the sender groups K
	// consecutive sequenced DATA frames into a block and emits R RepairPackets on
	// its fast legs; a receiver whose reorder frontier is gap-blocked reconstructs
	// the missing data frame from any K of the block's K+R symbols (removing the
	// wait on the slow leg that striped the frame). Erasure recovery delay is then
	// bound by the FAST legs, not the slow one. A peer without this bit never
	// receives RepairPackets and falls back cleanly to reorder+SACK.
	CapFEC uint16 = 1 << 5
	// CapLegState: the peer supports leg active/standby signaling (LegStatePacket).
	// When BOTH edges advertise it (and CapMux, which it requires), the side that
	// parks/promotes a mux leg tells the other end, which mirrors the state on ITS
	// send side — so on a download the bulk sender stripes only across the legs the
	// receiver has kept active, instead of every established leg (the wide-mux
	// head-of-line stall). A peer without this bit never receives one and keeps the
	// prior send-side-only standby behavior.
	CapLegState uint16 = 1 << 6
	// CapUniDir: the peer supports UNIDIRECTIONAL per-leg send selection. When BOTH
	// edges advertise it (and CapMux), each end restricts its OWN send to legs
	// matching its direction — the initiator (upload/forward) sends on the DIRECT
	// (1-hop) leg, the acceptor (download/reverse) sends on the MULTIHOP mux legs —
	// so the light direction rides the low-latency direct transport and the heavy
	// direction aggregates over the mux, instead of both directions striping every
	// leg. Each end decides locally from its role + leg directness (no per-packet
	// signaling); the assignment can later be FLIPPED (heavy direction gets the
	// mux) via LegState-style coordination. A peer without the bit keeps striping
	// every leg both ways.
	CapUniDir uint16 = 1 << 7
	// CapLegRehome: the peer supports LEG RE-HOME — moving a standby route
	// group's whole built chain into an ACTIVE group as one of its mux legs, in
	// place, with no setup-node dial (LegRehomePacket). When BOTH edges advertise
	// it (and CapMux, which it requires), each edge rewrites that chain's single
	// consume rule from the standby group's descriptor to the active group's; the
	// descriptorless intermediate hops are untouched. It takes the bit
	// docs/design/shared-warm-route-pool.md Phase 3 reserved, and is the
	// incremental half of it: one chain still terminates in one consume rule, it
	// just changes owner. A peer without the bit never receives a LegRehomePacket
	// and the caller falls back to dialing a pool-sourced leg.
	CapLegRehome uint16 = 1 << 8
	// CapDeliveryCRC: the peer supports the in-mux DELIVERY check. When BOTH
	// edges advertise it (and CapMux, which it requires), every sequenced DATA
	// frame's payload becomes app_payload ‖ crc32c(seq_be ‖ app_payload) —
	// DeliveryCRCSize extra bytes, stamped before the per-frame AEAD seal so a
	// retransmit or an FEC reconstruction reproduces identical bytes. The
	// receiver verifies and strips the trailing 4 bytes at DELIVERY time (after
	// reordering, on the in-order path), so a reorder/flush defect that hands
	// the app the right bytes in the wrong order is caught in the router instead
	// of surfacing as an application hash failure. Per-frame AEAD already covers
	// wire corruption of ONE frame; this covers the reassembled run. A peer
	// without the bit is never stamped and never strips.
	CapDeliveryCRC uint16 = 1 << 9
)

Capability bitmap flags for extended handshake negotiation. Transmitted as a little-endian uint16 at HandshakePacket payload bytes 1-2.

View Source
const (
	// DirectionAuto releases a manual pin — the flip controller resumes on both
	// ends from the current mapping.
	DirectionAuto byte = 0
	// DirectionPinDefault pins the DEFAULT mapping: the initiator sends on the
	// DIRECT (1-hop) leg, the acceptor (the download) on the MULTIHOP mux legs.
	DirectionPinDefault byte = 1
	// DirectionPinFlipped pins the FLIPPED mapping: the initiator sends on the
	// multihop mux legs, the acceptor on the direct leg (upload gets the mux).
	DirectionPinFlipped byte = 2
)

DirectionPacket payload modes: the direction→leg-class mapping an operator pins on a unidirectional (CapUniDir) group, or auto to release the pin.

View Source
const (
	// RuleReverse represents a hop to the route's destination visor.
	// A packet referencing this rule is to be consumed locally.
	RuleReverse = RuleType(0)

	// RuleForward represents a hop from the route's source visor.
	// A packet referencing this rule is to be sent to a remote visor.
	RuleForward = RuleType(1)

	// RuleIntermediary represents a hop which is not from the route's source,
	// nor to the route's destination.
	RuleIntermediary = RuleType(2)
)
View Source
const DeliveryCRCSize = 4

DeliveryCRCSize is the byte size of the CRC32C (Castagnoli) trailer appended to a sequenced DATA frame's payload when CapDeliveryCRC is negotiated.

View Source
const DirectionPayloadSize = 1

DirectionPayloadSize is the DirectionPacket payload: one mode byte.

View Source
const FECRepairHdr = 7

FECRepairHdr is the fixed prefix of a RepairPacket payload: blockID(4) + idx(1) + symLen(2), followed by the repair symbol bytes. symLen is the block's adaptive erasure-symbol length, which the receiver needs to size the block for decoding.

View Source
const LegControlFrameSize = 4 + LegRehomeSize

LegControlFrameSize is the encoded body length: magic(2) version(1) kind(1) plus the LegRehomePacket payload's own 13 bytes.

View Source
const LegControlKindRehome byte = 1

LegControlKindRehome is the leg re-home / leg split control frame: the same nonce, ports and flags routing.MakeLegRehomePacket carries.

View Source
const LegControlMagic uint16 = 0x4C43

LegControlMagic marks a mux frame body as a leg control frame. It is a sanity check, not a security boundary: the frame is already authenticated by the per-frame AEAD (or, without it, covered by the same CRC32C a data frame is).

View Source
const LegControlVersion byte = 1

LegControlVersion is the body version. A receiver drops a version it does not know rather than guessing at the layout — a half-read instruction would move a live chain to the wrong group.

View Source
const LegRehomeSize = 13

LegRehomeSize is the LegRehomePacket payload: nonce(8 BE) | flags(1) | srcPort(2 BE) | dstPort(2 BE).

View Source
const LegStatePayloadSize = 1

LegStatePayloadSize is the LegStatePacket payload: one byte (1=standby, 0=active).

View Source
const MaxBatchRoutes = 32

MaxBatchRoutes bounds one batched setup request. It is a protocol limit, not a tuning knob: it caps the work one RPC handler can queue on the setup node (each route holds route-ID reservations on every hop it traverses until the batch resolves) and bounds the reply size. A caller wanting more routes sends more batches.

View Source
const (
	RuleHeaderSize = 8 + 1 + 4
)

RuleHeaderSize represents the base size of a rule. All rules should be at-least this size.

View Source
const SACKDSACKFieldSize = 5

SACKDSACKFieldSize is the size of the optional trailing DSACK field appended by MakeSACKPacketWithDSACK: [flag:1][dsackSeq:4 BE]. A peer that predates the field reads exactly word_count words and ignores these trailing bytes.

View Source
const SACKMaxWords = 32

SACKMaxWords bounds the SACK bitmap to the mux reorder window: each word acknowledges 64 sequences, so 32 words cover 2048 outstanding sequences — the receiver force-flushes its reorder buffer beyond that, so acking further is pointless. Keeps a SACK payload at most 5+32*8 = 261 bytes.

View Source
const SACKMinPayloadSize = 5

SACKMinPayloadSize is the smallest legal SACK payload: last_contiguous_seq (uint32) + word_count (uint8) = 5 bytes (zero words).

View Source
const SACKPayloadSize = 12

SACKPayloadSize is retained for the wire-compat single-word (legacy 12-byte) SACK shape referenced by size-sensitive callers; the current encoder emits a variable-length body (see MakeSACKPacket).

View Source
const SeqSize = 4

SeqSize is the byte size of the sequence number prepended to DataPacket payloads when mux mode is active.

View Source
const TransportBwAckSize = 12

TransportBwAckSize is the ack payload size: probeID(4) + estBps(8).

View Source
const TransportBwProbeHdr = 8

TransportBwProbeHdr is the meaningful prefix of a probe payload: probeID(4) + seq(2) + total(2); the remainder is padding.

View Source
const TransportBwProbeSize = 1400

TransportBwProbeSize is the on-wire size of each packet-pair probe packet. ~1400 B (sub-MTU) so consecutive packets are large enough to be spaced by the bottleneck link's serialization delay — the signal dispersion measures.

View Source
const TransportPingPayloadSize = 8

TransportPingPayloadSize is the size of a transport ping/pong payload (8 bytes for unix nano timestamp).

Variables

View Source
var (
	ErrBatchEmpty          = errors.New("route setup batch carries no routes")
	ErrBatchTooLarge       = fmt.Errorf("route setup batch carries more than %d routes", MaxBatchRoutes)
	ErrBatchDuplicateID    = errors.New("route setup batch has a duplicate correlation id")
	ErrBatchMixedEndpoints = errors.New("route setup batch mixes source/destination pairs")
)

Errors returned by BidirectionalRouteBatch.Check.

View Source
var (
	ErrCascadeTooShort     = errors.New("cascade: message too short")
	ErrCascadeInvalidPhase = errors.New("cascade: invalid phase")
	ErrCascadeSigInvalid   = errors.New("cascade: RSN signature verification failed")
	ErrCascadeUntrustedRSN = errors.New("cascade: RSN public key not trusted")
)
View Source
var (
	ErrBiRouteHasNoForwardHops = errors.New("bidirectional route does not have forward hops")
	ErrBiRouteHasNoReverseHops = errors.New("bidirectional route does not have reverse hops")
	ErrBiRouteHasInvalidDesc   = errors.New("bidirectional route has an invalid route description")
)

Errors associated with BidirectionalRoute

View Source
var (
	// ErrRuleNotFound is returned while trying to access non-existing rule
	ErrRuleNotFound = errors.New("rule not found")
	// ErrRuleTimedOut is being returned while trying to access the rule which timed out
	ErrRuleTimedOut = errors.New("rule keep-alive timeout exceeded")
	// ErrNoAvailableRoutes is returned when there're no more available routeIDs
	ErrNoAvailableRoutes = errors.New("no available routeIDs")
)
View Source
var ErrInvalidRule = errors.New("invalid routing rule")

ErrInvalidRule is returned for rule bytes that are too short for their type or carry an unknown type. Rules from outside the process are checked with Rule.Validate before use; the accessors below assume a valid rule.

View Source
var (
	// ErrPayloadTooBig is returned when passed payload is too big (more than math.MaxUint16).
	ErrPayloadTooBig = errors.New("packet size exceeded")
)

Functions

func EncodeLegControlFrame

func EncodeLegControlFrame(kind byte, nonce uint64, srcPort, dstPort Port, flags byte) []byte

EncodeLegControlFrame builds the body of an in-band leg control frame. The caller hands it to the mux, which seals or stamps it and sends it as a DataPacket on the chain being moved.

func SerializeRules

func SerializeRules(rules []Rule) []byte

SerializeRules serializes multiple routing rules into a single byte slice with length prefixes: [count:1][len:2][rule:...]...

Types

type Addr

type Addr struct {
	PubKey cipher.PubKey `json:"pk"`
	Port   Port          `json:"port"`
}

Addr represents a network address combining public key and port. Implements net.Addr

func (Addr) Network

func (a Addr) Network() string

Network returns type of `a`'s network

func (*Addr) Set

func (a *Addr) Set(s string) error

Set implements pflag.Value for Addr.

func (Addr) String

func (a Addr) String() string

type BatchRouteRequest

type BatchRouteRequest struct {
	ID    uint32
	Route BidirectionalRoute
}

BatchRouteRequest is one member of a batched setup request. ID is assigned by the CALLER and is echoed on the matching BatchRouteResult — the results are not required to come back in request order, and a partial batch returns fewer results than it was sent.

type BatchRouteResult

type BatchRouteResult struct {
	ID    uint32
	Rules EdgeRules
	Error string
}

BatchRouteResult is one route's outcome. Error is the empty string on success; a non-empty Error means Rules is meaningless for that route and the caller falls back to its own retry (a single DialRouteGroup, a different candidate path) for that member alone.

The error travels as a STRING rather than an error value because this struct crosses the setup RPC: the wire codec has no error type, and the initiator only ever logs / classifies the text.

func (BatchRouteResult) Failed

func (r BatchRouteResult) Failed() bool

Failed reports whether this member did not install.

type BidirectionalRoute

type BidirectionalRoute struct {
	Desc      RouteDescriptor
	KeepAlive time.Duration
	Forward   []Hop
	Reverse   []Hop
}

BidirectionalRoute is a Route with both forward and reverse Paths.

func (*BidirectionalRoute) Check

func (br *BidirectionalRoute) Check() error

Check checks whether the bidirectional route is valid.

func (*BidirectionalRoute) ForwardAndReverse

func (br *BidirectionalRoute) ForwardAndReverse() (forward, reverse Route)

ForwardAndReverse generate forward and reverse routes for bidirectional route.

func (*BidirectionalRoute) String

func (br *BidirectionalRoute) String() string

String implements fmt.Stringer

type BidirectionalRouteBatch

type BidirectionalRouteBatch struct {
	Routes []BatchRouteRequest
}

BidirectionalRouteBatch is up to MaxBatchRoutes bidirectional routes that share one source and one destination visor, set up in a single request.

Same source and same destination is a REQUIREMENT, not a convention: the coalescing the setup node performs (one id reservation per distinct hop, one rule install per distinct hop) is only a saving because the source and the destination are common to every member, and a mixed batch would let one caller reserve route IDs on a peer it never names in a route it owns.

func (*BidirectionalRouteBatch) Check

func (b *BidirectionalRouteBatch) Check() error

Check validates the batch as a whole: non-empty, within MaxBatchRoutes, correlation ids unique, every member a valid BidirectionalRoute, and every member sharing the first member's source and destination.

It deliberately does NOT reject a batch whose members repeat a path — two identical paths are two distinct route groups with their own route-ID chains, which is a legitimate (if unusual) thing to ask for.

func (*BidirectionalRouteBatch) DistinctHopPKs

func (b *BidirectionalRouteBatch) DistinctHopPKs() int

DistinctHopPKs counts the visors a batch touches — source, destination and every intermediate, each once. It is what the per-hop coalescing saving is measured against: without a batch the setup node does this much work PER ROUTE, with one it does it once for the batch.

func (*BidirectionalRouteBatch) Dst

Dst returns the batch's common destination visor. Only meaningful after Check.

func (*BidirectionalRouteBatch) Hops

func (b *BidirectionalRouteBatch) Hops() [][]Hop

Hops returns every forward and reverse hop list in the batch, in member order (forward then reverse per member) — the exact shape NewIDReserver takes, so one reserver covers the whole batch and each distinct hop is dialed and asked for its route IDs exactly once.

func (*BidirectionalRouteBatch) Src

Src returns the batch's common source visor. Only meaningful after Check.

type BidirectionalRouteBatchReply

type BidirectionalRouteBatchReply struct {
	Results []BatchRouteResult
}

BidirectionalRouteBatchReply carries one result per route the setup node attempted. A member missing from Results was never attempted (the batch was truncated by the node's own limit) and the caller must treat it as failed.

type CascadeAck

type CascadeAck struct {
	SessionID uint64
	Phase     uint8
	RouteIDs  []RouteID // reserved IDs (Reserve phase) or empty (Install phase)
	Error     string    // non-empty on failure
}

CascadeAck is the per-hop cascade acknowledgment.

func UnmarshalCascadeAck

func UnmarshalCascadeAck(data []byte) (*CascadeAck, error)

UnmarshalCascadeAck deserializes a CascadeAck from binary.

func (*CascadeAck) Marshal

func (ca *CascadeAck) Marshal() ([]byte, error)

Marshal serializes CascadeAck to binary.

Wire format:

[SessionID:8][Phase:1][RouteIDCount:1][RouteIDs:4*N][ErrorLen:2][Error:...]

func (*CascadeAck) PrependRouteIDs

func (ca *CascadeAck) PrependRouteIDs(ids []RouteID)

PrependRouteIDs adds this hop's reserved IDs to the front of the ACK.

type CascadeSetup

type CascadeSetup struct {
	Phase     uint8         // 0=Reserve, 1=Install
	SessionID uint64        // correlates reserve/install phases
	RSNPK     cipher.PubKey // RSN that authorized this setup (33 bytes)
	Nonce     uint64        // anti-replay, unique per session+hop
	RSNSig    cipher.Sig    // signature over (Phase||SessionID||RSNPK||Nonce||TargetPK||EdgeDesc||RuleData)
	RuleData  []byte        // serialized routing rules for this hop (empty in Reserve phase)
	ReserveN  uint8         // number of route IDs to reserve (Reserve phase only)
	RelayTpID uuid.UUID     // transport to forward Payload on (zero = terminal hop)
	// EdgeDesc, when non-zero, marks this hop as a route-group EDGE (the
	// responding destination): the hop must call router.IntroduceRules with
	// EdgeRules{Desc: EdgeDesc, Forward: RuleData[0], Reverse: RuleData[1]} so it
	// creates/joins a route group (and notifies its launcher) rather than only
	// installing forwarding rules. Zero on intermediaries (Install phase) and
	// throughout the Reserve phase.
	EdgeDesc RouteDescriptor
	Payload  []byte // next hop's CascadeSetup (opaque to this hop)
}

CascadeSetup is the per-hop cascade setup message.

func UnmarshalCascadeSetup

func UnmarshalCascadeSetup(data []byte) (*CascadeSetup, error)

UnmarshalCascadeSetup deserializes a CascadeSetup from binary.

func (*CascadeSetup) IsEdge

func (cs *CascadeSetup) IsEdge() bool

IsEdge reports whether this Install-phase hop is a route-group edge (the responding destination): EdgeDesc is set, so the hop must IntroduceRules.

func (*CascadeSetup) IsTerminal

func (cs *CascadeSetup) IsTerminal() bool

IsTerminal returns true if this is the last hop (no further relay).

func (*CascadeSetup) Marshal

func (cs *CascadeSetup) Marshal() ([]byte, error)

Marshal serializes CascadeSetup to binary.

Wire format:

[Phase:1][SessionID:8][RSNPK:33][Nonce:8][RSNSig:65][ReserveN:1][RelayTpID:16]
[RuleDataLen:2][RuleData:...][PayloadLen:2][Payload:...][EdgeDesc:70]

EdgeDesc is appended LAST as optional trailing data: nodes that predate it parse up to Payload and ignore the trailing bytes (and relay the inner payload — which carries the destination's own trailing EdgeDesc — opaquely), so only the source and destination need to understand it.

func (*CascadeSetup) Sign

func (cs *CascadeSetup) Sign(targetPK cipher.PubKey, rsnSK cipher.SecKey) error

Sign signs the message for a specific target visor PK using the RSN's secret key.

func (*CascadeSetup) SignablePayload

func (cs *CascadeSetup) SignablePayload(targetPK cipher.PubKey) []byte

SignablePayload returns the bytes that are signed/verified.

EdgeDesc is deliberately NOT signed: it is appended as optional trailing wire data so that un-upgraded intermediaries (which predate EdgeDesc) still parse and verify the message and relay the inner payload opaquely — cascade then works as soon as the SOURCE and DESTINATION are upgraded, regardless of intermediary versions. EdgeDesc only selects the destination's local action (IntroduceRules vs SaveRule); the rules it acts on ARE signed via RuleData, so a tampered EdgeDesc can at worst break that one route (a relay can already do that by dropping packets), never forge or escalate.

func (*CascadeSetup) Verify

func (cs *CascadeSetup) Verify(targetPK cipher.PubKey) error

Verify checks the RSN signature against the target visor's PK.

type CloseCode

type CloseCode byte

CloseCode represents close code for ClosePacket.

const (
	// CloseRequested is used when a closing is requested by visor.
	CloseRequested CloseCode = iota
	// CloseLegRetired closes ONE leg of a multiplexed route group without
	// tearing down the whole group. Intermediary relays handle it exactly like
	// CloseRequested (delete the leg's intermediary rule, forward onward), so
	// they reclaim the retired leg's rules immediately instead of waiting out
	// the ~10-minute idle-rule GC. The DESTINATION endpoint treats it specially:
	// it prunes only the leg whose consume rule the packet arrived on and keeps
	// the route group (and its other legs) alive. A visor that predates this
	// code falls back to the default branch and closes the whole group, so a
	// source must only emit CloseLegRetired to peers known to support it (gated
	// separately from this receive-side handling, which is inert until a source
	// opts in).
	CloseLegRetired
)

func (CloseCode) String

func (cc CloseCode) String() string

type EdgeRules

type EdgeRules struct {
	Desc    RouteDescriptor
	Forward Rule
	Reverse Rule
}

EdgeRules represents edge forward and reverse rules. Edge rules are forward and consume rules.

func (EdgeRules) String

func (er EdgeRules) String() string

String implements fmt.Stringer

func (EdgeRules) Validate

func (er EdgeRules) Validate() error

Validate checks that Forward is a valid forward rule and Reverse a valid consume rule, the roles every consumer of EdgeRules reads them in.

type Failure

type Failure struct {
	Code FailureCode `json:"code"`
	Msg  string      `json:"msg"`
}

Failure describes a routing failure.

func (Failure) Error

func (f Failure) Error() string

type FailureCode

type FailureCode byte

FailureCode is a code that indicates a reason why a failure happened.

const (
	FailureUnknown FailureCode = iota
	FailureAddRules
	FailureCreateRoutes
	FailureRoutesCreated
	FailureReserveRtIDs
)

Failure codes

func (FailureCode) String

func (fc FailureCode) String() string

type Hop

type Hop struct {
	TpID uuid.UUID
	From cipher.PubKey
	To   cipher.PubKey
	// Latency is this hop's measured transport latency in milliseconds, as
	// recorded by the route-finder from per-edge TPD data (0/omitted when the
	// edge has no measurement). It is informational — it lets callers rank or
	// display routes by predicted latency without re-querying, and is NOT used
	// in route-rule setup. Older route-finders simply omit it.
	Latency float64 `json:"Latency,omitempty"`
	// Type and ThroughputBps are the edge's transport type and passively
	// observed throughput, from the same TPD data. With Latency they are
	// everything the dialer ranks and filters hops on, so a route-finder
	// route needs no TPD snapshot of its own. A route-finder that sets Type
	// always sets it, so an empty Type means an older route-finder.
	Type          string  `json:"Type,omitempty"`
	ThroughputBps float64 `json:"ThroughputBps,omitempty"`
}

Hop defines a route hop between 2 nodes.

func (Hop) String

func (h Hop) String() string

String implements fmt.Stringer

type Packet

type Packet []byte

Packet defines generic packet recognized by all skywire visors. The unit of communication for routing/router is called packets. Packet format:

| type (byte) | route ID (uint32) | payload size (uint16) | payload (~) |
| 1[0:1]      | 4[1:5]            | 2[5:7]                | [7:~]       |

func MakeCascadeAckPacket

func MakeCascadeAckPacket(payload []byte) (Packet, error)

MakeCascadeAckPacket constructs a cascade ACK packet (route ID = 0).

func MakeCascadeSetupPacket

func MakeCascadeSetupPacket(payload []byte) (Packet, error)

MakeCascadeSetupPacket constructs a cascade setup packet (route ID = 0).

func MakeClosePacket

func MakeClosePacket(id RouteID, code CloseCode) Packet

MakeClosePacket constructs a new ClosePacket.

func MakeDataPacket

func MakeDataPacket(id RouteID, payload []byte) (Packet, error)

MakeDataPacket constructs a new DataPacket. If payload size is more than uint16, MakeDataPacket returns an error.

func MakeDatagramPacket

func MakeDatagramPacket(id RouteID, payload []byte) (Packet, error)

MakeDatagramPacket constructs a DatagramPacket. Faithful-UDP path: no sequence number, no reorder buffer, no SACK on the receive side. Loss is loss, ordering is best-effort, head-of-line blocking does not occur on the route group's read path. Payload is opaque to the router — the DatagramRouteGroup wraps it in a per-datagram AEAD (see RFC #2607 Stage 3) before this constructor is called, so what lands on the wire is ciphertext + the 8-byte nonce-counter prefix produced at that layer. This function is wire-format only.

Returns ErrPayloadTooBig if the payload (after AEAD wrapping) does not fit in a single skywire frame. Callers should check the DatagramRouteGroup's MaxPayload() before constructing.

func MakeDirectionPacket

func MakeDirectionPacket(id RouteID, mode byte) Packet

MakeDirectionPacket constructs a DirectionPacket pinning (mode 1/2) or releasing (mode 0) the unidirectional direction→leg-class mapping, addressed to the route group the id belongs to. Sent on the group's primary leg; the receiver applies the same pin so both ends keep sending on disjoint classes.

func MakeErrorPacket

func MakeErrorPacket(id RouteID, errPayload []byte) (Packet, error)

MakeErrorPacket constructs a new ErrorPacket. If payload size is more than uint16, MakeErrorPacket returns an error.

func MakeHandshakePacket

func MakeHandshakePacket(id RouteID, supportEncryption bool, capabilities uint16) Packet

MakeHandshakePacket constructs a new HandshakePacket with capability bitmap. Payload layout: [encryption flag (1 byte)][capabilities (2 bytes, little-endian)] Old visors only read byte 0 and ignore the rest, so this is backward compatible.

func MakeHandshakePacketRaw

func MakeHandshakePacketRaw(id RouteID, payload []byte) Packet

MakeHandshakePacketRaw constructs a HandshakePacket with an arbitrary payload. Used for forwarding handshake packets through intermediary nodes.

func MakeHandshakePacketWithNoise

func MakeHandshakePacketWithNoise(id RouteID, supportEncryption bool, capabilities uint16, noiseMsg []byte) Packet

MakeHandshakePacketWithNoise builds a handshake packet whose payload is the standard [enc][caps] prefix followed by a piggybacked noise KK handshake message. Used only when CapPerFrameNoise is negotiated; a nil/empty noiseMsg yields the same 3-byte payload as MakeHandshakePacket.

func MakeKeepAlivePacket

func MakeKeepAlivePacket(id RouteID) Packet

MakeKeepAlivePacket constructs a new KeepAlivePacket.

func MakeLegRehomePacket

func MakeLegRehomePacket(id RouteID, nonce uint64, srcPort, dstPort Port, flags byte) Packet

MakeLegRehomePacket constructs a LegRehomePacket. id is the next-hop route ID of the chain being moved, so the packet rides that chain and each edge identifies it by the route it arrives on. srcPort/dstPort are the SENDER's own ports for the TARGET group; the receiver mirrors them onto the arriving chain's PK pair to find its own side of that group, which is what confines a re-home to two groups already joining the same two visors. nonce ties the request, the ack and the commit of one re-home together.

func MakeLegStatePacket

func MakeLegStatePacket(id RouteID, standby bool) Packet

MakeLegStatePacket constructs a LegStatePacket announcing that the leg it is sent on is now standby (true) or active (false) on this side, so the remote can mirror the state on its send side. id is the leg's next-hop route ID (the packet is sent ON that leg, exactly like an aux-leg handshake, so the leg is identified by the route it arrives on — no leg index is carried).

func MakePingPacket

func MakePingPacket(id RouteID, timestamp, throughput int64) Packet

MakePingPacket constructs a new MakePingPacket.

func MakePongPacket

func MakePongPacket(id RouteID, timestamp int64) Packet

MakePongPacket constructs a new PongPacket.

func MakeRepairPacket

func MakeRepairPacket(id RouteID, blockID uint32, idx uint8, symLen int, symbol []byte) (Packet, error)

MakeRepairPacket constructs a RepairPacket carrying one FEC repair symbol for route group id. Payload: blockID(u32 BE) idx(u8) symLen(u16 BE) symbol...

func MakeSACKPacket

func MakeSACKPacket(id RouteID, lastContiguousSeq uint32, words []uint64) Packet

MakeSACKPacket constructs a SACK (Selective Acknowledgment) packet. Payload: [last_contiguous_seq (4 bytes BE)][word_count (1 byte)][words...(8 bytes BE each)] For word w and bit i, a set bit means (last_contiguous_seq + 1 + w*64 + i) has been received. The variable-length body lets a SACK acknowledge the whole outstanding window (up to SACKMaxWords*64 sequences), not just the first 64 — without it, a persistent frontier gap leaves the sender unable to purge the received-but-unackable sequences above the gap, its retx buffer fills, new packets stop being stored for retransmission, and a later loss wedges the mux stream permanently (the "carries-then-stalls" failure).

func MakeSACKPacketWithDSACK

func MakeSACKPacketWithDSACK(id RouteID, lastContiguousSeq uint32, words []uint64, dsackSeq uint32) Packet

MakeSACKPacketWithDSACK is MakeSACKPacket plus a trailing DSACK (duplicate-SACK) field: dsackSeq is a sequence the receiver got AGAIN (a duplicate). On the mux's reliable, ordered legs a duplicate is almost always the sender's own spurious retransmit, so this tells the sender to WIDEN its RACK reorder window — it retransmitted too eagerly (RFC 8985 §7.2 reorder-window adaptation). The field is appended AFTER the received bitmap as [flag:1=0x01][dsackSeq:4 BE]; a peer that predates it reads exactly word_count words (SACKWords) and ignores the trailing bytes, so the packet stays backward compatible with no capability bit.

func MakeSequencedDataPacket

func MakeSequencedDataPacket(id RouteID, seq uint32, payload []byte) (Packet, error)

MakeSequencedDataPacket constructs a DataPacket with a 4-byte sequence number prepended to the payload. Used when mux mode is active.

func MakeTransportBwAckPacket

func MakeTransportBwAckPacket(probeID uint32, estBps uint64) Packet

MakeTransportBwAckPacket constructs the prober-bound estimate reply.

func MakeTransportBwProbePacket

func MakeTransportBwProbePacket(probeID uint32, seq, total uint16) Packet

MakeTransportBwProbePacket constructs one packet of a bandwidth-probe train (route ID = 0), padded to TransportBwProbeSize.

func MakeTransportPingPacket

func MakeTransportPingPacket(timestamp int64) Packet

MakeTransportPingPacket constructs a transport-level ping packet. Route ID is 0 (no route); payload is an 8-byte unix nano timestamp.

func MakeTransportPongPacket

func MakeTransportPongPacket(timestamp int64) Packet

MakeTransportPongPacket constructs a transport-level pong packet. Echoes the timestamp from the ping.

func (Packet) BwAckFields

func (p Packet) BwAckFields() (probeID uint32, estBps uint64, ok bool)

BwAckFields returns (probeID, estBps) from a TransportBwAckPacket payload, and false if the payload is too short.

func (Packet) BwProbeFields

func (p Packet) BwProbeFields() (probeID uint32, seq, total uint16, ok bool)

BwProbeFields returns (probeID, seq, total) from a TransportBwProbePacket payload, and false if the payload is too short.

func (Packet) DataPayloadAfterSeq

func (p Packet) DataPayloadAfterSeq() []byte

DataPayloadAfterSeq returns the data payload after the sequence number prefix.

func (Packet) DirectionMode

func (p Packet) DirectionMode() byte

DirectionMode returns a DirectionPacket's mode byte (DirectionAuto / DirectionPinDefault / DirectionPinFlipped). A malformed/empty payload reads as DirectionAuto — the safe default (it never forces a mapping the sender did not ask for; at worst it releases a pin back to the controller).

func (Packet) HandshakeCapabilities

func (p Packet) HandshakeCapabilities() uint16

HandshakeCapabilities extracts the capability bitmap from an extended handshake payload. Returns 0 if the payload is too short (old visor).

func (Packet) HandshakeNoisePayload

func (p Packet) HandshakeNoisePayload() []byte

HandshakeNoisePayload returns the piggybacked noise handshake message from an extended handshake payload (bytes after the 3-byte enc+caps prefix), or nil.

func (Packet) LegRehomeFields

func (p Packet) LegRehomeFields() (nonce uint64, srcPort, dstPort Port, flags byte, ok bool)

LegRehomeFields reads a LegRehomePacket payload. ok is false for a malformed or truncated one, which the receiver drops: a re-home never proceeds on a half-read instruction, since it would move a live chain to the wrong group.

func (Packet) LegStateStandby

func (p Packet) LegStateStandby() bool

LegStateStandby reports whether a LegStatePacket announces standby (true) or active (false). A malformed/empty payload reads as active (the safe default — it never parks a leg the sender still wants to use).

func (Packet) Payload

func (p Packet) Payload() []byte

Payload returns payload from a Packet.

func (Packet) RepairBlockID

func (p Packet) RepairBlockID() uint32

RepairBlockID extracts the FEC block ID from a RepairPacket.

func (Packet) RepairIndex

func (p Packet) RepairIndex() uint8

RepairIndex extracts the repair-symbol index (0..R-1) from a RepairPacket.

func (Packet) RepairSymLen

func (p Packet) RepairSymLen() int

RepairSymLen extracts the block's adaptive symbol length from a RepairPacket.

func (Packet) RepairSymbol

func (p Packet) RepairSymbol() []byte

RepairSymbol returns the repair symbol bytes of a RepairPacket.

func (Packet) RouteID

func (p Packet) RouteID() RouteID

RouteID returns RouteID from a Packet.

func (Packet) SACKDSACK

func (p Packet) SACKDSACK() (uint32, bool)

SACKDSACK extracts the optional trailing DSACK (duplicate-SACK) sequence from a SACK packet: the seq the receiver reported getting twice (see MakeSACKPacketWithDSACK). Returns (seq, true) when present, (0, false) when the SACK carries no DSACK field (the common case) or is truncated. The offset is computed from the word_count byte, so it lands exactly past the bitmap the same way SACKWords reads it.

func (Packet) SACKLastContiguousSeq

func (p Packet) SACKLastContiguousSeq() uint32

SACKLastContiguousSeq extracts the last contiguous sequence number from a SACK packet.

func (Packet) SACKWords

func (p Packet) SACKWords() []uint64

SACKWords extracts the received-bitmap words from a SACK packet. Bit (w*64+i) set means (SACKLastContiguousSeq + 1 + w*64 + i) has been received. Returns nil for a malformed / truncated payload (treated as "nothing above the contiguous point acked", which is safe — it only forgoes purging).

func (Packet) SequenceNumber

func (p Packet) SequenceNumber() uint32

SequenceNumber extracts the 4-byte sequence number from a sequenced DataPacket payload.

func (Packet) Size

func (p Packet) Size() uint16

Size returns Packet's payload size.

func (Packet) Type

func (p Packet) Type() PacketType

Type returns Packet's type.

type PacketType

type PacketType byte

PacketType represents packet purpose.

const (
	DataPacket PacketType = iota
	ClosePacket
	KeepAlivePacket
	HandshakePacket
	PingPacket
	PongPacket
	ErrorPacket
	SACKPacket
	TransportPingPacket // transport-level ping (route ID = 0), payload: timestamp (8 bytes, unix nano)
	TransportPongPacket // transport-level pong (route ID = 0), payload: timestamp (8 bytes, echoed)
	CascadeSetupPacket  // cascade route setup (route ID = 0), payload: serialized CascadeSetup
	CascadeAckPacket    // cascade acknowledgment (route ID = 0), payload: serialized CascadeAck
	DHTPacket           // DHT RPC over transport (route ID = 0), payload: DHT message
	SetupRPCPacket      // RSN RPC relay over transport (route ID = 0), payload: virtual stream data
	VisorRPCPacket      // visor RPC over transport (route ID = 0), payload: virtual stream data
	SkynetForwardPacket // skynet port forwarding over direct transport (route ID = 0), virtual stream
	AppDirectPacket     // skywire-network app direct dial over direct transport (route ID = 0), virtual stream
	DatagramPacket      // faithful-UDP routed datagram (route ID > 0), payload: opaque bytes (AEAD-sealed at the DatagramRouteGroup layer). No sequence number — counter lives in the AEAD nonce (see RFC #2607).
	// TransportBwProbePacket is one packet of a back-to-back packet-pair
	// train (route ID = 0) used to estimate a transport's bottleneck
	// bandwidth from receive-side inter-arrival DISPERSION — a few KB, not a
	// saturating burst. Payload: probeID(u32) seq(u16) total(u16) + padding to
	// TransportBwProbeSize so the bottleneck link spaces consecutive packets.
	TransportBwProbePacket
	// TransportBwAckPacket carries the receiver's dispersion estimate back to
	// the prober (route ID = 0). Payload: probeID(u32) estBps(u64).
	TransportBwAckPacket
	// RepairPacket carries one FEC repair symbol for the mux data plane (route
	// ID > 0, same route group as the sequenced DataPackets it protects). Payload:
	// blockID(u32 BE) idx(u8) then the symbol bytes. When both edges advertise
	// CapFEC, the sender emits R repair packets per K-frame block onto its fast
	// legs; a receiver whose reorder frontier is gap-blocked reconstructs the
	// missing data frame from any K of the block's K+R symbols instead of waiting
	// for the slow leg. A peer without CapFEC never sees these and is unaffected.
	//
	// FORWARD-COMPAT (see #4270 RLNC note): the `idx` field ties a repair symbol
	// to a SPECIFIC known Cauchy generator row — i.e. this format assumes the
	// SENDER generated it (both ends share the generator, so no coefficients are
	// carried). A future hop-wise variant (an intermediate RECODING symbols, RLNC-
	// style) produces arbitrary linear combinations that must carry their own
	// coding vector; that is an ADDITIVE extension (a new packet type or an idx
	// sentinel selecting a coding-vector layout), NOT a break to this one — and the
	// decoder is already general (gfSolve solves any coefficient matrix). Keep the
	// symbol/block framing agnostic about WHO makes repair symbols so the hop-wise
	// path stays open without a format change.
	RepairPacket
	// LegStatePacket signals a mux leg's active/standby state to the REMOTE end
	// (route ID > 0, same route group as the leg it names — the packet is sent ON
	// that leg, so the leg is identified by the route ID it arrives stamped with,
	// exactly like an aux-leg HandshakePacket). Payload: one byte, 1 = standby,
	// 0 = active. Standby is otherwise a purely send-side decision, so on a
	// DOWNLOAD (the remote is the bulk sender) the remote would stripe across every
	// established leg — including ones this side has parked — head-of-line-stalling
	// the no-skip reorder buffer on the slowest. This packet mirrors the parking to
	// the sender so both ends stripe over the same active set. Gated by CapLegState;
	// a peer without it never receives one and keeps the send-side-only behavior.
	LegStatePacket
	// DirectionPacket pins (or releases) a unidirectional group's direction→
	// leg-class mapping — the LegState-style coordination the CapUniDir doc
	// promises for flips, applied to a MANUAL operator pin (route ID > 0, sent on
	// the group's primary leg). Payload: one byte — 0 = auto (release the pin, the
	// flip controller resumes), 1 = pin-default (initiator sends on the direct
	// leg / the download rides the multihop mux), 2 = pin-flipped (the swapped
	// mapping). Both ends must hold the same mapping or they send on the same leg
	// class; the receiver applies the pin too, so its flip controller does not
	// fight the sender's. The wire framing is length-prefixed and unknown types
	// fall through handlePacket harmlessly, so an OLD peer ignores this packet —
	// a pin against such a peer is best-effort local-only.
	DirectionPacket
	// LegRehomePacket moves a whole route CHAIN from one route group to another
	// between the same two visors, without a setup-node dial: both edges rewrite
	// the chain's single ConsumeRule from the standby group's descriptor to the
	// active group's, and the chain becomes one of the active group's mux legs
	// (route ID > 0 — it is sent ON the chain being moved, so the chain is
	// identified by the route the packet arrives on, exactly like an aux-leg
	// HandshakePacket). The intermediate hops carry no descriptor and are never
	// told. Payload: LegRehomeSize bytes, see MakeLegRehomePacket. Gated by
	// CapLegRehome; a peer without it never receives one. See
	// docs/design/leg-rehome.md.
	LegRehomePacket
)

Possible PacketType values: - DataPacket - Payload is just the underlying data. - ClosePacket - Payload is a type CloseCode byte. - KeepAlivePacket - Payload is empty. - HandshakePacket - Payload is supportEncryptionVal byte. - PingPacket - Payload is timestamp and throughput. - PongPacket - Payload is timestamp. - ErrorPacket - Payload is error.

func (PacketType) Known

func (t PacketType) Known() bool

Known reports whether t is a packet type this build defines. It is the single place the wire-level "is this frame sane" checks ask, so a NEW packet type only has to be added to String() and to the bound below — see TestPacketTypeKnownTracksString, which fails when the two drift apart.

It has to be kept current: the read loop used to compare against DirectionPacket directly, so every LegRehomePacket (added after it) was counted as a malformed frame and logged as "peer framing off" on both the intermediates and the exit.

func (PacketType) String

func (t PacketType) String() string

type PathEdges

type PathEdges [2]cipher.PubKey

PathEdges are the edge nodes of a path

func (PathEdges) MarshalText

func (p PathEdges) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler

func (*PathEdges) UnmarshalText

func (p *PathEdges) UnmarshalText(b []byte) error

UnmarshalText implements json.Unmarshaler. The form is "<pk>:<pk>"; anything else is an error, not a panic — it arrives straight from a request body.

type Port

type Port uint16

Port is a network port number

func DecodeLegControlFrame

func DecodeLegControlFrame(b []byte) (kind byte, nonce uint64, srcPort, dstPort Port, flags byte, ok bool)

DecodeLegControlFrame reads a leg control frame body. ok is false for a body that is truncated, not a control frame, or of an unknown version — all of which are dropped, exactly as a malformed LegRehomePacket payload is.

type Route

type Route struct {
	Desc      RouteDescriptor `json:"desc"`
	Hops      []Hop           `json:"path"`
	KeepAlive time.Duration   `json:"keep_alive"`
}

Route is a succession of transport entries that denotes a path from source visor to destination visor

func (Route) String

func (r Route) String() string

func (Route) TotalLatency

func (r Route) TotalLatency() float64

TotalLatency returns the route's predicted one-way latency: the sum of its hops' measured per-edge latencies (ms, populated by the route-finder). Hops with no measurement contribute 0, so a route crossing unmeasured edges reports a lower bound — callers that must penalize unmeasured edges should inspect per-hop Hop.Latency directly.

type RouteDescriptor

type RouteDescriptor [routeDescriptorSize]byte

RouteDescriptor describes a route (from the perspective of the source and destination edges).

func NewRouteDescriptor

func NewRouteDescriptor(srcPK, dstPK cipher.PubKey, srcPort, dstPort Port) RouteDescriptor

NewRouteDescriptor returns a new RouteDescriptor.

func (*RouteDescriptor) Dst

func (rd *RouteDescriptor) Dst() Addr

Dst returns destination Addr from RouteDescriptor.

func (*RouteDescriptor) DstPK

func (rd *RouteDescriptor) DstPK() cipher.PubKey

DstPK returns destination public key from RouteDescriptor.

func (*RouteDescriptor) DstPort

func (rd *RouteDescriptor) DstPort() Port

DstPort returns destination port from RouteDescriptor.

func (*RouteDescriptor) Invert

func (rd *RouteDescriptor) Invert() RouteDescriptor

Invert inverts source and destination.

func (*RouteDescriptor) Src

func (rd *RouteDescriptor) Src() Addr

Src returns source Addr from RouteDescriptor.

func (*RouteDescriptor) SrcPK

func (rd *RouteDescriptor) SrcPK() cipher.PubKey

SrcPK returns source public key from RouteDescriptor.

func (*RouteDescriptor) SrcPort

func (rd *RouteDescriptor) SrcPort() Port

SrcPort returns source port from RouteDescriptor.

func (*RouteDescriptor) String

func (rd *RouteDescriptor) String() string

type RouteDescriptorFields

type RouteDescriptorFields struct {
	DstPK   cipher.PubKey `json:"dst_pk"`
	SrcPK   cipher.PubKey `json:"src_pk"`
	DstPort Port          `json:"dst_port"`
	SrcPort Port          `json:"src_port"`
}

RouteDescriptorFields summarizes route descriptor fields of a RoutingRule.

type RouteID

type RouteID uint32

RouteID represents ID of a Route in a Packet.

type RoutingTableStats

type RoutingTableStats struct {
	Count  int            `json:"count"`
	NextID RouteID        `json:"next_id"`
	ByType map[string]int `json:"by_type"`
}

RoutingTableStats summarizes a routing table for observability: the live rule count, the monotonic route-ID high-water mark (RouteIDs are never reused, so this only ever grows — tracking it surfaces reservation leaks under churn), and a per-rule-type breakdown.

type Rule

type Rule []byte

Rule represents a routing rule. There are two types of routing rules; App and Forward.

func ConsumeRule

func ConsumeRule(keepAlive time.Duration, key RouteID, lPK, rPK cipher.PubKey, lPort, rPort Port) Rule

ConsumeRule constructs a new Consume rule.

func DeserializeRules

func DeserializeRules(data []byte) ([]Rule, error)

DeserializeRules deserializes rules from the format produced by SerializeRules.

func ForwardRule

func ForwardRule(
	keepAlive time.Duration,
	key, nextRt RouteID,
	nextTp uuid.UUID,
	lPK, rPK cipher.PubKey,
	lPort, rPort Port,
) Rule

ForwardRule constructs a new Forward rule.

func IntermediaryForwardRule

func IntermediaryForwardRule(keepAlive time.Duration, key, nextRoute RouteID, nextTransport uuid.UUID) Rule

IntermediaryForwardRule constructs a new IntermediaryForward rule.

func (Rule) Body

func (r Rule) Body() []byte

Body returns Body from the rule.

func (Rule) KeepAlive

func (r Rule) KeepAlive() time.Duration

KeepAlive returns rule's keep-alive timeout.

func (Rule) KeyRouteID

func (r Rule) KeyRouteID() RouteID

KeyRouteID returns KeyRouteID from the rule: it is used as the key to retrieve the rule.

func (Rule) NextRouteID

func (r Rule) NextRouteID() RouteID

NextRouteID returns NextRouteID from the rule.

func (Rule) NextTransportID

func (r Rule) NextTransportID() uuid.UUID

NextTransportID returns next transport ID for a forward rule.

func (Rule) RouteDescriptor

func (r Rule) RouteDescriptor() RouteDescriptor

RouteDescriptor returns RouteDescriptor from the rule.

func (Rule) SetKeyRouteID

func (r Rule) SetKeyRouteID(id RouteID)

SetKeyRouteID sets KeyRouteID of a rule.

func (Rule) String

func (r Rule) String() string

String returns rule's string representation.

func (Rule) Summary

func (r Rule) Summary() *RuleSummary

Summary returns the RoutingRule's summary.

func (Rule) Type

func (r Rule) Type() RuleType

Type returns type of a rule.

func (Rule) Validate

func (r Rule) Validate() error

Validate reports whether r is long enough for its type and of a known type, so that every accessor can read it without panicking.

type RuleConsumeFields

type RuleConsumeFields struct {
	RouteDescriptor RouteDescriptorFields `json:"route_descriptor"`
}

RuleConsumeFields summarizes consume fields of a RoutingRule.

type RuleForwardFields

type RuleForwardFields struct {
	RouteDescriptor RouteDescriptorFields `json:"route_descriptor"`
	NextRID         RouteID               `json:"next_rid"`
	NextTID         uuid.UUID             `json:"next_tid"`
}

RuleForwardFields summarizes Forward fields of a RoutingRule.

type RuleIntermediaryForwardFields

type RuleIntermediaryForwardFields struct {
	NextRID RouteID   `json:"next_rid"`
	NextTID uuid.UUID `json:"next_tid"`
}

RuleIntermediaryForwardFields summarizes IntermediaryForward fields of a RoutingRule.

type RuleSummary

type RuleSummary struct {
	KeepAlive                 time.Duration                  `json:"keep_alive"`
	Type                      RuleType                       `json:"rule_type"`
	KeyRouteID                RouteID                        `json:"key_route_id"`
	ConsumeFields             *RuleConsumeFields             `json:"app_fields,omitempty"`
	ForwardFields             *RuleForwardFields             `json:"forward_fields,omitempty"`
	IntermediaryForwardFields *RuleIntermediaryForwardFields `json:"intermediary_forward_fields,omitempty"`
}

RuleSummary provides a summary of a RoutingRule.

func (*RuleSummary) ToRule

func (rs *RuleSummary) ToRule() (Rule, error)

ToRule converts RoutingRuleSummary to RoutingRule.

type RuleType

type RuleType byte

RuleType defines type of a routing rule

func (RuleType) String

func (rt RuleType) String() string

type Table

type Table interface {
	// ReserveKeys reserves n RouteIDs.
	ReserveKeys(n int) ([]RouteID, error)

	// SaveRule sets RoutingRule for a given RouteID.
	SaveRule(Rule) error

	// Rule returns RoutingRule with a given RouteID.
	Rule(RouteID) (Rule, error)

	UpdateActivity(RouteID) error

	// AllRules returns all non timed out rules with a given route descriptor.
	RulesWithDesc(RouteDescriptor) []Rule

	// AllRules returns all non timed out rules.
	AllRules() []Rule

	// HasTransport returns true if any active (non-timed-out) routing rule
	// references the given transport ID. Used to protect transports that are
	// actively carrying route traffic from being torn down.
	HasTransport(id uuid.UUID) bool

	// DelRules removes RoutingRules with a given a RouteIDs.
	DelRules([]RouteID)

	// Count returns the number of RoutingRule entries stored.
	Count() int

	// Stats returns observability counters: live rule count, the monotonic
	// route-ID high-water mark (never reused), and a per-type breakdown.
	Stats() RoutingTableStats

	// CollectGarbage checks all the stored rules, removes and returns ones that timed out.
	CollectGarbage() []Rule
}

Table represents a routing table implementation.

func NewTable

func NewTable(log *logging.Logger) Table

NewTable returns an in-memory routing table implementation with a specified configuration.

Jump to

Keyboard shortcuts

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