aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2022-10-17 11:03:16 +0200
committermetamuffin <metamuffin@disroot.org>2022-10-17 11:03:16 +0200
commitb739641a78bad5381aa2a8f7de3d464f9c5ce01f (patch)
treef3d3a84d6edb7a8f5616dce919adaa4a05807575
parentd625152c478355b32965d8bec1cdf6ce60f4b23e (diff)
downloadtrash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar
trash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar.bz2
trash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar.zst
hot reload
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock23
-rw-r--r--Cargo.toml2
-rw-r--r--readme.md7
-rw-r--r--src/main.rs75
5 files changed, 88 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index ea8c4bf..68de79d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/target
+/proxy.yaml
diff --git a/Cargo.lock b/Cargo.lock
index f34ce1c..7e6b9fe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -951,6 +951,28 @@ dependencies = [
]
[[package]]
+name = "inotify"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abf888f9575c290197b2c948dc9e9ff10bd1a39ad1ea8585f734585fa6b9d3f9"
+dependencies = [
+ "bitflags",
+ "futures-core",
+ "inotify-sys",
+ "libc",
+ "tokio 1.21.2",
+]
+
+[[package]]
+name = "inotify-sys"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
+dependencies = [
+ "libc",
+]
+
+[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1637,6 +1659,7 @@ dependencies = [
"bytes 1.2.1",
"env_logger",
"future-utils",
+ "inotify",
"log 0.4.17",
"parking_lot 0.12.1",
"serde",
diff --git a/Cargo.toml b/Cargo.toml
index 5d7ba41..6f0e179 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,3 +22,5 @@ serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9.13"
future-utils = "0.12.1"
bytes = "1.2.1"
+inotify = "0.10.0"
+
diff --git a/readme.md b/readme.md
index 4d7abfd..076005e 100644
--- a/readme.md
+++ b/readme.md
@@ -2,11 +2,14 @@
A really bad minecraft reverse proxy for authentification of offline clients.
-Supported version: 1.19.2
-
Whenever a client connects, the username is checked against all tokens in the
whitelist, the first match will determine the username you log in as.
+## Features
+
+- Supported protocol version: 1.19.2
+- Hot-reload config on changes
+
## Usage
- Install with `cargo install --path .`
diff --git a/src/main.rs b/src/main.rs
index 220c4c9..16006cb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -12,15 +12,18 @@ use azalea_protocol::{
};
use bytes::BytesMut;
use config::Config;
+use inotify::{EventMask, Inotify, WatchMask};
use log::{error, info, warn};
-use std::{fs::read_to_string, sync::Arc};
+use std::{
+ fs::read_to_string,
+ sync::{Arc, RwLock},
+};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::{
tcp::{OwnedReadHalf, OwnedWriteHalf},
TcpListener, TcpStream,
},
- sync::RwLock,
};
#[tokio::main]
@@ -30,17 +33,49 @@ async fn main() {
.parse_env("LOG")
.init();
- let config = RwLock::new(Arc::new(
+ let config = Arc::new(RwLock::new(Arc::new(
serde_yaml::from_str::<Config>(&read_to_string("proxy.yaml").unwrap()).unwrap(),
- ));
+ )));
+
+ {
+ let config = config.clone();
+ std::thread::spawn(move || {
+ let mut inotify = Inotify::init().unwrap();
+ inotify
+ .add_watch(
+ ".",
+ WatchMask::MODIFY | WatchMask::CREATE | WatchMask::DELETE,
+ )
+ .unwrap();
+ let mut buffer = [0u8; 4096];
+ loop {
+ let events = inotify
+ .read_events_blocking(&mut buffer)
+ .expect("Failed to read inotify events");
- let listener = TcpListener::bind(config.read().await.bind).await.unwrap();
+ for event in events {
+ if event.mask.contains(EventMask::MODIFY) {
+ info!("reloading config");
+ match serde_yaml::from_str::<Config>(&read_to_string("proxy.yaml").unwrap())
+ {
+ Ok(conf) => *config.write().unwrap() = Arc::new(conf),
+ Err(e) => error!("config has errors: {e}"),
+ }
+ }
+ }
+ }
+ });
+ }
+
+ let listener = TcpListener::bind(config.read().unwrap().bind)
+ .await
+ .unwrap();
info!("listening");
loop {
match listener.accept().await {
Ok((sock, addr)) => {
info!("connected: {addr}");
- let config = config.read().await.clone();
+ let config = config.read().unwrap().clone();
tokio::spawn(async move {
match handle_client(config, sock).await {
Ok(()) => info!("disconnected: {addr}"),
@@ -72,7 +107,7 @@ async fn handle_client(config: Arc<Config>, sock: TcpStream) -> Result<(), anyho
"new client (version={}, intent={:?})",
p.protocol_version, p.intention
);
- if p.protocol_version == config.protocol {
+ if p.protocol_version != config.protocol {
bail!("protocol version unsupported")
}
match p.intention {
@@ -101,7 +136,7 @@ async fn handle_client(config: Arc<Config>, sock: TcpStream) -> Result<(), anyho
match profile {
Some(profile) => {
- info!("auth as {}", profile.username);
+ info!("login as {:?}", profile.username);
p.username = profile.username.clone();
}
None => bail!("no profile found, disconnecting client"),
@@ -131,11 +166,13 @@ async fn handle_client(config: Arc<Config>, sock: TcpStream) -> Result<(), anyho
)
.await?;
- tokio::spawn(async move {
- connect(downstream_writer, upstream_reader).await.unwrap();
- });
-
- connect(upstream_writer, downstream_reader).await?;
+ let task_res = tokio::spawn(async move { connect(downstream_writer, upstream_reader).await });
+ let res = connect(upstream_writer, downstream_reader).await;
+ task_res.abort();
+ res?;
+ if let Ok(r) = task_res.await {
+ r?;
+ }
Ok(())
}
@@ -174,11 +211,13 @@ async fn handle_status_intent(
)
.await?;
- tokio::spawn(async move {
- connect(writer, upstream_reader).await.unwrap();
- });
-
- connect(upstream_writer, reader).await?;
+ let task_res = tokio::spawn(async move { connect(writer, upstream_reader).await });
+ let res = connect(upstream_writer, reader).await;
+ task_res.abort();
+ res?;
+ if let Ok(r) = task_res.await {
+ r?;
+ }
return Ok(());
}