diff --git a/server/src/config.rs b/server/src/config.rs index 212b8ae..0459f4b 100644 --- a/server/src/config.rs +++ b/server/src/config.rs @@ -19,6 +19,7 @@ pub struct Config { pub port: u16, pub token: HashSet<[u8; 32]>, pub authentication_timeout: Duration, + pub max_udp_relay_packet_size: usize, pub log_level: LevelFilter, } @@ -76,6 +77,7 @@ impl Config { .collect(); let authentication_timeout = Duration::from_secs(raw.authentication_timeout); + let max_udp_relay_packet_size = raw.max_udp_relay_packet_size; let log_level = raw.log_level; Ok(Self { @@ -83,6 +85,7 @@ impl Config { port, token, authentication_timeout, + max_udp_relay_packet_size, log_level, }) } @@ -111,6 +114,9 @@ struct RawConfig { #[serde(default = "default::alpn")] alpn: Vec, + #[serde(default = "default::max_udp_relay_packet_size")] + max_udp_relay_packet_size: usize, + #[serde(default = "default::log_level")] log_level: LevelFilter, } @@ -126,6 +132,7 @@ impl Default for RawConfig { max_idle_time: default::max_idle_time(), authentication_timeout: default::authentication_timeout(), alpn: default::alpn(), + max_udp_relay_packet_size: default::max_udp_relay_packet_size(), log_level: default::log_level(), } } @@ -193,6 +200,13 @@ impl RawConfig { "ALPN_PROTOCOL", ); + opts.optopt( + "", + "max-udp-relay-packet-size", + "UDP relay mode QUIC can transmit UDP packets larger than the MTU. Set this to a higher value allows outbound to receive larger UDP packet. Default: 1500", + "MAX_UDP_RELAY_PACKET_SIZE", + ); + opts.optopt( "", "log-level", @@ -274,6 +288,10 @@ impl RawConfig { raw.authentication_timeout = timeout.parse()?; }; + if let Some(size) = matches.opt_str("max-udp-relay-packet-size") { + raw.max_udp_relay_packet_size = size.parse()?; + }; + let alpn = matches.opt_strs("alpn"); if !alpn.is_empty() { @@ -345,6 +363,10 @@ mod default { Vec::new() } + pub(super) const fn max_udp_relay_packet_size() -> usize { + 1500 + } + pub(super) const fn log_level() -> LevelFilter { LevelFilter::Info } diff --git a/server/src/connection/mod.rs b/server/src/connection/mod.rs index 0a2b802..258e556 100644 --- a/server/src/connection/mod.rs +++ b/server/src/connection/mod.rs @@ -38,7 +38,12 @@ pub struct Connection { } impl Connection { - pub async fn handle(conn: Connecting, token: Arc>, auth_timeout: Duration) { + pub async fn handle( + conn: Connecting, + token: Arc>, + auth_timeout: Duration, + max_pkt_size: usize, + ) { let rmt_addr = conn.remote_address().restore_ipv4(); match conn.await { @@ -51,7 +56,7 @@ impl Connection { }) => { log::debug!("[{rmt_addr}] [establish]"); - let (udp_sessions, recv_pkt_rx) = UdpSessionMap::new(); + let (udp_sessions, recv_pkt_rx) = UdpSessionMap::new(max_pkt_size); let is_closed = IsClosed::new(); let is_authed = IsAuthenticated::new(is_closed.clone()); diff --git a/server/src/connection/udp.rs b/server/src/connection/udp.rs index b546353..9271d45 100644 --- a/server/src/connection/udp.rs +++ b/server/src/connection/udp.rs @@ -52,16 +52,18 @@ pub type RecvPacketReceiver = Receiver<(u32, Bytes, Address)>; pub struct UdpSessionMap { map: Mutex>, recv_pkt_tx_for_clone: RecvPacketSender, + max_pkt_size: usize, } impl UdpSessionMap { - pub fn new() -> (Self, RecvPacketReceiver) { + pub fn new(max_pkt_size: usize) -> (Self, RecvPacketReceiver) { let (recv_pkt_tx, recv_pkt_rx) = mpsc::channel(1); ( Self { map: Mutex::new(HashMap::new()), recv_pkt_tx_for_clone: recv_pkt_tx, + max_pkt_size, }, recv_pkt_rx, ) @@ -85,8 +87,13 @@ impl UdpSessionMap { log::info!("[{src_addr}] [associate] [{assoc_id}]"); drop(map); - let assoc = - UdpSession::new(assoc_id, self.recv_pkt_tx_for_clone.clone(), src_addr).await?; + let assoc = UdpSession::new( + assoc_id, + self.recv_pkt_tx_for_clone.clone(), + src_addr, + self.max_pkt_size, + ) + .await?; let send_pkt_tx = assoc.0.clone(); @@ -114,6 +121,7 @@ impl UdpSession { assoc_id: u32, recv_pkt_tx: RecvPacketSender, src_addr: SocketAddr, + max_pkt_size: usize, ) -> Result { let socket = Arc::new(UdpSocket::bind(SocketAddr::from((Ipv6Addr::UNSPECIFIED, 0))).await?); let (send_pkt_tx, send_pkt_rx) = mpsc::channel(1); @@ -121,7 +129,7 @@ impl UdpSession { tokio::spawn(async move { match tokio::select!( res = Self::listen_send_packet(socket.clone(), send_pkt_rx) => res, - res = Self::listen_receive_packet(socket, assoc_id, recv_pkt_tx) => res, + res = Self::listen_receive_packet(socket, assoc_id, recv_pkt_tx,max_pkt_size) => res, ) { Ok(()) => (), Err(err) => log::warn!("[{src_addr}] [udp-session] [{assoc_id}] {err}"), @@ -153,9 +161,10 @@ impl UdpSession { socket: Arc, assoc_id: u32, recv_pkt_tx: RecvPacketSender, + max_pkt_size: usize, ) -> Result<(), IoError> { loop { - let mut buf = vec![0; 65535]; + let mut buf = vec![0; max_pkt_size]; let (len, addr) = socket.recv_from(&mut buf).await?; buf.truncate(len); diff --git a/server/src/main.rs b/server/src/main.rs index e2cdd47..a3d0c31 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -37,6 +37,7 @@ async fn main() { config.port, config.token, config.authentication_timeout, + config.max_udp_relay_packet_size, ) { Ok(server) => server, Err(err) => { diff --git a/server/src/server.rs b/server/src/server.rs index 351a24b..1834ce0 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -15,6 +15,7 @@ pub struct Server { port: u16, token: Arc>, authentication_timeout: Duration, + max_pkt_size: usize, } impl Server { @@ -23,6 +24,7 @@ impl Server { port: u16, token: HashSet<[u8; 32]>, auth_timeout: Duration, + max_pkt_size: usize, ) -> Result { let socket = Socket::new(Domain::IPV6, Type::DGRAM, Some(Protocol::UDP))?; socket.set_only_v6(false)?; @@ -39,6 +41,7 @@ impl Server { port, token: Arc::new(token), authentication_timeout: auth_timeout, + max_pkt_size, }) } @@ -48,7 +51,12 @@ impl Server { while let Some(conn) = self.incoming.next().await { let token = self.token.clone(); - tokio::spawn(Connection::handle(conn, token, self.authentication_timeout)); + tokio::spawn(Connection::handle( + conn, + token, + self.authentication_timeout, + self.max_pkt_size, + )); } } }