Physical iOS iproxy tunnel client¶
Decision¶
Option 1 is chosen: retain libusbmuxd’s iproxy behind an injected
IosTunnelClient. DefaultIosTunnelClient owns the child/PID, local and device
ports (device port only for remote tunnels), argv-only launch, startup liveness
polling, output capture, supervision, and graceful/forced cleanup. FakeIosTunnelClient supports deterministic manager
tests without USB hardware. No new dependency or transport fallback is added.
The manager still owns runner sequencing and host-port allocation. Its callbacks
preserve the stop → host-port check → remote tunnel launch sequence, and preserve
RemoteServicePortUnavailableError recovery through the existing runner restart.
A local tunnel’s recorded port keeps runner launch and ownership checks aligned.
Support and provenance¶
This change verifies unit behavior using fake executors and FakeTimer, for local
and remote-runner tunnel paths. No physical-device, Xcode-version, iOS-version,
or libusbmuxd-version matrix was exercised here. It therefore establishes no new
supported Xcode/iOS combinations; existing physical CtrlProxy prerequisites apply.
The binary is requested as iproxy through the existing executor, resolved by the
host’s PATH (the remote host for remote execution). Binary provenance/version
pinning is NOT done here. Existing logs do not claim an inspected absolute binary
path, signature, version, or provenance. The installation and connected USB device remain trusted host prerequisites.
Lifecycle and diagnostics¶
The refactor preserves existing lifecycle log lines and levels. Stdout/stderr logging trims whitespace and caps each excerpt at 500 characters; no additional redaction work is introduced. Ready retains the existing process-liveness definition, rather than claiming an HTTP, TCP-bind, or device-service readiness proof.
The existing ProcessSupervisor checks every five seconds and retries with
exponential delay from one second, capped at fifteen seconds. Retry count remains
unlimited until stop or device disconnect; this refactor does not add an attempt
limit. Stop cancels scheduled restarts. Startup failure preserves the original
error type and text and leaves a launched tunnel tracked on readiness failure.
Stopping during readiness retains the old polling interleaving: a late successful
status response can rearm supervision. Exit-wait listeners retain their existing
once-listener lifecycle. Local restarts use the current service port for both
argv ports; remote restarts retain the recorded device port.
Cleanup retains the existing tracked-child graceful signal, one-second wait, forced signal, and one-second wait, plus the shutdown force-stop path and remote-runner stop call. It does not introduce a new process-tree discovery or signaling algorithm. Physical USB disconnect, actual port binding, and host process cleanup still require device validation.
Non-goals¶
Options 2–4 are dropped: discovering an Apple replacement mechanism, retiring physical CtrlProxy, and designing an AutoMobile transport. Binary installation, version pinning, capability discovery, changes to runner recovery ordering, and new tool schemas are outside this change.