feat(client): pin relay route before opening TAP
Create the relay host-route pin in the Windows client before the TAP adapter is opened and marked connected. The guard is held until after `ClientSession` shutdown so both the active tunnel and the QUIC close path keep using the pre-TAP interface. Route inspection or route creation failure now aborts startup before TAP activation, and the client explicitly closes the relay session in that failure path. Once the pin is installed, the client reports both the original best-route snapshot and the pinned route. Default-route takeover detection/neutralization is still future work. Verification note: I attempted to check `lanparty-client-win` for `x86_64-pc-windows-msvc`, but this host still lacks the Windows C headers needed by `ring`; the build stops at `assert.h` before the binary crate can be typechecked for Windows. Test Plan: - cargo fmt --check - cargo test --workspace - cargo clippy --workspace --all-targets -- -D warnings - cargo check -p lanparty-client-route --target x86_64-pc-windows-msvc - cargo clippy -p lanparty-client-route --target x86_64-pc-windows-msvc --all-targets -- -D warnings - git diff --check Refs: PLAN.md
This commit is contained in:
@@ -13,7 +13,7 @@ use lanparty_client_core::{
|
||||
ClientIdentity, ClientIdentityStore, ClientSession, ClientSessionConfig, connect_client,
|
||||
};
|
||||
#[cfg(windows)]
|
||||
use lanparty_client_route::RouteSnapshot;
|
||||
use lanparty_client_route::{PinnedRelayRoute, RouteSnapshot};
|
||||
#[cfg(windows)]
|
||||
use lanparty_client_tap::TapAdapter;
|
||||
use lanparty_ctrl::RoomCode;
|
||||
@@ -100,17 +100,28 @@ async fn main() -> Result<()> {
|
||||
session.welcome().room_id(),
|
||||
session.welcome().effective_tap_mtu()
|
||||
);
|
||||
#[cfg(windows)]
|
||||
let relay_route_pin = match pin_relay_route_before_tap(session.config().relay_addr().ip()) {
|
||||
Ok(pin) => pin,
|
||||
Err(error) => {
|
||||
session.shutdown("client startup failed").await;
|
||||
return Err(error);
|
||||
}
|
||||
};
|
||||
let run_result = run_client(&session).await;
|
||||
session.shutdown("client shutting down").await;
|
||||
#[cfg(windows)]
|
||||
drop(relay_route_pin);
|
||||
|
||||
run_result
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
async fn run_client(session: &ClientSession) -> Result<()> {
|
||||
log_relay_route_before_tap(session.config().relay_addr().ip());
|
||||
let tap = open_tap_adapter(session)?;
|
||||
println!("bridging TAP frames; route pinning is not wired yet; press Ctrl-C to stop");
|
||||
println!(
|
||||
"bridging TAP frames; relay route is pinned; default-route neutralization is not wired yet; press Ctrl-C to stop"
|
||||
);
|
||||
|
||||
tokio::select! {
|
||||
result = run_tap_frame_pump(session.relay_io(), tap) => result,
|
||||
@@ -129,13 +140,15 @@ async fn run_client(session: &ClientSession) -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn log_relay_route_before_tap(destination: std::net::IpAddr) {
|
||||
match lanparty_client_route::best_route_to(destination) {
|
||||
Ok(route) => print_relay_route(&route),
|
||||
Err(error) => eprintln!(
|
||||
"failed to inspect relay route before TAP activation; route pinning is not wired yet: {error:#}"
|
||||
),
|
||||
}
|
||||
fn pin_relay_route_before_tap(destination: std::net::IpAddr) -> Result<PinnedRelayRoute> {
|
||||
let route = lanparty_client_route::best_route_to(destination)
|
||||
.context("failed to inspect relay route before TAP activation")?;
|
||||
print_relay_route(&route);
|
||||
let pin = lanparty_client_route::pin_relay_route(&route)
|
||||
.context("failed to pin relay route before TAP activation")?;
|
||||
print_pinned_relay_route(&pin);
|
||||
|
||||
Ok(pin)
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -155,6 +168,19 @@ fn print_relay_route(route: &RouteSnapshot) {
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn print_pinned_relay_route(route: &PinnedRelayRoute) {
|
||||
println!(
|
||||
"relay route pinned before TAP: destination {} next hop {} interface index {} LUID {}",
|
||||
route.destination(),
|
||||
route
|
||||
.next_hop()
|
||||
.map_or_else(|| "on-link".to_string(), |next_hop| next_hop.to_string()),
|
||||
route.interface_index(),
|
||||
route.interface_luid()
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
fn open_tap_adapter(session: &ClientSession) -> Result<lanparty_client_tap::TapAdapter> {
|
||||
let tap = lanparty_client_tap::open_first_adapter()?;
|
||||
|
||||
Reference in New Issue
Block a user