diff --git a/README.md b/README.md index 48d2deb..d03306f 100644 --- a/README.md +++ b/README.md @@ -207,14 +207,17 @@ cargo run -p lanparty-client-win -- \ The Windows client binary currently connects to the relay as `role = client` with a generated locally administered virtual MAC persisted in -`lanparty-client-identity.json`, resolves the relay DNS name before TAP -activation, completes the control-stream hello/welcome handshake, pins a host -route for the resolved relay IP on the current pre-TAP interface, verifies that -the relay route still uses that pinned host route after TAP activation, and then -bridges Ethernet frames between the relay and the first TAP-Windows6 adapter -until shutdown. `--relay` accepts a DNS name or socket address; bare hosts -default to UDP/443. Before opening the adapter, it writes the -generated tunnel MAC to the TAP driver's `NetworkAddress` registry setting. +`lanparty-client-identity.json`. Before resolving or connecting to the relay, +it selects the TAP-Windows6 adapter and marks TAP media disconnected to clear +stale connected state from a previous crashed run. It then resolves the relay +DNS name before TAP activation, completes the control-stream hello/welcome +handshake, pins a host route for the resolved relay IP on the current pre-TAP +interface, verifies that the relay route still uses that pinned host route +after TAP activation, and then bridges Ethernet frames between the relay and +the first TAP-Windows6 adapter until shutdown. `--relay` accepts a DNS name or +socket address; bare hosts default to UDP/443. Before opening the adapter for +bridging, it writes the generated tunnel MAC to the TAP driver's +`NetworkAddress` registry setting. If the exact relay host route already exists, the client uses it and leaves it alone on exit. The startup status reports whether the relay already has a LAN gateway for the room. diff --git a/TESTING.md b/TESTING.md index b4bc4bc..b8421a3 100644 --- a/TESTING.md +++ b/TESTING.md @@ -118,6 +118,7 @@ one explicitly: Expected client output: ```text +prepared TAP adapter ... media disconnected before relay connect lanparty-client-win connected as peer ... relay route pinned before TAP ... relay route verified after TAP activation ... @@ -218,6 +219,11 @@ drop_reason=ControlPlaneEtherType If the client says `Waiting for LAN gateway`, check that the gateway uses the same room code and is connected to the same relay. +If startup fails before the relay connection while preparing the TAP adapter, +check that the terminal is elevated, TAP-Windows6 is installed, and +`--tap-instance-id` selects the intended adapter when more than one TAP adapter +exists. + If the client says `Waiting for TAP IP`, DHCP is not making the full round trip. Check relay/gateway frame logs for broadcast traffic and check that the gateway is on wired Ethernet. diff --git a/crates/lanparty-client-win/src/main.rs b/crates/lanparty-client-win/src/main.rs index a89ea13..8753287 100644 --- a/crates/lanparty-client-win/src/main.rs +++ b/crates/lanparty-client-win/src/main.rs @@ -145,6 +145,9 @@ async fn main() -> Result<()> { return Ok(()); } + #[cfg(windows)] + prepare_tap_before_relay_connect(args.tap_instance_id.as_deref())?; + let config = args.into_config()?; println!( "lanparty-client-win connecting virtual MAC {} to relay {} room {}", @@ -197,6 +200,21 @@ fn print_available_tap_adapters() -> Result<()> { Ok(()) } +#[cfg(windows)] +fn prepare_tap_before_relay_connect(tap_instance_id: Option<&str>) -> Result<()> { + let adapters = lanparty_client_tap::available_adapters() + .context("failed to list TAP-Windows6 adapters before relay connect")?; + let info = select_tap_adapter(adapters, tap_instance_id)?; + let device_path = info.device_path(); + let tap = TapAdapter::open(info)?; + tap.set_media_connected(false) + .with_context(|| format!("failed to mark TAP media disconnected for {device_path}"))?; + + println!("prepared TAP adapter {device_path}: media disconnected before relay connect"); + + Ok(()) +} + #[cfg(windows)] async fn run_client( session: &ClientSession,