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

visorcore

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: 19 Imported by: 0

Documentation

Overview

Package visorcore pkg/visor/visorcore/autoconnect.go c3-vis-core

Package visorcore pkg/visor/visorcore/autoconnect_backoff.go c3-vis-core

Per-target dial backoff for the autoconnect Connector. Offline public visors stay in the discovery lists for a long time, and without this every visor on the network re-dialed the same dead keys each cycle — several address-resolver lookups per attempt, fleet-wide (a third of the AR's load on 2026-09-10 was this plus self-lookups). The wait doubles per consecutive failure from dialBackoffMin up to dialBackoffMax and is forgotten on the first success. Keyed per (target, type): a visor that is unreachable over one carrier may still answer on another.

Package visorcore pkg/visor/visorcore/dmsg.go c3-vis-core

Package visorcore pkg/visor/visorcore/router.go c3-vis-core

Package visorcore pkg/visor/visorcore/services.go c3-vis-core native visor (pkg/visor) and the browser wasm-visor (cmd/wasm-visor), so the two stop diverging on how a visor is wired from its subsystems. It must stay LEAN — it may import pkg/dmsg, pkg/transport, pkg/router, pkg/app/appserver, deployment and visorconfig, but NOT pkg/visor itself (which pulls in the OS launcher / dmsgpty / HTTP-API code that does not compile under js/wasm). A `GOOS=js GOARCH=wasm go build ./pkg/visor/visorcore/` gate enforces that.

See docs/visor-core-convergence.md for the full design + incremental plan.

Package visorcore pkg/visor/visorcore/transport.go c3-vis-core

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildRouter

func BuildRouter(serveCtx context.Context, deps RouterDeps) (router.Router, error)

BuildRouter assembles router.Config from deps, creates the router, and starts it serving under serveCtx. router.Serve starts its goroutines and returns immediately, so its error is checked synchronously here — the browser edge previously fired it in a `go r.Serve(ctx)` goroutine that discarded the error. One place owns the Config field mapping + New + Serve, so the native visor and the wasm edge cannot drift on it (e.g. the MinHops==0 ⇒ "routing disabled" gotcha, or a newly-added Config field reaching only one of the two).

func BuildTransportManager

func BuildTransportManager(serveCtx context.Context, deps TransportManagerDeps) (*transport.Manager, error)

BuildTransportManager creates the transport.Manager from deps, optionally registers the dmsg client, optionally starts it serving, and registers any dial-only transport clients. One place owns the NewManager call signature and the init/serve ordering, so the native visor and the wasm edge cannot drift on it (e.g. a changed NewManager signature, or a forgotten InitClient).

func DmsgServicePKs

func DmsgServicePKs(svc Services) cipher.PubKeys

DmsgServicePKs returns the dmsg public keys of the deployment services that run as dmsg DIRECT clients — dmsg-discovery, transport-discovery, address- resolver, route-finder, service-discovery, config, uptime-tracker — parsed from their `dmsg://<pk>:<port>` service URLs (empty/unparseable entries are skipped).

These services never publish to the dmsg-discovery, so a visor MUST seed their entries into its dmsg client's cache (native: seedDmsgServiceEntries; wasm: StartDmsgSeeded's servicePKs) or a DialStream to them 404s ("entry is not found in discovery"). Both the native visor and the wasm edge derive the set here, from the same visorcore.Services, so they can't drift on it — the omission that once left the wasm edge's network-view / services-health / uptime aggregation empty while the native visor worked.

Route-setup nodes are NOT included: they are seeded separately and the two shells differ on whether they add them here (the wasm edge appends svc.RouteSetupNodes after this call). Keep that decision at the call site.

func ICEURLs

func ICEURLs(stunServers []string) []string

ICEURLs prefixes each bare STUN "host:port" with the "stun:" scheme the WebRTC stack expects, for network.ClientFactory.ICEURLs. Both the native visor and the wasm edge feed their deployment STUN servers through this so the WebRTC transport dials identically on either platform.

func ShufflePubKeys

func ShufflePubKeys(keys []cipher.PubKey) []cipher.PubKey

ShufflePubKeys returns the given slice shuffled in place using crypto/rand.

Types

type ConnectPhaseResult

type ConnectPhaseResult struct {
	Connected []cipher.PubKey
	Count     int
}

ConnectPhaseResult tracks the outcome of a connection phase.

type Connector

type Connector struct {
	Tm    *transport.Manager
	DmsgC *dmsg.Client // for reachability probes
	Log   *logging.Logger
	// contains filtered or unexported fields
}

Connector is the platform-neutral "connect to visors" primitive shared by the native visor (pkg/visor) and the browser wasm-visor. It owns the per-target transport-establishment logic (skip self / existing / same-LAN, then SaveTransport) parameterized over the transport TYPE, so the native shell can drive it with [SUDPH, STCPR] while the wasm shell can later drive it with [WS, WT] without the primitive hardcoding either. The platform-coupled pieces (public-visor sourcing, transport-discovery caching, the periodic loop) stay in the calling shell.

func (*Connector) BackedOff

func (c *Connector) BackedOff(now time.Time) int

BackedOff returns how many (target, type) pairs are currently skipped.

func (*Connector) ConnectToVisors

func (c *Connector) ConnectToVisors(
	ctx context.Context,
	selfPK cipher.PubKey,
	targets []cipher.PubKey,
	tpType tptypes.Type,
	existingByPK map[cipher.PubKey]map[tptypes.Type]bool,
	sudphCapable map[cipher.PubKey]struct{},
	maxCount int,
	currentCount int,
	trackAll bool,
) (result ConnectPhaseResult, err error)

ConnectToVisors attempts to establish transports of the given type to the given PKs. Skips self, existing transports, same-LAN visors, and non-SUDPH-capable visors. Returns the list of PKs we attempted (for tracking) and the count of new transports.

type RouterDeps

type RouterDeps struct {
	DmsgC            *dmsg.Client
	PubKey           cipher.PubKey
	SecKey           cipher.SecKey
	TransportManager *transport.Manager
	RouteFinder      rfclient.Client
	// PreferLocalRouteTo is router.Config.PreferLocalRouteTo: try a local
	// route to dst before the route finder (a hypervisor's attached visors).
	PreferLocalRouteTo    func(dst cipher.PubKey) bool
	RouteGroupDialer      router.RouteGroupDialer
	SetupNodes            []cipher.PubKey
	MinHops               uint16
	ExcludeTransportTypes []string
	// NoTransit refuses to act as an intermediate hop on another visor's route
	// (visorconfig.Routing.NoTransit).
	NoTransit          bool
	ParallelRouteSetup int
	AwaitSetupListener *dmsg.Listener
	Logger             *logging.Logger
	MasterLogger       *logging.MasterLogger

	AppLookup       func(routing.Port) (string, bool)
	DialHook        router.DialHook
	RulesGCInterval time.Duration
	SetupHooks      []router.RouteSetupHook

	// PolicyOnControlPorts opts the routing policy back in for control-plane
	// destination ports (default OFF — those ports bypass the policy). Seeded
	// from Routing.PolicyOnControlPorts. See router.Config.PolicyOnControlPorts.
	PolicyOnControlPorts bool

	// MuxFEC advertises CapFEC on mux route groups (repair frames striped
	// alongside data). Seeded from Routing.MuxFEC; off by default.
	MuxFEC bool

	// ExcludeSameLANHops (default ON) drops same-LAN peers as routing
	// intermediates; see router.Config.ExcludeSameLANHops. SelfPublicIP feeds its
	// NAT-hairpin check (nil until STUN resolves).
	ExcludeSameLANHops bool
	SelfPublicIP       func() net.IP
}

RouterDeps is the platform-neutral input to BuildRouter: the router.Config fields plus the dmsg client and setup hooks. The caller builds the platform- specific pieces (the route-finder client over its own HTTP/dmsg transport, the setup-node dialer with or without an embedded RSN, and — native only — the routing-policy DialHook / AppLookup / setup hooks); BuildRouter owns the Config field mapping + New + Serve so the two visors can't drift on it.

Zero values for the optional native-only fields (AppLookup, DialHook, RulesGCInterval, SetupHooks) are correct for a browser edge.

type Services

type Services struct {
	// dmsg
	DmsgServers       []deployment.DmsgServerEntry // seed/embedded server set
	DmsgDiscovery     string                       // clearnet dmsg-discovery (native)
	DmsgDiscoveryDmsg string                       // dmsg://… dmsg-discovery (browser / dmsg-only)
	// transport discovery
	TransportDiscovery     string
	TransportDiscoveryDmsg string
	// address resolver
	AddressResolver     string
	AddressResolverDmsg string
	// routing
	RouteFinder     string
	RouteFinderDmsg string
	RouteSetupNodes []cipher.PubKey
	// TransportSetupNodes is the trust list for the transport-setup accept side
	// (dmsg port 47): only these PKs may command this visor to add/remove
	// transports. Mirrors the native visor's EffectiveTransportSetupPKs.
	TransportSetupNodes []cipher.PubKey
	MinHops             uint16
	// service discovery
	ServiceDiscovery     string
	ServiceDiscoveryDmsg string
	// config-bootstrap service
	Conf     string
	ConfDmsg string
	// uptime tracker
	// reward system (theskywirenetwork.net) — dmsg URL powers the "rewards" resolver
	// alias so the in-tab browser can reach reward.dmsg / rewards.dmsg.
	RewardSystem     string
	RewardSystemDmsg string
	// misc
	StunServers []string
	GeoIP       string // HTTP-only (dmsg doesn't preserve client IP); no config override
}

Services is the resolved set of deployment service endpoints the subsystems need, with both the dmsg-HTTP ("…Dmsg") and clearnet-HTTP variants. It is the single shape both shells build their subsystems from — produced by exactly one merge function (ResolveServices), so config sourcing cannot drift.

func ResolveServices

func ResolveServices(v1 *visorconfig.V1) Services

ResolveServices merges an operator config (v1, nullable) over the embedded deployment defaults (deployment.Prod) — the single place the "operator-override-else-deployment-default" rule lives. The native visor's scattered pick() calls across init_*.go collapse onto this; the browser visor passes v1 == nil to get pure deployment defaults.

MinHops defaults to 1 (origination enabled; a direct transport still downgrades to a 0-intermediate-hop path) so an edge can SET UP routes; the router treats MinHops==0 as "routing disabled".

type TransportManagerDeps

type TransportManagerDeps struct {
	Log      *logging.Logger
	ARClient any
	EB       any
	Config   *transport.ManagerConfig
	Factory  network.ClientFactory

	// DmsgC, when non-nil, is registered as the dmsg transport client
	// (InitDmsgClient) before Serve — the browser edge does this inline; the
	// native visor defers dmsg-client init to its own init_dmsg stage and
	// leaves this nil.
	DmsgC *dmsg.Client

	// Serve starts `go tm.Serve(serveCtx)`. The browser edge sets it; the
	// native visor keeps Serve in its own WaitGroup-wrapped goroutine (its
	// close-stack needs the wg handle for graceful shutdown) and passes false.
	Serve bool

	// DialOnlyClients are transport types registered via InitClient after Serve
	// — the browser edge's {WS, WT, WEBRTC} dial-only set. The native visor
	// registers its (STUN/config-gated) clients from its own init modules and
	// passes nil here.
	DialOnlyClients []types.Type
}

TransportManagerDeps is the platform-neutral input to BuildTransportManager. The caller builds the platform-specific pieces — the ManagerConfig (native wraps its HTTP discovery client with CXO; the browser edge uses a dmsg-only tpdclient), and the network.ClientFactory (native pre-enables its TCP/UDP port demux, which is not TinyGo-safe, before handing it in) — and this owns the NewManager → optional InitDmsgClient → optional Serve → dial-only InitClient sequence so the native visor and the wasm edge can't drift on it.

ARClient and EB are typed `any` for the same reason transport.NewManager types them so: addrresolver (net/http) and appevent must stay out of the TinyGo graph. Native passes its *addrresolver.APIClient / *appevent.Broadcaster; the browser edge passes nil ARClient and its appevent broadcaster.

Jump to

Keyboard shortcuts

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