Changes from Build 16
STUN NAT keepalive (major fix)
Root cause of all WiFi sleep degradation found and fixed. Home WiFi routers expire UDP NAT mappings after 30-120 seconds of inactivity. When iOS sleeps, WireGuard keepalives stop (TUN device frozen), TURN sockets go silent, NAT mapping expires. Next pion permission refresh arrives with a new external port → VK TURN rejects with 400 Bad Request.
Each TURN connection now sends a STUN Binding request every 25 seconds, keeping the NAT mapping alive independently of WireGuard traffic. Confirmed working with pf udp.multiple=60s — the exact scenario that previously caused hundreds of 400 errors.
Faster silent-degradation detection
Watchdog condition 3 threshold lowered from 10 to 5 errors. Detects VK permission rejection ~8 minutes faster in degraded scenarios.
Wake-time fast-path health check
iOS wake() now triggers an immediate tunnel health check (threshold 5 pion errors). If degradation accumulated during sleep, reconnects instantly instead of waiting for the next 30-second watchdog tick.
Wake check threshold tuned (2 → 5)
Single transient errors no longer cause false-positive reconnects on wake.
Test results
- WiFi sleep 12 min (udp.multiple=60s, build 18): 0 errors, 0 reconnects ← previously 400 Bad Request cascade
- WiFi awake 30 min: 0 errors, 3 lost pings out of 1499
- LTE sleep 72 min: 2 reconnects (condition 1 only), 0 pion errors
- WiFi→LTE handoff: automatic recovery with captcha solve