diff options
author | metamuffin <metamuffin@disroot.org> | 2022-10-17 11:03:16 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2022-10-17 11:03:16 +0200 |
commit | b739641a78bad5381aa2a8f7de3d464f9c5ce01f (patch) | |
tree | f3d3a84d6edb7a8f5616dce919adaa4a05807575 | |
parent | d625152c478355b32965d8bec1cdf6ce60f4b23e (diff) | |
download | trash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar trash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar.bz2 trash-proxy-b739641a78bad5381aa2a8f7de3d464f9c5ce01f.tar.zst |
hot reload
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Cargo.lock | 23 | ||||
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | readme.md | 7 | ||||
-rw-r--r-- | src/main.rs | 75 |
5 files changed, 88 insertions, 20 deletions
@@ -1 +1,2 @@ /target +/proxy.yaml @@ -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", @@ -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" + @@ -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(()); } |