Skip to content

fix(wda): reach WDA via CoreDevice tunnel IP on iOS 17+ devices - #171

Merged
mauricecarrier7 merged 1 commit into
mainfrom
fix/ios17-device-tunnel-host
Jun 24, 2026
Merged

fix(wda): reach WDA via CoreDevice tunnel IP on iOS 17+ devices#171
mauricecarrier7 merged 1 commit into
mainfrom
fix/ios17-device-tunnel-host

Conversation

@mauricecarrier7

Copy link
Copy Markdown
Contributor

Problem

bootstrap-device builds, installs, and launches WDA fine on a physical iOS 26 device, but the /status smoke (and every later tool call) fails with Connection refused. WDA announces the first on-device IP it finds via ServerURLHere->http://<ip>:<port> — often localhost (no routable Wi-Fi IP) or a Wi-Fi IP on a network the Mac can't reach (AP isolation / different subnet) — and simdrive smoke-tested that host directly.

On iOS 17+ a USB-attached device is reachable from the host only via the RemoteServiceTunnel, whose address devicectl reports as connectionProperties.tunnelIPAddress (an IPv6 ULA, e.g. fd1a:431c:b5a0::1).

Fix

Add choose_reachable_host(): probe the tunnel IP → announced host → localhost, and use the first that answers GET /status. WDA binds 0.0.0.0:<port> on-device, so the tunnel IP reaches it. The resolved host is persisted to the registry, so session_start / wda/client.py connect to a reachable address (a bracketed IPv6 flows through f"http://{host}:{port}" unchanged). Wired into both bootstrap_device() and the wda-up relaunch path.

Validation

End-to-end on Moes Max (iPhone 17 Pro Max, iOS 26.5.1): WDA announced 192.168.1.10 (unreachable from host) → fell back to [fd1a:431c:b5a0::1] → smoke passed ready=True → device session started and drove the app (observe / swipe / tap) in Airplane Mode over USB.

  • New tests: tests/test_a14_wda_tunnel_host.py (5) — tunnel fallback for localhost + unreachable Wi-Fi IP, no-tunnel fallback, nothing-reachable error path.
  • Full wda/bootstrap suite stays green (223 passed).

Note on the MCP auto-restart issue

Separately observed: a stale (pre-b12) MCP server auto-restarts on version drift and wedges the stdio transport (-32602 on every call). That is already fixed in b12 by the _MCP_SERVER_MODE gate in server.py (suppresses os.execv while serving MCP) — no change needed here.

🤖 Generated with Claude Code

bootstrap-device built, installed, and launched WDA fine on a physical
iOS 26 device, but the /status smoke (and every later tool call) failed
with "Connection refused": WDA announces the first on-device IP it finds
via ServerURLHere — often `localhost` (no routable Wi-Fi IP) or a Wi-Fi IP
on a network the Mac can't reach (AP isolation / different subnet) — and
simdrive smoke-tested that host directly. On iOS 17+ a USB-attached device
is reachable from the host only via the RemoteServiceTunnel, whose address
devicectl reports as connectionProperties.tunnelIPAddress (an IPv6 ULA).

Add choose_reachable_host(): probe the tunnel IP, the announced host, then
localhost, and use the first that answers GET /status. WDA binds 0.0.0.0
on-device, so the tunnel IP reaches it. The resolved host is persisted to
the registry, so session_start / wda/client.py connect to a reachable
address (a bracketed IPv6 flows through f"http://{host}:{port}" unchanged).
Wired into both bootstrap_device() and the wda-up relaunch path.

Validated end-to-end on Moes Max (iPhone 17 Pro Max, iOS 26.5.1): WDA
announced 192.168.1.10 (unreachable), fell back to [fd1a:431c:b5a0::1],
smoke passed ready=True, device session started + drove the app.

Tests: tests/test_a14_wda_tunnel_host.py (5) cover tunnel fallback for
localhost + unreachable Wi-Fi IP, no-tunnel fallback, and the
nothing-reachable error path. Full wda/bootstrap suite stays green.

**Not done:** does not set up a persistent host→device port-forward (uses
the tunnel IP directly, which suffices because WDA binds 0.0.0.0); does not
touch the simulator path or the MCP version-drift auto-restart (fix #1 was
already resolved in b12's _MCP_SERVER_MODE gate); not yet pushed/PR'd.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mauricecarrier7
mauricecarrier7 merged commit dcdae8f into main Jun 24, 2026
5 of 6 checks passed
@mauricecarrier7
mauricecarrier7 deleted the fix/ios17-device-tunnel-host branch June 24, 2026 19:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant