Skip to content

feat(ncm): ship go-ncm as a standalone release binary - #805

Open
danielpaulus wants to merge 1 commit into
mainfrom
feat/issue-538-go-ncm-binary
Open

feat(ncm): ship go-ncm as a standalone release binary#805
danielpaulus wants to merge 1 commit into
mainfrom
feat/issue-538-go-ncm-binary

Conversation

@danielpaulus

@danielpaulus danielpaulus commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Problem

ios list and device resolution are tied to local usbmuxd discovery. On a host that can reach an iOS 17+ RSD/userspace tunnel (e.g. a remote-device bridge where the phone is physically attached to another machine), ios list returns {"deviceList": []} and commands like rsd ls/info fail early with Device not found: <udid> — even when the user passes explicit --address/--rsd-port/--userspace-port coordinates that are perfectly reachable.

Design

Two additions, both on the CLI/resolution layer:

  1. Second discovery source for ios list. The list command now also queries the go-ios tunnel agent's existing /tunnels HTTP API (via the existing tunnel.ListRunningTunnels, honoring --tunnel-info-host/--tunnel-info-port/GO_IOS_AGENT_HOST/GO_IOS_AGENT_PORT) and merges tunnel-backed devices that usbmuxd does not report into the output. Merged entries carry a distinct transport marker: connectionType: "userspaceTunnel" (or "tunnel" for kernel TUN tunnels). usbmuxd entries win for devices known to both sources. ios list only hard-fails if both usbmuxd and the tunnel agent are unreachable. In --details mode, tunnel-only devices are listed with identity + transport instead of dying on the unreachable usbmuxd/lockdown path.

  2. Direct-target resolution. When --address and --rsd-port are supplied, a device missing from usbmuxd is no longer fatal: the DeviceEntry is built from the explicit coordinates, --userspace-port (+ --userspace-host) is preserved as the local forward endpoint, and --udid is treated as identity metadata. If no --udid is given, the UDID from the RSD handshake response is used. The RSD handshake itself is unchanged and still validated eagerly.

Implementation

  • cli_device_resolution.go
    • resolveDevice: the explicit --address/--rsd-port branch now runs before the Device not found exit; on usbmuxd miss it builds a directTargetDevice entry instead of failing.
    • New helpers: directTargetDevice, tunnelBackedDevices (queries /tunnels), tunnelBackedDeviceEntry, mergeTunnelDevices, isTunnelOnlyDevice, plus the connectionTypeTunnel/connectionTypeUserspaceTunnel markers.
  • main.go
    • printDeviceList(details, tunnelInfo): merges the tunnel source, tolerates a missing usbmuxd when the tunnel agent answers (warns instead of exiting).
    • detailsEntryForDevice: shared by JSON/no-JSON detailed output; skips lockdown GetValues for tunnel-only entries.
    • deviceWithRsdProvider: when GetDeviceWithAddress fails after a successful RSD handshake, keep the direct-target entry (attach the handshake's RsdPortProvider, backfill the UDID from the handshake) instead of exiting.
  • cmd_global.go: pass the tunnel-info config into the list command.
  • ios/tunnel/tunnel_api.go is untouched (read-side only via the existing ListRunningTunnels), deliberately avoiding overlap with the concurrent TunnelManager rework.

Options considered

  • Merge /tunnels into ios list + direct --address/--rsd-port target path (chosen). Reuses the tunnel agent API and the existing RSD plumbing (NewWithAddrPortDevice + Handshake), keeps changes additive and on the CLI layer, and matches what users expect (ios list shows reachable devices; explicit coordinates just work). This is also intentionally aligned with the Proposal: reuse Apple's CoreDevice tunnel on macOS instead of bringing up our own #713 Phase-1 direction: it's the same resolver-source plumbing (tunnel agent as a device source next to usbmuxd) that a future multi-source resolver can formalize, without committing to new library API now.
  • Separate specialist commands for RSD-only devices (e.g. ios rsd list). Works, but users would still hit the deviceList: [] / "Device not found" wall in normal commands; discoverability is poor.
  • Emulate usbmuxd from the bridge host. Heaviest option; duplicates discovery/forwarding logic go-ios already has for RSD and userspace tunnels.
  • Keep usbmuxd-only discovery (status quo): blocks remote/cloud workflows entirely.

Test plan

  • New unit tests in cli_device_resolution_test.go (device-free, run in CI) against a fake tunnel-agent HTTP server on 127.0.0.1:
    • /tunnels entries convert + merge into an empty usbmux list with correct udid, address, userspace TUN fields, and userspaceTunnel/tunnel transport markers.
    • Merge dedupes: usbmuxd entry wins for a shared UDID; tunnel-only entries are appended.
    • Direct-target resolution builds a usable entry from --address/--rsd-port with --udid as identity metadata (and empty UDID left for the RSD handshake to fill).
    • printDeviceList output contains the tunnel-only device.
    • --details output labels tunnel-only devices with the transport marker instead of failing.
  • go build ./..., go test ./... (all green), gofmt -l clean on changed files.
  • Real-device e2e suite via CI (/test-devices).

Fixes #538

🤖 Generated with Claude Code

https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk

Move the go-ncm main from cmd/cdc-ncm into the ncm module at
ncm/cmd/go-ncm so the CDC-NCM driver module is self-contained, and add
a --version flag (stamped via -ldflags -X main.version).

The release workflow now builds go-ncm for linux amd64+arm64 natively
on amd64/arm64 runners (cgo + libusb rules out easy cross-compilation)
and attaches go-ncm-linux.zip as a release asset, so other tools like
pymobiledevice3 can fetch the driver binary directly. release-canary.yml
mirrors the build and packaging steps to prove the path without cutting
a release.

Fixes #538

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J8eMENxJ1nec9CeHp4tjWk
@danielpaulus

Copy link
Copy Markdown
Owner Author

/test-devices

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

🧪 Running real-device tests on PR #805run.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

❌ Real-device tests failed — see run.

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.

go-ncm as a seperate exectuable

1 participant