From ff136c2a4a53e0042ae35a5a64afbe50cec9745d Mon Sep 17 00:00:00 2001 From: Ryan Johnson Date: Tue, 1 Nov 2022 20:27:08 -0700 Subject: [PATCH] Clean up Config docs and add compression threshold (#148) --- src/config.rs | 103 +++++++++++++++++++++++-------------- src/protocol/codec.rs | 2 +- src/server.rs | 13 ++--- src/server/byte_channel.rs | 2 +- src/server/login.rs | 2 +- 5 files changed, 73 insertions(+), 49 deletions(-) diff --git a/src/config.rs b/src/config.rs index 2fdf11f..e1ed617 100644 --- a/src/config.rs +++ b/src/config.rs @@ -85,9 +85,9 @@ pub trait Config: Sized + Send + Sync + 'static { STANDARD_TPS } - /// Called once at startup to get the connection mode option, which - /// determines if client authentication and encryption should take place - /// and if the server should get the player data from a proxy. + /// Called to get the connection mode option, which determines if client + /// authentication and encryption should take place and if the server + /// should get the player data from a proxy. /// /// # Default Implementation /// @@ -96,13 +96,62 @@ pub trait Config: Sized + Send + Sync + 'static { ConnectionMode::Online } - /// Called once at startup to get the "prevent-proxy-connections" option, - /// which determines if client IP validation should take place. - /// - /// When prevent_proxy_connections is enabled, clients can no longer log-in - /// if they connected to the yggdrasil server using a different IP. + /// Obtains the compression threshold to use for compressing packets. For a + /// compression threshold of `Some(N)`, packets with encoded lengths >= `N` + /// are compressed while all others are not. `None` disables compression. /// /// # Default Implementation + /// + /// If the connection mode is [`ConnectionMode::Online`], `Some(256)` is + /// returned. Otherwise, compression is disabled. + fn compression_threshold(&self) -> Option { + match self.connection_mode() { + ConnectionMode::Online => Some(256), + _ => None, + } + } + + /// Called upon every client login to obtain the full URL to use for session + /// server requests. This is done to authenticate player accounts. This + /// method is not called unless [online mode] is enabled. + /// + /// It is assumed that upon successful request, a structure matching the + /// description in the [wiki](https://wiki.vg/Protocol_Encryption#Server) was obtained. + /// Providing a URL that does not return such a structure will result in a + /// disconnect for every client that connects. + /// + /// The arguments are described in the linked wiki article. + /// + /// # Default Implementation + /// + /// Uses the official Minecraft session server. This is formatted as + /// `https://sessionserver.mojang.com/session/minecraft/hasJoined?username=&serverId=&ip=`. + /// + /// [online mode]: crate::config::ConnectionMode::Online + fn session_server( + &self, + server: &SharedServer, + username: Username<&str>, + auth_digest: &str, + player_ip: &IpAddr, + ) -> String { + if self.prevent_proxy_connections() { + format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}&ip={player_ip}") + } else { + format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}") + } + } + + /// Called from the default implementation of [`Config::session_server`] to + /// get the "prevent-proxy-connections" option, which determines if client + /// IP validation should take place. + /// + /// When `prevent_proxy_connections` is enabled, clients can no longer + /// log-in if they connected to the yggdrasil server using a different + /// IP. + /// + /// # Default Implementation + /// /// Proxy connections are allowed. /// /// Returns `false`. @@ -119,8 +168,8 @@ pub trait Config: Sized + Send + Sync + 'static { /// /// # Default Implementation /// - /// An unspecified value is returned that should be adequate in most - /// situations. + /// An unspecified value is returned that should be adequate for most + /// situations. This default may change in future versions. fn incoming_capacity(&self) -> usize { MAX_PACKET_SIZE as usize } @@ -134,8 +183,8 @@ pub trait Config: Sized + Send + Sync + 'static { /// /// # Default Implementation /// - /// An unspecified value is returned that should be adequate in most - /// situations. + /// An unspecified value is returned that should be adequate for most + /// situations. This default may change in future versions. fn outgoing_capacity(&self) -> usize { MAX_PACKET_SIZE as usize * 4 } @@ -229,30 +278,6 @@ pub trait Config: Sized + Send + Sync + 'static { Ok(()) } - /// Called upon (every) client connect (if online mode is enabled) to obtain - /// the full URL to use for session server requests. Defaults to - /// `https://sessionserver.mojang.com/session/minecraft/hasJoined?username=&serverId=&ip=`. - /// - /// It is assumed, that upon successful request, a structure matching the - /// description in the [wiki](https://wiki.vg/Protocol_Encryption#Server) was obtained. - /// Providing a URL that does not return such a structure will result in a - /// disconnect for every client that connects. - /// - /// The arguments are described in the linked wiki article. - fn format_session_server_url( - &self, - server: &SharedServer, - username: Username<&str>, - auth_digest: &str, - player_ip: &IpAddr, - ) -> String { - if self.prevent_proxy_connections() { - format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}&ip={player_ip}") - } else { - format!("https://sessionserver.mojang.com/session/minecraft/hasJoined?username={username}&serverId={auth_digest}") - } - } - /// Called after the server is created, but prior to accepting connections /// and entering the update loop. /// @@ -276,7 +301,7 @@ pub trait Config: Sized + Send + Sync + 'static { /// # Default Implementation /// /// The default implementation does nothing. - fn update(&self, server: &mut Server); + fn update(&self, server: &mut Server) {} } /// The result of the [`server_list_ping`](Config::server_list_ping) callback. @@ -316,7 +341,7 @@ pub enum ConnectionMode { /// This mode should be used for all publicly exposed servers which are not /// behind a proxy. /// - /// [configured session server]: Config::format_session_server_url + /// [configured session server]: Config::session_server #[default] Online, /// Disables client authentication with the configured session server. @@ -395,6 +420,4 @@ where type WorldState = W; type ChunkState = Ch; type PlayerListState = P; - - fn update(&self, _server: &mut Server) {} } diff --git a/src/protocol/codec.rs b/src/protocol/codec.rs index 344fe21..b8f2ab0 100644 --- a/src/protocol/codec.rs +++ b/src/protocol/codec.rs @@ -53,7 +53,7 @@ impl PacketEncoder { if let Some(threshold) = self.compression_threshold { if data_len >= threshold as usize { - let mut z = ZlibEncoder::new(&mut self.compress_buf, Compression::best()); + let mut z = ZlibEncoder::new(&mut self.compress_buf, Compression::new(4)); pkt.encode_packet(&mut z)?; drop(z); diff --git a/src/server.rs b/src/server.rs index 326d324..e34e5a5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -615,13 +615,14 @@ async fn handle_login( ConnectionMode::Velocity { secret } => login::velocity(ctrl, username, secret).await?, }; - let compression_threshold = 256; - ctrl.send_packet(&SetCompression { - threshold: VarInt(compression_threshold as i32), - }) - .await?; + if let Some(threshold) = server.0.cfg.compression_threshold() { + ctrl.send_packet(&SetCompression { + threshold: VarInt(threshold as i32), + }) + .await?; - ctrl.set_compression(Some(compression_threshold)); + ctrl.set_compression(Some(threshold)); + } if let Err(reason) = server.0.cfg.login(server, &ncd).await { log::info!("Disconnect at login: \"{reason}\""); diff --git a/src/server/byte_channel.rs b/src/server/byte_channel.rs index cb072e7..72973ca 100644 --- a/src/server/byte_channel.rs +++ b/src/server/byte_channel.rs @@ -123,7 +123,7 @@ impl ByteSender { pub enum TrySendError { #[error("sender disconnected")] Disconnected(BytesMut), - #[error("channel full")] + #[error("channel full (see `Config::outgoing_capacity`)")] Full(BytesMut), } diff --git a/src/server/login.rs b/src/server/login.rs index d89f51f..e25cc8d 100644 --- a/src/server/login.rs +++ b/src/server/login.rs @@ -96,7 +96,7 @@ pub(super) async fn online( .chain(&server.0.public_key_der) .finalize(); - let url = server.config().format_session_server_url( + let url = server.config().session_server( server, username.as_str_username(), &auth_digest(&hash),