Skip to content

Move usbmux framing and the WebSocket protocol into webmuxd - #3

Merged
rickmark merged 1 commit into
masterfrom
claude/project-thread-nkuvk1
Oct 18, 2026
Merged

rickmark merged 1 commit into
masterfrom
claude/project-thread-nkuvk1

Conversation

@rickmark

Copy link
Copy Markdown
Member

Requested by Rick · project thread

Before: webmuxd only claimed the USB interface and polled the bulk endpoint, so every usbmux packet and TCP ACK made a round trip to go-webmuxd. RemoteChannel and transport.proto lived in webmuxd-example. yarn build, yarn lint and yarn test all failed on a current Node, and nothing ran CI on pull requests.

After: the package speaks usbmux in the browser (device.startMux() then mux.connect(62078)), ships RemoteChannel and the protobuf protocol, and build, lint, typecheck and 43 tests pass in a new CI workflow. This finishes the two roadmap items that belong to this repo, and closes #1 and #2.

How:

  • src/usbmux/ is a TypeScript port of the host side of usbmuxd's device.c. It handles version negotiation (v1 and v2), the setup packet, sequence numbers, magic checks and control frames, and reassembles packets that are split across or packed into USB transfers. TcpChannel does SYN / SYN-ACK / ACK, ACKs device data straight away, keeps writes inside the device's advertised window, chunks large writes, and closes with RST the way usbmuxd does. go-webmuxd's version was missing the final ACK of the handshake.
  • MobileDevice now reads in a continuous loop instead of a 1 s interval and clears stalls. It sends a zero length packet when a write fills a whole number of USB packets, and open() throws instead of swallowing errors. It no longer touches window, so it can be tested in Node.
  • RemoteChannel and transport.proto moved in from webmuxd-example. The URL, reopen flag and WebSocket factory are options. The old new RemoteChannel(true) call still works.
    • raw mode (the default) keeps the existing wire format. I checked it against go-webmuxd's generated Go code. The browser now forwards only complete mux packets (Revise the protobuf API to send complete messages #2).
    • mux mode adds OpenChannel, ChannelData, CloseChannel and ChannelStateChanged messages, so framing and ACKs stay in the browser. go-webmuxd will need changes before it can use this mode.
  • Toolchain: TypeScript 5, Jest 29, ESLint 8 with typescript-eslint 8, and ts-proto 2 on @bufbuild/protobuf. Repository URLs now point to hack-different. The release workflow used npm ci with only a yarn.lock in the repo, so I switched it to yarn. Version bumped to 0.9.0.

Still open, in other repos: mux mode in go-webmuxd, switching webmuxd-example to depend on this package, and webmuxd-ui.

Not yet tested on a real iPhone. All tests run against a fake device that follows usbmuxd's behaviour.


Generated by Claude Code

Port the host side of usbmuxd to TypeScript: version negotiation, the
setup packet, sequence numbers, packet reassembly across USB transfers,
control frames, and the minimal TCP usbmux expects (SYN/SYN-ACK/ACK,
prompt ACKs, device window flow control, RST on close). MobileDevice
gains startMux() and a continuous read loop, sends zero length packets
when a write fills whole USB packets, and surfaces open errors.

Move RemoteChannel and transport.proto from webmuxd-example. Raw mode
stays wire compatible with go-webmuxd and now forwards only complete mux
packets; a new mux mode runs usbmux in the browser and relays channel
bytes. Upgrade the toolchain (TypeScript 5, Jest 29, ESLint 8) so build,
lint and tests run again, add tests and a CI workflow.

Closes #1, closes #2.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WX5EpsMSD7hjw6UNJCo3eg
@rickmark rickmark self-assigned this Oct 18, 2026
@rickmark
rickmark marked this pull request as ready for review October 18, 2026 04:56
@rickmark
rickmark merged commit 02f25f7 into master Oct 18, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Move USB framing to the JS/TS layer

2 participants