feat(gateway): connect to relay control plane

The gateway binary now has a real relay-facing configuration and QUIC control
handshake. It accepts a relay socket address, expected TLS server name, pinned
DER relay certificate, room code, LAN interface name, and advertised datagram
budget, then connects as role = gateway and waits for a welcome response.

The ALPN token moved into lanparty-ctrl so relay and gateway share the same
protocol identifier instead of carrying duplicate private constants. The gateway
still stops after the control-plane connection; AF_PACKET capture and injection
remain a later slice.

The connector test spins up a local Quinn server with a self-signed certificate,
trusts that certificate explicitly, verifies the outgoing gateway hello, and
checks the received welcome metadata.

Test Plan:
- cargo fmt --check
- cargo test --workspace
- cargo clippy --workspace --all-targets -- -D warnings

Refs: PLAN.md Linux gateway outbound relay connection
This commit is contained in:
2026-05-21 18:06:22 +02:00
parent 956650ea8a
commit 763a55bfba
7 changed files with 449 additions and 5 deletions
+26 -2
View File
@@ -1,3 +1,27 @@
fn main() {
println!("Hello, world!");
use clap::Parser;
use lanparty_gateway::{GatewayArgs, connect_gateway};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = GatewayArgs::parse().into_config()?;
println!(
"lanparty-gateway connecting interface {} to relay {} room {}",
config.interface(),
config.relay_addr(),
config.room()
);
let gateway = connect_gateway(config).await?;
println!(
"lanparty-gateway connected as peer {} in room id {} with TAP MTU {}",
gateway.welcome().peer_id(),
gateway.welcome().room_id(),
gateway.welcome().effective_tap_mtu()
);
println!("AF_PACKET bridging is not wired yet; press Ctrl-C to stop");
tokio::signal::ctrl_c().await?;
gateway.shutdown("gateway shutting down").await;
Ok(())
}