Context
The #72 fix re-binds QUIC listeners when the device's active interface changes (Wi-Fi↔cellular handoff, DHCP renew, NAT remap). The current implementation polls getifaddrs every 3s (reconcile_quic_listeners on the interface_watch tick in engine/mod.rs) and diffs the routable-IP set against the bound quic_listeners map. This is robust and FFI-free but reacts up to 3s late.
Task
Add a Network.framework NWPathMonitor binding (mirror the objc2/block2 pattern in dioxus/lifecycle/ios.rs) that pushes path-change events into the engine via an mpsc channel, so re-listen happens within ~1s. All swarm mutation must stay on the event loop — feed changes via the channel, never touch the swarm from the monitor callback (Rule 2.10). Keep the 3s poll as a fallback, or remove it once the monitor is proven on-device.
Acceptance
- A Wi-Fi↔cellular handoff triggers a re-listen and relay reconnect within ~1s on-device.
- No swarm-held-across-await regressions.
References
- Gap P0-2 follow-up in
docs/research/ios-sync-state-of-the-art.md
Context
The #72 fix re-binds QUIC listeners when the device's active interface changes (Wi-Fi↔cellular handoff, DHCP renew, NAT remap). The current implementation polls
getifaddrsevery 3s (reconcile_quic_listenerson theinterface_watchtick inengine/mod.rs) and diffs the routable-IP set against the boundquic_listenersmap. This is robust and FFI-free but reacts up to 3s late.Task
Add a
Network.frameworkNWPathMonitorbinding (mirror the objc2/block2 pattern indioxus/lifecycle/ios.rs) that pushes path-change events into the engine via an mpsc channel, so re-listen happens within ~1s. All swarm mutation must stay on the event loop — feed changes via the channel, never touch the swarm from the monitor callback (Rule 2.10). Keep the 3s poll as a fallback, or remove it once the monitor is proven on-device.Acceptance
References
docs/research/ios-sync-state-of-the-art.md