diff --git a/crates/lanspread-peer/src/config.rs b/crates/lanspread-peer/src/config.rs index 39a81f5..e20ff5c 100644 --- a/crates/lanspread-peer/src/config.rs +++ b/crates/lanspread-peer/src/config.rs @@ -23,6 +23,18 @@ pub const PEER_DOWNLOAD_STREAM_WINDOW: usize = 4; /// Maximum number of retry attempts for failed chunk downloads. pub const MAX_RETRY_COUNT: usize = 3; +/// QUIC connection-level receive window for bulk LAN transfers (64 MiB). +pub const QUIC_CONNECTION_DATA_WINDOW: u64 = 64 * 1024 * 1024; + +/// QUIC per-stream receive window for bulk LAN transfers (32 MiB). +pub const QUIC_STREAM_DATA_WINDOW: u64 = 32 * 1024 * 1024; + +/// Maximum queued send data per QUIC stream (32 MiB). +pub const QUIC_MAX_SEND_BUFFER_SIZE: u32 = 32 * 1024 * 1024; + +/// Initial congestion window for LAN-oriented BBR transfers (1 MiB). +pub const QUIC_INITIAL_CONGESTION_WINDOW: u32 = 1024 * 1024; + /// Fallback interval for reconciling missed filesystem watcher events (seconds). pub const LOCAL_GAME_FALLBACK_SCAN_SECS: u64 = 300; diff --git a/crates/lanspread-peer/src/network.rs b/crates/lanspread-peer/src/network.rs index e30bc5b..c96b066 100644 --- a/crates/lanspread-peer/src/network.rs +++ b/crates/lanspread-peer/src/network.rs @@ -10,19 +10,46 @@ use futures::{SinkExt, StreamExt}; use if_addrs::{IfAddr, Interface, get_if_addrs}; use lanspread_db::db::GameFileDescription; use lanspread_proto::{Hello, HelloAck, LibraryDelta, Message, Request, Response}; -use s2n_quic::{Client as QuicClient, Connection, client::Connect, provider::limits::Limits}; +use s2n_quic::{ + Client as QuicClient, + Connection, + client::Connect, + provider::{congestion_controller, limits::Limits}, +}; use tokio_util::codec::{FramedRead, FramedWrite, LengthDelimitedCodec}; -use crate::config::CERT_PEM; +use crate::config::{ + CERT_PEM, + QUIC_CONNECTION_DATA_WINDOW, + QUIC_INITIAL_CONGESTION_WINDOW, + QUIC_MAX_SEND_BUFFER_SIZE, + QUIC_STREAM_DATA_WINDOW, +}; + +pub(crate) fn quic_limits() -> eyre::Result { + Ok(Limits::default() + .with_data_window(QUIC_CONNECTION_DATA_WINDOW)? + .with_bidirectional_local_data_window(QUIC_STREAM_DATA_WINDOW)? + .with_bidirectional_remote_data_window(QUIC_STREAM_DATA_WINDOW)? + .with_unidirectional_data_window(QUIC_STREAM_DATA_WINDOW)? + .with_max_send_buffer_size(QUIC_MAX_SEND_BUFFER_SIZE)?) +} + +pub(crate) fn quic_congestion_controller() -> congestion_controller::Bbr { + congestion_controller::bbr::Builder::default() + .with_initial_congestion_window(QUIC_INITIAL_CONGESTION_WINDOW) + .build() +} /// Establishes a QUIC connection to a peer. pub async fn connect_to_peer(addr: SocketAddr) -> eyre::Result { - let limits = Limits::default().with_max_handshake_duration(Duration::from_secs(3))?; + let limits = quic_limits()?.with_max_handshake_duration(Duration::from_secs(3))?; let client = QuicClient::builder() .with_tls(CERT_PEM)? .with_io("0.0.0.0:0")? .with_limits(limits)? + .with_congestion_controller(quic_congestion_controller())? .start()?; let conn = Connect::new(addr).with_server_name("localhost"); diff --git a/crates/lanspread-peer/src/services/server.rs b/crates/lanspread-peer/src/services/server.rs index 4b20795..c9e636d 100644 --- a/crates/lanspread-peer/src/services/server.rs +++ b/crates/lanspread-peer/src/services/server.rs @@ -2,7 +2,7 @@ use std::{net::SocketAddr, time::Duration}; -use s2n_quic::{Connection, Server, provider::limits::Limits}; +use s2n_quic::{Connection, Server}; use tokio::sync::mpsc::UnboundedSender; use crate::{ @@ -10,6 +10,7 @@ use crate::{ config::{CERT_PEM, KEY_PEM}, context::PeerCtx, events, + network::{quic_congestion_controller, quic_limits}, services::{ advertise::{monitor_mdns_events, start_mdns_advertiser}, stream::handle_peer_stream, @@ -22,7 +23,7 @@ pub async fn run_server_component( ctx: PeerCtx, tx_notify_ui: UnboundedSender, ) -> eyre::Result<()> { - let limits = Limits::default() + let limits = quic_limits()? .with_max_handshake_duration(Duration::from_secs(3))? .with_max_idle_timeout(Duration::from_secs(3))?; @@ -30,6 +31,7 @@ pub async fn run_server_component( .with_tls((CERT_PEM, KEY_PEM))? .with_io(addr)? .with_limits(limits)? + .with_congestion_controller(quic_congestion_controller())? .start()?; let server_addr = server.local_addr()?;