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:
Generated
+9
@@ -451,6 +451,15 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "lanparty-gateway"
|
name = "lanparty-gateway"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap",
|
||||||
|
"lanparty-ctrl",
|
||||||
|
"quinn",
|
||||||
|
"rcgen",
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lanparty-obs"
|
name = "lanparty-obs"
|
||||||
|
|||||||
@@ -68,3 +68,18 @@ replies with `welcome` or `reject`, and forwards live Ethernet QUIC datagrams
|
|||||||
between accepted peers in the same room. It currently uses a generated
|
between accepted peers in the same room. It currently uses a generated
|
||||||
self-signed development certificate; production certificate and client trust
|
self-signed development certificate; production certificate and client trust
|
||||||
handling remain future work.
|
handling remain future work.
|
||||||
|
|
||||||
|
## Gateway
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo run -p lanparty-gateway -- \
|
||||||
|
--relay 203.0.113.10:443 \
|
||||||
|
--server-name lanparty-relay.local \
|
||||||
|
--relay-ca-cert relay-cert.der \
|
||||||
|
--room ROOM1 \
|
||||||
|
--interface eth0
|
||||||
|
```
|
||||||
|
|
||||||
|
The gateway currently connects to the relay as `role = gateway`, completes the
|
||||||
|
control-stream hello/welcome handshake, and then waits for shutdown. AF_PACKET
|
||||||
|
capture and injection are not wired yet.
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ pub use lanparty_obs::TunnelStats;
|
|||||||
use lanparty_proto::{MIN_USEFUL_TAP_MTU, MacAddr, MtuError, recommended_tap_mtu};
|
use lanparty_proto::{MIN_USEFUL_TAP_MTU, MacAddr, MtuError, recommended_tap_mtu};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub const RELAY_ALPN: &[u8] = b"lanparty-l2/1";
|
||||||
pub const CONTROL_PROTOCOL_VERSION: u16 = 1;
|
pub const CONTROL_PROTOCOL_VERSION: u16 = 1;
|
||||||
pub const MIN_ROOM_CODE_LEN: usize = 1;
|
pub const MIN_ROOM_CODE_LEN: usize = 1;
|
||||||
pub const MAX_ROOM_CODE_LEN: usize = 64;
|
pub const MAX_ROOM_CODE_LEN: usize = 64;
|
||||||
|
|||||||
@@ -4,3 +4,12 @@ version.workspace = true
|
|||||||
edition.workspace = true
|
edition.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
clap.workspace = true
|
||||||
|
lanparty-ctrl = { path = "../lanparty-ctrl" }
|
||||||
|
quinn.workspace = true
|
||||||
|
rustls.workspace = true
|
||||||
|
tokio.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
rcgen.workspace = true
|
||||||
|
|||||||
@@ -0,0 +1,387 @@
|
|||||||
|
//! Linux LAN gateway control-plane connection.
|
||||||
|
//!
|
||||||
|
//! This crate owns the gateway binary's relay connection and, in later slices,
|
||||||
|
//! will add the AF_PACKET capture/injection loop that feeds Ethernet frames into
|
||||||
|
//! this established QUIC session.
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
|
||||||
|
path::PathBuf,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result, bail};
|
||||||
|
use clap::Parser;
|
||||||
|
use lanparty_ctrl::{
|
||||||
|
CONTROL_LENGTH_PREFIX_LEN, ControlMessage, EndpointHello, MAX_CONTROL_MESSAGE_LEN, RELAY_ALPN,
|
||||||
|
RoomCode, ServerWelcome, decode_control_frame, encode_control_message,
|
||||||
|
};
|
||||||
|
use quinn::{ClientConfig, Endpoint, crypto::rustls::QuicClientConfig};
|
||||||
|
use rustls::pki_types::CertificateDer;
|
||||||
|
|
||||||
|
const MAX_CONTROL_FRAME_LEN: usize = CONTROL_LENGTH_PREFIX_LEN + MAX_CONTROL_MESSAGE_LEN;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(
|
||||||
|
name = "lanparty-gateway",
|
||||||
|
about = "Linux LAN gateway for the LAN party L2 tunnel"
|
||||||
|
)]
|
||||||
|
pub struct GatewayArgs {
|
||||||
|
/// Relay UDP socket address, for example 203.0.113.10:443.
|
||||||
|
#[arg(long)]
|
||||||
|
relay: SocketAddr,
|
||||||
|
|
||||||
|
/// TLS server name expected in the relay certificate.
|
||||||
|
#[arg(long, default_value = "lanparty-relay.local")]
|
||||||
|
server_name: String,
|
||||||
|
|
||||||
|
/// DER-encoded relay CA/certificate to trust.
|
||||||
|
#[arg(long, value_name = "PATH")]
|
||||||
|
relay_ca_cert: PathBuf,
|
||||||
|
|
||||||
|
/// Room code to join as the LAN gateway.
|
||||||
|
#[arg(long)]
|
||||||
|
room: RoomCode,
|
||||||
|
|
||||||
|
/// Wired LAN interface that will later be opened with AF_PACKET.
|
||||||
|
#[arg(long)]
|
||||||
|
interface: String,
|
||||||
|
|
||||||
|
/// Gateway's advertised QUIC datagram budget before relay clamping.
|
||||||
|
#[arg(long, default_value_t = 1400)]
|
||||||
|
max_datagram_size: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GatewayArgs {
|
||||||
|
pub fn into_config(self) -> Result<GatewayConfig> {
|
||||||
|
let relay_ca_cert = fs::read(&self.relay_ca_cert).with_context(|| {
|
||||||
|
format!(
|
||||||
|
"failed to read relay CA certificate {}",
|
||||||
|
self.relay_ca_cert.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
GatewayConfig::new(
|
||||||
|
self.relay,
|
||||||
|
self.server_name,
|
||||||
|
relay_ca_cert,
|
||||||
|
self.room,
|
||||||
|
self.interface,
|
||||||
|
self.max_datagram_size,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct GatewayConfig {
|
||||||
|
relay_addr: SocketAddr,
|
||||||
|
server_name: String,
|
||||||
|
relay_ca_cert_der: Vec<u8>,
|
||||||
|
room: RoomCode,
|
||||||
|
interface: String,
|
||||||
|
max_datagram_size: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GatewayConfig {
|
||||||
|
pub fn new(
|
||||||
|
relay_addr: SocketAddr,
|
||||||
|
server_name: impl Into<String>,
|
||||||
|
relay_ca_cert_der: Vec<u8>,
|
||||||
|
room: RoomCode,
|
||||||
|
interface: impl Into<String>,
|
||||||
|
max_datagram_size: u16,
|
||||||
|
) -> Result<Self> {
|
||||||
|
let server_name = server_name.into();
|
||||||
|
if server_name.trim().is_empty() {
|
||||||
|
bail!("relay server name cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
if relay_ca_cert_der.is_empty() {
|
||||||
|
bail!("relay CA certificate cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
let interface = interface.into();
|
||||||
|
if interface.trim().is_empty() {
|
||||||
|
bail!("gateway interface cannot be empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
EndpointHello::gateway(room.clone(), max_datagram_size)
|
||||||
|
.context("invalid gateway datagram budget")?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
relay_addr,
|
||||||
|
server_name,
|
||||||
|
relay_ca_cert_der,
|
||||||
|
room,
|
||||||
|
interface,
|
||||||
|
max_datagram_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn relay_addr(&self) -> SocketAddr {
|
||||||
|
self.relay_addr
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn server_name(&self) -> &str {
|
||||||
|
&self.server_name
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn relay_ca_cert_der(&self) -> &[u8] {
|
||||||
|
&self.relay_ca_cert_der
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn room(&self) -> &RoomCode {
|
||||||
|
&self.room
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn interface(&self) -> &str {
|
||||||
|
&self.interface
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn max_datagram_size(&self) -> u16 {
|
||||||
|
self.max_datagram_size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct GatewayConnection {
|
||||||
|
endpoint: Endpoint,
|
||||||
|
connection: quinn::Connection,
|
||||||
|
config: GatewayConfig,
|
||||||
|
welcome: ServerWelcome,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GatewayConnection {
|
||||||
|
#[must_use]
|
||||||
|
pub const fn config(&self) -> &GatewayConfig {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn welcome(&self) -> &ServerWelcome {
|
||||||
|
&self.welcome
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn shutdown(self, reason: &str) {
|
||||||
|
self.connection.close(0_u32.into(), reason.as_bytes());
|
||||||
|
self.endpoint.wait_idle().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn connect_gateway(config: GatewayConfig) -> Result<GatewayConnection> {
|
||||||
|
let client_config = relay_client_config(config.relay_ca_cert_der())?;
|
||||||
|
let mut endpoint = Endpoint::client(client_bind_addr(config.relay_addr()))
|
||||||
|
.context("failed to bind gateway QUIC endpoint")?;
|
||||||
|
endpoint.set_default_client_config(client_config);
|
||||||
|
|
||||||
|
let connection = endpoint
|
||||||
|
.connect(config.relay_addr(), config.server_name())?
|
||||||
|
.await
|
||||||
|
.with_context(|| format!("failed to connect to relay {}", config.relay_addr()))?;
|
||||||
|
let peer_datagram_size = connection
|
||||||
|
.max_datagram_size()
|
||||||
|
.context("relay did not negotiate QUIC DATAGRAM support")?;
|
||||||
|
let hello_datagram_size = usize::from(config.max_datagram_size())
|
||||||
|
.min(peer_datagram_size)
|
||||||
|
.min(usize::from(u16::MAX)) as u16;
|
||||||
|
let hello = EndpointHello::gateway(config.room().clone(), hello_datagram_size)
|
||||||
|
.context("failed to build gateway hello")?;
|
||||||
|
let response = request_control_message(&connection, ControlMessage::Hello(hello)).await?;
|
||||||
|
|
||||||
|
match response {
|
||||||
|
ControlMessage::Welcome(welcome) => Ok(GatewayConnection {
|
||||||
|
endpoint,
|
||||||
|
connection,
|
||||||
|
config,
|
||||||
|
welcome,
|
||||||
|
}),
|
||||||
|
ControlMessage::Reject(reject) => bail!(
|
||||||
|
"relay rejected gateway hello: {:?}: {}",
|
||||||
|
reject.reason(),
|
||||||
|
reject.message()
|
||||||
|
),
|
||||||
|
other => bail!("relay sent unexpected gateway handshake response: {other:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn relay_client_config(relay_ca_cert_der: &[u8]) -> Result<ClientConfig> {
|
||||||
|
let mut roots = rustls::RootCertStore::empty();
|
||||||
|
roots
|
||||||
|
.add(CertificateDer::from(relay_ca_cert_der.to_vec()))
|
||||||
|
.context("failed to trust relay CA certificate")?;
|
||||||
|
|
||||||
|
let mut client_crypto = rustls::ClientConfig::builder()
|
||||||
|
.with_root_certificates(roots)
|
||||||
|
.with_no_client_auth();
|
||||||
|
client_crypto.alpn_protocols = vec![RELAY_ALPN.to_vec()];
|
||||||
|
|
||||||
|
Ok(ClientConfig::new(Arc::new(
|
||||||
|
QuicClientConfig::try_from(client_crypto).context("failed to build QUIC client config")?,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn client_bind_addr(relay_addr: SocketAddr) -> SocketAddr {
|
||||||
|
match relay_addr.ip() {
|
||||||
|
IpAddr::V4(_) => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
|
||||||
|
IpAddr::V6(_) => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn request_control_message(
|
||||||
|
connection: &quinn::Connection,
|
||||||
|
message: ControlMessage,
|
||||||
|
) -> Result<ControlMessage> {
|
||||||
|
let (mut send, mut recv) = connection.open_bi().await?;
|
||||||
|
let request = encode_control_message(&message)?;
|
||||||
|
send.write_all(&request).await?;
|
||||||
|
send.finish()?;
|
||||||
|
|
||||||
|
let response = recv.read_to_end(MAX_CONTROL_FRAME_LEN).await?;
|
||||||
|
|
||||||
|
Ok(decode_control_frame(&response)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use lanparty_ctrl::Role;
|
||||||
|
use quinn::{ServerConfig, TransportConfig, crypto::rustls::QuicServerConfig};
|
||||||
|
use rustls::pki_types::{PrivateKeyDer, PrivatePkcs8KeyDer};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validates_gateway_config() {
|
||||||
|
let room = RoomCode::new("ROOM1").unwrap();
|
||||||
|
let cert = vec![1, 2, 3];
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
GatewayConfig::new(
|
||||||
|
"127.0.0.1:443".parse().unwrap(),
|
||||||
|
"relay.local",
|
||||||
|
cert.clone(),
|
||||||
|
room.clone(),
|
||||||
|
"eth0",
|
||||||
|
1400,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
GatewayConfig::new(
|
||||||
|
"127.0.0.1:443".parse().unwrap(),
|
||||||
|
"",
|
||||||
|
cert.clone(),
|
||||||
|
room.clone(),
|
||||||
|
"eth0",
|
||||||
|
1400,
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
GatewayConfig::new(
|
||||||
|
"127.0.0.1:443".parse().unwrap(),
|
||||||
|
"relay.local",
|
||||||
|
Vec::new(),
|
||||||
|
room.clone(),
|
||||||
|
"eth0",
|
||||||
|
1400,
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
GatewayConfig::new(
|
||||||
|
"127.0.0.1:443".parse().unwrap(),
|
||||||
|
"relay.local",
|
||||||
|
cert,
|
||||||
|
room,
|
||||||
|
"",
|
||||||
|
1400,
|
||||||
|
)
|
||||||
|
.is_err()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn connects_to_relay_control_stream_as_gateway() {
|
||||||
|
let (server_config, certificate) = test_server_config();
|
||||||
|
let endpoint = Endpoint::server(server_config, "127.0.0.1:0".parse().unwrap()).unwrap();
|
||||||
|
let server_addr = endpoint.local_addr().unwrap();
|
||||||
|
let server_task = tokio::spawn(async move {
|
||||||
|
let incoming = endpoint.accept().await.unwrap();
|
||||||
|
let connection = incoming.await.unwrap();
|
||||||
|
let (mut send, mut recv) = connection.accept_bi().await.unwrap();
|
||||||
|
let request = recv.read_to_end(MAX_CONTROL_FRAME_LEN).await.unwrap();
|
||||||
|
let message = decode_control_frame(&request).unwrap();
|
||||||
|
let ControlMessage::Hello(hello) = message else {
|
||||||
|
panic!("expected gateway hello");
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(hello.role(), Role::Gateway);
|
||||||
|
assert_eq!(hello.room().as_str(), "ROOM1");
|
||||||
|
|
||||||
|
let response = encode_control_message(&ControlMessage::Welcome(
|
||||||
|
ServerWelcome::new(7, 1, 1200).unwrap(),
|
||||||
|
))
|
||||||
|
.unwrap();
|
||||||
|
send.write_all(&response).await.unwrap();
|
||||||
|
send.finish().unwrap();
|
||||||
|
|
||||||
|
connection.closed().await;
|
||||||
|
endpoint.close(0_u32.into(), b"test complete");
|
||||||
|
endpoint.wait_idle().await;
|
||||||
|
});
|
||||||
|
let config = GatewayConfig::new(
|
||||||
|
server_addr,
|
||||||
|
"lanparty-relay.local",
|
||||||
|
certificate.as_ref().to_vec(),
|
||||||
|
RoomCode::new("ROOM1").unwrap(),
|
||||||
|
"eth0",
|
||||||
|
1400,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let gateway = connect_gateway(config).await.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(gateway.config().interface(), "eth0");
|
||||||
|
assert_eq!(gateway.welcome().room_id(), 7);
|
||||||
|
assert_eq!(gateway.welcome().peer_id(), 1);
|
||||||
|
|
||||||
|
gateway.shutdown("test complete").await;
|
||||||
|
tokio::time::timeout(Duration::from_secs(5), server_task)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_server_config() -> (ServerConfig, CertificateDer<'static>) {
|
||||||
|
let certified_key =
|
||||||
|
rcgen::generate_simple_self_signed(vec!["lanparty-relay.local".into()]).unwrap();
|
||||||
|
let certificate = certified_key.cert.der().clone();
|
||||||
|
let cert_chain = vec![certificate.clone()];
|
||||||
|
let private_key = PrivateKeyDer::Pkcs8(PrivatePkcs8KeyDer::from(
|
||||||
|
certified_key.signing_key.serialize_der(),
|
||||||
|
));
|
||||||
|
let mut tls_config = rustls::ServerConfig::builder()
|
||||||
|
.with_no_client_auth()
|
||||||
|
.with_single_cert(cert_chain, private_key)
|
||||||
|
.unwrap();
|
||||||
|
tls_config.alpn_protocols = vec![RELAY_ALPN.to_vec()];
|
||||||
|
|
||||||
|
let mut server_config =
|
||||||
|
ServerConfig::with_crypto(Arc::new(QuicServerConfig::try_from(tls_config).unwrap()));
|
||||||
|
let mut transport = TransportConfig::default();
|
||||||
|
transport.datagram_receive_buffer_size(Some(4 * 1024 * 1024));
|
||||||
|
transport.datagram_send_buffer_size(4 * 1024 * 1024);
|
||||||
|
server_config.transport_config(Arc::new(transport));
|
||||||
|
|
||||||
|
(server_config, certificate)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,27 @@
|
|||||||
fn main() {
|
use clap::Parser;
|
||||||
println!("Hello, world!");
|
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(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ use anyhow::{Context, Result, anyhow};
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use lanparty_ctrl::{
|
use lanparty_ctrl::{
|
||||||
CONTROL_LENGTH_PREFIX_LEN, ControlCodecError, ControlMessage, EndpointHello,
|
CONTROL_LENGTH_PREFIX_LEN, ControlCodecError, ControlMessage, EndpointHello,
|
||||||
MAX_CONTROL_MESSAGE_LEN, PeerInfo, Reject, RejectReason, Role, RoomCode, ServerWelcome,
|
MAX_CONTROL_MESSAGE_LEN, PeerInfo, RELAY_ALPN, Reject, RejectReason, Role, RoomCode,
|
||||||
decode_control_frame, encode_control_message,
|
ServerWelcome, decode_control_frame, encode_control_message,
|
||||||
};
|
};
|
||||||
use lanparty_proto::{FrameType, decode_datagram, encode_datagram};
|
use lanparty_proto::{FrameType, decode_datagram, encode_datagram};
|
||||||
use quinn::crypto::rustls::QuicServerConfig;
|
use quinn::crypto::rustls::QuicServerConfig;
|
||||||
@@ -16,7 +16,6 @@ use tokio::sync::Mutex;
|
|||||||
|
|
||||||
use crate::{RelayConfig, RoomRegistry};
|
use crate::{RelayConfig, RoomRegistry};
|
||||||
|
|
||||||
const RELAY_ALPN: &[u8] = b"lanparty-l2/1";
|
|
||||||
const DATAGRAM_BUFFER_BYTES: usize = 4 * 1024 * 1024;
|
const DATAGRAM_BUFFER_BYTES: usize = 4 * 1024 * 1024;
|
||||||
const MAX_CONTROL_FRAME_LEN: usize = CONTROL_LENGTH_PREFIX_LEN + MAX_CONTROL_MESSAGE_LEN;
|
const MAX_CONTROL_FRAME_LEN: usize = CONTROL_LENGTH_PREFIX_LEN + MAX_CONTROL_MESSAGE_LEN;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user