From 716cd48eac0365d9affe88a0ca35425c39dead26 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:00:32 -0800
Subject: [PATCH 01/21] Add `SIGSTOP` and `SIGCONT` functions, fix some docs
 stuff

---
 src/lobby.rs   |  2 +-
 src/mc/uuid.rs |  2 +-
 src/os/unix.rs | 40 ++++++++++++++++++++++++++++++++++------
 3 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/src/lobby.rs b/src/lobby.rs
index e79ef2f..fc8fab4 100644
--- a/src/lobby.rs
+++ b/src/lobby.rs
@@ -42,7 +42,7 @@ const SERVER_JOIN_GAME_TIMEOUT: Duration = Duration::from_secs(20);
 ///
 /// Notchian servers are slow, we must wait a little before sending play packets, because the
 /// server needs time to transition the client into this state.
-/// See warning at: https://wiki.vg/Protocol#Login_Success
+/// See warning at: <https://wiki.vg/Protocol#Login_Success>
 const SERVER_WARMUP: Duration = Duration::from_secs(1);
 
 /// Serve lobby service for given client connection.
diff --git a/src/mc/uuid.rs b/src/mc/uuid.rs
index 0aee292..c54540a 100644
--- a/src/mc/uuid.rs
+++ b/src/mc/uuid.rs
@@ -18,7 +18,7 @@ pub fn offline_player_uuid(username: &str) -> Uuid {
 ///
 /// Static factory to retrieve a type 3 (name based) `Uuid` based on the specified byte array.
 ///
-/// Ported from: https://git.io/J1b6A
+/// Ported from: <https://git.io/J1b6A>
 fn java_name_uuid_from_bytes(data: &[u8]) -> Uuid {
     let mut hasher = Md5::new();
     hasher.update(data);
diff --git a/src/os/unix.rs b/src/os/unix.rs
index 753b3ff..05bc5b7 100644
--- a/src/os/unix.rs
+++ b/src/os/unix.rs
@@ -1,26 +1,54 @@
-/// Force kill process on Unix by sending SIGKILL.
+/// Force kill process on Unix by sending `SIGKILL`.
 ///
 /// This is unsafe because the PID isn't checked.
 pub unsafe fn force_kill(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGKILL signal to {} to kill server", pid);
+    debug!(target: "lazymc", "Sending SIGKILL signal to {pid} to kill server");
     let result = libc::kill(pid as i32, libc::SIGKILL);
 
     if result != 0 {
-        trace!(target: "lazymc", "SIGKILL failed: {}", result);
+        trace!(target: "lazymc", "SIGKILL failed: {result}");
     }
 
     result == 0
 }
 
-/// Gracefully kill process on Unix by sending SIGTERM.
+/// Gracefully kill process on Unix by sending `SIGTERM`.
 ///
 /// This is unsafe because the PID isn't checked.
 pub unsafe fn kill_gracefully(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGTERM signal to {} to kill server", pid);
+    debug!(target: "lazymc", "Sending SIGTERM signal to {pid} to kill server");
     let result = libc::kill(pid as i32, libc::SIGTERM);
 
     if result != 0 {
-        warn!(target: "lazymc", "Sending SIGTERM signal to server failed: {}", result);
+        warn!(target: "lazymc", "Sending SIGTERM signal to server failed: {result}");
+    }
+
+    result == 0
+}
+
+/// Freeze process on Unix by sending `SIGSTOP`.
+///
+/// This is unsaft because the PIS isn't checked.
+pub unsafe fn freeze(pid: u32) -> bool {
+    debug!(target: "lazymc", "Sending SIGSTOP signal to {pid} to kill server");
+    let result = libc::kill(pid as i32, libc::SIGSTOP);
+
+    if result != 0 {
+        warn!(target: "lazymc", "Sending SIGSTOP signal to server failed: {result}");
+    }
+
+    result == 0
+}
+
+/// Unfreeze process on Unix by sending `SIGCONT`.
+///
+/// This is unsaft because the PIS isn't checked.
+pub unsafe fn unfreeze(pid: u32) -> bool {
+    debug!(target: "lazymc", "Sending SIGCONT signal to {pid} to unfreeze server");
+    let result = libc::kill(pid as i32, libc::SIGCONT);
+
+    if result != 0 {
+        warn!(target: "lazymc", "Sending SIGCONT signal to server failed: {result}");
     }
 
     result == 0

From d3cb880dd0589eccfaa0b5e20f9b153711b31e36 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:03:00 -0800
Subject: [PATCH 02/21] `cargo clippy` is angry

---
 src/config.rs               | 8 +-------
 src/mc/server_properties.rs | 2 +-
 src/probe.rs                | 6 +-----
 src/service/file_watcher.rs | 7 +++----
 4 files changed, 6 insertions(+), 17 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index c9e362a..07ecf3b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -478,19 +478,13 @@ impl Default for Advanced {
 }
 
 /// Config configuration.
-#[derive(Debug, Deserialize)]
+#[derive(Debug, Deserialize, Default)]
 #[serde(default)]
 pub struct ConfigConfig {
     /// Configuration for lazymc version.
     pub version: Option<String>,
 }
 
-impl Default for ConfigConfig {
-    fn default() -> Self {
-        Self { version: None }
-    }
-}
-
 fn option_pathbuf_dot() -> Option<PathBuf> {
     Some(".".into())
 }
diff --git a/src/mc/server_properties.rs b/src/mc/server_properties.rs
index 2fcd8f7..85e1098 100644
--- a/src/mc/server_properties.rs
+++ b/src/mc/server_properties.rs
@@ -114,7 +114,7 @@ fn rewrite_contents(contents: String, mut changes: HashMap<&str, String>) -> Opt
             }
 
             // Try to split property
-            let (key, value) = match line.split_once("=") {
+            let (key, value) = match line.split_once('=') {
                 Some(result) => result,
                 None => return line,
             };
diff --git a/src/probe.rs b/src/probe.rs
index d200d64..9820047 100644
--- a/src/probe.rs
+++ b/src/probe.rs
@@ -157,11 +157,7 @@ async fn connect_to_server_no_timeout(
 
     // Select server address to use, add magic if Forge
     let server_addr = if config.server.forge {
-        format!(
-            "{}{}",
-            config.server.address.ip().to_string(),
-            forge::STATUS_MAGIC,
-        )
+        format!("{}{}", config.server.address.ip(), forge::STATUS_MAGIC,)
     } else {
         config.server.address.ip().to_string()
     };
diff --git a/src/service/file_watcher.rs b/src/service/file_watcher.rs
index 284061a..fa0ecb9 100644
--- a/src/service/file_watcher.rs
+++ b/src/service/file_watcher.rs
@@ -151,10 +151,9 @@ fn reload_whitelist(config: &Config, server: &Server, dir: &Path) {
     }
 
     // Must be enabled in server.properties
-    let enabled =
-        server_properties::read_property(&dir.join(server_properties::FILE), "white-list")
-            .map(|v| v.trim() == "true")
-            .unwrap_or(false);
+    let enabled = server_properties::read_property(dir.join(server_properties::FILE), "white-list")
+        .map(|v| v.trim() == "true")
+        .unwrap_or(false);
     if !enabled {
         server.set_whitelist_blocking(None);
         debug!(target: "lazymc", "Not using whitelist, not enabled in {}", server_properties::FILE);

From b561351a2a35d250a30ebda018005212ebfcc27d Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:18:43 -0800
Subject: [PATCH 03/21] Scuffed code, not tested yet

---
 src/os/mod.rs | 34 ++++++++++++++++++++++++++++++++++
 src/server.rs | 11 +++++++++--
 2 files changed, 43 insertions(+), 2 deletions(-)

diff --git a/src/os/mod.rs b/src/os/mod.rs
index 614a646..9f9bfae 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -39,3 +39,37 @@ pub fn kill_gracefully(pid: u32) -> bool {
         "gracefully killing Minecraft server process not implemented on non-Unix platforms"
     );
 }
+
+/// Freeze process.
+/// Results in undefined behavior if PID is invaild.
+///
+/// # Panics
+/// Panics on platforms other than Unix.
+#[allow(unreachable_code)]
+pub fn freeze(pid: u32) -> bool {
+    #[cfg(unix)]
+    unsafe {
+        return unix::freeze(pid);
+    }
+
+    unimplemented!(
+        "Freezing the Minecraft server process is not implemented on non-Unix platforms."
+    );
+}
+
+/// Unfreeze process.
+/// Results in undefined behavior if PID is invaild.
+///
+/// # Panics
+/// Panics on platforms other than Unix.
+#[allow(unreachable_code)]
+pub fn unfreeze(pid: u32) -> bool {
+    #[cfg(unix)]
+    unsafe {
+        return unix::unfreeze(pid);
+    }
+
+    unimplemented!(
+        "Unfreezing the Minecraft server process is not implemented on non-Unix platforms."
+    );
+}
diff --git a/src/server.rs b/src/server.rs
index 7d852c1..c0b67bf 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -218,7 +218,10 @@ impl Server {
         }
 
         // Spawn server in new task
-        Self::spawn_server_task(config, server);
+        // TODO uncomment this and add config option
+        //Self::spawn_server_task(config, server);
+        // TODO actual error handling
+        os::unfreeze((*server.pid.lock().await).unwrap());
 
         true
     }
@@ -587,9 +590,13 @@ async fn stop_server_signal(config: &Config, server: &Server) -> bool {
     };
 
     // Send kill signal
-    if !crate::os::kill_gracefully(pid) {
+    // TODO uncomment this and add a config option
+    /*if !crate::os::kill_gracefully(pid) {
         error!(target: "lazymc", "Failed to send stop signal to server process");
         return false;
+    }*/
+    if !os::freeze(pid) {
+        error!(target: "lazymc", "Failed to send freeze signal to server process.");
     }
 
     // Update from starting/started to stopping

From bd9f81f1f0b8802b5420cedffcec84c666b427c9 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:29:17 -0800
Subject: [PATCH 04/21] It would be a good idea to actually start the server

---
 src/server.rs | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/server.rs b/src/server.rs
index c0b67bf..eee890a 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -217,12 +217,13 @@ impl Server {
             None => info!(target: "lazymc", "Starting server..."),
         }
 
-        // Spawn server in new task
-        // TODO uncomment this and add config option
-        //Self::spawn_server_task(config, server);
-        // TODO actual error handling
-        os::unfreeze((*server.pid.lock().await).unwrap());
+        // TODO add config option for this
+        if let Some(pid) = *server.pid.lock().await {
+            return os::unfreeze(pid);
+        }
 
+        // Spawn server in new task
+        Self::spawn_server_task(config, server);
         true
     }
 

From 2d8173aba827a75cdfb2c2511219b821db3776c2 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:33:05 -0800
Subject: [PATCH 05/21] Optimize release builds (and format toml file)

---
 Cargo.toml | 44 +++++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 11 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml
index 73043ef..a6e56f4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,16 +8,15 @@ homepage = "https://timvisee.com/projects/lazymc"
 repository = "https://gitlab.com/timvisee/lazymc"
 description = "Put your Minecraft server to rest when idle."
 keywords = ["minecraft", "server", "idle", "cli"]
-categories = [
-    "command-line-interface",
-    "games",
-]
-exclude = [
-    "/.github",
-    "/contrib",
-]
+categories = ["command-line-interface", "games"]
+exclude = ["/.github", "/contrib"]
 edition = "2021"
 
+[profile.release]
+codegen-units = 1
+lto = true
+strip = true
+
 [features]
 default = ["rcon", "lobby"]
 
@@ -35,7 +34,14 @@ anyhow = "1.0"
 base64 = "0.13"
 bytes = "1.1"
 chrono = "0.4"
-clap = { version = "3.0", default-features = false, features = [ "std", "cargo", "color", "env", "suggestions", "unicode" ]}
+clap = { version = "3.0", default-features = false, features = [
+    "std",
+    "cargo",
+    "color",
+    "env",
+    "suggestions",
+    "unicode",
+] }
 colored = "2.0"
 derive_builder = "0.10"
 dotenv = "0.15"
@@ -53,7 +59,17 @@ serde = "1.0"
 serde_json = "1.0"
 shlex = "1.1"
 thiserror = "1.0"
-tokio = { version = "1", default-features = false, features = ["rt-multi-thread", "io-util", "net", "macros", "time", "process", "signal", "sync", "fs"] }
+tokio = { version = "1", default-features = false, features = [
+    "rt-multi-thread",
+    "io-util",
+    "net",
+    "macros",
+    "time",
+    "process",
+    "signal",
+    "sync",
+    "fs",
+] }
 toml = "0.5"
 version-compare = "0.1"
 
@@ -69,4 +85,10 @@ uuid = { version = "0.7", optional = true, features = ["v3"] }
 libc = "0.2"
 
 [target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3", features = ["winuser", "processthreadsapi", "handleapi", "ntdef", "minwindef"] }
+winapi = { version = "0.3", features = [
+    "winuser",
+    "processthreadsapi",
+    "handleapi",
+    "ntdef",
+    "minwindef",
+] }

From d46f8375c762bba8fa04521dfdcd4636c79f4c3c Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 12:40:09 -0800
Subject: [PATCH 06/21] Fix server infinitly stopping

---
 src/server.rs | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/src/server.rs b/src/server.rs
index eee890a..e717057 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -601,12 +601,21 @@ async fn stop_server_signal(config: &Config, server: &Server) -> bool {
     }
 
     // Update from starting/started to stopping
+
+    /* TODO uncomment this and add a config option
     server
         .update_state_from(Some(State::Starting), State::Stopping, config)
         .await;
     server
         .update_state_from(Some(State::Started), State::Stopping, config)
         .await;
+    */
+    server
+        .update_state_from(Some(State::Starting), State::Stopped, config)
+        .await;
+    server
+        .update_state_from(Some(State::Started), State::Stopped, config)
+        .await;
 
     true
 }

From f2087792b4678b800d6cf33dbb2f1f3781443f07 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 14:09:08 -0800
Subject: [PATCH 07/21] Update deps

---
 Cargo.lock | 574 ++++++++++++++++++++++++++++++++---------------------
 Cargo.toml |   4 +-
 2 files changed, 355 insertions(+), 223 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8c6adab..5b1030c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -10,24 +10,33 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.18"
+version = "0.7.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
-name = "anyhow"
-version = "1.0.58"
+name = "android_system_properties"
+version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.68"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "async-channel"
-version = "1.6.1"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
+checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833"
 dependencies = [
  "concurrent-queue",
  "event-listener",
@@ -36,23 +45,23 @@ dependencies = [
 
 [[package]]
 name = "async-executor"
-version = "1.4.1"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "871f9bb5e0a22eeb7e8cf16641feb87c9dc67032ccf8ff49e772eb9941d3a965"
+checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b"
 dependencies = [
+ "async-lock",
  "async-task",
  "concurrent-queue",
  "fastrand",
  "futures-lite",
- "once_cell",
  "slab",
 ]
 
 [[package]]
 name = "async-global-executor"
-version = "2.1.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd8b508d585e01084059b60f06ade4cb7415cd2e4084b71dd1cb44e7d3fb9880"
+checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776"
 dependencies = [
  "async-channel",
  "async-executor",
@@ -65,30 +74,32 @@ dependencies = [
 
 [[package]]
 name = "async-io"
-version = "1.7.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07"
+checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794"
 dependencies = [
+ "async-lock",
+ "autocfg 1.1.0",
  "concurrent-queue",
  "futures-lite",
  "libc",
  "log",
- "once_cell",
  "parking",
  "polling",
  "slab",
  "socket2",
  "waker-fn",
- "winapi 0.3.9",
+ "windows-sys",
 ]
 
 [[package]]
 name = "async-lock"
-version = "2.5.0"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e97a171d191782fba31bb902b14ad94e24a68145032b7eedf871ab0bc0d077b6"
+checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685"
 dependencies = [
  "event-listener",
+ "futures-lite",
 ]
 
 [[package]]
@@ -119,9 +130,9 @@ dependencies = [
 
 [[package]]
 name = "async-task"
-version = "4.2.0"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30696a84d817107fc028e049980e09d5e140e8da8f1caeb17e8e950658a3cea9"
+checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524"
 
 [[package]]
 name = "atomic-waker"
@@ -135,7 +146,7 @@ version = "0.2.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
  "winapi 0.3.9",
 ]
@@ -157,9 +168,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "base64"
-version = "0.13.0"
+version = "0.20.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5"
 
 [[package]]
 name = "bitflags"
@@ -169,32 +180,32 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "block-buffer"
-version = "0.10.2"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
+checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
 dependencies = [
  "generic-array",
 ]
 
 [[package]]
 name = "blocking"
-version = "1.2.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c6ccb65d468978a086b69884437ded69a90faab3bbe6e67f242173ea728acccc"
+checksum = "3c67b173a56acffd6d2326fb7ab938ba0b00a71480e14902b2591c87bc5741e8"
 dependencies = [
  "async-channel",
+ "async-lock",
  "async-task",
  "atomic-waker",
  "fastrand",
  "futures-lite",
- "once_cell",
 ]
 
 [[package]]
 name = "bumpalo"
-version = "3.10.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "byteorder"
@@ -204,21 +215,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "bytes"
-version = "1.1.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
-
-[[package]]
-name = "cache-padded"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
+checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
 
 [[package]]
 name = "cc"
-version = "1.0.73"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
 
 [[package]]
 name = "cesu8"
@@ -240,22 +245,24 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.19"
+version = "0.4.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
+checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
 dependencies = [
- "libc",
+ "iana-time-zone",
+ "js-sys",
  "num-integer",
  "num-traits",
  "time",
+ "wasm-bindgen",
  "winapi 0.3.9",
 ]
 
 [[package]]
 name = "clap"
-version = "3.2.5"
+version = "3.2.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
+checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5"
 dependencies = [
  "atty",
  "bitflags",
@@ -270,9 +277,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.2.2"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
 dependencies = [
  "os_str_bytes",
 ]
@@ -286,6 +293,16 @@ dependencies = [
  "bitflags",
 ]
 
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
 [[package]]
 name = "colored"
 version = "2.0.0"
@@ -299,13 +316,19 @@ dependencies = [
 
 [[package]]
 name = "concurrent-queue"
-version = "1.2.2"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
+checksum = "bd7bef69dc86e3c610e4e7aed41035e2a7ed12e72dd7530f61327a6579a4390b"
 dependencies = [
- "cache-padded",
+ "crossbeam-utils",
 ]
 
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
 [[package]]
 name = "crc32fast"
 version = "1.3.2"
@@ -317,19 +340,18 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.9"
+version = "0.8.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ff1f980957787286a554052d03c7aee98d99cc32e09f6d45f0a814133c87978"
+checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
 dependencies = [
  "cfg-if 1.0.0",
- "once_cell",
 ]
 
 [[package]]
 name = "crypto-common"
-version = "0.1.3"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
+checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
 dependencies = [
  "generic-array",
  "typenum",
@@ -337,19 +359,63 @@ dependencies = [
 
 [[package]]
 name = "ctor"
-version = "0.1.22"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
+checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
 dependencies = [
  "quote",
  "syn",
 ]
 
 [[package]]
-name = "darling"
-version = "0.12.4"
+name = "cxx"
+version = "1.0.85"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c"
+checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "darling"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa"
 dependencies = [
  "darling_core",
  "darling_macro",
@@ -357,9 +423,9 @@ dependencies = [
 
 [[package]]
 name = "darling_core"
-version = "0.12.4"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
+checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f"
 dependencies = [
  "fnv",
  "ident_case",
@@ -371,9 +437,9 @@ dependencies = [
 
 [[package]]
 name = "darling_macro"
-version = "0.12.4"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
+checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e"
 dependencies = [
  "darling_core",
  "quote",
@@ -382,18 +448,18 @@ dependencies = [
 
 [[package]]
 name = "derive_builder"
-version = "0.10.2"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30"
+checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
 dependencies = [
  "derive_builder_macro",
 ]
 
 [[package]]
 name = "derive_builder_core"
-version = "0.10.2"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
+checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
 dependencies = [
  "darling",
  "proc-macro2",
@@ -403,9 +469,9 @@ dependencies = [
 
 [[package]]
 name = "derive_builder_macro"
-version = "0.10.2"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
+checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
 dependencies = [
  "derive_builder_core",
  "syn",
@@ -413,9 +479,9 @@ dependencies = [
 
 [[package]]
 name = "digest"
-version = "0.10.3"
+version = "0.10.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
+checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
 dependencies = [
  "block-buffer",
  "crypto-common",
@@ -462,36 +528,36 @@ dependencies = [
 
 [[package]]
 name = "event-listener"
-version = "2.5.2"
+version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77f3309417938f28bf8228fcff79a4a37103981e3e186d2ccd19c74b38f4eb71"
+checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
 
 [[package]]
 name = "fastrand"
-version = "1.7.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
 dependencies = [
  "instant",
 ]
 
 [[package]]
 name = "filetime"
-version = "0.2.16"
+version = "0.2.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c"
+checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
  "redox_syscall",
- "winapi 0.3.9",
+ "windows-sys",
 ]
 
 [[package]]
 name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -546,9 +612,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
 
 [[package]]
 name = "futures"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
+checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -561,9 +627,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
+checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -571,15 +637,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -588,9 +654,9 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
 
 [[package]]
 name = "futures-lite"
@@ -609,21 +675,21 @@ dependencies = [
 
 [[package]]
 name = "futures-sink"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
 
 [[package]]
 name = "futures-task"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
 
 [[package]]
 name = "futures-util"
-version = "0.3.21"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -638,9 +704,9 @@ dependencies = [
 
 [[package]]
 name = "generic-array"
-version = "0.14.5"
+version = "0.14.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
 dependencies = [
  "typenum",
  "version_check",
@@ -648,9 +714,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if 1.0.0",
  "libc",
@@ -659,9 +725,9 @@ dependencies = [
 
 [[package]]
 name = "gloo-timers"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fb7d06c1c8cc2a29bee7ec961009a0b2caa0793ee4900c2ffb348734ba1c8f9"
+checksum = "98c4a8d6391675c6b2ee1a6c8d06e8e2d03605c44cec1270675985a4c2a5500b"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -671,9 +737,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.12.1"
+version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 
 [[package]]
 name = "hermit-abi"
@@ -684,6 +750,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "humantime"
 version = "1.3.0"
@@ -693,6 +768,30 @@ dependencies = [
  "quick-error",
 ]
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.53"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "winapi 0.3.9",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -701,9 +800,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "indexmap"
-version = "1.9.0"
+version = "1.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3"
+checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg 1.1.0",
  "hashbrown",
@@ -749,15 +848,15 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.2"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
 
 [[package]]
 name = "js-sys"
-version = "0.3.58"
+version = "0.3.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -832,15 +931,24 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.126"
+version = "0.2.139"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
 
 [[package]]
 name = "linked-hash-map"
-version = "0.5.4"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "log"
@@ -854,9 +962,9 @@ dependencies = [
 
 [[package]]
 name = "md-5"
-version = "0.10.1"
+version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "658646b21e0b72f7866c7038ab086d3d5e1cd6271f060fd37defb241949d0582"
+checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
 dependencies = [
  "digest",
 ]
@@ -898,9 +1006,9 @@ dependencies = [
 
 [[package]]
 name = "miniz_oxide"
-version = "0.5.3"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
 dependencies = [
  "adler",
 ]
@@ -926,9 +1034,9 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.3"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
+checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
 dependencies = [
  "libc",
  "log",
@@ -973,9 +1081,9 @@ dependencies = [
 
 [[package]]
 name = "net2"
-version = "0.2.37"
+version = "0.2.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
+checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631"
 dependencies = [
  "cfg-if 0.1.10",
  "libc",
@@ -1021,25 +1129,25 @@ dependencies = [
 
 [[package]]
 name = "num_cpus"
-version = "1.13.1"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
  "libc",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.12.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
+checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
 
 [[package]]
 name = "os_str_bytes"
-version = "6.1.0"
+version = "6.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
+checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
 
 [[package]]
 name = "parking"
@@ -1061,22 +1169,23 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "polling"
-version = "2.2.0"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
+checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6"
 dependencies = [
+ "autocfg 1.1.0",
  "cfg-if 1.0.0",
  "libc",
  "log",
  "wepoll-ffi",
- "winapi 0.3.9",
+ "windows-sys",
 ]
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.16"
+version = "0.2.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "pretty_env_logger"
@@ -1114,9 +1223,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.39"
+version = "1.0.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
 dependencies = [
  "unicode-ident",
 ]
@@ -1163,9 +1272,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
 
 [[package]]
 name = "quote"
-version = "1.0.19"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f53dc8cf16a769a6f677e09e7ff2cd4be1ea0f48754aac39520536962011de0d"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
 dependencies = [
  "proc-macro2",
 ]
@@ -1197,7 +1306,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
 dependencies = [
  "libc",
  "rand_chacha 0.3.1",
- "rand_core 0.6.3",
+ "rand_core 0.6.4",
 ]
 
 [[package]]
@@ -1217,7 +1326,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
 dependencies = [
  "ppv-lite86",
- "rand_core 0.6.3",
+ "rand_core 0.6.4",
 ]
 
 [[package]]
@@ -1237,9 +1346,9 @@ checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
 
 [[package]]
 name = "rand_core"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
  "getrandom",
 ]
@@ -1328,18 +1437,18 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.2.13"
+version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
 name = "regex"
-version = "1.5.6"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -1348,21 +1457,21 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.26"
+version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
 [[package]]
 name = "rustversion"
-version = "1.0.6"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
+checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
 
 [[package]]
 name = "ryu"
-version = "1.0.10"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
 
 [[package]]
 name = "same-file"
@@ -1374,19 +1483,25 @@ dependencies = [
 ]
 
 [[package]]
-name = "serde"
-version = "1.0.137"
+name = "scratch"
+version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
+
+[[package]]
+name = "serde"
+version = "1.0.152"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.137"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1395,9 +1510,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.81"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
 dependencies = [
  "itoa",
  "ryu",
@@ -1421,9 +1536,12 @@ dependencies = [
 
 [[package]]
 name = "slab"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg 1.1.0",
+]
 
 [[package]]
 name = "snafu"
@@ -1448,9 +1566,9 @@ dependencies = [
 
 [[package]]
 name = "socket2"
-version = "0.4.4"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
+checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
 dependencies = [
  "libc",
  "winapi 0.3.9",
@@ -1464,9 +1582,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "syn"
-version = "1.0.97"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233d6785e2e6b8442eb26736eaef8c8f0ce0e575c1457d06c3f2812f9cb4c8a0"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1496,27 +1614,27 @@ dependencies = [
 
 [[package]]
 name = "textwrap"
-version = "0.15.0"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
 dependencies = [
  "unicode-width",
 ]
 
 [[package]]
 name = "thiserror"
-version = "1.0.31"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.31"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1525,9 +1643,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.1.44"
+version = "0.1.45"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
 dependencies = [
  "libc",
  "wasi 0.10.0+wasi-snapshot-preview1",
@@ -1536,28 +1654,28 @@ dependencies = [
 
 [[package]]
 name = "tokio"
-version = "1.19.2"
+version = "1.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
+checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
 dependencies = [
+ "autocfg 1.1.0",
  "bytes",
  "libc",
  "memchr",
- "mio 0.8.3",
+ "mio 0.8.5",
  "num_cpus",
- "once_cell",
  "pin-project-lite",
  "signal-hook-registry",
  "socket2",
  "tokio-macros",
- "winapi 0.3.9",
+ "windows-sys",
 ]
 
 [[package]]
 name = "tokio-macros"
-version = "1.8.0"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1566,18 +1684,18 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.5.9"
+version = "0.5.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
 
 [[package]]
 name = "unicase"
@@ -1590,21 +1708,21 @@ dependencies = [
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.1"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
 
 [[package]]
 name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
 
 [[package]]
 name = "unicode-xid"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
 [[package]]
 name = "uuid"
@@ -1629,9 +1747,9 @@ dependencies = [
 
 [[package]]
 name = "version-compare"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73"
+checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
 
 [[package]]
 name = "version_check"
@@ -1670,9 +1788,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.81"
+version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
 dependencies = [
  "cfg-if 1.0.0",
  "wasm-bindgen-macro",
@@ -1680,13 +1798,13 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.81"
+version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
 dependencies = [
  "bumpalo",
- "lazy_static",
  "log",
+ "once_cell",
  "proc-macro2",
  "quote",
  "syn",
@@ -1695,9 +1813,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.31"
+version = "0.4.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f"
+checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
 dependencies = [
  "cfg-if 1.0.0",
  "js-sys",
@@ -1707,9 +1825,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.81"
+version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -1717,9 +1835,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.81"
+version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1730,15 +1848,15 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.81"
+version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
 
 [[package]]
 name = "web-sys"
-version = "0.3.58"
+version = "0.3.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -1798,46 +1916,60 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
 dependencies = [
+ "windows_aarch64_gnullvm",
  "windows_aarch64_msvc",
  "windows_i686_gnu",
  "windows_i686_msvc",
  "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
  "windows_x86_64_msvc",
 ]
 
 [[package]]
-name = "windows_aarch64_msvc"
-version = "0.36.1"
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.36.1"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
 
 [[package]]
 name = "ws2_32-sys"
diff --git a/Cargo.toml b/Cargo.toml
index a6e56f4..8bd796e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -31,7 +31,7 @@ lobby = ["md-5", "uuid"]
 
 [dependencies]
 anyhow = "1.0"
-base64 = "0.13"
+base64 = "0.20"
 bytes = "1.1"
 chrono = "0.4"
 clap = { version = "3.0", default-features = false, features = [
@@ -43,7 +43,7 @@ clap = { version = "3.0", default-features = false, features = [
     "unicode",
 ] }
 colored = "2.0"
-derive_builder = "0.10"
+derive_builder = "0.12"
 dotenv = "0.15"
 flate2 = { version = "1.0", default-features = false, features = ["default"] }
 futures = { version = "0.3", default-features = false, features = ["executor"] }

From f7fe00aa50006f1b26613491986877e174f3ebe5 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 14:24:21 -0800
Subject: [PATCH 08/21] Add nix crate, use it for signaling

---
 Cargo.lock     | 30 +++++++++++++++++++++++++++
 Cargo.toml     |  1 +
 src/os/mod.rs  | 22 ++++++--------------
 src/os/unix.rs | 55 --------------------------------------------------
 4 files changed, 37 insertions(+), 71 deletions(-)
 delete mode 100644 src/os/unix.rs

diff --git a/Cargo.lock b/Cargo.lock
index 5b1030c..00ba403 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -912,6 +912,7 @@ dependencies = [
  "md-5",
  "minecraft-protocol",
  "named-binary-tag",
+ "nix",
  "notify",
  "pretty_env_logger",
  "proxy-protocol",
@@ -981,6 +982,15 @@ version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
+[[package]]
+name = "memoffset"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+dependencies = [
+ "autocfg 1.1.0",
+]
+
 [[package]]
 name = "minecraft-protocol"
 version = "0.1.0"
@@ -1090,6 +1100,20 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "nix"
+version = "0.26.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46a58d1d356c6597d08cde02c2f09d785b09e28711837b1ed667dc652c08a694"
+dependencies = [
+ "bitflags",
+ "cfg-if 1.0.0",
+ "libc",
+ "memoffset",
+ "pin-utils",
+ "static_assertions",
+]
+
 [[package]]
 name = "notify"
 version = "4.0.17"
@@ -1574,6 +1598,12 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
 [[package]]
 name = "strsim"
 version = "0.10.0"
diff --git a/Cargo.toml b/Cargo.toml
index 8bd796e..43fe6a6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -80,6 +80,7 @@ async-std = { version = "1.9.0", default-features = false, optional = true }
 # Feature: lobby
 md-5 = { version = "0.10", optional = true }
 uuid = { version = "0.7", optional = true, features = ["v3"] }
+nix = "0.26"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/src/os/mod.rs b/src/os/mod.rs
index 9f9bfae..db8b05d 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -1,17 +1,15 @@
-#[cfg(unix)]
-pub mod unix;
 #[cfg(windows)]
 pub mod windows;
 
+use nix::{sys::signal, unistd::Pid};
+
 /// Force kill process.
 ///
 /// Results in undefined behavior if PID is invalid.
 #[allow(unreachable_code)]
 pub fn force_kill(pid: u32) -> bool {
     #[cfg(unix)]
-    unsafe {
-        return unix::force_kill(pid);
-    }
+    return signal::kill(Pid::from_raw(pid as i32), signal::SIGKILL) == Ok(());
 
     #[cfg(windows)]
     unsafe {
@@ -22,18 +20,14 @@ pub fn force_kill(pid: u32) -> bool {
 }
 
 /// Gracefully kill process.
-///
 /// Results in undefined behavior if PID is invalid.
 ///
 /// # Panics
-///
 /// Panics on platforms other than Unix.
 #[allow(unreachable_code, dead_code, unused_variables)]
 pub fn kill_gracefully(pid: u32) -> bool {
     #[cfg(unix)]
-    unsafe {
-        return unix::kill_gracefully(pid);
-    }
+    return signal::kill(Pid::from_raw(pid as i32), signal::SIGTERM) == Ok(());
 
     unimplemented!(
         "gracefully killing Minecraft server process not implemented on non-Unix platforms"
@@ -48,9 +42,7 @@ pub fn kill_gracefully(pid: u32) -> bool {
 #[allow(unreachable_code)]
 pub fn freeze(pid: u32) -> bool {
     #[cfg(unix)]
-    unsafe {
-        return unix::freeze(pid);
-    }
+    return signal::kill(Pid::from_raw(pid as i32), signal::SIGSTOP) == Ok(());
 
     unimplemented!(
         "Freezing the Minecraft server process is not implemented on non-Unix platforms."
@@ -65,9 +57,7 @@ pub fn freeze(pid: u32) -> bool {
 #[allow(unreachable_code)]
 pub fn unfreeze(pid: u32) -> bool {
     #[cfg(unix)]
-    unsafe {
-        return unix::unfreeze(pid);
-    }
+    return signal::kill(Pid::from_raw(pid as i32), signal::SIGCONT) == Ok(());
 
     unimplemented!(
         "Unfreezing the Minecraft server process is not implemented on non-Unix platforms."
diff --git a/src/os/unix.rs b/src/os/unix.rs
deleted file mode 100644
index 05bc5b7..0000000
--- a/src/os/unix.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-/// Force kill process on Unix by sending `SIGKILL`.
-///
-/// This is unsafe because the PID isn't checked.
-pub unsafe fn force_kill(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGKILL signal to {pid} to kill server");
-    let result = libc::kill(pid as i32, libc::SIGKILL);
-
-    if result != 0 {
-        trace!(target: "lazymc", "SIGKILL failed: {result}");
-    }
-
-    result == 0
-}
-
-/// Gracefully kill process on Unix by sending `SIGTERM`.
-///
-/// This is unsafe because the PID isn't checked.
-pub unsafe fn kill_gracefully(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGTERM signal to {pid} to kill server");
-    let result = libc::kill(pid as i32, libc::SIGTERM);
-
-    if result != 0 {
-        warn!(target: "lazymc", "Sending SIGTERM signal to server failed: {result}");
-    }
-
-    result == 0
-}
-
-/// Freeze process on Unix by sending `SIGSTOP`.
-///
-/// This is unsaft because the PIS isn't checked.
-pub unsafe fn freeze(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGSTOP signal to {pid} to kill server");
-    let result = libc::kill(pid as i32, libc::SIGSTOP);
-
-    if result != 0 {
-        warn!(target: "lazymc", "Sending SIGSTOP signal to server failed: {result}");
-    }
-
-    result == 0
-}
-
-/// Unfreeze process on Unix by sending `SIGCONT`.
-///
-/// This is unsaft because the PIS isn't checked.
-pub unsafe fn unfreeze(pid: u32) -> bool {
-    debug!(target: "lazymc", "Sending SIGCONT signal to {pid} to unfreeze server");
-    let result = libc::kill(pid as i32, libc::SIGCONT);
-
-    if result != 0 {
-        warn!(target: "lazymc", "Sending SIGCONT signal to server failed: {result}");
-    }
-
-    result == 0
-}

From 2c43446ed038c121fac965b6bf44ec9cba95b5f9 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Wed, 28 Dec 2022 14:37:08 -0800
Subject: [PATCH 09/21] Error handling and logging

---
 src/os/mod.rs | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/os/mod.rs b/src/os/mod.rs
index db8b05d..f445ba3 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -9,7 +9,7 @@ use nix::{sys::signal, unistd::Pid};
 #[allow(unreachable_code)]
 pub fn force_kill(pid: u32) -> bool {
     #[cfg(unix)]
-    return signal::kill(Pid::from_raw(pid as i32), signal::SIGKILL) == Ok(());
+    return unix_signal(pid, signal::SIGKILL);
 
     #[cfg(windows)]
     unsafe {
@@ -27,7 +27,7 @@ pub fn force_kill(pid: u32) -> bool {
 #[allow(unreachable_code, dead_code, unused_variables)]
 pub fn kill_gracefully(pid: u32) -> bool {
     #[cfg(unix)]
-    return signal::kill(Pid::from_raw(pid as i32), signal::SIGTERM) == Ok(());
+    return unix_signal(pid, signal::SIGTERM);
 
     unimplemented!(
         "gracefully killing Minecraft server process not implemented on non-Unix platforms"
@@ -42,7 +42,7 @@ pub fn kill_gracefully(pid: u32) -> bool {
 #[allow(unreachable_code)]
 pub fn freeze(pid: u32) -> bool {
     #[cfg(unix)]
-    return signal::kill(Pid::from_raw(pid as i32), signal::SIGSTOP) == Ok(());
+    return unix_signal(pid, signal::SIGSTOP);
 
     unimplemented!(
         "Freezing the Minecraft server process is not implemented on non-Unix platforms."
@@ -57,9 +57,20 @@ pub fn freeze(pid: u32) -> bool {
 #[allow(unreachable_code)]
 pub fn unfreeze(pid: u32) -> bool {
     #[cfg(unix)]
-    return signal::kill(Pid::from_raw(pid as i32), signal::SIGCONT) == Ok(());
+    return unix_signal(pid, signal::SIGCONT);
 
     unimplemented!(
         "Unfreezing the Minecraft server process is not implemented on non-Unix platforms."
     );
 }
+
+#[cfg(unix)]
+pub fn unix_signal(pid: u32, signal: signal::Signal) -> bool {
+    return match signal::kill(Pid::from_raw(pid as i32), signal) {
+        Ok(()) => true,
+        Err(err) => {
+            warn!(target: "lazymc", "Sending {signal} signal to server failed: {err}");
+            false
+        }
+    };
+}

From 3185ca855c8fc882c673ffd8927d7b89c6017bbc Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Fri, 30 Dec 2022 13:09:07 -0800
Subject: [PATCH 10/21] Add config option for process freezing

---
 src/config.rs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/config.rs b/src/config.rs
index 07ecf3b..ddabfe0 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -174,6 +174,11 @@ pub struct Server {
     )]
     pub address: SocketAddr,
 
+    /// Freeze the server process instead of restarting it when no players online, making it start up faster.
+    /// Only works on Unix (Linux or MacOS)
+    #[serde(default = "bool_true")]
+    pub freeze_process: bool,
+
     /// Immediately wake server when starting lazymc.
     #[serde(default)]
     pub wake_on_start: bool,

From f02217abd32ea8aa15575e9b0f16a28f25111b2a Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Fri, 30 Dec 2022 13:10:14 -0800
Subject: [PATCH 11/21] Update version number (should be 1 above current
 release) Also update deps

---
 Cargo.lock    | 6 +++---
 Cargo.toml    | 2 +-
 src/config.rs | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 00ba403..4842268 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -894,7 +894,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "lazymc"
-version = "0.2.6"
+version = "0.2.8"
 dependencies = [
  "anyhow",
  "async-std",
@@ -1163,9 +1163,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
 
 [[package]]
 name = "os_str_bytes"
diff --git a/Cargo.toml b/Cargo.toml
index 43fe6a6..6811b3c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lazymc"
-version = "0.2.6"
+version = "0.2.8"
 authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
 license = "GPL-3.0"
 readme = "README.md"
diff --git a/src/config.rs b/src/config.rs
index ddabfe0..e6eaddf 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -15,7 +15,7 @@ use crate::util::serde::to_socket_addrs;
 pub const CONFIG_FILE: &str = "lazymc.toml";
 
 /// Configuration version user should be using, or warning will be shown.
-const CONFIG_VERSION: &str = "0.2.6";
+const CONFIG_VERSION: &str = "0.2.8";
 
 /// Load config from file, based on CLI arguments.
 ///

From 05dfd19d8091bee028affa96d639d0e72060d7a9 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Fri, 30 Dec 2022 13:17:04 -0800
Subject: [PATCH 12/21] Implement config handling

---
 res/lazymc.toml |  4 ++++
 src/server.rs   | 55 ++++++++++++++++++++++++-------------------------
 2 files changed, 31 insertions(+), 28 deletions(-)

diff --git a/res/lazymc.toml b/res/lazymc.toml
index 38fe8e2..e1f35e8 100644
--- a/res/lazymc.toml
+++ b/res/lazymc.toml
@@ -33,6 +33,10 @@ directory = "."
 # Warning: if using a bash script read: https://git.io/JMIKH
 command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
 
+# Freeze the server process instead of restarting it when no players online, making it start up faster.
+# Only works on Unix (Linux or MacOS)
+#freeze_process = true
+
 # Immediately wake server when starting lazymc.
 #wake_on_start = false
 
diff --git a/src/server.rs b/src/server.rs
index e717057..d46602f 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -217,9 +217,10 @@ impl Server {
             None => info!(target: "lazymc", "Starting server..."),
         }
 
-        // TODO add config option for this
-        if let Some(pid) = *server.pid.lock().await {
-            return os::unfreeze(pid);
+        if config.server.freeze_process {
+            if let Some(pid) = *server.pid.lock().await {
+                return os::unfreeze(pid);
+            }
         }
 
         // Spawn server in new task
@@ -590,32 +591,30 @@ async fn stop_server_signal(config: &Config, server: &Server) -> bool {
         }
     };
 
-    // Send kill signal
-    // TODO uncomment this and add a config option
-    /*if !crate::os::kill_gracefully(pid) {
-        error!(target: "lazymc", "Failed to send stop signal to server process");
-        return false;
-    }*/
-    if !os::freeze(pid) {
-        error!(target: "lazymc", "Failed to send freeze signal to server process.");
+    if config.server.freeze_process {
+        if !os::freeze(pid) {
+            error!(target: "lazymc", "Failed to send freeze signal to server process.");
+        }
+
+        server
+            .update_state_from(Some(State::Starting), State::Stopped, config)
+            .await;
+        server
+            .update_state_from(Some(State::Started), State::Stopped, config)
+            .await;
+    } else {
+        if !crate::os::kill_gracefully(pid) {
+            error!(target: "lazymc", "Failed to send stop signal to server process");
+            return false;
+        }
+
+        server
+            .update_state_from(Some(State::Starting), State::Stopping, config)
+            .await;
+        server
+            .update_state_from(Some(State::Started), State::Stopping, config)
+            .await;
     }
 
-    // Update from starting/started to stopping
-
-    /* TODO uncomment this and add a config option
-    server
-        .update_state_from(Some(State::Starting), State::Stopping, config)
-        .await;
-    server
-        .update_state_from(Some(State::Started), State::Stopping, config)
-        .await;
-    */
-    server
-        .update_state_from(Some(State::Starting), State::Stopped, config)
-        .await;
-    server
-        .update_state_from(Some(State::Started), State::Stopped, config)
-        .await;
-
     true
 }

From 540137b93e0ce5b1bd1aef1138a507da75aed327 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Fri, 30 Dec 2022 13:32:11 -0800
Subject: [PATCH 13/21] disable `freeze_process` on windows

---
 src/config.rs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/config.rs b/src/config.rs
index e6eaddf..f24c074 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -57,6 +57,12 @@ pub fn load(matches: &ArgMatches) -> Config {
         }
     };
 
+    #[cfg(windows)]
+    {
+        // Don't try to use unix APIs on windows
+        config.server.freeze_process = false;
+    }
+
     config
 }
 

From 0ac9a07c934d727b6bf208d525d83dfdd106eebe Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@pm.me>
Date: Fri, 30 Dec 2022 13:32:39 -0800
Subject: [PATCH 14/21] add a todo here because it isn't an ideal solution

---
 src/config.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/config.rs b/src/config.rs
index f24c074..ca808f8 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -57,6 +57,7 @@ pub fn load(matches: &ArgMatches) -> Config {
         }
     };
 
+    // TODO better way to do this
     #[cfg(windows)]
     {
         // Don't try to use unix APIs on windows

From 5ef7c54ec61a13a14f021ab808d08b03e62c3c01 Mon Sep 17 00:00:00 2001
From: "[object Object]" <objekt-Objekt@proton.me>
Date: Wed, 25 Jan 2023 14:45:15 -0800
Subject: [PATCH 15/21] Implement suggested changes

---
 Cargo.lock      | 2 +-
 Cargo.toml      | 4 ++--
 res/lazymc.toml | 2 +-
 src/config.rs   | 2 +-
 src/os/mod.rs   | 4 ++--
 src/probe.rs    | 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0f1b5ee..7d22102 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -920,7 +920,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
 
 [[package]]
 name = "lazymc"
-version = "0.2.8"
+version = "0.2.6"
 dependencies = [
  "anyhow",
  "async-std",
diff --git a/Cargo.toml b/Cargo.toml
index 26f26b7..809b674 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lazymc"
-version = "0.2.8"
+version = "0.2.6"
 authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
 license = "GPL-3.0"
 readme = "README.md"
@@ -52,6 +52,7 @@ futures = { version = "0.3", default-features = false, features = ["executor"] }
 log = "0.4"
 minecraft-protocol = { git = "https://github.com/timvisee/rust-minecraft-protocol", rev = "edfdf87" }
 named-binary-tag = "0.6"
+nix = "0.26"
 notify = "4.0"
 pretty_env_logger = "0.4"
 proxy-protocol = "0.5"
@@ -82,7 +83,6 @@ async-std = { version = "1.9.0", default-features = false, optional = true }
 # Feature: lobby
 md-5 = { version = "0.10", optional = true }
 uuid = { version = "0.7", optional = true, features = ["v3"] }
-nix = "0.26"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/res/lazymc.toml b/res/lazymc.toml
index e1f35e8..15050f6 100644
--- a/res/lazymc.toml
+++ b/res/lazymc.toml
@@ -33,7 +33,7 @@ directory = "."
 # Warning: if using a bash script read: https://git.io/JMIKH
 command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
 
-# Freeze the server process instead of restarting it when no players online, making it start up faster.
+# Freeze the server process instead of restarting it when no players online, making it resume faster.
 # Only works on Unix (Linux or MacOS)
 #freeze_process = true
 
diff --git a/src/config.rs b/src/config.rs
index 26434bb..74f997d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -15,7 +15,7 @@ use crate::util::serde::to_socket_addrs;
 pub const CONFIG_FILE: &str = "lazymc.toml";
 
 /// Configuration version user should be using, or warning will be shown.
-const CONFIG_VERSION: &str = "0.2.8";
+const CONFIG_VERSION: &str = "0.2.6";
 
 /// Load config from file, based on CLI arguments.
 ///
diff --git a/src/os/mod.rs b/src/os/mod.rs
index f445ba3..348f56f 100644
--- a/src/os/mod.rs
+++ b/src/os/mod.rs
@@ -45,7 +45,7 @@ pub fn freeze(pid: u32) -> bool {
     return unix_signal(pid, signal::SIGSTOP);
 
     unimplemented!(
-        "Freezing the Minecraft server process is not implemented on non-Unix platforms."
+        "freezing the Minecraft server process is not implemented on non-Unix platforms"
     );
 }
 
@@ -60,7 +60,7 @@ pub fn unfreeze(pid: u32) -> bool {
     return unix_signal(pid, signal::SIGCONT);
 
     unimplemented!(
-        "Unfreezing the Minecraft server process is not implemented on non-Unix platforms."
+        "unfreezing the Minecraft server process is not implemented on non-Unix platforms"
     );
 }
 
diff --git a/src/probe.rs b/src/probe.rs
index 9820047..8ba6462 100644
--- a/src/probe.rs
+++ b/src/probe.rs
@@ -157,7 +157,7 @@ async fn connect_to_server_no_timeout(
 
     // Select server address to use, add magic if Forge
     let server_addr = if config.server.forge {
-        format!("{}{}", config.server.address.ip(), forge::STATUS_MAGIC,)
+        format!("{}{}", config.server.address.ip(), forge::STATUS_MAGIC)
     } else {
         config.server.address.ip().to_string()
     };

From a3fef88eaceee1010721fcfca27116fbe368343b Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 17:42:02 +0100
Subject: [PATCH 16/21] Don't use deprecated base64 method

---
 src/mc/favicon.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/mc/favicon.rs b/src/mc/favicon.rs
index 2a54e8f..7580c87 100644
--- a/src/mc/favicon.rs
+++ b/src/mc/favicon.rs
@@ -1,3 +1,5 @@
+use base64::Engine;
+
 use crate::proto::client::ClientInfo;
 
 /// Protocol version since when favicons are supported.
@@ -12,7 +14,11 @@ pub fn default_favicon() -> String {
 ///
 /// This assumes the favicon data to be a valid PNG image.
 pub fn encode_favicon(data: &[u8]) -> String {
-    format!("{}{}", "data:image/png;base64,", base64::encode(data))
+    format!(
+        "{}{}",
+        "data:image/png;base64,",
+        base64::engine::general_purpose::STANDARD.encode(data)
+    )
 }
 
 /// Check whether the status response favicon is supported based on the given client info.

From bc7bd908f6a8f5670cb3b92bc27e079d0208fbc1 Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 17:54:20 +0100
Subject: [PATCH 17/21] Fix process freezing not working when rcon is enabled

---
 src/server.rs | 103 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 76 insertions(+), 27 deletions(-)

diff --git a/src/server.rs b/src/server.rs
index d46602f..d4ce375 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -217,10 +217,10 @@ impl Server {
             None => info!(target: "lazymc", "Starting server..."),
         }
 
-        if config.server.freeze_process {
-            if let Some(pid) = *server.pid.lock().await {
-                return os::unfreeze(pid);
-            }
+        // Unfreeze server if it is frozen
+        #[cfg(unix)]
+        if config.server.freeze_process && unfreeze_server_signal(&config, &server).await {
+            return true;
         }
 
         // Spawn server in new task
@@ -240,6 +240,12 @@ impl Server {
     /// This will attempt to stop the server with all available methods.
     #[allow(unused_variables)]
     pub async fn stop(&self, config: &Config) -> bool {
+        // Try to freeze through signal
+        #[cfg(unix)]
+        if config.server.freeze_process && freeze_server_signal(config, self).await {
+            return true;
+        }
+
         // Try to stop through RCON if started
         #[cfg(feature = "rcon")]
         if self.state() == State::Started && stop_server_rcon(config, self).await {
@@ -591,30 +597,73 @@ async fn stop_server_signal(config: &Config, server: &Server) -> bool {
         }
     };
 
-    if config.server.freeze_process {
-        if !os::freeze(pid) {
-            error!(target: "lazymc", "Failed to send freeze signal to server process.");
-        }
-
-        server
-            .update_state_from(Some(State::Starting), State::Stopped, config)
-            .await;
-        server
-            .update_state_from(Some(State::Started), State::Stopped, config)
-            .await;
-    } else {
-        if !crate::os::kill_gracefully(pid) {
-            error!(target: "lazymc", "Failed to send stop signal to server process");
-            return false;
-        }
-
-        server
-            .update_state_from(Some(State::Starting), State::Stopping, config)
-            .await;
-        server
-            .update_state_from(Some(State::Started), State::Stopping, config)
-            .await;
+    if !crate::os::kill_gracefully(pid) {
+        error!(target: "lazymc", "Failed to send stop signal to server process");
+        return false;
     }
 
+    server
+        .update_state_from(Some(State::Starting), State::Stopping, config)
+        .await;
+    server
+        .update_state_from(Some(State::Started), State::Stopping, config)
+        .await;
+
+    true
+}
+
+/// Freeze server by sending SIGSTOP signal.
+///
+/// Only available on Unix.
+#[cfg(unix)]
+async fn freeze_server_signal(config: &Config, server: &Server) -> bool {
+    // Grab PID
+    let pid = match *server.pid.lock().await {
+        Some(pid) => pid,
+        None => {
+            debug!(target: "lazymc", "Could not send freeze signal to server process, PID unknown");
+            return false;
+        }
+    };
+
+    if !os::freeze(pid) {
+        error!(target: "lazymc", "Failed to send freeze signal to server process.");
+    }
+
+    server
+        .update_state_from(Some(State::Starting), State::Stopped, config)
+        .await;
+    server
+        .update_state_from(Some(State::Started), State::Stopped, config)
+        .await;
+
+    true
+}
+
+/// Unfreeze server by sending SIGCONT signal.
+///
+/// Only available on Unix.
+#[cfg(unix)]
+async fn unfreeze_server_signal(config: &Config, server: &Server) -> bool {
+    // Grab PID
+    let pid = match *server.pid.lock().await {
+        Some(pid) => pid,
+        None => {
+            debug!(target: "lazymc", "Could not send unfreeze signal to server process, PID unknown");
+            return false;
+        }
+    };
+
+    if !os::unfreeze(pid) {
+        error!(target: "lazymc", "Failed to send unfreeze signal to server process.");
+    }
+
+    server
+        .update_state_from(Some(State::Stopped), State::Started, config)
+        .await;
+    server
+        .update_state_from(Some(State::Starting), State::Started, config)
+        .await;
+
     true
 }

From 4b1857f48d5667c2e81a5d40c8564db39f330b4c Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 17:57:49 +0100
Subject: [PATCH 18/21] Don't disable process freeze in config on Windows,
 simply ignore setting

---
 res/lazymc.toml | 2 +-
 src/config.rs   | 7 -------
 2 files changed, 1 insertion(+), 8 deletions(-)

diff --git a/res/lazymc.toml b/res/lazymc.toml
index 15050f6..cd3e327 100644
--- a/res/lazymc.toml
+++ b/res/lazymc.toml
@@ -34,7 +34,7 @@ directory = "."
 command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
 
 # Freeze the server process instead of restarting it when no players online, making it resume faster.
-# Only works on Unix (Linux or MacOS)
+# Only works on Unix (Linux or MacOS), ignored on Windows
 #freeze_process = true
 
 # Immediately wake server when starting lazymc.
diff --git a/src/config.rs b/src/config.rs
index 74f997d..3ab1949 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -57,13 +57,6 @@ pub fn load(matches: &ArgMatches) -> Config {
         }
     };
 
-    // TODO better way to do this
-    #[cfg(windows)]
-    {
-        // Don't try to use unix APIs on windows
-        config.server.freeze_process = false;
-    }
-
     config
 }
 

From b609f86bdebe2586093ddf444eb0415b76d9afb6 Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 18:06:28 +0100
Subject: [PATCH 19/21] Require to build with rcon feature on Windows

---
 build.rs | 7 +++++++
 1 file changed, 7 insertions(+)
 create mode 100644 build.rs

diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..ec12475
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,7 @@
+fn main() {
+    // rcon is required on Windows
+    #[cfg(all(windows, not(feature = "rcon")))]
+    {
+        compile_error!("required feature missing on Windows: rcon");
+    }
+}

From 835ca62c0655e3257c5022e2d5b20d40a94ad8b3 Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 18:08:23 +0100
Subject: [PATCH 20/21] Change default protocol version to 1.19.3 (761)

---
 docs/protocol-version.md | 4 ++--
 res/lazymc.toml          | 4 ++--
 src/proto/mod.rs         | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/docs/protocol-version.md b/docs/protocol-version.md
index 524b88e..070c19b 100644
--- a/docs/protocol-version.md
+++ b/docs/protocol-version.md
@@ -21,8 +21,8 @@ In lazymc you may configure what protocol version to use:
 # Server version & protocol hint.
 # Sent to clients until actual server version is known.
 # See: https://git.io/J1Fvx
-version = "1.18.1"
-protocol = 757
+version = "1.19.3"
+protocol = 761
 
 # -- snip --
 ```
diff --git a/res/lazymc.toml b/res/lazymc.toml
index cd3e327..aa670f4 100644
--- a/res/lazymc.toml
+++ b/res/lazymc.toml
@@ -18,8 +18,8 @@
 # Server version & protocol hint.
 # Sent to clients until actual server version is known.
 # See: https://git.io/J1Fvx
-#version = "1.18.1"
-#protocol = 757
+#version = "1.19.3"
+#protocol = 761
 
 [server]
 # Server address. Internal IP and port of server started by lazymc to proxy to.
diff --git a/src/proto/mod.rs b/src/proto/mod.rs
index e917060..9e00ea1 100644
--- a/src/proto/mod.rs
+++ b/src/proto/mod.rs
@@ -9,7 +9,7 @@ pub mod packets;
 /// in the configuration.
 ///
 /// Should be kept up-to-date with latest supported Minecraft version by lazymc.
-pub const PROTO_DEFAULT_VERSION: &str = "1.18.1";
+pub const PROTO_DEFAULT_VERSION: &str = "1.19.3";
 
 /// Default minecraft protocol version.
 ///
@@ -17,7 +17,7 @@ pub const PROTO_DEFAULT_VERSION: &str = "1.18.1";
 /// in the configuration.
 ///
 /// Should be kept up-to-date with latest supported Minecraft version by lazymc.
-pub const PROTO_DEFAULT_PROTOCOL: u32 = 757;
+pub const PROTO_DEFAULT_PROTOCOL: u32 = 761;
 
 /// Compression threshold to use.
 // TODO: read this from server.properties instead

From aa1a74682e0f6a78bcba4f14fbe802689bb71851 Mon Sep 17 00:00:00 2001
From: timvisee <tim@visee.me>
Date: Mon, 30 Jan 2023 18:18:28 +0100
Subject: [PATCH 21/21] Fix incorrect state after unfreezing process

---
 src/server.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/server.rs b/src/server.rs
index d4ce375..8bc259d 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -659,10 +659,10 @@ async fn unfreeze_server_signal(config: &Config, server: &Server) -> bool {
     }
 
     server
-        .update_state_from(Some(State::Stopped), State::Started, config)
+        .update_state_from(Some(State::Stopping), State::Starting, config)
         .await;
     server
-        .update_state_from(Some(State::Starting), State::Started, config)
+        .update_state_from(Some(State::Stopped), State::Starting, config)
         .await;
 
     true