Repository navigation
Share this host: only offer addresses the server actually answers (no dead IPv6 links) - #31447
Merged
Merged
Conversation
The runtime WebSocket listener widens to 0.0.0.0, which never accepts IPv6, yet the Connection address picker and the default pairing address offered global IPv6 interfaces, minting links nothing answers. Filter the interface list by the family of the host the listener binds when serving the network. Reported-by: @fongyuan-2011
Contributor
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 13 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
ELI5
When you share this computer with another device, Orca offers a list of addresses to put in the link. Orca's server only answers on IPv4 addresses, but that list also offered IPv6 addresses. If you picked one (or it was the only one), the link pointed at a door nobody answers, and the other device said "Host unavailable". Now the list only offers addresses the server actually answers.
What Changed
ws://[<v6>]:6768, while the runtime listens on0.0.0.0:6768(IPv4 only), so every connection, even from the host itself, was refused. The mobile QR pairing list had the same entries, and on an IPv6-only host the default address was the dead IPv6 one.0.0.0.0listener that means IPv4 only. On a host with no usable IPv4 address, the runtime link reports "no reachable address" instead of minting a dead link; mobile pairing falls back to Relay, or LAN-only refuses with its existing guidance.getPairingNetworkInterfaces(the single source for the picker and forgetDefaultPairingAddress) now takes a requiredlistenerHostand drops interfaces whose family that host does not serve. The value comes from a newOrcaRuntimeRpcServer.getNetworkExposureBindHost(), which returns the host the listener binds once it is widened for pairing (pinnedBindHost ?? 0.0.0.0). It reports the widened host rather than the current bind because the listener is still on loopback until the user generates a link. An IPv6 bind (::) is treated as dual-stack, so if the bind ever changes, IPv6 entries come back with no other edits.Not changed: addresses the user types (Custom),
orca serve --pairing-address, and the SSH/orcad tunnel paths. Those are explicit choices that may sit behind a proxy or tunnel. Headlessorca servenever enumerated interfaces. The default bind scope and family are not touched.Why
The issue offered two options: advertise only addresses the listener serves, or also listen on IPv6. Binding
::would expose the runtime on another address family. That is a security and product decision already being tracked in #31387 and #31223, so it does not belong in a bug fix. Making the offered list honest about the listener fixes the dead link without widening exposure. Because the filter is derived from the listener's bind host at the one function every picker and default goes through, it stays correct if the bind changes later. A hardcoded "no IPv6" rule would not.Wire compatibility: nothing on the wire changes. This only affects which address the host puts into new links, and the address it now picks is one older clients can already reach.
Linked Issue
Fixes #31161
Thanks @fongyuan-2011 for the precise report (listener
lsofoutput,[::1]refusal, and the confirmed IPv4 workaround made the cause obvious).The Chinese wording feedback about the
orca servehint is already addressed on main by #31082 (shipped in v1.4.233): the hint now reads "在无窗口模式下运行 Orca?请在那台电脑上运行" with the command in a separate<code>element.Visual Proof
N/A. The only visible change is that IPv6 entries no longer appear in the Connection address dropdown. No layout or component changed.
Testing
I manually tested these changes locally
Automated tests added/updated, or explained why not below
New
src/main/ipc/mobile-pairing-listener-family.test.ts:OrcaRuntimeRpcServer, once widened to0.0.0.0, offers and advertises only the IPv4 address.src/main/ipc/mobile.test.ts: stubs now report the listener bind host. The two IPv6-inclusion tests moved to the new file under a dual-stack listener.Verified live on macOS (this machine has ULA IPv6 on
bridge100and a Tailscale v6). With realos.networkInterfaces()and a real Node listener on0.0.0.0, main's function offeredfd53:…(connection refused) and the Tailscale v6 (timed out). With the fix only IPv4 entries are offered, and every one accepted a TCP connection. Node0.0.0.0refusing::1while::accepts both was also confirmed live.Not verified live: the full Electron Settings UI flow and pairing a second Mac.
Ran every step of the "static analysis and typecheck" job locally, and all passed except one: the orcad terminal smoke failed in its native file-watcher preflight, which has a hard 5s timeout, while the machine was at a load average of about 230. That preflight runs before any pairing code. CI runs the smoke.
AI Disclosure
Review
gpt-6.1-sol, high): clean.::spelled other ways is now treated as dual-stack, and the test cleans up its temp dir.Agent skill upstream boundary
Notes
Security: no exposure change. Cross-platform: this is pure Node
net.isIPlogic and the Windows default-route path is unchanged. SSH/remote: explicit, tunnel, and orcad addresses are unchanged. Mobile: the QR default no longer picks an unreachable IPv6, and Relay still pairs without a direct address. Backwards compatibility: no wire change. Performance: none.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)