Bandwidth + bootstrap hardening on top of v0.7.2. Wire-compatible with
v0.7.0/v0.7.1/v0.7.2; no protocol changes.
EDM port scanner DISABLED
- hole_punch_with_scanning() now does only single quick punch + parallel
punch over 30s window. The EDM port-scanner branch is gone from the
live path because per-probe endpoint.connect() amplifies catastrophically:
iroh accumulates every connect() target into a per-endpoint paths set
and probes them all under QUIC NAT-traversal in the background. A
100-probes/sec / 5-min scan inserted ~30k paths; iroh probed all of
them. Observed at 22MB/s outbound from one client — DoS-grade.
- Scanner body preserved as edm_port_scan_disabled_v0_7_3() with all
supporting helpers (PortWalkIter, scanner_semaphore, role-based
scanner/puncher split, found_tx/found_rx channel pattern,
deadline + tokio::select! orchestration) marked #[allow(dead_code)].
Refactor target: replace per-probe endpoint.connect() with raw
socket.send_to() so probes don't enter iroh's path store.
Bootstrap probing batched
- New probe_anchors_batched() helper: 3 anchors in flight at a time,
2s stagger between batch dispatches, 10s per-anchor timeout, no abort
on success. First success unblocks the bootstrap flow; remaining
probes continue in background and fill peer connections naturally.
- Phase 2 (bootstrap fallback) still only fires when every discovered
anchor failed — preserves load-distribution intent. Replaces the
sequential 50s+ timeout cascade users observed with old data dirs.
Stale-anchor self-pruning
- New storage.get_known_anchor_last_seen() and storage.delete_known_anchor().
- maybe_prune_stale_anchor(): when a probe fails AND last_seen_ms > 3 days,
delete the entry from known_anchors immediately. Recoverable anchors
(failed once, succeeded recently) are preserved. Self-healing for old
data dirs whose discovered anchors point to keypairs that rotated
months ago.
Android close button kills NodeService
- New NodeService.stopFromNative() Kotlin static method called via JNI
from android_wifi::stop_node_service(). exit_app invokes it on Android
before app.exit(0). Previously the button ended the Activity but the
foreground service kept networking running.
Cosmetic
- Power-icon SVG (inline) replaces ⏻ so Android webviews lacking
U+23FB don't render a missing-image tofu box.
Docs
- design.html section 11 rewritten for portmapper (UPnP+NAT-PMP+PCP,
v0.7.2) including per-platform contract and bidirectional anchor
watcher.
- design.html section 10 marks session relay as opt-in (v0.7.2) and EDM
scanner as disabled-pending-refactor (v0.7.3).
- download.html carries v0.7.3 release notes.
- MEMORY.md updated; older v0.7.0/v0.7.1 status sections condensed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>