tpviz

package
v1.3.107 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: AGPL-3.0 Imports: 36 Imported by: 0

Documentation

Overview

Package tpviz pkg/tpviz/cxo_latency.go c4-vis-latency

The latency graph behind the latency-space view: an undirected, weighted graph over visor public keys where an edge weight is the measured round-trip time between the two visors.

Source is TPD's metrics CXO feed (metrics/day/<YYYY-MM-DD>), NOT the HTTP /metrics endpoint. The publisher writes []TransportMetric there every 60s and content-addressing means a subscriber pays the delta rather than the whole dataset — 85k transport rows is ~31MB over HTTP, and re-fetching that to move a few edges is what the feed exists to avoid. There is deliberately no HTTP fallback: a view that silently starts polling a rate-limited endpoint when the feed is cold is worse than a view that says the feed is cold.

Only the CURRENT day's leaf is read. Latency is transport-level current state, so that is the only leaf carrying it — and it is also the most representative of the network as it is now, which is what a positional embedding wants. Reading the whole 30-day window would decode ~30 multi-megabyte bodies to find latency in one of them.

Package tpviz pkg/tpviz/cxo_standalone.go c4-app-rewards

Standalone CXO wiring. When tp-viz runs OUTSIDE a visor (the reward server serving theskywirenetwork.net over dmsg), it has no visor to hand it a CXOSubMgr. SetCXOSubMgrFromDmsg builds an intermittent CXO subscriber (pkg/cxo/cxosub) over the server's own dmsg client and wires it in — so the standalone server sources TPD/SD/DMSG-D data from the same CXO feeds the hypervisor uses, instead of HTTP-over-dmsg polling. Feed publisher PKs are resolved from the config's dmsg:// service URLs (TPDURLDmsg / SDURLDmsg / DMSGURLDmsg).

Package tpviz pkg/tpviz/cxo_subscriber.go c4-app-rewards

Optional integration with the visor's on-demand CXO subscription manager. When the hypervisor wires one in via SetCXOSubMgr, /api/services and /api/dmsg/entries try the manager's local snapshot first and fall through to the existing HTTP fetcher on cache miss. AcquireFor / ReleaseFor on each request scopes the underlying CXO subscription to active UI traffic (with the manager's own 10s grace handling multi-fetch tab loads).

Tab and feed identifiers are int constants here that mirror the values defined on the visor side (CXOTab / CXOFeed). The hypervisor's wiring is responsible for matching them; this is a minimal compromise to keep tpviz independent of pkg/visor (which would create an import cycle).

Package tpviz pkg/tpviz/tpviz.go c4-app-rewards

Package tpviz pkg/tpviz/tpviz_legacy_on.go c4-app-rewards

Index

Constants

View Source
const (
	CXOTabNetworkVisualizer = 0
	CXOTabUptime            = 2 // TPD uptime feed
	CXOTabCLITransports     = 5 // TPD routing feed
)

Tab identifiers used in calls to CXOSubMgr.AcquireForTab / ReleaseForTab. Values match pkg/visor.CXOTab / cxosub.Tab; the hypervisor adapter and the standalone adapter pass them through.

View Source
const (
	CXOFeedTPDMetrics           = 0 // metrics/day/<YYYY-MM-DD> (legacy: metrics/days/<n>)
	CXOFeedTPDUptime            = 1 // uptimes/days/<n> — []VisorSummary
	CXOFeedSDServices           = 2 // services/<type>/all (batched; legacy .../<pk>/entry)
	CXOFeedDMSGDClientsByServer = 3 // clients-by-server/<server> (batched; legacy .../<client>/entry)
	CXOFeedTPDAllTransports     = 4 // transports/all/{with-self,without-self}
	CXOFeedTPDStats             = 5 // stats/{network,versions} — network aggregates
	CXOFeedTPDRouting           = 6 // routing/<pk> — the routing feed, one leaf per visor
)

Feed identifiers used in calls to CXOSubMgr.Walk. Values match pkg/visor.CXOFeed / cxosub.Feed; the adapters pass them through.

Variables

This section is empty.

Functions

func CacheDirFromURL

func CacheDirFromURL(serviceURL string) string

CacheDirFromURL returns a cache directory path based on the service URL host. For example, "dmsg://02b307…095ae:80" -> "/tmp/02b307…095ae".

func CacheFilePath

func CacheFilePath(cacheDir, fullURL string) string

CacheFilePath returns the full cache file path for a given URL. If cacheDir is empty, returns "" (disables caching). Creates the cache directory if it doesn't exist. Generates simple, descriptive filenames based on URL path/query.

func GetEmbeddedIndexWithNavLinks(navLinks []NavLink) (string, error)

GetEmbeddedIndexWithNavLinks returns the full embedded legacy index.html with navigation links. This is for the legacy JavaScript UI.

Types

type AppState

type AppState struct {
	Name           string   `json:"name"`
	Status         int      `json:"status"`          // 0=stopped, 1=running, 2=errored, 3=starting
	DetailedStatus string   `json:"detailed_status"` // Human-readable status
	AutoStart      bool     `json:"auto_start"`
	Port           uint16   `json:"port"`
	Args           []string `json:"args,omitempty"`
}

AppState represents the state of an application running on the visor.

type CXOSubMgr

type CXOSubMgr interface {
	AcquireForTab(tab int)
	ReleaseForTab(tab int)
	Walk(feed int, prefix string, fn func(path string, body []byte) bool) bool
}

CXOSubMgr is the minimal slice of pkg/visor.CXOSubscriptionManager tpviz needs. Defined as an interface so tpviz can be built and tested without importing pkg/visor (which would close an import cycle: visor → tpviz → visor). The hypervisor wires a thin adapter in pkg/visor/hypervisor.go.

type Config

type Config struct {
	// Addr is the address to bind to (default: 127.0.0.1)
	Addr string
	// Port is the port to listen on (default: 8080)
	Port int
	// CacheDirTPD is the cache directory for TPD data (default: /tmp/{tpd-host})
	// Set to "" to disable caching
	CacheDirTPD string
	// CacheDirUT is the cache directory for uptime tracker data (default: /tmp/{ut-host})
	// Set to "" to disable caching
	CacheDirUT string
	// CacheDirSD is the cache directory for service discovery data (default: /tmp/{sd-host})
	// Set to "" to disable caching
	CacheDirSD string
	// CacheDirDMSG is the cache directory for DMSG discovery data (default: /tmp/{dmsg-host})
	// Set to "" to disable caching
	CacheDirDMSG string
	// CacheMaxAge is the cache max age in minutes (default: 5)
	CacheMaxAge int
	// TPDURL is the transport discovery URL
	TPDURL string
	// SDURL is the service discovery URL
	SDURL string
	// DMSGURL is the DMSG discovery URL
	DMSGURL string
	// TPDURLDmsg / SDURLDmsg / DMSGURLDmsg are the dmsg:// forms of the
	// deployment-discovery URLs (default from deployment.Prod.*Dmsg). When a
	// dmsg HTTP client is set (SetDmsgHTTPClient), deployment discovery is
	// fetched over dmsg using these instead of the clearnet URLs above —
	// required on a dmsg-only deployment.
	TPDURLDmsg  string
	SDURLDmsg   string
	DMSGURLDmsg string
	// AllowClearnetDisc forces the legacy clearnet deployment-discovery fetches
	// even with no dmsg client / visor API. Default false: on a dmsg-only
	// deployment the clearnet HTTP frontends are dead (404), so the fetches are
	// gated to avoid spamming them.
	AllowClearnetDisc bool
	// NoCache disables caching when true
	NoCache bool
	// AutoRefresh enables auto-refresh of cache at specified interval
	AutoRefresh bool
	// SurveyDir is the directory containing visor surveys (node-info.json files)
	// Used for IP-based grouping without exposing actual IP addresses
	SurveyDir string
	// GeoIPURL is the URL of the geoip service (default from deployment.Prod.GeoIP)
	GeoIPURL string
}

Config holds the configuration for the visualizer server

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns a Config with default values

type DMSGData

type DMSGData struct {
	Servers      []DMSGServer `json:"servers"`
	EntriesCount int          `json:"entries_count"`
	Entries      []string     `json:"entries"` // list of all entry PKs
	LastUpdated  time.Time    `json:"last_updated"`
}

DMSGData holds cached DMSG discovery data

type DMSGHealthResponse

type DMSGHealthResponse struct {
	Status    string `json:"status"`
	BuildInfo string `json:"build_info,omitempty"`
	Message   string `json:"message,omitempty"`
	Error     string `json:"error,omitempty"`
}

DMSGHealthResponse contains the response from a DMSG health check.

type DMSGServer

type DMSGServer struct {
	PK                string   `json:"pk"`
	Address           string   `json:"address"`
	AvailableSessions int      `json:"available_sessions"`
	ServerType        string   `json:"server_type"`
	IP                string   `json:"ip,omitempty"`
	Country           string   `json:"country,omitempty"`
	Clients           []string `json:"clients,omitempty"` // PKs of clients connected to this server
}

DMSGServer represents a DMSG server entry

type LatencyEdge

type LatencyEdge struct {
	A string `json:"a"`
	B string `json:"b"`
	// MS is the round-trip time in milliseconds.
	MS float64 `json:"ms"`
	// N is how many transports between this pair were sampled.
	N int `json:"n"`
	// Type is the transport type that produced MS (the fastest one).
	Type string `json:"type"`
}

LatencyEdge is one visor pair and the round-trip time between them.

type LatencyGraph

type LatencyGraph struct {
	Edges []LatencyEdge `json:"edges"`
	// Visors is every public key that appears in Edges, sorted, so the
	// client can index points without a second pass.
	Visors []string `json:"visors"`
	Days   int      `json:"days"`
}

LatencyGraph is what the view consumes.

type LocalRoute

type LocalRoute struct {
	RouteID     uint32 `json:"route_id"`
	Type        string `json:"type"` // "forward", "consume", "intermediary"
	SrcPK       string `json:"src_pk,omitempty"`
	DstPK       string `json:"dst_pk,omitempty"`
	NextHopPK   string `json:"next_hop_pk,omitempty"` // For forward/intermediary routes
	TransportID string `json:"transport_id,omitempty"`
}

LocalRoute represents a routing rule from the local visor

type LocalTransport

type LocalTransport struct {
	ID        string `json:"id"`
	RemotePK  string `json:"remote_pk"`
	Type      string `json:"type"`
	Label     string `json:"label,omitempty"`
	IsSetup   bool   `json:"is_setup"`
	SentBytes uint64 `json:"sent_bytes"`
	RecvBytes uint64 `json:"recv_bytes"`
	// Bandwidth deltas for animation
	SentDelta uint64 `json:"sent_delta"`
	RecvDelta uint64 `json:"recv_delta"`
}

LocalTransport represents a transport from the local visor with traffic stats

type LocalVisorData

type LocalVisorData struct {
	Connected   bool             `json:"connected"`
	PubKey      string           `json:"pub_key,omitempty"`
	Country     string           `json:"country,omitempty"`
	IP          string           `json:"ip,omitempty"`
	Transports  []LocalTransport `json:"transports,omitempty"`
	Routes      []LocalRoute     `json:"routes,omitempty"`
	RoutesCount int              `json:"routes_count"`
	LastUpdated time.Time        `json:"last_updated"`
	// Bandwidth deltas for animation (bytes since last update)
	TotalSentDelta uint64 `json:"total_sent_delta"`
	TotalRecvDelta uint64 `json:"total_recv_delta"`
}

LocalVisorData holds data from the local visor for overlay display

type NavLink struct {
	URL   string
	Label string
}

NavLink represents a navigation link

type PingResponse

type PingResponse struct {
	Status     string  `json:"status"`
	LatencyMs  float64 `json:"latency_ms,omitempty"`
	Latencies  []int64 `json:"latencies,omitempty"` // Individual latencies in ms
	MinMs      float64 `json:"min_ms,omitempty"`
	MaxMs      float64 `json:"max_ms,omitempty"`
	AvgMs      float64 `json:"avg_ms,omitempty"`
	PacketLoss float64 `json:"packet_loss,omitempty"`
	Error      string  `json:"error,omitempty"`
	Mode       string  `json:"mode"` // "route" or "dmsg"
}

PingResponse contains the response from a ping operation.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is the transport visualizer HTTP server

func NewServer

func NewServer(cfg Config) *Server

NewServer creates a new visualizer server with the given config

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the HTTP handler for the server.

gzipped on the way out: this mux is mounted on two dmsg listeners (init_services.go) as well as TCP, and /api/transports writes the TPD all-transports snapshot verbatim — the ~3 MB body TPD itself caches pre-gzipped (all_transports_response_cache.go) and then serves raw from here. The content-type gate leaves the wasm blob (application/wasm) and the websocket upgrade alone.

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe starts the HTTP server

func (*Server) SetCXOSubMgr

func (s *Server) SetCXOSubMgr(m CXOSubMgr)

SetCXOSubMgr installs (or replaces, with nil to clear) the CXO subscription manager. Idempotent. Safe to call before or after the server is serving.

func (*Server) SetCXOSubMgrFromDmsg

func (s *Server) SetCXOSubMgrFromDmsg(dmsgC *dmsg.Client)

SetCXOSubMgrFromDmsg wires an intermittent CXO subscriber over dmsgC so a STANDALONE tp-viz sources deployment data from the TPD/SD/DMSG-D CXO feeds. No-op when dmsgC is nil. Keep any HTTP-over-dmsg client set via SetDmsgHTTPClient as the fallback: tp-viz tries CXO first and falls through on a cache miss (feed not yet synced), so the two compose safely.

func (*Server) SetDmsgHTTPClient

func (s *Server) SetDmsgHTTPClient(c *http.Client)

SetDmsgHTTPClient installs an HTTP-over-dmsg client so deployment discovery (TPD/SD/DMSG) is fetched over dmsg instead of the (now-dead) clearnet HTTP frontends. Standalone tpviz embeds (e.g. the reward UI) call this with a dmsg-backed client; the deployment URLs are then resolved to their dmsg:// forms. Pass nil to disable.

func (*Server) SetTPSAPI

func (s *Server) SetTPSAPI(api TPSAPI)

SetTPSAPI sets the embedded Transport Setup Node API. When set, the UI will show transport creation controls.

func (*Server) SetVisorAPI

func (s *Server) SetVisorAPI(api VisorAPI, pubKey string)

SetVisorAPI sets the visor API directly, bypassing RPC connection. This is used when the tp-viz server is embedded in the visor itself.

func (*Server) Start

func (s *Server) Start()

Start initializes the cache and starts auto-refresh without starting the HTTP server. Use this when embedding the tpviz server in another HTTP server.

func (*Server) Stop

func (s *Server) Stop()

Stop stops the server and cleans up resources

type ServiceInfo

type ServiceInfo struct {
	PK       string   `json:"pk"`
	Services []string `json:"services"`
	Country  string   `json:"country,omitempty"`
}

ServiceInfo holds service information for a visor

type TPSAPI

type TPSAPI interface {
	AddTransport(ctx context.Context, targetPK, remotePK, tpType string) (*TPSTransportResponse, error)
	RemoveTransport(ctx context.Context, targetPK, tpID string) error
	GetTransports(ctx context.Context, targetPK string) ([]TPSTransportResponse, error)
	PK() string
}

TPSAPI defines the interface for the embedded Transport Setup Node. Used to create/remove transports on remote visors and query their transport lists.

type TPSTransportResponse

type TPSTransportResponse struct {
	ID     string `json:"id"`
	Local  string `json:"local_pk"`
	Remote string `json:"remote_pk"`
	Type   string `json:"type"`
}

TPSTransportResponse represents a transport returned from TPS RPC operations.

type TransportSummary

type TransportSummary struct {
	ID      uuid.UUID           `json:"id"`
	Local   cipher.PubKey       `json:"local_pk"`
	Remote  cipher.PubKey       `json:"remote_pk"`
	Type    tptypes.Type        `json:"type"`
	Log     *transport.LogEntry `json:"log,omitempty"`
	IsSetup bool                `json:"is_setup"`
	Label   transport.Label     `json:"label"`
}

TransportSummary contains transport summary data. This mirrors visor.TransportSummary but is defined locally.

type VisorAPI

type VisorAPI interface {
	Overview() (*VisorOverview, error)
	RoutingRules() ([]routing.Rule, error)
	// AllTransports returns the network-wide all-transports JSON snapshot the
	// visor holds via its dmsg/CXO-backed transport-discovery feed — the same
	// payload TPD's HTTP /all-transports serves, but obtained over dmsg with no
	// clearnet request. Returns an error on a CXO cache miss (feed not yet
	// populated); the caller surfaces that rather than falling back to clearnet.
	AllTransports(ctx context.Context) ([]byte, error)
	AddTransport(ctx context.Context, remotePK, tpType string) (*TransportSummary, error)
	RemoveTransport(ctx context.Context, tpID string) error
	DMSGHealth(ctx context.Context, pk string) (*DMSGHealthResponse, error)
	Ping(ctx context.Context, pk string, useDMSG, localRoute bool, tries, sizeKB int) (*PingResponse, error)
	// App management
	Apps() ([]*AppState, error)
	StartApp(appName string) error
	StopApp(appName string) error
	SetAutoStart(appName string, autoStart bool) error
	SetAppPK(appName, pk string) error
	Close() error
}

VisorAPI defines the interface for accessing visor data. This is defined locally to avoid import cycles with the visor package.

type VisorOverview

type VisorOverview struct {
	PubKey      cipher.PubKey       `json:"local_pk"`
	Transports  []*TransportSummary `json:"transports"`
	RoutesCount int                 `json:"routes_count"`
}

VisorOverview contains visor overview data. This mirrors visor.Overview but is defined locally to avoid import cycles.

Directories

Path Synopsis
Package netview pkg/tpviz/netview/netview.go c3-vis-api
Package netview pkg/tpviz/netview/netview.go c3-vis-api
Package wasmgl pkg/tpviz/wasmgl/latencyoverlay.go c4-vis-latency Draws the spherical Voronoi cells over the latency view.
Package wasmgl pkg/tpviz/wasmgl/latencyoverlay.go c4-vis-latency Draws the spherical Voronoi cells over the latency view.

Jump to

Keyboard shortcuts

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