From 2b066b3e1126c1005e6ec2fe23f6192e88091a15 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Sat, 15 Aug 2026 00:13:43 +0200 Subject: [PATCH] =?UTF-8?q?fix(clients):=20the=20mgmt-port=20learn=20lande?= =?UTF-8?q?d=20without=20its=20Windows=20half=20=E2=80=94=20restore=20the?= =?UTF-8?q?=20three=20missing=20pieces?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 99eb679c wired the learned management port through every client, and its own commit message records the hole: 'NOT verified: the Windows client (192.168.1.133 unreachable)'. The Windows shell's usage sites landed, but the three definitions they lean on did not exist anywhere, so main's windows-client build has been red since the merge of #230: * clients/windows/src/trust.rs re-exports core's trust surface — learn_mgmt_port was added to core but never joined the re-export list (hosts.rs:729, E0425). * The Windows shell's own mDNS browser (discovery.rs, 'ported verbatim from the GTK client') never learned the mgmt TXT that pf_client_core::discovery already parses — DiscoveredHost gains the field, parsed the same way (hosts.rs:725/727/1062, E0609). * HostTarget ('the host a plan dials') never carried the port, so the Target the shell builds from a ConnectPlan had nothing to read (mod.rs:414, E0609). Wired From<&KnownHost> like mac; the two spawn-path literals stay None — a spawn plan never fetches the library, and each shell resolves the port itself at its fetch site. cargo fmt --all --check clean. pf-client-core/linux/session compile via the rust CI job; the windows-client job on this PR is the verification 99eb679c could not run. --- clients/linux/src/spawn.rs | 1 + clients/windows/src/discovery.rs | 6 ++++++ clients/windows/src/spawn.rs | 1 + clients/windows/src/trust.rs | 4 ++-- crates/pf-client-core/src/orchestrate.rs | 7 +++++++ 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/clients/linux/src/spawn.rs b/clients/linux/src/spawn.rs index b57ecccd..babf91b0 100644 --- a/clients/linux/src/spawn.rs +++ b/clients/linux/src/spawn.rs @@ -50,6 +50,7 @@ fn plan_for(req: &ConnectRequest, fp_hex: &str, tofu: bool, opts: &SpawnOpts) -> fp_hex: Some(fp_hex.to_string()), mac: req.mac.clone(), id: None, + mgmt_port: None, // this shell resolves the library port itself (`mgmt_port_for`) }, req.launch.as_ref().map(|(id, _)| id.clone()), // A plain card click carries no one-off: the resolver honors the host's own binding diff --git a/clients/windows/src/discovery.rs b/clients/windows/src/discovery.rs index afce6dd5..94dd0afe 100644 --- a/clients/windows/src/discovery.rs +++ b/clients/windows/src/discovery.rs @@ -28,6 +28,11 @@ pub struct DiscoveredHost { /// `linux[/][/]`), sanitized — drives the host tile's OS mark and is /// persisted like `mac`. Empty if absent (older host). pub os: String, + /// The management API's port from the mDNS `mgmt` TXT — where the game library is served. + /// Persisted like `mac` (`trust::learn_mgmt_port`), and load-bearing rather than cosmetic: + /// a host moved off 47990 loses its library once mDNS is gone unless we write this down. + /// `None` if absent (older host) — resolve via `library::DEFAULT_MGMT_PORT`. + pub mgmt_port: Option, } /// Forces the running browse to re-query now — the hosts page's Refresh. Mirrors @@ -124,6 +129,7 @@ pub fn browse() -> (async_channel::Receiver, Rescan) { .filter(|s| !s.is_empty()) .collect(), os: pf_client_core::os::sanitize_os(&val("os")), + mgmt_port: val("mgmt").parse().ok(), }; if tx.send_blocking(host).is_err() { break; // UI gone — stop browsing diff --git a/clients/windows/src/spawn.rs b/clients/windows/src/spawn.rs index ab907c74..2ce34078 100644 --- a/clients/windows/src/spawn.rs +++ b/clients/windows/src/spawn.rs @@ -160,6 +160,7 @@ pub(crate) fn spawn_session( fp_hex: Some(fp_hex.to_string()), mac: Vec::new(), // wake ran before this spawn (initiate_waking) — not the plan's job id: None, + mgmt_port: None, // the library fetch runs in the shell (`Target`), never off a spawn plan }, launch.map(str::to_string), profile.map(str::to_string), diff --git a/clients/windows/src/trust.rs b/clients/windows/src/trust.rs index e16463c9..96976620 100644 --- a/clients/windows/src/trust.rs +++ b/clients/windows/src/trust.rs @@ -8,6 +8,6 @@ //! still load via a serde alias in core. pub use pf_client_core::trust::{ - hex, learn_mac, learn_os, load_or_create_identity, pair_error_message, parse_hex32, KnownHost, - KnownHosts, Settings, + hex, learn_mac, learn_mgmt_port, learn_os, load_or_create_identity, pair_error_message, + parse_hex32, KnownHost, KnownHosts, Settings, }; diff --git a/crates/pf-client-core/src/orchestrate.rs b/crates/pf-client-core/src/orchestrate.rs index 7eb07676..72c49e4b 100644 --- a/crates/pf-client-core/src/orchestrate.rs +++ b/crates/pf-client-core/src/orchestrate.rs @@ -38,6 +38,12 @@ pub struct HostTarget { pub fp_hex: Option, pub mac: Vec, pub id: Option, + /// The host's management-API port (saved store or live advert) — where the library is + /// served, distinct from `port` (the native QUIC plane). Carried on the target for the same + /// reason as `mac`: a front-end holding a plan has no `KnownHost` in hand, and resolving to + /// [`crate::library::DEFAULT_MGMT_PORT`] there is what made a moved mgmt port work on the + /// LAN but not over a VPN. `None` = unknown, fall back to the constant. + pub mgmt_port: Option, } impl From<&KnownHost> for HostTarget { @@ -49,6 +55,7 @@ impl From<&KnownHost> for HostTarget { fp_hex: (!h.fp_hex.is_empty()).then(|| h.fp_hex.clone()), mac: h.mac.clone(), id: h.id.clone(), + mgmt_port: h.mgmt_port, } } } -- 2.54.0