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
- Variables
- type APIClient
- type BindPublisher
- type BindRequest
- type Error
- type Handshake
- type LocalAddresses
- type MockAPIClient
- func (_m *MockAPIClient) Addresses(ctx context.Context) string
- func (_m *MockAPIClient) BindQUIC(ctx context.Context, port string) error
- func (_m *MockAPIClient) BindSTCPR(ctx context.Context, port string) error
- func (_m *MockAPIClient) BindSUDPH(filter *pfilter.PacketFilter, handshake Handshake) (<-chan RemoteVisor, error)
- func (_m *MockAPIClient) BindWT(ctx context.Context, port string, certHash string) error
- func (_m *MockAPIClient) Close() error
- func (_m *MockAPIClient) LocalPublicIP() string
- func (_m *MockAPIClient) Resolve(ctx context.Context, netType string, pk cipher.PubKey) (VisorData, error)
- func (_m *MockAPIClient) SetPublicIP(publicIP string, publicIPv6 string)
- func (_m *MockAPIClient) Transports(ctx context.Context) (map[cipher.PubKey][]string, error)
- func (_m *MockAPIClient) TransportsType(ctx context.Context, tpType types.Type) (map[cipher.PubKey][]string, error)
- type RemoteVisor
- type SUDPHBinder
- type VisorData
Constants ¶
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 ¶
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))
// SetCXOKeepaliveHealthyFunc installs fn (or clears it with nil). While fn
// reports healthy on the epoch of the last accepted bind, an unchanged
// re-bind skips the HTTP POST.
SetCXOKeepaliveHealthyFunc(fn func() (healthy bool, epoch uint64))
}
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 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 ¶
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 ¶
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 ¶
Transports provides a mock function with given fields: ctx
type RemoteVisor ¶
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.