Files
wz-phone/docs/PRD-netcheck.md
Siavash Sameni 7b4bce69d5
Some checks failed
Mirror to GitHub / mirror (push) Failing after 28s
Build Release Binaries / build-amd64 (push) Failing after 3m36s
docs: update all docs for hard NAT detection + relay wiring
- PROGRESS.md: hard NAT Phase A, relay cross-wiring, 588 tests
- ARCHITECTURE.md: hard NAT port prediction diagram + pattern table
- PRD-p2p-direct.md: Phase 8.6 split into a/b/c/d with status
- PRD-hard-nat.md: Phase A done, B signal ready, effort table updated
- PRD-netcheck.md: port_allocation field + probe documented

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:33:12 +04:00

3.4 KiB

PRD: Network Diagnostic (Netcheck)

Phase: Implemented Status: Done (2026-04-14) Crate: wzp-client

Problem

When P2P connections fail or call quality is poor, there is no diagnostic tool to understand why. Users and developers must manually probe STUN, check NAT type, test relay connectivity, and verify port mapping support — all separately. Tailscale's netcheck consolidates all of this into a single diagnostic report.

Solution

A comprehensive run_netcheck() function that probes all network capabilities in parallel and produces a structured NetcheckReport. Exposed as a CLI subcommand (wzp-client --netcheck) and available for in-app diagnostics.

Implementation

New Module: crates/wzp-client/src/netcheck.rs

NetcheckReport:

pub struct NetcheckReport {
    pub nat_type: NatType,
    pub reflexive_addr: Option<String>,
    pub ipv4_reachable: bool,
    pub ipv6_reachable: bool,
    pub hairpin_works: Option<bool>,
    pub port_mapping: Option<PortMapProtocol>,
    pub relay_latencies: Vec<RelayLatency>,
    pub preferred_relay: Option<String>,
    pub stun_latency_ms: Option<u32>,
    pub upnp_available: bool,
    pub pcp_available: bool,
    pub nat_pmp_available: bool,
    pub gateway: Option<String>,
    pub duration_ms: u32,
    pub stun_probes: Vec<NatProbeResult>,
    pub port_allocation: Option<PortAllocation>,
}

Probes (all parallel via tokio::join!):

  1. STUN probesprobe_stun_servers() to all configured STUN servers
  2. Relay latenciesprobe_reflect_addr() to each configured relay
  3. Port mappingacquire_port_mapping() to detect NAT-PMP/PCP/UPnP
  4. Gatewaydefault_gateway() for the router address
  5. IPv6 — attempt to bind [::]:0 and send to an IPv6 STUN server
  6. Port allocationdetect_port_allocation() probes STUN servers from single socket to classify NAT pattern as PortPreserving/Sequential/Random (feeds into hard NAT prediction)

Derived fields:

  • nat_type / reflexive_addr — from classify_nat() on STUN probes
  • ipv4_reachable — true if any STUN probe succeeded
  • preferred_relay — relay with lowest RTT
  • port_mapping / nat_pmp_available / pcp_available / upnp_available — from portmap result

Human-readable output: format_report() produces a formatted text report with sections for NAT info, port mapping, STUN probes, relay latencies.

CLI Integration

wzp-client --netcheck <relay-addr> — runs the diagnostic using the specified relay plus default STUN servers, prints the report, and exits.

Deferred

  • Hairpin test — send packet from shared endpoint to own reflexive addr to test NAT hairpinning. Architecture is in place (hairpin_works: Option<bool>) but the actual probe is not yet implemented.
  • Android/Desktop in-app UI — expose via JNI (Android) and Tauri command (desktop) for user-facing diagnostics.

Files

File Change
crates/wzp-client/src/netcheck.rs New — NetcheckReport + run_netcheck + format_report
crates/wzp-client/src/lib.rs Add pub mod netcheck
crates/wzp-client/src/cli.rs --netcheck flag + handler

Testing

  • 5 unit tests: default config, report JSON serialization + roundtrip, RelayLatency serialization, format_report with empty relays, format_report with full data (STUN probes, relay latencies, preferred relay, port mapping)
  • 1 integration test (#[ignore]): full netcheck run