diff --git a/res/lazymc.toml b/res/lazymc.toml index 099743a..1d4d937 100644 --- a/res/lazymc.toml +++ b/res/lazymc.toml @@ -39,6 +39,10 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui" # Immediately wake server after crash. #wake_on_crash = false +# Server start/stop timeout in seconds. Force kill server process if it takes too long. +#start_timeout = 300 +#stop_timeout = 150 + [time] # Sleep after number of seconds. #sleep_after = 60 @@ -46,26 +50,34 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui" # Minimum time in seconds to stay online when server is started. #minimum_online_time = 60 -# Hold client for number of seconds on connect while server starts. -# 0 to disable and disconnect immediately, keep below Minecraft timeout of 30 seconds. -#hold_client_for = 25 - -# Server start/stop timeout in seconds. Force kill server process if it takes too long. -#start_timeout = 300 -#stop_timeout = 150 - -[messages] -# MOTDs, shown in server browser. -#motd_sleeping = "☠ Server is sleeping\n§2☻ Join to start it up" -#motd_starting = "§2☻ Server is starting...\n§7⌛ Please wait..." -#motd_stopping = "☠ Server going to sleep...\n⌛ Please wait..." +[motd] +# MOTD, shown in server browser. +#sleeping = "☠ Server is sleeping\n§2☻ Join to start it up" +#starting = "§2☻ Server is starting...\n§7⌛ Please wait..." +#stopping = "☠ Server going to sleep...\n⌛ Please wait..." # Use MOTD from Minecraft server once known. -#use_server_motd = false +#from_server = false -# Login messages, when user tries to connect. -#login_starting = "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute." -#login_stopping = "Server is going to sleep... §7☠§r\n\nPlease try to reconnect in a minute to wake it again." +[join] +# Methods to use to occupy a client on join while the server is starting. +# Methods are used in order if supported, and can be configured in the sections below. +# If no method is set, the client is disconnected without a message. +#methods = [ +# "hold", +# "kick", +#] + +[join.kick] +# Message shown when client is kicked while server is starting/stopping. +#starting = "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute." +#stopping = "Server is going to sleep... §7☠§r\n\nPlease try to reconnect in a minute to wake it again." + +[join.hold] +# Hold client for number of seconds on connect while server starts. +# If timeout is reached, the next join method is attempted. +# Keep below Minecraft timeout of 30 seconds. +#timeout = 25 [lockout] # Enable to prevent everybody from connecting through lazymc. Instantly kicks player. @@ -90,3 +102,8 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui" [advanced] # Automatically update values in Minecraft server.properties file as required. #rewrite_server_properties = true + +[config] +# lazymc version this configuration is for. +# Do not change unless you know what you're doing. +version = "0.2.0" diff --git a/src/config.rs b/src/config.rs index 17f8179..2627b7c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -69,9 +69,21 @@ pub struct Config { #[serde(default)] pub time: Time, - /// Messages, shown to the user. + /// MOTD configuration. #[serde(default)] - pub messages: Messages, + pub motd: Motd, + + /// Join configuration. + #[serde(default)] + pub join: Join, + + /// Join kick configuration. + #[serde(default)] + pub join_kick: JoinKick, + + /// Join hold configuration. + #[serde(default)] + pub join_hold: JoinHold, /// Lockout feature. #[serde(default)] @@ -140,6 +152,14 @@ pub struct Server { /// Immediately wake server after crash. #[serde(default)] pub wake_on_crash: bool, + + /// Server starting timeout. Force kill server process if it takes longer. + #[serde(default = "u32_300")] + pub start_timeout: u32, + + /// Server stopping timeout. Force kill server process if it takes longer. + #[serde(default = "u32_150")] + pub stop_timeout: u32, } /// Time configuration. @@ -152,24 +172,6 @@ pub struct Time { /// Minimum time in seconds to stay online when server is started. #[serde(default, alias = "minimum_online_time")] pub min_online_time: u32, - - /// Hold client for number of seconds while server starts, instead of kicking immediately. - pub hold_client_for: u32, - - /// Server starting timeout. Force kill server process if it takes longer. - #[serde(alias = "starting_timeout")] - pub start_timeout: u32, - - /// Server stopping timeout. Force kill server process if it takes longer. - #[serde(alias = "stopping_timeout")] - pub stop_timeout: u32, -} - -impl Time { - /// Whether to hold clients. - pub fn hold(&self) -> bool { - self.hold_client_for > 0 - } } impl Default for Time { @@ -177,49 +179,104 @@ impl Default for Time { Self { sleep_after: 60, min_online_time: 60, - hold_client_for: 25, - start_timeout: 300, - stop_timeout: 150, } } } -/// Message configuration. +/// MOTD configuration. #[derive(Debug, Deserialize)] #[serde(default)] -pub struct Messages { +pub struct Motd { /// MOTD when server is sleeping. - pub motd_sleeping: String, + pub sleeping: String, /// MOTD when server is starting. - pub motd_starting: String, + pub starting: String, /// MOTD when server is stopping. - pub motd_stopping: String, + pub stopping: String, /// Use MOTD from Minecraft server once known. - pub use_server_motd: bool, - - /// Login message when server is starting. - pub login_starting: String, - - /// Login message when server is stopping. - pub login_stopping: String, + pub from_server: bool, } -impl Default for Messages { +impl Default for Motd { fn default() -> Self { Self { - motd_sleeping: "☠ Server is sleeping\n§2☻ Join to start it up".into(), - motd_starting: "§2☻ Server is starting...\n§7⌛ Please wait...".into(), - motd_stopping: "☠ Server going to sleep...\n⌛ Please wait...".into(), - use_server_motd: false, - login_starting: "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute.".into(), - login_stopping: "Server is going to sleep... §7☠§r\n\nPlease try to reconnect in a minute to wake it again.".into(), + sleeping: "☠ Server is sleeping\n§2☻ Join to start it up".into(), + starting: "§2☻ Server is starting...\n§7⌛ Please wait...".into(), + stopping: "☠ Server going to sleep...\n⌛ Please wait...".into(), + from_server: false, } } } +/// Join method types. +#[derive(Debug, Deserialize, Copy, Clone, Eq, PartialEq)] +#[serde(rename_all = "lowercase")] +pub enum Method { + Hold, + Kick, +} + +/// Join configuration. +#[derive(Debug, Deserialize)] +#[serde(default)] +pub struct Join { + /// Join methods. + pub methods: Vec, +} + +impl Default for Join { + fn default() -> Self { + Self { + methods: vec![Method::Hold, Method::Kick], + } + } +} + +/// Join kick configuration. +#[derive(Debug, Deserialize)] +#[serde(default)] +pub struct JoinKick { + /// Kick message when server is starting. + pub starting: String, + + /// Kick message when server is stopping. + pub stopping: String, +} + +impl Default for JoinKick { + fn default() -> Self { + Self { + starting: "Server is starting... §c♥§r\n\nThis may take some time.\n\nPlease try to reconnect in a minute.".into(), + stopping: "Server is going to sleep... §7☠§r\n\nPlease try to reconnect in a minute to wake it again.".into(), + } + } +} + +/// Join hold configuration. +#[derive(Debug, Deserialize)] +#[serde(default)] +pub struct JoinHold { + /// Hold client for number of seconds on connect while server starts. + pub timeout: u32, +} + +impl JoinHold { + /// Whether to hold clients. + // TODO: remove this + pub fn hold(&self) -> bool { + self.timeout > 0 + } +} + +impl Default for JoinHold { + fn default() -> Self { + Self { timeout: 25 } + } +} + /// Lockout configuration. #[derive(Debug, Deserialize)] #[serde(default)] @@ -291,3 +348,11 @@ fn option_pathbuf_dot() -> Option { fn server_address_default() -> SocketAddr { "127.0.0.1:25566".parse().unwrap() } + +fn u32_300() -> u32 { + 300 +} + +fn u32_150() -> u32 { + 300 +} diff --git a/src/server.rs b/src/server.rs index 9769eb5..bf32c42 100644 --- a/src/server.rs +++ b/src/server.rs @@ -163,11 +163,11 @@ impl Server { // Update kill at time for starting/stopping state *self.kill_at.write().await = match new { - State::Starting if config.time.start_timeout > 0 => { - Some(Instant::now() + Duration::from_secs(config.time.start_timeout as u64)) + State::Starting if config.server.start_timeout > 0 => { + Some(Instant::now() + Duration::from_secs(config.server.start_timeout as u64)) } - State::Stopping if config.time.stop_timeout > 0 => { - Some(Instant::now() + Duration::from_secs(config.time.stop_timeout as u64)) + State::Stopping if config.server.stop_timeout > 0 => { + Some(Instant::now() + Duration::from_secs(config.server.stop_timeout as u64)) } _ => None, }; diff --git a/src/status.rs b/src/status.rs index 9748e83..51407ac 100644 --- a/src/status.rs +++ b/src/status.rs @@ -70,7 +70,7 @@ pub async fn serve( client.set_state(new_state); // If login handshake and holding is enabled, hold packets - if new_state == ClientState::Login && config.time.hold() { + if new_state == ClientState::Login && config.join_hold.hold() { hold_queue.extend(raw); } @@ -120,7 +120,7 @@ pub async fn serve( Server::start(config.clone(), server.clone(), username).await; // Hold client if enabled and starting - if config.time.hold() && server.state() == State::Starting { + if config.join_hold.hold() && server.state() == State::Starting { // Hold login packet and remaining read bytes hold_queue.extend(raw); hold_queue.extend(buf.split_off(0)); @@ -133,9 +133,9 @@ pub async fn serve( // Select message and kick let msg = match server.state() { server::State::Starting | server::State::Stopped | server::State::Started => { - &config.messages.login_starting + &config.join_kick.starting } - server::State::Stopping => &config.messages.login_stopping, + server::State::Stopping => &config.join_kick.stopping, }; kick(msg, &mut writer).await?; @@ -205,7 +205,7 @@ pub async fn hold<'a>( }; // Wait for server state with timeout - let timeout = Duration::from_secs(config.time.hold_client_for as u64); + let timeout = Duration::from_secs(config.join_hold.timeout as u64); match time::timeout(timeout, task_wait).await { // Relay client to proxy Ok(true) => { @@ -217,13 +217,13 @@ pub async fn hold<'a>( // Server stopping/stopped, this shouldn't happen, kick Ok(false) => { warn!(target: "lazymc", "Server stopping for held client, disconnecting"); - kick(&config.messages.login_stopping, &mut inbound.split().1).await?; + kick(&config.join_kick.stopping, &mut inbound.split().1).await?; } // Timeout reached, kick with starting message Err(_) => { - warn!(target: "lazymc", "Held client reached timeout of {}s, disconnecting", config.time.hold_client_for); - kick(&config.messages.login_starting, &mut inbound.split().1).await?; + warn!(target: "lazymc", "Held client reached timeout of {}s, disconnecting", config.join_hold.timeout); + kick(&config.join_kick.starting, &mut inbound.split().1).await?; } } @@ -270,13 +270,13 @@ async fn server_status(config: &Config, server: &Server) -> ServerStatus { // Select description, use server MOTD if enabled, or use configured let description = { - if config.messages.use_server_motd && status.is_some() { + if config.motd.from_server && status.is_some() { status.as_ref().unwrap().description.clone() } else { Message::new(Payload::text(match server.state() { - server::State::Stopped | server::State::Started => &config.messages.motd_sleeping, - server::State::Starting => &config.messages.motd_starting, - server::State::Stopping => &config.messages.motd_stopping, + server::State::Stopped | server::State::Started => &config.motd.sleeping, + server::State::Starting => &config.motd.starting, + server::State::Stopping => &config.motd.stopping, })) } };