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

addrresolver

package
v1.3.97 Latest Latest
Warning

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

Go to latest
Published: Sep 27, 2026 License: AGPL-3.0 Imports: 22 Imported by: 2

Documentation

Overview

Package addrresolver pkg/transport/network/addrresolver/client.go c2-net-transport

Package addrresolver pkg/transport/network/addrresolver/client_sudph.go c2-net-transport

SUDPH (UDP hole-punching) is the only part of the AR client that pulls in github.com/AudriusButkevicius/pfilter (and, transitively, quic-go) and xtaci/kcp-go. A browser visor can neither open a UDP socket nor run SUDPH, so these methods — and the pfilter-typed BindSUDPH — are build-tagged out of the js/wasm build. The rest of the AR client (bind/resolve over HTTP-over- dmsg, used to look up stcpr/quic/wt peers) stays platform-neutral in client.go. Callers that need SUDPH type-assert the APIClient to SUDPHBinder.

Index

Constants

View Source
const (

	// UDPKeepHeartbeatMessage is used as a heartbeat packet to keep connection alive.
	UDPKeepHeartbeatMessage = "heartbeat"

	// UDPDelBindMessage is used as a deletebind packet on visor shutdown.
	UDPDelBindMessage = "delBind"
)

Variables

View Source
var (
	// ErrNoEntry means that there exists no entry for this PK.
	ErrNoEntry = errors.New("no entry for this PK")
	// ErrNotReady is returned when address resolver is not ready.
	ErrNotReady = errors.New("address resolver is not ready")
	// ErrNoTransportsFound returned when no transports are found.
	ErrNoTransportsFound = errors.New("failed to get response data from AR transports endpoint")
)

Functions

This section is empty.

Types

type APIClient

type APIClient interface {
	BindSTCPR(ctx context.Context, port string) error
	BindQUIC(ctx context.Context, port string) error
	// BindWT registers this visor's WebTransport UDP port and the SHA-256 hex of
	// its self-signed cert (the hash dialing peers pin). Mirrors BindQUIC + the
	// cert hash.
	BindWT(ctx context.Context, port, certHash string) error
	Resolve(ctx context.Context, netType string, pk cipher.PubKey) (VisorData, error)
	Transports(ctx context.Context) (map[cipher.PubKey][]string, error)
	TransportsType(ctx context.Context, tpType types.Type) (map[cipher.PubKey][]string, error)
	Addresses(ctx context.Context) string
	LocalPublicIP() string
	// SetPublicIP records the visor's externally-reachable IPs once they have
	// been determined asynchronously (so the control plane need not wait on
	// the dmsg/STUN lookup). Passing empty strings signals "determination
	// finished, none available" and unblocks any pending bind.
	SetPublicIP(publicIP, publicIPv6 string)
	Close() error
}

APIClient implements address resolver API client.

func NewHTTP

func NewHTTP(remoteAddr string, pk cipher.PubKey, sk cipher.SecKey, httpC, httpCV6 *http.Client, clientPublicIP, clientPublicIPv6 string, log *logging.Logger, mLog *logging.MasterLogger) (APIClient, error)

NewHTTP creates a new client setting a public key to the client to be used for auth. When keys are set, the client will sign request before submitting. The signature information is transmitted in the header using: * SW-Public: The specified public key. * SW-Nonce: The nonce for that public key. * SW-Sig: The signature of the payload + the nonce.

When remoteAddr uses the dmsg:// scheme the URL host is a public key, not an IP, so it cannot be UDP-resolved for SUDPH. In that case the UDP target is left empty here and resolved from the AR's /health (udp_address field) once the auth client is ready. ARs that don't publish udp_address simply leave SUDPH unavailable to dmsg-only callers — the same behavior as before this change.

type BindPublisher

type BindPublisher interface {
	// SetBindPublishHook installs fn (or clears it with nil). fn is called
	// with the canonical transport-type wire name ("stcpr", "sudph",
	// "squicr", "swtr") and the LocalAddresses the visor just registered.
	SetBindPublishHook(fn func(netType string, payload LocalAddresses))
}

BindPublisher is the optional extension a caller type-asserts the APIClient to in order to mirror AR bindings onto a side channel (the CXO AR-bind feed). Only the httpClient implements it; keeping it off APIClient avoids touching the mock and the TinyGo-facing client variants (mirrors how SUDPHBinder is an optional extension).

type BindRequest

type BindRequest struct {
	Port string `json:"port"`
}

BindRequest stores bind request values.

type Error

type Error struct {
	Error string `json:"error"`
}

Error is the object returned to the client when there's an error.

type Handshake

type Handshake func(net.Conn) (net.Conn, error)

Handshake type is used to decouple client from handshake and network packages

type LocalAddresses

type LocalAddresses struct {
	Port      string   `json:"port"`
	Addresses []string `json:"addresses"`
	// PublicIP is the visor's STUN- or dmsg-derived public IPv4 address,
	// if known. AR uses this to override the observed source IP when the
	// latter is non-public (e.g., a visor running on the same Docker host
	// as AR reaches it via hairpin SNAT, so AR's UDP socket sees the
	// docker bridge gateway IP — 172.x.y.z — instead of the visor's
	// actual public IP). Old visors that don't set this field leave AR's
	// behavior unchanged: AR falls back to the observed source IP, which
	// is correct for any visor whose path to AR is not NAT'd into a
	// private space. Empty string means "let AR decide."
	//
	// Historical note: pre-#1525 this field carried either v4 or v6
	// indiscriminately. With Phase 2c, the convention is v4-only here;
	// PublicIPv6 carries v6. AR still accepts v6 in this field for
	// backward-compat with pre-Phase-2c visors.
	PublicIP string `json:"public_ip,omitempty"`
	// PublicIPv6 is the visor's declared IPv6 public address. Added in
	// #1525 Phase 2c so visors reaching AR via the dmsg-routed default
	// path (where AR observes the dmsg-bridge's source, not the visor's
	// own family) can still register their v6 endpoint. The AR populates
	// VisorData.RemoteAddrV6 from this field when the observed remote
	// source isn't v6. Empty when the visor is v4-only — preserves the
	// pre-Phase-2c single-stack contract.
	PublicIPv6 string `json:"public_ip_v6,omitempty"`
	// CertHash is the lowercase SHA-256 hex of the visor's self-signed
	// WebTransport certificate. WT has no CA; a dialing peer pins this hash. Only
	// the WT bind sets it (it rides VisorData via the embedded LocalAddresses, so
	// /resolve/wt returns it); empty for every other transport type.
	CertHash string `json:"cert_hash,omitempty"`
}

LocalAddresses contains outbound port and all network addresses of visor.

type MockAPIClient

type MockAPIClient struct {
	mock.Mock
}

MockAPIClient is an autogenerated mock type for the APIClient type

func NewMockAPIClient

func NewMockAPIClient(t interface {
	mock.TestingT
	Cleanup(func())
}) *MockAPIClient

NewMockAPIClient creates a new instance of MockAPIClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. The first argument is typically a *testing.T value.

func (*MockAPIClient) Addresses

func (_m *MockAPIClient) Addresses(ctx context.Context) string

Addresses provides a mock function with given fields: ctx

func (*MockAPIClient) BindQUIC

func (_m *MockAPIClient) BindQUIC(ctx context.Context, port string) error

BindQUIC provides a mock function with given fields: ctx, port

func (*MockAPIClient) BindSTCPR

func (_m *MockAPIClient) BindSTCPR(ctx context.Context, port string) error

BindSTCPR provides a mock function with given fields: ctx, port

func (*MockAPIClient) BindSUDPH

func (_m *MockAPIClient) BindSUDPH(filter *pfilter.PacketFilter, handshake Handshake) (<-chan RemoteVisor, error)

BindSUDPH provides a mock function with given fields: filter, handshake

func (*MockAPIClient) BindWT

func (_m *MockAPIClient) BindWT(ctx context.Context, port string, certHash string) error

BindWT provides a mock function with given fields: ctx, port, certHash

func (*MockAPIClient) Close

func (_m *MockAPIClient) Close() error

Close provides a mock function with no fields

func (*MockAPIClient) LocalPublicIP

func (_m *MockAPIClient) LocalPublicIP() string

LocalPublicIP provides a mock function with no fields

func (*MockAPIClient) Resolve

func (_m *MockAPIClient) Resolve(ctx context.Context, netType string, pk cipher.PubKey) (VisorData, error)

Resolve provides a mock function with given fields: ctx, netType, pk

func (*MockAPIClient) SetPublicIP

func (_m *MockAPIClient) SetPublicIP(publicIP string, publicIPv6 string)

SetPublicIP provides a mock function with given fields: publicIP, publicIPv6

func (*MockAPIClient) Transports

func (_m *MockAPIClient) Transports(ctx context.Context) (map[cipher.PubKey][]string, error)

Transports provides a mock function with given fields: ctx

func (*MockAPIClient) TransportsType

func (_m *MockAPIClient) TransportsType(ctx context.Context, tpType types.Type) (map[cipher.PubKey][]string, error)

TransportsType provides a mock function with given fields: ctx, tpType

type RemoteVisor

type RemoteVisor struct {
	PK   cipher.PubKey
	Addr string
}

RemoteVisor contains public key and address of remote visor.

type SUDPHBinder

type SUDPHBinder interface {
	APIClient
	BindSUDPH(filter *pfilter.PacketFilter, handshake Handshake) (<-chan RemoteVisor, error)
}

SUDPHBinder is APIClient plus the SUDPH bind entrypoint. The SUDPH transport (pkg/transport/network/sudph.go, itself !tinygo) type-asserts the resolver to this interface so the pfilter-typed method stays off the browser APIClient.

type VisorData

type VisorData struct {
	RemoteAddr   string `json:"remote_addr"`
	RemoteAddrV6 string `json:"remote_addr_v6,omitempty"`
	IsLocal      bool   `json:"is_local,omitempty"`
	LocalAddresses
}

VisorData stores visor data.

RemoteAddr is the visor's reachable IPv4 endpoint ("host:port"), observed by the AR server from the bind request's source socket (or carried via the visor's declared PublicIP). RemoteAddrV6 is the optional IPv6 counterpart, populated when the visor binds over an IPv6 HTTP client. A dual-stack visor calls bind twice (once per family) and the AR server merges into a single record; peers Resolve once and the dialer picks a family (v6 first per RFC 8305 with v4 fallback). Backward-compat: v4-only visors and older AR servers emit/store an empty RemoteAddrV6 and the rest of the pipeline behaves exactly as today.

Jump to

Keyboard shortcuts

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