8990514417cf0f029bccebfcb7fcd672427e1371
## Accept button regression — diagnosed from a user log
Field report: incoming call → callee taps Accept → debug log
shows the dual-path race being skipped with
`connect:dual_path_skipped {"has_own":false,"has_peer":true,
"role":"None"}` and the call falling to relay-only on the
callee side.
Root cause: the Accept button was calling `answer_call` with
`mode: 2` which falls through to `AcceptGeneric` (privacy
mode). By design, privacy mode SKIPS the reflex query on the
callee so the callee's IP stays hidden from the caller — but
the side effect is that `own_reflex_addr` never gets cached in
`SignalState`. When `connect` runs a moment later, it sees
`own_reflex_addr = None`, can't compute the deterministic role
for the dual-path race, and falls back to relay.
For a normal VoIP app where P2P is the desired default, the
right behavior is `AcceptTrusted` — which queries reflect,
advertises the callee's addr in the answer, and enables direct
P2P. Privacy mode can come back as a dedicated second button
if anyone actually needs it.
Changed `acceptCallBtn` click handler from `mode: 2` to
`mode: 1`. The next call from a Phase-5 APK should show
`connect:dual_path_race_start` + `connect:dual_path_race_won
{"path":"Direct"}` on a cone-NAT-to-cone-NAT pair.
## Debug log export — new Copy / Share buttons
Field-testing the GUI debug log required me to keep asking the
user to type out what they saw. Added two new buttons next to
Clear:
- **Copy log** — serialises the rolling buffer as plain text
(same HH:MM:SS.mmm format the on-screen panel uses) and
writes to `navigator.clipboard`. Falls back to the old
selection-based `execCommand("copy")` for WebViews that
refuse the new API without a permission prompt.
- **Share** — tries the Web Share API (`navigator.share(...)`)
first. On Android WebView this opens the system share sheet
so the user can send the text straight to a messaging app.
Falls back to clipboard copy on WebViews that don't expose
navigator.share (most desktop ones). Also falls back if the
user cancels the share sheet.
Flash status line below the buttons shows a 2.5s confirmation
("✓ Copied 47 entries") or an error hint. The log is plain
text so anyone can paste a log fragment into a message and
send it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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
Languages
Rust
78%
Kotlin
7.9%
Shell
6.7%
TypeScript
3.2%
C++
1.5%
Other
2.6%