From e5f6e44d12b72e8e66c5cdae7382d755138e8f15 Mon Sep 17 00:00:00 2001 From: ddidderr Date: Fri, 22 May 2026 08:45:02 +0200 Subject: [PATCH] fix(client): fail fast outside Windows The MVP client only has a real TAP and route-protection runtime on Windows. A non-Windows build was able to connect to the relay as a no-TAP client and then wait for control events, which could consume a room slot while giving the false impression that the Windows client path had been exercised. Reject normal runtime startup on non-Windows platforms before reading tunnel inputs or joining the relay. Keep non-Windows builds useful for type checking, and document that they are not runnable tunnel clients. Test Plan: - cargo fmt --check - cargo test -p lanparty-client-win - cargo check -p lanparty-client-win - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo run -p lanparty-client-win -- --relay 127.0.0.1:1 \ --relay-ca-cert /tmp/does-not-matter.der --room ROOM1 - git diff --check - git diff --cached --check Refs: MVP Windows TAP client boundary --- README.md | 8 ++++++-- crates/lanparty-client-win/src/main.rs | 27 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 68e761f..9fbbbec 100644 --- a/README.md +++ b/README.md @@ -235,8 +235,12 @@ cargo run -p lanparty-client-win -- \ --room ROOM1 ``` -The Windows client binary currently connects to the relay as `role = client` -with a generated locally administered virtual MAC persisted in +The Windows client binary is runtime-gated to Windows because the real client +path depends on TAP-Windows6 and Windows route protection. Non-Windows builds +are useful for type checking, but they fail before tunnel setup instead of +joining a room without a TAP adapter. On Windows, the binary connects to the +relay as `role = client` with a generated locally administered virtual MAC +persisted in `lanparty-client-identity.json`. Before resolving or connecting to the relay, it writes the generated tunnel MAC to the selected TAP driver's `NetworkAddress` registry setting and marks TAP media disconnected. That clears diff --git a/crates/lanparty-client-win/src/main.rs b/crates/lanparty-client-win/src/main.rs index c821b55..744e936 100644 --- a/crates/lanparty-client-win/src/main.rs +++ b/crates/lanparty-client-win/src/main.rs @@ -172,6 +172,7 @@ async fn main() -> Result<()> { return Ok(()); } + ensure_supported_platform()?; let startup_config = args.into_startup_config()?; #[cfg(windows)] prepare_tap_before_relay_connect( @@ -218,6 +219,18 @@ async fn main() -> Result<()> { run_result } +#[cfg(windows)] +fn ensure_supported_platform() -> Result<()> { + Ok(()) +} + +#[cfg(not(windows))] +fn ensure_supported_platform() -> Result<()> { + bail!( + "lanparty-client-win can only run on Windows; TAP-Windows6 and relay route protection are Windows-only" + ) +} + fn print_available_tap_adapters() -> Result<()> { let adapters = lanparty_client_tap::available_adapters()?; for line in format_tap_adapter_list(&adapters) { @@ -1235,6 +1248,20 @@ mod tests { use lanparty_net::DEFAULT_RELAY_PORT; use lanparty_obs::{QuicDiagnostics, TunnelStats}; + #[cfg(not(windows))] + #[test] + fn rejects_runtime_on_non_windows() { + let error = ensure_supported_platform().unwrap_err(); + + assert!(error.to_string().contains("can only run on Windows")); + } + + #[cfg(windows)] + #[test] + fn accepts_runtime_on_windows() { + assert!(ensure_supported_platform().is_ok()); + } + #[test] fn accepts_matching_tap_driver_mac() { assert!(validate_tap_driver_mac(mac(1), mac(1)).is_ok());