Siavash Sameni 00deb97a5d fix(reflect): drop LAN/private reflex addrs from NAT classification
Real-world report: a user with one LAN relay + one internet relay
got "Multiple IPs — treating as symmetric" because the LAN relay
saw the client's LAN IP (172.16.81.172) while the internet relay
saw the WAN IP (150.228.49.65). Two observations of "different
public IPs" from the classifier's perspective, but semantically
they describe two different network paths and shouldn't be
compared.

The LAN relay's reflection is always true, just not useful for
public NAT classification: there's no NAT between the client and
the LAN relay, so that path's reflex addr is always the LAN
interface IP regardless of what the public-facing NAT beyond it
looks like.

Fix: new `is_private_or_loopback` helper filters the probe set
before classification. Drops:
 - 127.0.0.0/8 loopback
 - 10/8, 172.16/12, 192.168/16 RFC1918 private
 - 169.254/16 link-local
 - 100.64/10 CGNAT shared-transition (same reasoning: a relay
   that sees the client with a CGNAT addr is on the same carrier
   network and can't describe public NAT state)
 - IPv6 loopback, unspecified, fe80::/10 link-local

Failed probes still filtered out of classification (they were
already) but now dimmed in the UI list instead of highlighted
amber. Same rationale: a momentarily-offline probe target isn't
a warning-worthy state, it's just a fact about the probe run.

UI palette rebalance: only Cone gets green, everything else
neutral text-dim. Wording changed from warning-tone
"⚠ must use relay" to informational "ℹ P2P falls back to relay,
calls still work" — symmetric NAT isn't broken state, it just
means media takes the relay path.

Tests added (4 new in wzp_client::reflect):
- classify_drops_private_ip_probes — LAN + public → Unknown
- classify_drops_loopback_probes — loopback + 2 public → Cone
- classify_drops_cgnat_probes — CGNAT + 2 public same-IP-
  diff-port → SymmetricPort
- classify_two_lan_probes_is_unknown_not_cone — all LAN → Unknown

Existing multi_reflect integration test updated: two loopback
relays now correctly classify as Unknown (because loopback reflex
addrs are filtered) with the plumbing-works invariant preserved.

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

WarzonePhone

Custom lossy VoIP protocol built in Rust. E2E encrypted, FEC-protected, adaptive quality, designed for hostile network conditions.

Quick Start

# Build
cargo build --release

# Run relay
./target/release/wzp-relay --listen 0.0.0.0:4433

# Send a test tone
./target/release/wzp-client --send-tone 5 relay-addr:4433

# Web bridge (browser calls)
./target/release/wzp-web --port 8080 --relay 127.0.0.1:4433 --tls
# Open https://localhost:8080/room-name in two browser tabs

Architecture

See docs/ARCHITECTURE.md for the full system architecture with Mermaid diagrams covering:

  • System overview and data flow
  • Crate dependency graph (8 crates)
  • Wire formats (MediaHeader, MiniHeader, TrunkFrame, SignalMessage)
  • Cryptographic handshake (X25519 + Ed25519 + ChaCha20-Poly1305)
  • Identity model (BIP39 seed, featherChat compatible)
  • Quality profiles (GOOD/DEGRADED/CATASTROPHIC)
  • FEC protection (RaptorQ with interleaving)
  • Adaptive jitter buffer (NetEq-inspired)
  • Telemetry stack (Prometheus + Grafana)
  • Deployment topology

Features

  • 3 quality tiers: Opus 24k (28.8 kbps) / Opus 6k (9 kbps) / Codec2 1200 (2.4 kbps)
  • RaptorQ FEC: Recovers from 20-100% packet loss depending on tier
  • E2E encryption: ChaCha20-Poly1305 with X25519 key exchange
  • Adaptive jitter buffer: EMA-based playout delay tracking
  • Silence suppression: VAD + comfort noise (~50% bandwidth savings)
  • ML noise removal: RNNoise (nnnoiseless pure Rust port)
  • Mini-frames: 67% header compression for steady-state packets
  • Trunking: Multiplex sessions into batched datagrams
  • featherChat integration: Shared BIP39 identity, token auth, call signaling
  • Prometheus metrics: Relay, web bridge, inter-relay probes
  • Grafana dashboard: Pre-built JSON with 18 panels

Documentation

Document Description
ARCHITECTURE.md Full system architecture with diagrams
TELEMETRY.md Prometheus metrics specification
INTEGRATION_TASKS.md featherChat integration tracker
WZP-FC-SHARED-CRATES.md Shared crate strategy
grafana-dashboard.json Importable Grafana dashboard

Binaries

Binary Description
wzp-relay Relay daemon (SFU room mode, forward mode, probes)
wzp-client CLI client (send-tone, record, live mic, echo-test, drift-test, sweep)
wzp-web Browser bridge (HTTPS + WebSocket + AudioWorklet)
wzp-bench Component benchmarks

Linux Build

./scripts/build-linux.sh --prepare   # Create Hetzner VM + install deps
./scripts/build-linux.sh --build     # Build release binaries
./scripts/build-linux.sh --transfer  # Download to target/linux-x86_64/
./scripts/build-linux.sh --destroy   # Delete VM

Tests

cargo test --workspace   # 272 tests

License

MIT OR Apache-2.0

Description
No description provided
Readme 147 MiB
Languages
Rust 78%
Kotlin 7.9%
Shell 6.7%
TypeScript 3.2%
C++ 1.5%
Other 2.6%