Repository navigation
Home network: send beacons on every home-network adapter, so sync works with a VPN on (#222) - #223
Merged
Merged
Conversation
When Home network sync can't find a linked machine, the Sync & backup line now names it and, when this machine can tell, why: a VPN or virtual adapter carrying the broadcasts, no network, Windows calling the network Public, macOS Local Network access off, another Patch Pilot version, or another rig's Patch Pilot on the network. It no longer says "In sync" while nobody is here. The details list each machine and a checklist. - patchpilot_local::lan_diagnosis: pure diagnose() over gathered facts, adapter classification (name and Windows description), egress kind, bind error wording; tested with hand-built facts. - patchpilot_local::netinfo: read-only probes (UDP connect + local_addr, sysinfo interfaces, PowerShell adapter description and profile with a 5 s deadline at below-normal priority). - lan::read tells this rig, another version, another rig and noise apart. - sync.rs keeps the relay's list of linked machines, so machines added from an export file or removed never show as missing. - lan.rs gathers facts on the existing 10 s beacon thread, looks at the network only while a machine is missing and none is here, and tells the UI only when the diagnosis changes. Decision #123 (amends #94). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # app/CHANGELOG.md
Each linked machine keeps a small sealed net/<machine id> report on the relay: Home network on, its subnets, whether its broadcasts leave through a VPN, and which linked machines it hears. Sent on change and, only while a machine is missing or can't hear this one, every 5 minutes. The others use it to say why they can't find that machine: Home network off there, asleep or closed, VPN there, a different network, one-way hearing (firewall), or the same network with neither hearing the other. Decision #124 (Proposed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A matching subnet alone no longer counts as the same network: most routers use the same few ranges. The relay now answers a PUT with the client's address, and "blocked" needs the same public address too (same family, neither side's internet through a VPN); a different one means "different network". - Report age is judged by when it reached the relay, on this machine's clock (relay x-age header), never the other machine's clock. - "Can't hear this machine" waits until the other machine had listened 30 s when it made its report, so a quick restart isn't deafness. - Peers count as here by the wall clock (a Mac's Instant stops in sleep). - A port that won't open is "can't listen", not "Home network off". - A definite reason from the other machine beats this machine's guesses; the deaf line names only this machine's own VPN/virtual adapter. - A report counts as sent only once the relay took it, so failures retry. - Network facts older than 90 s are left out of reports, and a machine heard here lately is never called quiet. - sync no longer assumes the home-network state exists at startup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A missing machine's report names a reason only if it reached the relay after this machine last heard that machine, and while this machine is online: a report made before it slept, quit or moved said "hears this machine" and was read as a firewall problem. - "It hears this machine" and "blocked" need its own sends known fine (no VPN, no failed broadcast) and a report made since this machine started listening. - A virtual adapter there is its own reason, not "a VPN". - An unknown report age (older relay) names only "off"; "last checked in" counts from when the machine was last heard if that's later. - Machines whose report says Home network is off no longer keep the others heartbeating or looking at their network. - Windows adapter descriptions are looked up whenever the network is looked at (cached 10 min), so a VPN called "Ethernet 4" isn't missed. - Network facts and their schedule use the wall clock; listening_since is fixed once, so a healthy machine's report doesn't look changed. - The public address is forgotten when subnets change, and a report is sent again at once when an upload reveals a new one; no report is asked for while offline (the session start sends one). - Line and details agree on which cause or reason is shown. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- "It hears this machine" needs a report made at least 55 s after this machine last heard it and after this run started (its list keeps a machine 45 s); other reasons need 20 s, two beacons, not one. - "Different network" by subnets comes before "it hears this machine", so a machine that moved isn't read as a firewall problem. - "Blocked" and "it hears this machine" also need this machine's own broadcasts to go out fine; a send that fails without an OS code counts. - The public address is forgotten at the start of each relay session. - The live connection counts as offline when a ping goes unanswered, so reports aren't trusted over a connection that died silently; a stale report nudge doesn't put the same report twice. - This machine's network facts older than 90 s are ignored by the diagnosis too; a clock stepped back means "look again". - An adapter Windows couldn't describe counts as unknown (retried each minute), not the home network. - A cause here gives way when every missing machine has a reason on its own side (incl. another network), so a laptop at a café isn't told to make its Wi-Fi Private; one that gave way marks nothing on the checklist. - Missing and deaf at once is said plainly; the deaf cause is found then. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- This machine's VPN explains a machine here that can't hear it, in its own field; it's no longer named as why another machine is missing. - Advice about this machine's network (Public, a VPN for the internet) is left out while a missing machine reports from a network this machine can't confirm is its own: a laptop at a café isn't told to make the café's Wi-Fi Private, even when the addresses can't be compared. - Waking from sleep (a beacon round over 30 s late) drops the reports read before and restarts the relay session at once; nothing from before sleep counts as current until it's read again. - One unanswered ping is enough to count the connection as dead (timed by the ticks themselves). - A VPN carrying the other machine's internet traffic, on this range and hearing nothing, is named as a likely reason; "it hears this machine" needs no VPN for the internet on either side. - While a machine here can't hear this one, reports go out every minute, and a fresh report that doesn't list this machine prompts a network look straight away, so "a firewall here" shows in about a minute, not six. - A Windows adapter with no description counts as unknown even when its network profile is known. - Machines whose report says Home network is off aren't "in sync"; with someone here, each missing machine's own reason is in the line. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Beacons still go to 255.255.255.255 and now also to the directed broadcast
address of each Wi-Fi/Ethernet subnet (e.g. 192.168.1.255). On Windows the
limited broadcast follows the lowest-metric route, usually a VPN's or a
Hyper-V/WSL adapter's, so machines on the same Wi-Fi never heard each other;
a directed broadcast follows its subnet's own route out of that adapter.
Sync now works with a VPN on unless it blocks local traffic. Older builds
receive these unchanged.
The subnet list is one interface listing, refreshed at most every minute on
the existing beacon. With direct sends a VPN on the broadcast route is only
the likely reason ("most likely blocking local traffic", vpn_blocks) and a
virtual adapter none; reports say `direct` so the other side words it the
same. Decision #125 (Proposed).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A VPN on the broadcast route is only a guess with direct sends (vpn_blocks): ranked after Local Network off and a Public network, left out while a missing machine may be elsewhere or hears this one, and never given as why a machine heard here can't hear this one. - The Public/Private profile is read from the home adapter direct sends use when a VPN holds the broadcast route. - Direct sends that all fail count as a failed broadcast (macOS Local Network off). - On Windows only adapters Windows has described get direct sends (each asked about once per launch), so no beacon goes into a VPN named "Ethernet 3"; the list is worked out again when the internet route's source changes and after looking at the network. - The other machine's VPN with direct sends is named after "another network"; a virtual adapter on the route doesn't stop "blocked". - Changelog no longer promises virtual-adapter reasons. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Looking at the network marks the direct list stale instead of dropping it, so the diagnosis and report in the same round don't think direct sends stopped (which briefly brought back the sure VPN reasons). - The other machine's VPN isn't named while it hears this machine. - With direct sends, Public is named only when Windows says so of every home adapter (a Public Dante NIC isn't the Wi-Fi the beacons use). - A direct send the OS accepted clears a failed 255.255.255.255 send. - Adapter descriptions: one PowerShell run at a time, failures retried after 10 minutes, and a network look no longer drops descriptions learned meanwhile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 of 6 tasks
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.
Closes #222. Stacked on #221, which is itself stacked on #218. Please merge in order: #218, then #221, then this one; each retargets to
mainas the one below merges.Why
Home-network beacons go to 255.255.255.255. On Windows that leaves through the lowest-metric route, which with a VPN on is usually the VPN's adapter (a Hyper-V/WSL adapter can do the same). So two machines on the same Wi-Fi never hear each other, even when the VPN allows local traffic. That was Brian's case when we first linked machines.
What changes
192.168.1.255). That follows the subnet's own route out of the Wi-Fi/Ethernet adapter, past the VPN's default route.0.0.0.0. Replies and pulls were already unicast to the peer's address.vpn_blocks: "Patch Pilot also sends straight onto your home network, so the VPN is most likely blocking local traffic". It ranks below sure causes (Local Network off, Public network) and isn't named while the other machine may be on another network or hears this one.direct, so the other machine words it the same way.A VPN that blocks all local traffic (kill switch, "block LAN") still stops sync. The app then says so.
Decision
#125 is Proposed. It's the last row of
docs/decisions.md.Review
Testing
cargo fmt --check,clippy -D warnings,cargo teston both workspaces: 489 core tests, 7 new. App tests pass;npm run buildpasses.10.0.0.255, WSL adapter left out), and the beacon arrives at a listener bound like Patch Pilot's. Run it with:cargo test -p patchpilot-local directed -- --ignored --nocapture🤖 Generated with Claude Code