feat(forward): ios forward --list (like adb forward --list) - #812
Open
danielpaulus wants to merge 4 commits into
Open
feat(forward): ios forward --list (like adb forward --list)#812danielpaulus wants to merge 4 commits into
danielpaulus wants to merge 4 commits into
Conversation
ios forward captured the numeric usbmux device id once at startup. usbmuxd assigns a fresh id every time a device is plugged in, so after a disconnect/reconnect every new client connection failed with 'could not connect to phone' while iproxy kept working in the same session. Each accepted client connection still dials with the captured id first; when that connect fails, the device is looked up again by udid (the serial survives a replug) and the connect is retried once with the fresh id. The retry seam is an injected resolver func, so the behavior is unit-tested device-free against a fake usbmuxd on a temp unix socket. Also closes the usbmux socket on a failed Connect instead of leaking it. The exported StartNewProxyConnection signature is unchanged. Fixes #378 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Owner
Author
|
/test-devices |
Contributor
Contributor
|
❌ Real-device tests failed — see run. |
Register the temp-dir removal with t.Cleanup immediately after MkdirTemp so a subsequent net.Listen failure (which t.Fatalf's) can no longer leak the directory. Split the listener close into its own cleanup so ordering stays correct (listener closed before its dir is removed). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Adds a file-backed per-user registry of active forwards: every `ios forward` process writes one JSON entry (udid, hostPort, devicePort, pid) per forward under <user config dir>/go-ios/forwards and removes it on clean shutdown. `ios forward --list` reads the registry and prints the active forwards as JSON (or adb-style lines with --nojson), pruning entries whose owning process is no longer alive so killed forwards don't linger. Listing needs no device and is dispatched as a global command. Fixes #681 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
Register wrote each entry with a plain os.WriteFile straight to the final path. That truncates the file before rewriting it, so a concurrent List — which prunes (os.Remove) any file it cannot json-unmarshal — could observe the truncated intermediate, treat it as garbage, and delete a live forward's entry, permanently dropping it from 'ios forward --list'. Write to a temp file in the same dir and rename it into place so List only ever sees a complete file (the temp lacks the .json suffix List scans for). TestRegistryConcurrentRegisterList reproduces the drop against the old non-atomic write and passes with the rename. Also create the state dir 0700 and entries 0600 (was 0755/0644) so the device udid, forwarded ports and pid of a per-user forward are not readable by other local users, matching the repo's hardening posture. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
danielpaulus
force-pushed
the
feat/issue-681-forward-list
branch
from
August 7, 2026 13:56
8fb0452 to
f7de563
Compare
Owner
Author
|
Adversarial review (with codex cross-check). Verdict: ship-worthy after fix. One real data-loss race fixed + perms hardened, pushed to this branch. This branch was rebased so it stays exactly Fixes applied (
Reviewed, no change needed
Dismissed (codex flagged, accepted as-is)
Verified on this branch (804+feature): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
There is no way to see which ports are currently forwarded on a host, like
adb forward --listprovides for Android (device serial + local/remote port of every active forward). (#681)Design
A file-backed per-user registry of active forwards:
ios forwardprocess registers each forward as one JSON file<pid>-<hostPort>.json(fields:udid,hostPort,devicePort,pid) under<user config dir>/go-ios/forwards(os.UserConfigDir()), and unregisters on clean shutdown.ios forward --listreads that dir and prints the entries. Entries whose owning pid is no longer alive are pruned on read, so forwards that died without cleanup (SIGKILL, crash) disappear on the next list instead of lingering.Implementation
ios/forward/registry.go:Entry,Registry(Register/Unregister/Listwith prune),DefaultRegistryDir, portable pid-liveness probe (signal 0 on unix incl. EPERM-means-alive;os.FindProcesson Windows).main.go:startForwarding/startMultiForwardingregister each forward (best-effort — a registry failure never breaks the forward) and unregister on shutdown;runForwardListCommandprints JSON by default or adb-style<udid> tcp:<hostPort> tcp:<devicePort> pid:<pid>lines with--nojson.cmd_global.go: globalforward --listcommand; docopt usage gains[--list]on the forward pattern.Options considered
ios forwardCLI on this user account.ios forwardmust then depend on a running agent (which iOS <17 setups don't need at all), needs new API surface/ports, and still misses forwards started when the agent is down.Test plan
Device-free unit tests in
ios/forward/registry_test.goagainst a temp state dir:TestRegistryRegisterListUnregister— register/list (sorted), unregister, idempotent double-unregister.TestRegistryPrunesDeadPids— an entry owned by a genuinely dead pid (spawned helper process that exited) is dropped from the listing and its file is pruned; the live entry survives.TestRegistryListMissingDirAndGarbage— never-created dir lists empty without error; invalid JSON entries are pruned; non-registry files are left alone.Manual smoke test:
ios forward --list(JSON and--nojson) with a live-pid and a dead-pid entry in the real state dir — live one listed in both formats, dead one pruned.go build ./...,go test -race ./...andgofmt -lare clean.Fixes #681
🤖 Generated with Claude Code
https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk