You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- In dev, `network.firstTriggerDone` is `false`, so launch-time mDNS is gated off. When macOS auto-remounts an SMB share at login, `volumes::watcher::try_upgrade_smb_mount` fired before mDNS had discovered the host, so `statfs`'s IP couldn't be mapped to a hostname. Keychain credentials keyed by hostname (`smb://naspolya/share`) missed, and we prompted for credentials the user had already saved a few seconds before mDNS warmed up.
- Both upgrade entry points (`commands::network::upgrade_to_smb_volume` and the FSEvents watcher path) now call `network::ensure_mdns_started` (idempotent, no-op if `network.enabled` is off) and use the new `resolve_ip_to_hostname_with_wait` (polls 100ms up to 1500ms, only for private-range IPv4 — Tailscale/public IPs skip the wait).
- Added a runtime `network::NETWORK_ENABLED` flag (mirrors `network.enabled`) so BE paths can short-circuit cleanly when the user disabled networking, instead of needlessly polling.
- Unit tests cover the three short-circuits (non-private IP, disabled, timeout fallback).
- The wait fails open: if mDNS never warms, the existing IP-only Keychain lookup still runs.
Copy file name to clipboardExpand all lines: apps/desktop/src-tauri/src/network/CLAUDE.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,6 +46,11 @@ lifecycle:
46
46
-**`network.firstTriggerDone`** (boolean, default `false`, hidden): tracks whether we've already performed a gated
47
47
network action. Persisted across launches.
48
48
49
+
The runtime mirror of `network.enabled` lives in `network::NETWORK_ENABLED` (`AtomicBool`). `lib.rs::setup` seeds it
50
+
from the persisted settings; `commands::network::set_network_enabled` keeps it in sync with the live toggle.
51
+
`network::is_network_enabled()` is the runtime accessor; BE-side upgrade paths check this before kicking off mDNS or
52
+
waiting on hostname resolution.
53
+
49
54
At startup, mDNS starts only if `network.enabled && (firstTriggerDone || smb-e2e feature)`. On a fresh install,
50
55
`firstTriggerDone == false` so we stay quiet and the macOS "Cmdr wants to find devices on local networks" prompt
51
56
doesn't fire at app launch.
@@ -160,4 +165,14 @@ convention) and passes it as an explicit mount point to `NetFSMountURLSync`. The
160
165
-**Mount URL must include port when non-standard**: `mount_share_sync` builds `smb://server:port/share` for non-445 ports. The port is passed as a separate parameter through `mount_share` → `mount_share_sync`, not embedded in the server string (embedding it would cause `build_smb_addr` to double the port: `localhost:10480:10480`). `SmbMountInfo.port` extracts the port from `statfs` mount source for upgrade paths.
161
166
-**Strip `.local` from addr for smb2**: `smb2::Connection::connect()` extracts `server_name` from the addr string and uses it in UNC paths. Passing `"foo.local:445"` creates `\\foo.local\IPC$` which some servers reject. The `build_addr` helper in `smb_connection.rs` handles this.
162
167
-**Manual hosts always set `hostname`**: The share listing pipeline guards on `host.hostname` being truthy. `create_network_host` always sets `hostname` (to the address, even for IPs) so manual hosts flow through the pipeline correctly.
168
+
-**SMB upgrade waits briefly for mDNS to warm**: When macOS auto-remounts an SMB share at login, FSEvents fires before
169
+
mDNS has discovered the host, so `statfs` gives us an IP but the host map is empty. Stored Keychain credentials are
170
+
keyed by mDNS hostname (`smb://naspolya/share`), not by IP, so a sync IP→hostname lookup misses and we'd prompt the
171
+
user for credentials they already saved. The upgrade path now (a) kicks off mDNS via `network::ensure_mdns_started`
172
+
before resolving and (b) calls `smb_upgrade::resolve_ip_to_hostname_with_wait` which polls the discovered-host map
173
+
every 100ms up to 1500ms for private-range IPv4. Non-private IPs (Tailscale, public DNS) skip the wait — mDNS won't
174
+
help there. The wait fails open: if mDNS never warms, the IP-only Keychain lookup still runs. Only relevant in dev,
175
+
where `network.firstTriggerDone == false` keeps mDNS off at launch; prod users hit this once on the very first install
176
+
but never afterwards. Both entry points are covered: `commands::network::upgrade_to_smb_volume` (manual "Connect
177
+
directly") and `volumes::watcher::try_upgrade_smb_mount` (FSEvents auto-upgrade).
163
178
-**`statfs` can return mDNS service names instead of IPs**: When macOS auto-reconnects an SMB mount on login, `statfs.f_mntfromname` may contain `//user@Naspolya._smb._tcp.local/share` instead of `//user@192.168.1.111/share`. These service names are not DNS-resolvable. `resolve_server_address()` in `commands/network.rs` detects these (by checking for `._tcp`/`._udp`) and resolves them to IPs via `get_discovered_hosts()`. All upgrade paths (startup, mount-time, manual) go through this resolution. Similarly, `friendly_server_name()` extracts the display name (e.g., `Naspolya`) for UI display.
0 commit comments