Type Parameters:
K: comparable
V: comparable AddrMap is a bidirectional map between a key K and a mapped address of value
type V, generating a new mapped address on first lookup of a key. It is the
Go analog of the Rust AddrMap. Get returns the mapped address for key, generating and recording one if it
does not yet exist. Len returns the number of mappings. Intended for tests and metrics. Lookup returns the key that maps to addr, if any. Remove deletes the mapping for key, if any. The next Get of the same key
generates a fresh mapped address.
func NewAddrMap[K, V](gen func() V, addrOf func(V) netip.Addr) *AddrMap[K, V]
BiasedRttPathSelector is the default [PathSelector]. It sorts paths by
(tier, biased RTT): the primary tier always beats the backup tier, and within
a tier the lowest biased RTT wins. IPv6 paths receive a [IPv6RttAdvantage]
bias. Switching within a tier requires the candidate's biased RTT to be at
least [RttSwitchingMin] better than the current path (no flapping); switching
across tiers is immediate.
It mirrors the Rust BiasedRttPathSelector
(iroh/src/socket/biased_rtt_path_selector.rs:135).
The zero value is ready to use. Select implements [PathSelector]. It returns the best candidate to use, or
ok=false to keep the current selection. The decision follows the Rust
single-pass algorithm (biased_rtt_path_selector.rs:136): find the
lowest-keyed candidate and the lowest key seen for the current path, then
switch across tiers immediately and within a tier only when the improvement
meets [RttSwitchingMin].
BiasedRttPathSelector : PathSelector
Connection is the minimal view of a QUIC connection the [RemoteStateActor]
needs. The iroh package adapts a qng *quic.Conn to it; tests use a fake. It
stays small on purpose: the actor only reads liveness and RTT.
SmoothedRTT returns the connection's active-path smoothed RTT. Done is closed
when the connection ends. RemoteAddr reports the path the connection is on,
so the actor can register it as a candidate path. Done is closed when the connection is closed. RemoteAddr returns the transport address the connection is using. SmoothedRTT returns the smoothed round-trip time of the active path.
func (*RemoteMap).AddConnection(remote key.EndpointID, conn Connection) <-chan PathEvent
func (*RemoteMap).AddConnectionActor(remote key.EndpointID, conn Connection) (<-chan PathEvent, *RemoteStateActor)
func (*RemoteStateActor).AddConnection(conn Connection) (events <-chan PathEvent, ok bool)
func (*RemoteStateActor).PathInfos(conn Connection) []PathInfo
func (*RemoteStateActor).TriggerHolepunchConn(conn Connection) error
CustomTransport is a pluggable transport backend for custom addresses. It is
intentionally small: the transport owns its wire format and reports datagrams
as iroh custom addresses for the magic socket to map into qng paths. Send sends p to remote. local is nil when qng did not select a specific
local custom address for the path. Serve runs the transport until ctx is done. Each received datagram should
be passed to recv. recv reports false when the magic socket is shutting
down or its receive queue is full.PacketTransport(interface)
func NewMagicConnRelayOnly(sock *Socket, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewMagicConnWithTransports(sock *Socket, udp *net.UDPConn, actor *RelayActor, custom ...CustomTransport) *MagicConn
EndpointIDMappedAddr addresses a remote endpoint via any/all of its paths. It
is used for the initial connection, before a path is selected: the socket
duplicates datagrams sent here onto every candidate path. Addr returns the underlying IPv6 address. AddrPort returns the mapped address with the fixed dummy port, suitable for
handing to quic-go as a path's net.Addr.
func EndpointIDMappedAddrFromAddr(a netip.Addr) EndpointIDMappedAddr
func NewEndpointIDMappedAddr() EndpointIDMappedAddr
func (*Socket).EndpointIDMappedAddrFor(id key.EndpointID) EndpointIDMappedAddr
func (*Socket).LookupEndpointID(m EndpointIDMappedAddr) (key.EndpointID, bool)
IpTransport is the direct-UDP transport: it reads datagrams from a
net.PacketConn and forwards them to the [MagicConn]'s recv channel, and sends
datagrams the magic socket routes to it. It is the Go analog of the Rust
IpTransport (iroh/src/socket/transports/ip.rs).
Create one with [NewIpTransport] and start its recv loop with [IpTransport.Serve]. LocalAddr returns the bound local address of the underlying socket. Serve runs the receive loop until ctx is cancelled or the socket is closed.
Each datagram is delivered to the recv channel tagged with its real remote IP
address (canonicalized: an IPv4-mapped IPv6 source becomes plain IPv4, to
match iroh/src/socket/transports/ip.rs:221 to_canonical). Empty datagrams and
transient errors are skipped; a closed socket ends the loop cleanly.
func NewIpTransport(conn *net.UDPConn, recvCh chan<- recvBatch) *IpTransport
MagicConn is the single net.PacketConn handed to a quic-go Transport. It
presents every iroh network path — direct IP, relay, custom — as one UDP
socket, mapping non-IP paths to synthetic IPv6 ULAs so quic-go can address
them. It is the Go analog of the Rust `impl AsyncUdpSocket for Transport`
(iroh/src/socket/transports.rs:1067).
MagicConn satisfies net.PacketConn. It deliberately does not satisfy
quic-go's OOBCapablePacketConn: GRO and ECN receive metadata do not
generalize across relay and custom transports. On Linux it exposes a narrower
send-message method so qng can use GSO for direct IP destinations and split
the same write for other transports. Correctness does not depend on it.
Create one with [NewMagicConn] and start it with [MagicConn.Serve]. The zero
value is not usable. Close releases the magic socket. It marks the shared [Socket] closed and
closes the underlying UDP socket, which ends the receive loop. It implements
net.PacketConn. LocalAddr returns the bound local address of the underlying UDP socket. It
implements net.PacketConn. Metrics returns a point-in-time copy of magic-socket counters. MetricsSet returns the shared magic-socket counter set. ReadFrom delivers the next datagram from any transport into p, returning its
length and the net.Addr quic-go should associate with the path it arrived on.
For IP paths that addr is the real remote IP; for relay and custom paths it is
the synthetic mapped IPv6 ULA (port 12345). It implements net.PacketConn. RecordRelayHomeChange increments the relay-home change counter. Relay returns the relay transport, or nil if no relay actor was configured. SendAddr routes p to one concrete magic-socket transport address. It is used
by RemoteStateActor endpoint-id fanout. Serve runs the magic socket's receive loops until ctx is cancelled or the
underlying socket is closed. It blocks; run it in its own goroutine. SetDeadline sets both the read and write deadlines. It implements
net.PacketConn. SetEndpointSender sets the callback used for endpoint-id mapped addresses.
The callback should route p through the remote endpoint's actor and report
whether it accepted the datagram. A nil callback restores blackhole behavior. SetReadBuffer sets the kernel receive buffer size on the underlying UDP
socket. quic-go calls it to raise the buffer to its desired size. SetReadDeadline sets the deadline for future ReadFrom calls. It implements
net.PacketConn. SetWriteBuffer sets the kernel send buffer size on the underlying UDP socket. SetWriteDeadline sets the deadline for future WriteTo calls. Writes go
straight to the underlying socket, so the deadline is applied there. It
implements net.PacketConn. SyscallConn returns the underlying UDP socket's raw connection. quic-go uses
it to size the kernel receive buffer and to set the Don't Fragment bit on the
direct-IP path. Exposing it does not make MagicConn an OOBCapablePacketConn.
On Linux qng combines it with MagicConn's send-message method for send-side
GSO only. WriteMsgUDP writes a possibly segmented datagram. Direct IP destinations use
the kernel's UDP_SEGMENT path. Other transports receive one datagram per
segment through the ordinary magic-socket router. WriteTo routes p to the transport addressed by addr and reports success.
addr is classified by [Classify]: a real IP routes to the IP transport; the
EndpointID, relay, and custom mapped ULAs route to their transports. A send to
a path with no live transport, an unknown mapped address, or a closed socket
is blackholed — WriteTo still returns (len(p), nil). quic-go observes the send
as successful and its loss recovery retransmits the lost datagram, matching
the Rust Sender::poll_send blackhole invariant
(iroh/src/socket/transports.rs:1176).
*MagicConn : github.com/pion/datachannel.ReadDeadliner
*MagicConn : github.com/pion/datachannel.WriteDeadliner
*MagicConn : github.com/prometheus/common/expfmt.Closer
*MagicConn : io.Closer
*MagicConn : net.PacketConn
*MagicConn : syscall.Conn
func NewMagicConn(sock *Socket, udp *net.UDPConn) *MagicConn
func NewMagicConnRelayOnly(sock *Socket, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewMagicConnWithRelay(sock *Socket, udp *net.UDPConn, actor *RelayActor) *MagicConn
func NewMagicConnWithTransports(sock *Socket, udp *net.UDPConn, actor *RelayActor, custom ...CustomTransport) *MagicConn
PacketTransport is a custom transport that owns received packet buffers. Send sends p to remote. local is nil when qng did not select a specific
local custom address for the path. SendPacket sends p to remote. The transport must not retain p after the
call returns. Serve runs the transport until ctx is done. Each received datagram should
be passed to recv. recv reports false when the magic socket is shutting
down or its receive queue is full. ServePackets runs the transport until ctx is done. Received packets are
owned by the transport until their Free callback runs.
PacketTransport : CustomTransport
PathCandidate is one path offered to a [PathSelector], pairing its [Addr] with
the most recent RTT observed for it. It is the Go analog of the Rust
PathSelectionData (biased_rtt_path_selector.rs). Addr is the path's transport address. RTT is the smoothed round-trip time observed on the path.
qng multipath paths use per-path RTT when available; otherwise the socket
layer falls back to connection-level active-path RTT.
func BiasedRttPathSelector.Select(current *Addr, candidates []PathCandidate) (Addr, bool)
func PathSelector.Select(current *Addr, candidates []PathCandidate) (selected Addr, ok bool)
PathEvent is a lifecycle notification for a network path of a connection. It
is the Go analog of the Rust PathEvent enum (path_watcher.rs:55).
For Opened, Closed, and Selected, Addr identifies the path. For Lagged, Missed
is the number of events the subscriber missed and Addr is the zero value. Addr is the path's transport address (zero for Lagged). Kind is which kind of event this is. Missed is the number of dropped events (only for Lagged).
func (*PathWatcher).Subscribe() (<-chan PathEvent, func())
func (*RemoteMap).AddConnection(remote key.EndpointID, conn Connection) <-chan PathEvent
func (*RemoteMap).AddConnectionActor(remote key.EndpointID, conn Connection) (<-chan PathEvent, *RemoteStateActor)
func (*RemoteStateActor).AddConnection(conn Connection) (events <-chan PathEvent, ok bool)
func (*RemoteStateActor).PathEvents() (<-chan PathEvent, func())
func (*PathWatcher).Send(ev PathEvent)
PathInfo is qng multipath path state observed through a [Connection]. Addr and
RTT are set only when qng reports them; socket must not fabricate Addr from
the connection's original RemoteAddr. Addr is the path's transport address, when HasAddr is true. BytesInFlight is the path's current application-data bytes in flight,
when HasBytesInFlight is true. BytesReceived is the cumulative application-data bytes received on this
path, when HasBytesReceived is true. BytesSent is the cumulative application-data bytes sent on this path,
when HasBytesSent is true. CongestionWindow is the path's current congestion window, when
HasCongestionWindow is true. HasAddr reports whether Addr was observed from qng route metadata. HasBytesInFlight reports whether BytesInFlight was observed from qng
per-path state. HasBytesReceived reports whether BytesReceived was observed from qng
per-path state. HasBytesSent reports whether BytesSent was observed from qng per-path
state. HasCongestionWindow reports whether CongestionWindow was observed from qng
per-path state. HasLoss reports whether LostPackets and LostBytes were observed from qng
per-path state. HasRTT reports whether RTT was observed from qng per-path state. ID is the QUIC multipath PathID. LostBytes is the number of application-data bytes declared lost on this
path, when HasLoss is true. LostPackets is the number of application-data packets declared lost on
this path, when HasLoss is true. RTT is the path's smoothed round-trip time, when HasRTT is true. Selected reports whether this path is currently selected for application
data transmission. Validated reports whether the path can carry non-probing application data.
func (*RemoteStateActor).MultipathPaths() []PathInfo
func (*RemoteStateActor).PathInfos(conn Connection) []PathInfo
PathSelector chooses the preferred path among the candidates for a remote
endpoint. It is a pure function of the candidate set and the currently
selected path. Implementations must not block.
It is the Go analog of the Rust PathSelector trait
(iroh/src/socket/remote_map/remote_state.rs). The default implementation is
[BiasedRttPathSelector]. Select returns the address of the path to use, or ok=false to keep the
current selection (including keeping no selection). current is the
currently selected path, if any.BiasedRttPathSelector
func NewRemoteMap(ctx context.Context, selector PathSelector, resolve ResolveFunc) *RemoteMap
func NewRemoteMapWithMetrics(ctx context.Context, selector PathSelector, resolve ResolveFunc, metrics *Metrics) *RemoteMap
PathState is the per-path bookkeeping kept by [RemotePathState]. Status is the current lifecycle status of the path.
PathWatcher is a drop-oldest broadcast of [PathEvent]s to any number of
subscribers. Each subscriber has its own ring buffer of [PathBroadcastCapacity]
events; when a subscriber falls behind, the oldest buffered event is dropped
and the next event the subscriber receives is a [PathEventLagged] with the
running missed count, mirroring tokio::broadcast's lagged-receiver behavior
(path_watcher.rs).
PathWatcher is safe for concurrent use. The writer calls [PathWatcher.Send];
readers call [PathWatcher.Subscribe] and consume the returned channel. Each
subscriber is served by a dedicated delivery goroutine that stops when the
subscriber is cancelled or the watcher is closed. Close stops every subscriber's delivery goroutine, closing its channel, and
rejects future sends and subscriptions. It is idempotent. It is the analog of
dropping the Rust broadcast sender, which ends every outstanding receiver. Send broadcasts ev to every subscriber. A subscriber whose ring buffer is full
has its oldest pending event dropped and its missed counter incremented; the
next event that subscriber receives is a [PathEventLagged] carrying the missed
count. Send never blocks. Subscribe registers a new subscriber and returns the channel its events are
delivered on plus a function to unsubscribe and stop delivery. Events sent
before Subscribe are not replayed. The channel is closed when the subscriber
is cancelled or the watcher is closed.
The cancel function should be called when the subscriber is done, like
[time.Ticker.Stop]: each subscription runs a delivery goroutine, which
cancel stops without waiting for the subscriber to drain. [PathWatcher.Close]
stops the goroutine of every remaining subscriber, so an abandoned
subscription outlives at most the watcher itself. Events already buffered on
the channel stay readable after it is closed; events still pending delivery
when a subscriber stops reading are dropped.
func NewPathWatcher() *PathWatcher
RecvInfo carries the per-datagram metadata a transport reports alongside the
payload: the remote [Addr] it came from and, for custom transports, the local
custom address that received it. It mirrors the Rust RecvInfo
(iroh/src/socket/transports.rs:572). For IP and relay paths Local is the zero
value. HasLocal reports whether Local is set (custom transports only).Localnetaddr.CustomAddrRemoteAddr
RelayActor manages connections to relay servers. It starts one [activeRelay]
per relay URL on demand, routes outgoing datagrams to the right one, and
surfaces received datagrams on a single queue. It tracks the home relay and
publishes its status through a [watch.Value].
It is the Go analog of the Rust RelayActor
(iroh/src/socket/transports/relay/actor.rs:855). Create one with
[NewRelayActor] and start it with [RelayActor.Run]. HomeRelayStatus returns a watcher over the home relay's connection status. The
value is nil until a home relay is set with [RelayActor.SetHomeRelay]. InsertRelay adds or replaces url's relay configuration, returning the
previous config when one existed. If there is no home relay, url becomes home. Recv returns the queue of datagrams received from relays. A [RelayTransport]
drains it; the channel is closed when the actor stops. RemoveRelay removes url's configuration, returning it when present. Any live
non-home connection to url is stopped. If url was the home relay, the next
configured relay (if any) becomes home. Run drives the actor until ctx is cancelled. It starts active relays on demand
from queued send items. It blocks; run it in its own goroutine. When it
returns it has closed the recv channel and stopped all active relays. Send queues item for delivery to its relay. It never blocks: if the queue is
full the item is dropped (treated as datagram loss so QUIC's loss recovery
retransmits), matching the Rust non-blocking send invariant
(iroh/src/socket/transports.rs:1176). Send reports whether the item was
queued; a false result is a dropped (lost) datagram, not an error. SetHomeRelay designates url as the home relay, ensuring an [activeRelay] for
it (which then never idles out) and demoting any previous home relay. A zero
url clears the home relay. It mirrors the Rust on_network_change /
set_home_relay path (iroh/src/socket/transports/relay/actor.rs:1126).
func NewRelayActor(cfg RelayActorConfig) *RelayActor
func NewMagicConnRelayOnly(sock *Socket, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewMagicConnWithRelay(sock *Socket, udp *net.UDPConn, actor *RelayActor) *MagicConn
func NewMagicConnWithTransports(sock *Socket, udp *net.UDPConn, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewRelayTransport(sock *Socket, actor *RelayActor, recvCh chan<- recvBatch) *RelayTransport
RelayActorConfig configures a [RelayActor].
SecretKey is required. The zero value is otherwise not usable; build a config
and pass it to [NewRelayActor]. Map is the relay map; consulted for per-relay auth tokens. SecretKey is the local endpoint's secret key, used to authenticate to
relays. Required.
func NewRelayActor(cfg RelayActorConfig) *RelayActor
RelayConnState is the connection state of a relay, published through the home
relay watcher. It is the Go analog of the Rust RelayConnectionState
(iroh/src/socket/transports/relay/actor.rs:897).( RelayConnState) String() string
RelayConnState : expvar.Var
RelayConnState : fmt.Stringer
const RelayConnected
const RelayConnecting
const RelayDisconnected
RelayRecvDatagram is a datagram received from a relay. It is the Go analog of
the Rust RelayRecvDatagram (iroh/src/socket/transports/relay/actor.rs:1383). Datagrams is the payload. Src is the endpoint that sent it. URL is the relay it arrived on.
func (*RelayActor).Recv() <-chan RelayRecvDatagram
RelaySendItem is one or more datagrams to send to a remote endpoint via a
relay. It is the Go analog of the Rust RelaySendItem
(iroh/src/socket/transports/relay/actor.rs:846). Datagrams is the payload. RemoteEndpoint is the destination endpoint. URL is the relay through which to reach RemoteEndpoint.
func (*RelayActor).Send(item RelaySendItem) bool
RelayStatus is the connection status of a single home relay, observed through
[RelayActor.HomeRelayStatus]. It is the Go analog of the Rust RelayStatus
(iroh/src/endpoint.rs:1832).
The zero value reports no home relay; use [RelayActor.HomeRelayStatus] to
observe it. LastError is the most recent connection error while disconnected, or nil. State is the current connection state. URL is the home relay URL. IsConnected reports whether the relay is connected.
RelayTransport is the magic socket's relay path: it owns a [RelayActor],
forwards datagrams received from relays into the [MagicConn]'s recv channel
(tagged so they surface as a [RelayMappedAddr]), and routes outgoing datagrams
addressed to a relay mapped address to the right relay connection.
It is the Go analog of the Rust RelayTransport
(iroh/src/socket/transports/relay.rs:31). Create one with [NewRelayTransport]
and start it with [RelayTransport.Serve]. The zero value is not usable. HomeRelayStatus returns a watcher over the home relay's connection status. See
[RelayActor.HomeRelayStatus]. InsertRelay adds or replaces a relay config in the underlying actor. RemoveRelay removes a relay config from the underlying actor. Send routes p to the relay addressed by the relay mapped address m. It looks
up the (relay url, endpoint id) pair m maps to and queues a datagram to the
relay actor. It reports whether the datagram was routed; a false result means
the address is unknown or the send queue was full, in which case the datagram
is treated as lost (QUIC's loss recovery retransmits), matching the Rust
blackhole-on-failure invariant (iroh/src/socket/transports.rs:1176). Serve runs the relay actor and the recv-forwarding loop until ctx is
cancelled. It blocks; run it in its own goroutine. SetHomeRelay designates url as the endpoint's home relay. See
[RelayActor.SetHomeRelay].
func NewRelayTransport(sock *Socket, actor *RelayActor, recvCh chan<- recvBatch) *RelayTransport
func (*MagicConn).Relay() *RelayTransport
RemoteMap is the registry of per-remote [RemoteStateActor]s, keyed by
[key.EndpointID]. It spawns an actor on first reference to a remote and
removes it when the actor idles out. It is the Go analog of the Rust RemoteMap
(iroh/src/socket/remote_map.rs).
Actor insertion and idle-teardown deregistration are serialized by a single
mutex, and an actor only removes itself if it is still the actor registered
under its id. So an AddConnection arriving exactly as the 60s idle timeout
fires yields exactly one actor: the teardown either runs first (the next
reference spawns a fresh actor) or the AddConnection runs first (which resets
the actor's idle timer, so it does not tear down). See [RemoteMap.ResolveRemote]
/ [RemoteMap.AddConnection] and the onExit closure in [RemoteMap.actor].
RemoteMap is safe for concurrent use. Create one with [NewRemoteMap]. Actor returns the running actor for id, spawning one if none exists. AddConnection registers conn with the actor for remote, spawning the actor if
needed, and returns the connection's path-event channel. Registering a
connection resets the actor's idle timer, so this can race the idle teardown
safely (O12): if the actor is mid-teardown the send observes its done channel
and a fresh actor is spawned on the retry. AddConnectionActor is like [RemoteMap.AddConnection], but also returns the
actor that accepted conn. AddNATTraversalAddresses reconciles local QNT candidates on currently-active
remote actors. It does not spawn actors and ignores per-actor errors, because
candidate updates must not make an established endpoint fail. DisableHolepunch stops actors from initiating NAT traversal or direct-path
validation on their upgrade tick. Endpoints without IP transports set it:
there is no direct path to punch toward, and a traversal round initiated on
a relay-only connection stalls its in-flight relay streams. Set it before
the first remote is referenced. Len returns the number of registered actors. Intended for tests and metrics. RemoteInfo returns a snapshot for id if a running actor exists. It does not
spawn a new actor. ResolveRemote asks the actor for addr.ID to resolve and register more
candidate paths, spawning the actor if needed. It returns the lookup error if
any. It races idle teardown the same way as [RemoteMap.AddConnection]. SetOnEvict sets f to be called when a remote's actor is reaped with no
successor, passing the remote's known path addresses. The endpoint uses it to
release the remote's mapped addresses (see [Socket.EvictRemote]), so the
mapped-address tables do not grow without bound under peer churn. f is called
with the map's internal mutex held and must not call back into the RemoteMap.
Set it before the first remote is referenced.
func NewRemoteMap(ctx context.Context, selector PathSelector, resolve ResolveFunc) *RemoteMap
func NewRemoteMapWithMetrics(ctx context.Context, selector PathSelector, resolve ResolveFunc, metrics *Metrics) *RemoteMap
RemotePathState tracks all candidate paths to a single remote endpoint:
direct IP, relay, and custom transport addresses, each with a [PathStatus].
It is the Go analog of the Rust RemotePathState (path_state.rs).
Paths added by address lookup start [PathStatusUnknown]; QUIC path events move
them through Open and Inactive; failed hole-punches mark them Unusable. The
set is bounded by [RemotePathState.Prune], which keeps at most
[MaxNonRelayPaths] non-relay paths plus [MaxInactiveNonRelayPaths] inactive
non-relay paths. Relay paths are never pruned.
RemotePathState is not safe for concurrent use; it is owned by a single
[RemoteStateActor] goroutine. Add records a candidate path with [PathStatusUnknown] if it is not already
known. A path already present keeps its current status. AddWithProvenance records a candidate path with lookup provenance. Addrs returns the addresses of all known paths in unspecified order. ExpireIdle closes open paths that have not been observed within their path
idle timeout. Direct and custom paths use [PathMaxIdleTimeout]; relay paths
use [RelayPathMaxIdleTimeout]. IsEmpty reports whether no paths are known. Len returns the number of known paths, including relay paths. OpenAddrs returns the addresses of all currently open paths. Prune bounds the non-relay path set. It is a no-op when there are fewer than
[MaxNonRelayPaths] non-relay paths. Otherwise it removes failed (unusable)
paths and all but the [MaxInactiveNonRelayPaths] most-recently-closed inactive
paths. Open and unknown paths are always kept; relay paths are never pruned or
counted. It mirrors prune_non_relay_paths (path_state.rs:254). RemoteAddrs returns all known remote addresses with active/inactive usage. SetClosed transitions addr toward an inactive/unusable status, recording the
close time for inactive pruning. It mirrors the Rust remove_path transition
(path_state.rs:106): an open or already-inactive path becomes inactive (still
considered usable later); an unusable or unknown path becomes unusable. SetOpen marks addr as open, adding it if unknown. It mirrors the Rust
add_path / on path-open transition (path_state.rs:90). SetOpenAt marks addr as open with an explicit activity time. It is used by
tests and by the actor heartbeat, which already has a shared timestamp for
all observed paths. SetUnusable marks addr unusable: a hole-punch was attempted and failed. Status returns the status of addr and whether it is known.
func NewRemotePathState() *RemotePathState
RemoteStateActor manages all connection and path state for a single remote
endpoint. Exactly one goroutine runs per remote, driven by a single select
loop over the inbox (which carries add-connection, resolve, and
connection-closed messages) and timers (heartbeat, upgrade, idle teardown). It
is the Go analog of the Rust RemoteStateActor
(iroh/src/socket/remote_map/remote_state.rs).
The actor does not build NAT traversal frames itself. It advertises vetted
local candidates and asks qng to start traversal rounds; qng owns probe
timers, response matching, and route-bearing path opening. Path selection is
driven by qng path observability.
Create an actor with the RemoteMap; do not construct one directly. AddConnection registers conn with the actor and returns a channel of path
events for it. ok is false if the actor stopped before it could register the
connection; the caller should retry with a fresh actor. The returned channel
is closed when the connection closes or the actor stops; the subscription's
lifetime is managed by the actor, so the caller may simply stop reading. AddNATTraversalAddresses reconciles the full local QNT candidate set for
active qng connections. Candidate discovery stays outside this method:
callers must pass already-vetted local candidates, such as endpoint-bound
direct addresses and QAD reflexive addresses. qng owns QNT state, wire frames,
probe timers, and eventual path opening. AddRemoteNATTraversalAddresses seeds remote QNT candidates from an
authenticated endpoint address, such as the address used to dial the peer. ID returns the remote endpoint this actor manages. MultipathPaths returns qng multipath path state observed from active
connections. Paths with explicit qng route metadata are also registered with
RemotePathState by the actor loop and can produce path events. NATTraversalAddresses returns the remote QNT ADD_ADDRESS set observed on
active qng connections. Duplicate addresses are removed in first-seen order. PathEvents returns a fresh subscription to this actor's path events and a
function to cancel it. PathInfos returns a snapshot of currently open paths for conn. RemoteInfo returns a snapshot of known addresses for this remote endpoint. ResolveRemote asks the actor to resolve more addresses for addr via the
[ResolveFunc] and register them as candidate paths as they arrive. It returns
once the resolver stream has been started. With no resolver and no addrs it
returns nil immediately. SelectedPath returns the actor's currently selected path and whether one is
selected. It is safe to call concurrently with the actor loop. SendDatagram routes a datagram toward the remote via send. If a path is
selected it sends there; otherwise it sends to every known path. It NEVER
returns an error for an unreachable path: an unroutable datagram is treated as
lost so QUIC loss recovery handles it (the socket-core blackhole invariant,
iroh/src/socket/remote_map/remote_state.rs:782). send's bool result is
advisory only.
qng addresses datagrams to a concrete path directly through the MagicConn, so
this method backs the Mixed-EndpointID send path, which is exercised by unit
tests rather than the QUIC data plane in this slice. TriggerHolepunch attempts to open a new direct path by NAT traversal. It is
gated on an active qng connection with QNT support: socket advertises its
already-known local candidates and asks qng to initiate one NAT traversal
round. qng owns QNT frames, probe timers, response matching, and path opening. TriggerHolepunchConn attempts NAT traversal on conn. It returns
[context.Canceled] if conn is no longer registered, or
[ErrExtensionNotNegotiated] if conn does not support QNT. ValidateDirectPath asks qng to open and validate one ordinary multipath path
over the current direct socket. This is the RFC 9000 path-validation path used
before or independent of QNT-discovered NAT candidates.
func (*RemoteMap).Actor(id key.EndpointID) *RemoteStateActor
func (*RemoteMap).AddConnectionActor(remote key.EndpointID, conn Connection) (<-chan PathEvent, *RemoteStateActor)
ResolveFunc streams additional transport addresses for a remote endpoint. It
is supplied by the iroh package (which owns the address-lookup services) so
the socket package does not import iroh. A nil ResolveFunc disables
lookup-driven resolution.
It is the hook for the Rust RemoteStateActor::resolve_remote path
(remote_state.rs:843), wired in slice G's address lookup.
func NewRemoteMap(ctx context.Context, selector PathSelector, resolve ResolveFunc) *RemoteMap
func NewRemoteMapWithMetrics(ctx context.Context, selector PathSelector, resolve ResolveFunc, metrics *Metrics) *RemoteMap
Socket holds the magic socket's mapped-address tables: the bidirectional maps
between transport addresses and the synthetic IPv6 ULAs that quic-go uses to
address paths. It is the Go analog of the Rust Socket's mapped_addrs
(iroh/src/socket.rs:332).
A Socket is created by [NewSocket] and shared by a [MagicConn] and its
[Transports]. It is safe for concurrent use. The zero Socket is not usable;
use [NewSocket]. Close marks the socket closed. Subsequent sends are dropped (blackholed) so
quic-go's loss recovery handles in-flight datagrams rather than seeing a hard
error. It is idempotent. CustomMappedAddrFor returns the custom mapped address for c, allocating one on
first use and recording the reverse mapping back to c. EndpointIDMappedAddrFor returns the endpoint-id mapped address for id,
allocating one on first use. EvictRemote drops the mapped addresses recorded for a reaped remote: the
endpoint-id mapping for id, every relay mapping whose remote endpoint is id,
and the custom mappings among addrs (the remote's known transport
addresses). Without eviction the tables grow without bound under peer churn
(the upstream Rust implementation has the same leak, iroh issue #4293). A
mapping is regenerated on the next use of the same key, so evicting a remote
that immediately returns only costs a fresh mapped address. IsClosed reports whether the socket has been closed. LookupCustom returns the custom address for a custom mapped address, if known. LookupEndpointID returns the endpoint id for an endpoint-id mapped address, if
known. LookupRelay returns the (url, eid) pair for a relay mapped address, if known. PathAddr classifies a QUIC connection's remote net.Addr into the magic
socket's transport [Addr]: a real IP becomes an IP path; a relay or custom
mapped ULA is reverse-looked-up through the mapped-address tables. An unknown
mapped address (or one whose mapping has been forgotten) falls back to an IP
path so the per-remote actor still tracks a stable address. remoteID is used
for relay paths, which are keyed by (relay url, endpoint id). RelayMappedAddrFor returns the relay mapped address for the (url, eid) pair,
allocating one on first use.
func NewSocket() *Socket
func NewMagicConn(sock *Socket, udp *net.UDPConn) *MagicConn
func NewMagicConnRelayOnly(sock *Socket, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewMagicConnWithRelay(sock *Socket, udp *net.UDPConn, actor *RelayActor) *MagicConn
func NewMagicConnWithTransports(sock *Socket, udp *net.UDPConn, actor *RelayActor, custom ...CustomTransport) *MagicConn
func NewRelayTransport(sock *Socket, actor *RelayActor, recvCh chan<- recvBatch) *RelayTransport
Transports multiplexes the magic socket's network paths: a direct-IP
transport plus optional relay and custom transports. It is the Go analog of
the Rust Transports struct (iroh/src/socket/transports.rs:47).
The IP transport is nil for relay-only endpoints. The relay transport is
present when the endpoint has relays configured; otherwise relay-addressed
sends are blackholed (reported as success so quic-go's loss recovery
retransmits). Custom transports are present only when callers configure them.
Package-Level Functions (total 24)
Classify reports which mapped kind addr belongs to, or KindIP if it is a real
address. The order matches the Rust MultipathMappedAddr::from conversion.
CustomAddr returns an [Addr] for a custom-transport path.
CustomMappedAddrFromAddr wraps an existing custom mapped IPv6 address. It is
used to reverse-look-up the custom address via [Socket.LookupCustom].
EndpointIDMappedAddrFromAddr wraps an existing endpoint-id mapped IPv6
address. It is used to reverse-look-up the endpoint id via
[Socket.LookupEndpointID].
IPAddr returns an [Addr] for a direct IP path. The address is canonicalized
so an IPv4-mapped IPv6 address becomes a plain IPv4 address, matching Rust's
SocketAddr -> Addr conversion (iroh/src/socket/transports.rs:825).
Type Parameters:
K: comparable
V: comparable NewAddrMap returns an AddrMap whose missing keys are filled with gen(), keyed
in reverse by addrOf(value).
NewCustomMappedAddr allocates a fresh custom mapped address.
NewEndpointIDMappedAddr allocates a fresh endpoint-id mapped address.
NewIpTransport returns an IpTransport over conn that delivers received
datagrams to recvCh. The transport does not take ownership of conn; the caller
closes it.
NewMagicConn returns a MagicConn whose sole transport is an [IpTransport]
bound to udp. sock holds the mapped-address tables shared with the transports.
Start the receive loop with [MagicConn.Serve] before handing the MagicConn to
a quic-go Transport.
NewMagicConnRelayOnly returns a MagicConn with no direct-IP transport. Relay
and custom transports are still available. Start the receive loops with
[MagicConn.Serve].
NewMagicConnWithRelay returns a MagicConn with an IP transport over udp and,
if actor is non-nil, a relay transport driven by it. Datagrams received from
relays surface through [MagicConn.ReadFrom] as a [RelayMappedAddr]; sends to a
relay mapped address route to the actor. Start the receive loops with
[MagicConn.Serve].
NewMagicConnWithTransports returns a MagicConn with direct IP, optional relay,
and optional custom transports.
NewPathWatcher returns an empty broadcast with no subscribers.
NewRelayActor returns a RelayActor ready to be started with [RelayActor.Run].
NewRelayMappedAddr allocates a fresh relay mapped address.
NewRelayTransport returns a RelayTransport that drives actor and delivers
received relay datagrams to recvCh. sock supplies the relay mapped-address
table shared with the [MagicConn]. The transport does not start the actor;
call [RelayTransport.Serve].
NewRemoteMap returns a RemoteMap whose actors live until ctx is cancelled or
they idle out. selector is the path selector shared by all actors (nil uses
[BiasedRttPathSelector]); resolve is the address-lookup hook (nil disables
lookup-driven resolution).
NewRemoteMapWithMetrics is like [NewRemoteMap], but records actor path
lifecycle counters in metrics.
NewRemotePathState returns an empty path-state tracker.
NewSocket returns a ready Socket with empty mapped-address tables.
RelayAddr returns an [Addr] for a relay path reaching eid through url.
RelayMappedAddrFromAddr wraps an existing relay mapped IPv6 address. It is
used to reverse-look-up the (relay, endpoint) pair an address maps to via
[Socket.LookupRelay]; it does not allocate a new mapping.
SnapshotPerformanceStats returns zero counters in an ordinary build.
Package-Level Variables (only one)
ErrExtensionNotNegotiated is returned by hole-punching and other operations
that depend on a QUIC extension that is not negotiated on an active
connection. Endpoint defaults advertise qng multipath; QNT/DISCO
hole-punching is still gated separately.
Package-Level Constants (total 32)
ActorMaxIdleTimeout is how long an actor with no connections stays alive
before it exits and deregisters. remote_state.rs:74.
AddrCustom is a custom-transport path.
AddrIP is a direct IP address path.
AddrRelay is a relay path, identified by a relay URL and endpoint id.
GoodEnoughLatency is the RTT at or under which a direct path is considered
good enough that the actor does not try to upgrade to a better path.
HeartbeatInterval is how often the actor wakes to keep paths alive and
re-evaluate path selection. remote_state.rs HEARTBEAT_INTERVAL / socket.rs.
HolepunchAttemptsInterval throttles hole-punch attempts when the NAT
candidate set has not changed. remote_state.rs:52.
IPv6RttAdvantage is how much lower an IPv6 path's biased RTT is made,
expressing a default preference for IPv6 over IPv4.
KindCustom is a CustomMappedAddr.
KindEndpointID is an EndpointIDMappedAddr.
KindIP is a real (non-mapped) IP address.
KindRelay is a RelayMappedAddr.
MaxInactiveNonRelayPaths is the maximum number of inactive (previously
open, now closed) non-relay paths kept per remote.
MaxNonRelayPaths is the maximum number of non-relay paths kept per remote.
PathBroadcastCapacity is the per-subscriber buffer capacity for path events. A
subscriber that falls more than this many events behind is told how many it
missed via a [PathEventLagged] event rather than silently dropping. It matches
the Rust BROADCAST_CAPACITY
(iroh/src/socket/remote_map/remote_state/path_watcher.rs:50).
PathEventClosed reports a closed network path.
PathEventLagged reports that events were dropped before a subscriber read
them; Missed carries the count.
PathEventOpened reports a newly-opened network path.
PathEventSelected reports that a path was selected for transmission.
PathMaxIdleTimeout is the idle timeout for a non-relay path.
iroh/src/socket.rs PATH_MAX_IDLE_TIMEOUT.
PathStatusInactive is a path that was open at some point but has since
closed. The time records when it closed, used to prune oldest-first.
PathStatusOpen is a path that is currently open in QUIC.
PathStatusUnknown is a path that has never been dialed: it was added by an
address-lookup mechanism and is only potentially usable.
PathStatusUnusable is a path where hole-punching was attempted and failed.
RelayConnected means the connection is established and handshaked.
RelayConnecting means the actor is dialing or handshaking.
RelayDisconnected means there is no connection: an attempt failed or a
previously-established connection was lost.
RelayPathMaxIdleTimeout is the idle timeout for a relay path.
iroh/src/socket.rs RELAY_PATH_MAX_IDLE_TIMEOUT.
RttSwitchingMin is the minimum biased-RTT improvement required to switch
to a different path in the same tier. It prevents flapping under jitter.
TransportAddrActive means the address is currently used.
TransportAddrInactive means the address is known but not currently used.
UpgradeInterval is how often the actor tries to upgrade to a better path
even when a working non-relay route exists. remote_state.rs:66.
The pages are generated with Goldsv0.8.4. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.