Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0c69752fec | ||
|
6e8ff5b1b3 | ||
|
fba581d4bd | ||
|
d7b601d6e3 | ||
|
4d76058472 | ||
|
5b5a2bf8ae | ||
|
c477e45553 |
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.2.7 (2021-12-13)
|
||||||
|
|
||||||
|
- Update default Minecraft version to 1.18.1
|
||||||
|
- Update dependencies
|
||||||
|
|
||||||
|
## 0.2.6 (2021-11-28)
|
||||||
|
|
||||||
|
- Add whitelist support, use server whitelist to prevent unknown users from waking server
|
||||||
|
- Update dependencies
|
||||||
|
|
||||||
## 0.2.5 (2021-11-25)
|
## 0.2.5 (2021-11-25)
|
||||||
|
|
||||||
- Add support Minecraft 1.16.3 to 1.17.1 with lobby join method
|
- Add support Minecraft 1.16.3 to 1.17.1 with lobby join method
|
||||||
|
77
Cargo.lock
generated
77
Cargo.lock
generated
@@ -19,9 +19,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.48"
|
version = "1.0.51"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e"
|
checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-channel"
|
name = "async-channel"
|
||||||
@@ -177,9 +177,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
@@ -261,9 +261,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "3.0.0-beta.5"
|
version = "3.0.0-rc.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
|
checksum = "967965e82fc46fee1a88147a7a977a66d615ed5f83eb95b18577b342c08f90ff"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"atty",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
@@ -307,9 +307,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.2"
|
version = "1.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f"
|
checksum = "738c290dfaea84fc1ca15ad9c168d083b05a714e1efddd8edaab678dc28d2836"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
@@ -324,6 +324,15 @@ dependencies = [
|
|||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "567569e659735adb39ff2d4c20600f7cd78be5471f8c58ab162bce3c03fdbc5f"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.1.21"
|
version = "0.1.21"
|
||||||
@@ -402,10 +411,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.9.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
checksum = "8549e6bfdecd113b7e221fe60b433087f6957387a20f8118ebca9b12af19143d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -649,9 +660,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gloo-timers"
|
name = "gloo-timers"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f"
|
checksum = "6f16c88aa13d2656ef20d1c042086b8767bbe2bdb62526894275a1b062161b2e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -786,7 +797,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazymc"
|
name = "lazymc"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-std",
|
"async-std",
|
||||||
@@ -823,9 +834,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.108"
|
version = "0.2.111"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
|
checksum = "8e167738f1866a7ec625567bae89ca0d44477232a4f7c52b1c7f2adc2c98804f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked-hash-map"
|
name = "linked-hash-map"
|
||||||
@@ -845,13 +856,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.9.1"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b5a279bb9607f9f53c22d496eade00d138d1bdcccd07d74650387cf94942a15"
|
checksum = "e6a38fc55c8bbc10058782919516f88826e70320db6d206aebc49611d24216ae"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
|
||||||
"digest",
|
"digest",
|
||||||
"opaque-debug",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1048,17 +1057,11 @@ version = "1.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "opaque-debug"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_str_bytes"
|
name = "os_str_bytes"
|
||||||
version = "4.2.0"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
|
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -1136,9 +1139,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.32"
|
version = "1.0.33"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
|
checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
@@ -1386,15 +1389,15 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.5"
|
version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088"
|
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.5"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
@@ -1407,18 +1410,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.130"
|
version = "1.0.131"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
|
checksum = "b4ad69dfbd3e45369132cc64e6748c2d65cdfb001a2b1c232d128b4ad60561c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.130"
|
version = "1.0.131"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
|
checksum = "b710a83c4e0dff6a3d511946b95274ad9ca9e5d3ae497b63fda866ac955358d2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "lazymc"
|
name = "lazymc"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
|
authors = ["Tim Visee <3a4fb3964f@sinenomine.email>"]
|
||||||
license = "GPL-3.0"
|
license = "GPL-3.0"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@@ -35,7 +35,7 @@ anyhow = "1.0"
|
|||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bytes = "1.1"
|
bytes = "1.1"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
clap = { version = "3.0.0-beta.5", default-features = false, features = [ "std", "cargo", "color", "env", "suggestions", "unicode" ]}
|
clap = { version = "=3.0.0-rc.4", default-features = false, features = [ "std", "cargo", "color", "env", "suggestions", "unicode" ]}
|
||||||
colored = "2.0"
|
colored = "2.0"
|
||||||
derive_builder = "0.10"
|
derive_builder = "0.10"
|
||||||
dotenv = "0.15"
|
dotenv = "0.15"
|
||||||
@@ -62,7 +62,7 @@ rust_rcon = { package = "rcon", version = "0.5.2", optional = true }
|
|||||||
async-std = { version = "1.9.0", default-features = false, optional = true }
|
async-std = { version = "1.9.0", default-features = false, optional = true }
|
||||||
|
|
||||||
# Feature: lobby
|
# Feature: lobby
|
||||||
md-5 = { version = "0.9", optional = true }
|
md-5 = { version = "0.10", optional = true }
|
||||||
uuid = { version = "0.7", optional = true, features = ["v3"] }
|
uuid = { version = "0.7", optional = true, features = ["v3"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
@@ -62,15 +62,18 @@ Then configure the lobby to your likings:
|
|||||||
# The client will be teleported to the real server once it is ready.
|
# The client will be teleported to the real server once it is ready.
|
||||||
# This may keep the client occupied forever if no timeout is set.
|
# This may keep the client occupied forever if no timeout is set.
|
||||||
# Consumes client, not allowing other join methods afterwards.
|
# Consumes client, not allowing other join methods afterwards.
|
||||||
|
# See: https://git.io/JMIi4
|
||||||
|
|
||||||
# !!! WARNING !!!
|
# !!! WARNING !!!
|
||||||
# This is highly experimental and unstable.
|
# This is highly experimental, incomplete and unstable.
|
||||||
# This may break the game and crash clients.
|
# This may break the game and crash clients.
|
||||||
# Don't enable this unless you know what you're doing.
|
# Don't enable this unless you know what you're doing.
|
||||||
#
|
#
|
||||||
# - Only works with offline mode
|
# - Server must be in offline mode
|
||||||
# - Only works with vanilla Minecraft clients, does not work with modded
|
# - Server must use Minecraft version 1.16.3 to 1.17.1 (tested with 1.17.1)
|
||||||
# - Only tested with Minecraft 1.17.1
|
# - Server must use vanilla Minecraft
|
||||||
|
# - May work with Forge, enable in config, depends on used mods, test before use
|
||||||
|
# - Does not work with other mods, such as FTB
|
||||||
|
|
||||||
# Maximum time in seconds in the lobby while the server starts.
|
# Maximum time in seconds in the lobby while the server starts.
|
||||||
timeout = 600
|
timeout = 600
|
||||||
|
@@ -21,8 +21,8 @@ In lazymc you may configure what protocol version to use:
|
|||||||
# Server version & protocol hint.
|
# Server version & protocol hint.
|
||||||
# Sent to clients until actual server version is known.
|
# Sent to clients until actual server version is known.
|
||||||
# See: https://git.io/J1Fvx
|
# See: https://git.io/J1Fvx
|
||||||
version = "1.17.1"
|
version = "1.18.1"
|
||||||
protocol = 756
|
protocol = 757
|
||||||
|
|
||||||
# -- snip --
|
# -- snip --
|
||||||
```
|
```
|
||||||
|
@@ -18,8 +18,8 @@
|
|||||||
# Server version & protocol hint.
|
# Server version & protocol hint.
|
||||||
# Sent to clients until actual server version is known.
|
# Sent to clients until actual server version is known.
|
||||||
# See: https://git.io/J1Fvx
|
# See: https://git.io/J1Fvx
|
||||||
#version = "1.17.1"
|
#version = "1.18.1"
|
||||||
#protocol = 756
|
#protocol = 757
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
# Server address. Internal IP and port of server started by lazymc to proxy to.
|
# Server address. Internal IP and port of server started by lazymc to proxy to.
|
||||||
@@ -50,6 +50,9 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
|
|||||||
#start_timeout = 300
|
#start_timeout = 300
|
||||||
#stop_timeout = 150
|
#stop_timeout = 150
|
||||||
|
|
||||||
|
# To wake server, user must be in server whitelist if enabled on server.
|
||||||
|
#wake_whitelist = true
|
||||||
|
|
||||||
# Block banned IPs as listed in banned-ips.json in server directory.
|
# Block banned IPs as listed in banned-ips.json in server directory.
|
||||||
#block_banned_ips = true
|
#block_banned_ips = true
|
||||||
|
|
||||||
@@ -180,4 +183,4 @@ command = "java -Xmx1G -Xms1G -jar server.jar --nogui"
|
|||||||
[config]
|
[config]
|
||||||
# lazymc version this configuration is for.
|
# lazymc version this configuration is for.
|
||||||
# Don't change unless you know what you're doing.
|
# Don't change unless you know what you're doing.
|
||||||
version = "0.2.5"
|
version = "0.2.7"
|
||||||
|
@@ -27,7 +27,7 @@ pub fn app() -> App<'static> {
|
|||||||
.global(true)
|
.global(true)
|
||||||
.value_name("FILE")
|
.value_name("FILE")
|
||||||
.default_value(crate::config::CONFIG_FILE)
|
.default_value(crate::config::CONFIG_FILE)
|
||||||
.about("Use config file")
|
.help("Use config file")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@@ -15,7 +15,7 @@ use crate::util::serde::to_socket_addrs;
|
|||||||
pub const CONFIG_FILE: &str = "lazymc.toml";
|
pub const CONFIG_FILE: &str = "lazymc.toml";
|
||||||
|
|
||||||
/// Configuration version user should be using, or warning will be shown.
|
/// Configuration version user should be using, or warning will be shown.
|
||||||
const CONFIG_VERSION: &str = "0.2.1";
|
const CONFIG_VERSION: &str = "0.2.6";
|
||||||
|
|
||||||
/// Load config from file, based on CLI arguments.
|
/// Load config from file, based on CLI arguments.
|
||||||
///
|
///
|
||||||
@@ -198,6 +198,10 @@ pub struct Server {
|
|||||||
#[serde(default = "u32_150")]
|
#[serde(default = "u32_150")]
|
||||||
pub stop_timeout: u32,
|
pub stop_timeout: u32,
|
||||||
|
|
||||||
|
/// To wake server, user must be in server whitelist if enabled on server.
|
||||||
|
#[serde(default = "bool_true")]
|
||||||
|
pub wake_whitelist: bool,
|
||||||
|
|
||||||
/// Block banned IPs as listed in banned-ips.json in server directory.
|
/// Block banned IPs as listed in banned-ips.json in server directory.
|
||||||
#[serde(default = "bool_true")]
|
#[serde(default = "bool_true")]
|
||||||
pub block_banned_ips: bool,
|
pub block_banned_ips: bool,
|
||||||
|
@@ -7,6 +7,7 @@ pub mod rcon;
|
|||||||
pub mod server_properties;
|
pub mod server_properties;
|
||||||
#[cfg(feature = "lobby")]
|
#[cfg(feature = "lobby")]
|
||||||
pub mod uuid;
|
pub mod uuid;
|
||||||
|
pub mod whitelist;
|
||||||
|
|
||||||
/// Minecraft ticks per second.
|
/// Minecraft ticks per second.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@@ -145,3 +145,37 @@ fn rewrite_contents(contents: String, mut changes: HashMap<&str, String>) -> Opt
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the given property from the given server.properties file.o
|
||||||
|
///
|
||||||
|
/// Returns `None` if file does not contain the property.
|
||||||
|
pub fn read_property<P: AsRef<Path>>(file: P, property: &str) -> Option<String> {
|
||||||
|
// File must exist
|
||||||
|
if !file.as_ref().is_file() {
|
||||||
|
warn!(target: "lazymc",
|
||||||
|
"Failed to read property from {} file, it does not exist",
|
||||||
|
FILE,
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read contents
|
||||||
|
let contents = match fs::read_to_string(&file) {
|
||||||
|
Ok(contents) => contents,
|
||||||
|
Err(err) => {
|
||||||
|
error!(target: "lazymc",
|
||||||
|
"Failed to read property from {} file, could not load: {}",
|
||||||
|
FILE,
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find property, return value
|
||||||
|
contents
|
||||||
|
.lines()
|
||||||
|
.filter_map(|line| line.split_once('='))
|
||||||
|
.find(|(p, _)| p.trim().to_lowercase() == property.to_lowercase())
|
||||||
|
.map(|(_, v)| v.trim().to_string())
|
||||||
|
}
|
||||||
|
107
src/mc/whitelist.rs
Normal file
107
src/mc/whitelist.rs
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
/// Whitelist file name.
|
||||||
|
pub const WHITELIST_FILE: &str = "whitelist.json";
|
||||||
|
|
||||||
|
/// OPs file name.
|
||||||
|
pub const OPS_FILE: &str = "ops.json";
|
||||||
|
|
||||||
|
/// Whitelisted users.
|
||||||
|
///
|
||||||
|
/// Includes list of OPs, which are also automatically whitelisted.
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct Whitelist {
|
||||||
|
/// Whitelisted users.
|
||||||
|
whitelist: Vec<String>,
|
||||||
|
|
||||||
|
/// OPd users.
|
||||||
|
ops: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Whitelist {
|
||||||
|
/// Check whether a user is whitelisted.
|
||||||
|
pub fn is_whitelisted(&self, username: &str) -> bool {
|
||||||
|
self.whitelist.iter().any(|u| u == username) || self.ops.iter().any(|u| u == username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A whitelist user.
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct WhitelistUser {
|
||||||
|
/// Whitelisted username.
|
||||||
|
#[serde(rename = "name", alias = "username")]
|
||||||
|
pub username: String,
|
||||||
|
|
||||||
|
/// Whitelisted UUID.
|
||||||
|
pub uuid: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An OP user.
|
||||||
|
#[derive(Debug, Deserialize, Clone)]
|
||||||
|
pub struct OpUser {
|
||||||
|
/// OP username.
|
||||||
|
#[serde(rename = "name", alias = "username")]
|
||||||
|
pub username: String,
|
||||||
|
|
||||||
|
/// OP UUID.
|
||||||
|
pub uuid: Option<String>,
|
||||||
|
|
||||||
|
/// OP level.
|
||||||
|
pub level: Option<u32>,
|
||||||
|
|
||||||
|
/// Whether OP can bypass player limit.
|
||||||
|
#[serde(rename = "bypassesPlayerLimit")]
|
||||||
|
pub byapsses_player_limit: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load whitelist from directory.
|
||||||
|
pub fn load_dir(path: &Path) -> Result<Whitelist, Box<dyn Error>> {
|
||||||
|
let whitelist_file = path.join(WHITELIST_FILE);
|
||||||
|
let ops_file = path.join(OPS_FILE);
|
||||||
|
|
||||||
|
// Load whitelist users
|
||||||
|
let whitelist = if whitelist_file.is_file() {
|
||||||
|
load_whitelist(&whitelist_file)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Load OPd users
|
||||||
|
let ops = if ops_file.is_file() {
|
||||||
|
load_ops(&ops_file)?
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!(target: "lazymc", "Loaded {} whitelist and {} OP users", whitelist.len(), ops.len());
|
||||||
|
|
||||||
|
Ok(Whitelist { whitelist, ops })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load whitelist from file.
|
||||||
|
fn load_whitelist(path: &Path) -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
|
// Load file contents
|
||||||
|
let contents = fs::read_to_string(path)?;
|
||||||
|
|
||||||
|
// Parse contents
|
||||||
|
let users: Vec<WhitelistUser> = serde_json::from_str(&contents)?;
|
||||||
|
|
||||||
|
// Pluck usernames
|
||||||
|
Ok(users.into_iter().map(|user| user.username).collect())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load OPs from file.
|
||||||
|
fn load_ops(path: &Path) -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
|
// Load file contents
|
||||||
|
let contents = fs::read_to_string(path)?;
|
||||||
|
|
||||||
|
// Parse contents
|
||||||
|
let users: Vec<OpUser> = serde_json::from_str(&contents)?;
|
||||||
|
|
||||||
|
// Pluck usernames
|
||||||
|
Ok(users.into_iter().map(|user| user.username).collect())
|
||||||
|
}
|
@@ -9,7 +9,7 @@ pub mod packets;
|
|||||||
/// in the configuration.
|
/// in the configuration.
|
||||||
///
|
///
|
||||||
/// Should be kept up-to-date with latest supported Minecraft version by lazymc.
|
/// Should be kept up-to-date with latest supported Minecraft version by lazymc.
|
||||||
pub const PROTO_DEFAULT_VERSION: &str = "1.17.1";
|
pub const PROTO_DEFAULT_VERSION: &str = "1.18.1";
|
||||||
|
|
||||||
/// Default minecraft protocol version.
|
/// Default minecraft protocol version.
|
||||||
///
|
///
|
||||||
@@ -17,7 +17,7 @@ pub const PROTO_DEFAULT_VERSION: &str = "1.17.1";
|
|||||||
/// in the configuration.
|
/// in the configuration.
|
||||||
///
|
///
|
||||||
/// Should be kept up-to-date with latest supported Minecraft version by lazymc.
|
/// Should be kept up-to-date with latest supported Minecraft version by lazymc.
|
||||||
pub const PROTO_DEFAULT_PROTOCOL: u32 = 756;
|
pub const PROTO_DEFAULT_PROTOCOL: u32 = 757;
|
||||||
|
|
||||||
/// Compression threshold to use.
|
/// Compression threshold to use.
|
||||||
// TODO: read this from server.properties instead
|
// TODO: read this from server.properties instead
|
||||||
|
@@ -14,6 +14,7 @@ use tokio::time;
|
|||||||
|
|
||||||
use crate::config::{Config, Server as ConfigServer};
|
use crate::config::{Config, Server as ConfigServer};
|
||||||
use crate::mc::ban::{BannedIp, BannedIps};
|
use crate::mc::ban::{BannedIp, BannedIps};
|
||||||
|
use crate::mc::whitelist::Whitelist;
|
||||||
use crate::os;
|
use crate::os;
|
||||||
use crate::proto::packets::play::join_game::JoinGameData;
|
use crate::proto::packets::play::join_game::JoinGameData;
|
||||||
|
|
||||||
@@ -73,6 +74,9 @@ pub struct Server {
|
|||||||
/// List of banned IPs.
|
/// List of banned IPs.
|
||||||
banned_ips: RwLock<BannedIps>,
|
banned_ips: RwLock<BannedIps>,
|
||||||
|
|
||||||
|
/// Whitelist if enabled.
|
||||||
|
whitelist: RwLock<Option<Whitelist>>,
|
||||||
|
|
||||||
/// Lock for exclusive RCON operations.
|
/// Lock for exclusive RCON operations.
|
||||||
#[cfg(feature = "rcon")]
|
#[cfg(feature = "rcon")]
|
||||||
rcon_lock: Semaphore,
|
rcon_lock: Semaphore,
|
||||||
@@ -346,6 +350,18 @@ impl Server {
|
|||||||
futures::executor::block_on(async { self.is_banned_ip(ip).await })
|
futures::executor::block_on(async { self.is_banned_ip(ip).await })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether the given username is whitelisted.
|
||||||
|
///
|
||||||
|
/// Returns `true` if no whitelist is currently used.
|
||||||
|
pub async fn is_whitelisted(&self, username: &str) -> bool {
|
||||||
|
self.whitelist
|
||||||
|
.read()
|
||||||
|
.await
|
||||||
|
.as_ref()
|
||||||
|
.map(|w| w.is_whitelisted(username))
|
||||||
|
.unwrap_or(true)
|
||||||
|
}
|
||||||
|
|
||||||
/// Update the list of banned IPs.
|
/// Update the list of banned IPs.
|
||||||
pub async fn set_banned_ips(&self, ips: BannedIps) {
|
pub async fn set_banned_ips(&self, ips: BannedIps) {
|
||||||
*self.banned_ips.write().await = ips;
|
*self.banned_ips.write().await = ips;
|
||||||
@@ -355,6 +371,16 @@ impl Server {
|
|||||||
pub fn set_banned_ips_blocking(&self, ips: BannedIps) {
|
pub fn set_banned_ips_blocking(&self, ips: BannedIps) {
|
||||||
futures::executor::block_on(async { self.set_banned_ips(ips).await })
|
futures::executor::block_on(async { self.set_banned_ips(ips).await })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the whitelist.
|
||||||
|
pub async fn set_whitelist(&self, whitelist: Option<Whitelist>) {
|
||||||
|
*self.whitelist.write().await = whitelist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the whitelist.
|
||||||
|
pub fn set_whitelist_blocking(&self, whitelist: Option<Whitelist>) {
|
||||||
|
futures::executor::block_on(async { self.set_whitelist(whitelist).await })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Server {
|
impl Default for Server {
|
||||||
@@ -371,6 +397,7 @@ impl Default for Server {
|
|||||||
keep_online_until: Default::default(),
|
keep_online_until: Default::default(),
|
||||||
kill_at: Default::default(),
|
kill_at: Default::default(),
|
||||||
banned_ips: Default::default(),
|
banned_ips: Default::default(),
|
||||||
|
whitelist: Default::default(),
|
||||||
#[cfg(feature = "rcon")]
|
#[cfg(feature = "rcon")]
|
||||||
rcon_lock: Semaphore::new(1),
|
rcon_lock: Semaphore::new(1),
|
||||||
#[cfg(feature = "rcon")]
|
#[cfg(feature = "rcon")]
|
||||||
|
@@ -1,119 +0,0 @@
|
|||||||
use std::path::Path;
|
|
||||||
use std::sync::mpsc::channel;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::thread;
|
|
||||||
use std::time::Duration;
|
|
||||||
|
|
||||||
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
|
||||||
|
|
||||||
use crate::config::{Config, Server as ConfigServer};
|
|
||||||
use crate::mc::ban;
|
|
||||||
use crate::server::Server;
|
|
||||||
|
|
||||||
/// File debounce time.
|
|
||||||
const WATCH_DEBOUNCE: Duration = Duration::from_secs(2);
|
|
||||||
|
|
||||||
/// Service to reload banned IPs when its file changes.
|
|
||||||
pub fn service(config: Arc<Config>, server: Arc<Server>) {
|
|
||||||
// TODO: check what happens when file doesn't exist at first?
|
|
||||||
|
|
||||||
// Ensure we need to reload banned IPs
|
|
||||||
if !config.server.block_banned_ips && !config.server.drop_banned_ips {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure server directory is set, it must exist
|
|
||||||
let dir = match ConfigServer::server_directory(&config) {
|
|
||||||
Some(dir) => dir,
|
|
||||||
None => {
|
|
||||||
warn!(target: "lazymc", "Not blocking banned IPs, server directory not configured, unable to find {} file", ban::FILE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Determine file path, ensure it exists
|
|
||||||
let path = dir.join(crate::mc::ban::FILE);
|
|
||||||
if !path.is_file() {
|
|
||||||
warn!(target: "lazymc", "Not blocking banned IPs, {} file does not exist", ban::FILE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load banned IPs once
|
|
||||||
match ban::load(&path) {
|
|
||||||
Ok(ips) => server.set_banned_ips_blocking(ips),
|
|
||||||
Err(err) => {
|
|
||||||
error!(target: "lazymc", "Failed to load banned IPs from {}: {}", ban::FILE, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show warning if 127.0.0.1 is banned
|
|
||||||
if server.is_banned_ip_blocking(&("127.0.0.1".parse().unwrap())) {
|
|
||||||
warn!(target: "lazymc", "Local address 127.0.0.1 IP banned, probably not what you want");
|
|
||||||
warn!(target: "lazymc", "Use '/pardon-ip 127.0.0.1' on the server to unban");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep watching
|
|
||||||
while watch(&server, &path) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Watch the given file.
|
|
||||||
fn watch(server: &Server, path: &Path) -> bool {
|
|
||||||
// The file must exist
|
|
||||||
if !path.is_file() {
|
|
||||||
warn!(target: "lazymc", "File {} does not exist, not watching changes", ban::FILE);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create watcher for banned IPs file
|
|
||||||
let (tx, rx) = channel();
|
|
||||||
let mut watcher =
|
|
||||||
watcher(tx, WATCH_DEBOUNCE).expect("failed to create watcher for banned-ips.json");
|
|
||||||
if let Err(err) = watcher.watch(path, RecursiveMode::NonRecursive) {
|
|
||||||
error!(target: "lazymc", "An error occured while creating watcher for {}: {}", ban::FILE, err);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Take next event
|
|
||||||
let event = rx.recv().unwrap();
|
|
||||||
|
|
||||||
// Decide whether to reload and rewatch
|
|
||||||
let (reload, rewatch) = match event {
|
|
||||||
// Reload on write
|
|
||||||
DebouncedEvent::NoticeWrite(_) | DebouncedEvent::Write(_) => (true, false),
|
|
||||||
|
|
||||||
// Reload and rewatch on rename/remove
|
|
||||||
DebouncedEvent::NoticeRemove(_)
|
|
||||||
| DebouncedEvent::Remove(_)
|
|
||||||
| DebouncedEvent::Rename(_, _)
|
|
||||||
| DebouncedEvent::Rescan
|
|
||||||
| DebouncedEvent::Create(_) => {
|
|
||||||
trace!(target: "lazymc", "File banned-ips.json removed, trying to rewatch after 1 second");
|
|
||||||
thread::sleep(WATCH_DEBOUNCE);
|
|
||||||
(true, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ignore chmod changes
|
|
||||||
DebouncedEvent::Chmod(_) => (false, false),
|
|
||||||
|
|
||||||
// Rewatch on error
|
|
||||||
DebouncedEvent::Error(_, _) => (false, true),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reload banned IPs
|
|
||||||
if reload {
|
|
||||||
debug!(target: "lazymc", "Reloading list of banned IPs...");
|
|
||||||
match ban::load(path) {
|
|
||||||
Ok(ips) => server.set_banned_ips_blocking(ips),
|
|
||||||
Err(err) => {
|
|
||||||
error!(target: "lazymc", "Failed reload list of banned IPs from {}: {}", ban::FILE, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewatch
|
|
||||||
if rewatch {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
173
src/service/file_watcher.rs
Normal file
173
src/service/file_watcher.rs
Normal file
@@ -0,0 +1,173 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
||||||
|
|
||||||
|
use crate::config::{Config, Server as ConfigServer};
|
||||||
|
use crate::mc::ban::{self, BannedIps};
|
||||||
|
use crate::mc::{server_properties, whitelist};
|
||||||
|
use crate::server::Server;
|
||||||
|
|
||||||
|
/// File watcher debounce time.
|
||||||
|
const WATCH_DEBOUNCE: Duration = Duration::from_secs(2);
|
||||||
|
|
||||||
|
/// Service to watch server file changes.
|
||||||
|
pub fn service(config: Arc<Config>, server: Arc<Server>) {
|
||||||
|
// Ensure server directory is set, it must exist
|
||||||
|
let dir = match ConfigServer::server_directory(&config) {
|
||||||
|
Some(dir) if dir.is_dir() => dir,
|
||||||
|
_ => {
|
||||||
|
warn!(target: "lazymc", "Server directory doesn't exist, can't watch file changes to reload whitelist and banned IPs");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep watching
|
||||||
|
#[allow(clippy::blocks_in_if_conditions)]
|
||||||
|
while {
|
||||||
|
// Update all files once
|
||||||
|
reload_bans(&config, &server, &dir.join(ban::FILE));
|
||||||
|
reload_whitelist(&config, &server, &dir);
|
||||||
|
|
||||||
|
// Watch for changes, update accordingly
|
||||||
|
watch_server(&config, &server, &dir)
|
||||||
|
} {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Watch server directory.
|
||||||
|
///
|
||||||
|
/// Returns `true` if we should watch again.
|
||||||
|
#[must_use]
|
||||||
|
fn watch_server(config: &Config, server: &Server, dir: &Path) -> bool {
|
||||||
|
// Directory must exist
|
||||||
|
if !dir.is_dir() {
|
||||||
|
error!(target: "lazymc", "Server directory does not exist at {} anymore, not watching changes", dir.display());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create watcher for directory
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
let mut watcher =
|
||||||
|
watcher(tx, WATCH_DEBOUNCE).expect("failed to create watcher for banned-ips.json");
|
||||||
|
if let Err(err) = watcher.watch(dir, RecursiveMode::NonRecursive) {
|
||||||
|
error!(target: "lazymc", "An error occured while creating watcher for server files: {}", err);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle change events
|
||||||
|
loop {
|
||||||
|
match rx.recv().unwrap() {
|
||||||
|
// Handle file updates
|
||||||
|
DebouncedEvent::Create(ref path)
|
||||||
|
| DebouncedEvent::Write(ref path)
|
||||||
|
| DebouncedEvent::Remove(ref path) => {
|
||||||
|
update(config, server, dir, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle file updates on both paths for rename
|
||||||
|
DebouncedEvent::Rename(ref before_path, ref after_path) => {
|
||||||
|
update(config, server, dir, before_path);
|
||||||
|
update(config, server, dir, after_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore write/remove notices, will receive write/remove event later
|
||||||
|
DebouncedEvent::NoticeWrite(_) | DebouncedEvent::NoticeRemove(_) => {}
|
||||||
|
|
||||||
|
// Ignore chmod changes
|
||||||
|
DebouncedEvent::Chmod(_) => {}
|
||||||
|
|
||||||
|
// Rewatch on rescan
|
||||||
|
DebouncedEvent::Rescan => {
|
||||||
|
debug!(target: "lazymc", "Rescanning server directory files due to file watching problem");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rewatch on error
|
||||||
|
DebouncedEvent::Error(err, _) => {
|
||||||
|
error!(target: "lazymc", "Error occurred while watching server directory for file changes: {}", err);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Process a file change on the given path.
|
||||||
|
///
|
||||||
|
/// Should be called both when created, changed or removed.
|
||||||
|
fn update(config: &Config, server: &Server, dir: &Path, path: &Path) {
|
||||||
|
// Update bans
|
||||||
|
if path.ends_with(ban::FILE) {
|
||||||
|
reload_bans(config, server, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update whitelist
|
||||||
|
if path.ends_with(whitelist::WHITELIST_FILE)
|
||||||
|
|| path.ends_with(whitelist::OPS_FILE)
|
||||||
|
|| path.ends_with(server_properties::FILE)
|
||||||
|
{
|
||||||
|
reload_whitelist(config, server, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reload banned IPs.
|
||||||
|
fn reload_bans(config: &Config, server: &Server, path: &Path) {
|
||||||
|
// Bans must be enabled
|
||||||
|
if !config.server.block_banned_ips && !config.server.drop_banned_ips {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!(target: "lazymc", "Reloading banned IPs...");
|
||||||
|
|
||||||
|
// File must exist, clear file otherwise
|
||||||
|
if !path.is_file() {
|
||||||
|
debug!(target: "lazymc", "No banned IPs, {} does not exist", ban::FILE);
|
||||||
|
// warn!(target: "lazymc", "Not blocking banned IPs, {} file does not exist", ban::FILE);
|
||||||
|
server.set_banned_ips_blocking(BannedIps::default());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load and update banned IPs
|
||||||
|
match ban::load(path) {
|
||||||
|
Ok(ips) => server.set_banned_ips_blocking(ips),
|
||||||
|
Err(err) => {
|
||||||
|
debug!(target: "lazymc", "Failed load banned IPs from {}, ignoring: {}", ban::FILE, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show warning if 127.0.0.1 is banned
|
||||||
|
if server.is_banned_ip_blocking(&("127.0.0.1".parse().unwrap())) {
|
||||||
|
warn!(target: "lazymc", "Local address 127.0.0.1 IP banned, probably not what you want");
|
||||||
|
warn!(target: "lazymc", "Use '/pardon-ip 127.0.0.1' on the server to unban");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reload whitelisted users.
|
||||||
|
fn reload_whitelist(config: &Config, server: &Server, dir: &Path) {
|
||||||
|
// Whitelist must be enabled
|
||||||
|
if !config.server.wake_whitelist {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
if !enabled {
|
||||||
|
server.set_whitelist_blocking(None);
|
||||||
|
debug!(target: "lazymc", "Not using whitelist, not enabled in {}", server_properties::FILE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
trace!(target: "lazymc", "Reloading whitelisted users...");
|
||||||
|
|
||||||
|
// Load and update whitelisted users
|
||||||
|
match whitelist::load_dir(dir) {
|
||||||
|
Ok(whitelist) => server.set_whitelist_blocking(Some(whitelist)),
|
||||||
|
Err(err) => {
|
||||||
|
debug!(target: "lazymc", "Failed load whitelist from {}, ignoring: {}", dir.display(), err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
pub mod ban_reload;
|
pub mod file_watcher;
|
||||||
pub mod monitor;
|
pub mod monitor;
|
||||||
pub mod probe;
|
pub mod probe;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
@@ -59,7 +59,7 @@ pub async fn service(config: Arc<Config>) -> Result<(), ()> {
|
|||||||
tokio::spawn(service::probe::service(config.clone(), server.clone()));
|
tokio::spawn(service::probe::service(config.clone(), server.clone()));
|
||||||
tokio::task::spawn_blocking({
|
tokio::task::spawn_blocking({
|
||||||
let (config, server) = (config.clone(), server.clone());
|
let (config, server) = (config.clone(), server.clone());
|
||||||
|| service::ban_reload::service(config, server)
|
|| service::file_watcher::service(config, server)
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route all incomming connections
|
// Route all incomming connections
|
||||||
|
@@ -27,6 +27,9 @@ const BAN_MESSAGE_PREFIX: &str = "Your IP address is banned from this server.\nR
|
|||||||
/// Default ban reason if unknown.
|
/// Default ban reason if unknown.
|
||||||
const DEFAULT_BAN_REASON: &str = "Banned by an operator.";
|
const DEFAULT_BAN_REASON: &str = "Banned by an operator.";
|
||||||
|
|
||||||
|
/// The not-whitelisted kick message.
|
||||||
|
const WHITELIST_MESSAGE: &str = "You are not white-listed on this server!";
|
||||||
|
|
||||||
/// Server icon file path.
|
/// Server icon file path.
|
||||||
const SERVER_ICON_FILE: &str = "server-icon.png";
|
const SERVER_ICON_FILE: &str = "server-icon.png";
|
||||||
|
|
||||||
@@ -159,6 +162,15 @@ pub async fn serve(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kick if client is not whitelisted to wake server
|
||||||
|
if let Some(ref username) = username {
|
||||||
|
if !server.is_whitelisted(username).await {
|
||||||
|
info!(target: "lazymc", "User '{}' tried to wake server but is not whitelisted, disconnecting", username);
|
||||||
|
action::kick(&client, WHITELIST_MESSAGE, &mut writer).await?;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start server if not starting yet
|
// Start server if not starting yet
|
||||||
Server::start(config.clone(), server.clone(), username).await;
|
Server::start(config.clone(), server.clone(), username).await;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user