nettest

package
v0.1.13 Latest Latest
Warning

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

Go to latest
Published: Jun 1, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AggregateSamples

func AggregateSamples(method string, samples []float64) report.LatencyResult

AggregateSamples reduces a slice of RTT samples (ms) to min / median / p95 / max / stddev. Exposed for tests that want to exercise aggregation in isolation.

func LookupClientGeo

func LookupClientGeo(ctx context.Context) (report.ClientGeo, error)

LookupClientGeo queries ipinfo.io for city-level geolocation of the caller's current public IP. No API key required for anonymous requests; rate-limited to 50k/month per IP. Returns a zero-value ClientGeo and an error on any failure; callers should treat that as "unknown" not fatal.

func MeasureClockSkew

func MeasureClockSkew(ctx context.Context, url string) (int64, error)

MeasureClockSkew fetches the echo-ts endpoint and returns the signed difference (local_clock - server_clock) in milliseconds. A positive result means the local clock is ahead of the server. Large skew breaks TLS cert validation and Kerberos, so IT uses this to spot drifting home machines.

func MeasureDNS

func MeasureDNS(ctx context.Context, host string) (int64, error)

MeasureDNS returns the wall-clock milliseconds taken to resolve host via the default resolver. Large values point at a broken resolv.conf or an overloaded captive DNS server on the user's network.

func MeasureDownload

func MeasureDownload(ctx context.Context, url string) (float64, error)

MeasureDownload fetches url with a GET and returns the effective download throughput in Mbps. Mbps is computed as (bytes * 8) / (elapsed_seconds * 1_000_000) — decimal megabits, the convention used by networking vendors.

If the POP replies 503 with Retry-After (bandwidth semaphore full), the wait is excluded from the measurement — a fresh `start` is taken on each attempt and only the successful attempt's transfer time counts.

On context-deadline / partial-read failures the error is wrapped with what was actually received so the UI can show "download stalled at 3.2 Mbps after 15s (received 6.0 MB of 10 MB)" instead of a bare "context deadline exceeded".

func MeasureJitter

func MeasureJitter(ctx context.Context, in JitterInput) (report.Jitter, int, int, error)

MeasureJitter runs a background HTTP download while TCP-pinging Host:Port at PingInterval for Duration. The variance of the ping RTTs is returned — this is the "jitter under load" measurement from PRD §5.3 that catches flaky home Wi-Fi that single-shot pings miss. It also returns the number of pings actually attempted and the number that failed to dial; the per-POP runner sums these across tests to compute POPResult.Loss.Pct from real counts rather than a theoretical attempt estimate.

func MeasureLatency

func MeasureLatency(ctx context.Context, in LatencyInput) (report.LatencyResult, string, int, int, error)

MeasureLatency runs round-trip samples against Host. It prefers ICMP echo; on privilege or availability failure it falls back to TCP connect to TCPPort. Returns the aggregated result, the method actually used, the number of samples actually attempted, and the number that were dropped, so upstream can populate POPResult.Loss.Pct from real counts.

func MeasureMTU

func MeasureMTU(ctx context.Context, url string) (report.MTUResult, error)

MeasureMTU fetches url and checks whether the 1400-byte payload arrived intact. A short response suggests fragmentation or a black-hole proxy. On any transport error the result is black-hole — the error field on the POPResult captures the specific cause separately.

func MeasureTCP

func MeasureTCP(ctx context.Context, host string, port int, timeout time.Duration) report.Reachability

MeasureTCP attempts a single TCP connect within timeout and returns the resulting Reachability status. Used for the TCP/443 broker-reachability probe per PRD §5.3.

func MeasureUDPEcho

func MeasureUDPEcho(ctx context.Context, in UDPEchoInput) (report.Reachability, error)

MeasureUDPEcho sends a datagram prefixed with the magic bytes + a random 8-byte nonce, and waits for the same payload to echo back. The nonce check ensures we don't accept a stray UDP packet from another source as a valid reply.

func MeasureUpload

func MeasureUpload(ctx context.Context, url string, sizeBytes int) (float64, error)

MeasureUpload POSTs sizeBytes random bytes to url and returns the effective upload throughput in Mbps. Payload is cryptographically random to defeat any transparent compression.

503 Retry-After is honoured and retry wait is excluded from the measurement (see MeasureDownload for the pattern).

func RunAll

func RunAll(ctx context.Context, cfg *config.Config, progress chan<- Progress) (report.Network, []report.Error)

RunAll fans RunPOP across cfg.POPs with bounded concurrency. It also fetches /preflight/whoami once (from the first POP) to populate the top-level public_ip / detected_geo fields before the per-POP loop starts.

func RunPOP

func RunPOP(ctx context.Context, in POPInput, cfg *config.Config, progress chan<- Progress) (report.POPResult, []report.Error)

RunPOP executes every network test for one POP sequentially and returns the aggregated POPResult plus any per-test errors. Progress events are emitted to the optional channel.

Sequencing rationale: latency + throughput + jitter are ordered because jitter specifically measures RTT under the throughput-induced load. Reachability and DNS are cheap and run at the end.

Types

type JitterInput

type JitterInput struct {
	Host         string
	TCPPort      int
	DownloadURL  string
	Duration     time.Duration // defaults to 30s
	PingInterval time.Duration // defaults to 500ms
}

type LatencyInput

type LatencyInput struct {
	Host        string
	TCPPort     int           // used when ICMP is unavailable; typically 443
	Samples     int           // defaults to 20
	PerSampleTO time.Duration // defaults to 1s
	ForceTCP    bool          // tests: skip ICMP attempt entirely
}

LatencyInput describes one latency measurement run against a target host.

type POPInput

type POPInput struct {
	POP      config.POP
	BaseURL  string // test override; if empty, derived from POP.Hostname
	TCPPort  int    // test override; defaults to 443
	UDPPort  int    // test override; defaults to 4172
	ForceTCP bool   // test override; skip ICMP attempt
}

POPInput overrides derivation in tests. In production the runner uses the POP's Hostname with scheme "https" and ports 443 (TCP) / 4172 (UDP).

type Progress

type Progress struct {
	POPID   string
	Test    string
	Phase   string // "start" | "done" | "failed"
	Err     string
	Summary string // human-friendly value on done, e.g. "42 ms", "102 Mbps"
}

Progress is emitted to the progress channel as each per-POP test starts, completes, or fails. The wizard frontend forwards these events to the UI.

type UDPEchoInput

type UDPEchoInput struct {
	Host    string
	Port    int
	Magic   string        // "PFLT" per PRD §6.2
	Timeout time.Duration // defaults to 3s
}

type WhoamiResult

type WhoamiResult struct {
	PublicIP string
	POPID    string
	Geo      string
}

WhoamiResult is what the /preflight/whoami endpoint echoes back — the client's public IP as seen by the nearest POP, plus the POP's region label.

func Whoami

func Whoami(ctx context.Context, url string) (WhoamiResult, error)

Whoami fetches /preflight/whoami and decodes the JSON response.

Jump to

Keyboard shortcuts

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