From d21e25eda9b1b7e959072082102f7d726e1693e6 Mon Sep 17 00:00:00 2001 From: MeexReay Date: Tue, 12 Nov 2024 21:43:38 +0300 Subject: [PATCH] abaunda --- Cargo.lock | 329 +++---------------- Cargo.toml | 14 +- README.md | 2 +- config.yml | 2 +- src/main.rs | 99 +----- src/meexprox/config.rs | 111 ++----- src/meexprox/connection.rs | 180 ++++++++++ src/meexprox/error.rs | 26 ++ src/meexprox/event.rs | 303 ++++------------- src/meexprox/meexprox.rs | 656 ++++--------------------------------- src/meexprox/mod.rs | 4 +- 11 files changed, 414 insertions(+), 1312 deletions(-) create mode 100644 src/meexprox/connection.rs diff --git a/Cargo.lock b/Cargo.lock index d5332b8..80c13cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,46 +3,22 @@ version = 3 [[package]] -name = "addr2line" -version = "0.22.0" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] -name = "adler" -version = "1.0.2" +name = "anyhow" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" [[package]] name = "bytebuffer" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7bfaf7cd08cacd74cdc6b521c37ac39cbc92692e5ab5c21ed5657a749b577c" +checksum = "2618ff1f07e000264e355904bff5c0527091fcbad883ff7f71383c5428915f4b" dependencies = [ "byteorder", ] @@ -53,29 +29,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "cc" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "contracts" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9424f2ca1e42776615720e5746eed6efa19866fdbaac2923ab51c294ac4d1f2" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "crc32fast" version = "1.4.2" @@ -94,72 +53,34 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", ] -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "ignore-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "665ff4dce8edd10d490641ccb78949832f1ddbff02c584fb1f85ab888fe0e50c" + [[package]] name = "indexmap" version = "2.2.6" @@ -184,15 +105,13 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libyml" -version = "0.0.3" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e281a65eeba3d4503a2839252f86374528f9ceafe6fed97c1d3b52e1fb625c1" - -[[package]] -name = "linux-raw-sys" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" +dependencies = [ + "anyhow", + "version_check", +] [[package]] name = "log" @@ -204,13 +123,11 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" name = "meexprox" version = "0.1.0" dependencies = [ - "derivative", + "ignore-result", "log", - "no_deadlocks", "rust_mc_proto", "serde_yml", "simplelog", - "tokio", "uuid", ] @@ -222,21 +139,11 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", -] - -[[package]] -name = "no_deadlocks" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0e0af0e4fcf0d695f224cafbf5e4fb750b85aa1cd1ad0b37d8d0d98c0d2ce5e" -dependencies = [ - "backtrace", - "vector-map", + "adler2", ] [[package]] @@ -254,36 +161,12 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" -dependencies = [ - "memchr", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" -[[package]] -name = "ppv-lite86" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro2" version = "1.0.86" @@ -302,77 +185,16 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom", - "libc", - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - [[package]] name = "rust_mc_proto" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5392814ae7129d56b0afcbdd5d6d4764ca51273fab7ff604ebe73018dbb562" +version = "0.1.16" +source = "git+https://github.com/MeexReay/rust_mc_proto#26a78af446bd7ceba54fa2fa34d2f6570e827904" dependencies = [ "bytebuffer", "flate2", "uuid", ] -[[package]] -name = "rustc-demangle" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" - -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys", -] - [[package]] name = "ryu" version = "1.0.18" @@ -396,35 +218,22 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.71", -] - -[[package]] -name = "serde_json" -version = "1.0.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" -dependencies = [ - "itoa", - "ryu", - "serde", + "syn", ] [[package]] name = "serde_yml" -version = "0.0.10" +version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ce6afeda22f0b55dde2c34897bce76a629587348480384231205c14b59a01f" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" dependencies = [ "indexmap", "itoa", "libyml", - "log", "memchr", "ryu", "serde", - "serde_json", - "tempfile", + "version_check", ] [[package]] @@ -438,17 +247,6 @@ dependencies = [ "time", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.71" @@ -460,18 +258,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys", -] - [[package]] name = "termcolor" version = "1.4.1" @@ -514,16 +300,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tokio" -version = "1.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" -dependencies = [ - "backtrace", - "pin-project-lite", -] - [[package]] name = "unicode-ident" version = "1.0.12" @@ -532,25 +308,15 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" [[package]] -name = "vector-map" -version = "1.0.1" +name = "version_check" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550f72ae94a45c0e2139188709e6c4179f0b5ff9bdaa435239ad19048b0cd68c" -dependencies = [ - "contracts", - "rand", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "winapi-util" @@ -633,24 +399,3 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zerocopy" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" -dependencies = [ - "byteorder", - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.71", -] diff --git a/Cargo.toml b/Cargo.toml index 30087e6..1b1c45d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,11 +4,13 @@ version = "0.1.0" edition = "2021" [dependencies] -serde_yml = "0.0.10" -rust_mc_proto = "0.1.15" -uuid = "1.10.0" +serde_yml = "0.0.12" +rust_mc_proto = { git = "https://github.com/MeexReay/rust_mc_proto", features = ["atomic_clone"] } +uuid = "1.11.0" log = "0.4.22" simplelog = "0.12.2" -derivative = "2.2.0" -no_deadlocks = "1.3.2" -tokio = {version = "1.39.2", features = ["rt"] } +# derivative = "2.2.0" +# no_deadlocks = "1.3.2" +# tokio = {version = "1.39.3", features = ["full"] } +# async-trait = "0.1.81" +ignore-result = "0.2.0" \ No newline at end of file diff --git a/README.md b/README.md index b2e57fd..292978f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Proxy for minecraft servers on rust `in developement` todo list: (✅ / ❌) -- ❌ (deadlock) add methods `connect_to_ip`, `connect_to_server`, `connect_to_stream`, `reconnect` +- ❌ add methods `connect_to_ip`, `connect_to_server`, `connect_to_stream`, `reconnect` - ❌ make setting `no_pf_for_ip_connect` working - ❌ make talk server - ❌ create bukkit plugin for player formatting support and talking diff --git a/config.yml b/config.yml index bcf2133..84d8a19 100644 --- a/config.yml +++ b/config.yml @@ -4,7 +4,7 @@ talk_host: 127.0.0.1:12346 # secret host to talk with meexprox (optional) talk_secret: qwerty123456 # secret token for talk with meexprox (optional) servers: # verified servers (name -> ip) - play: 6.tcp.eu.ngrok.io:17753 + play: 127.0.0.1:12345 forced_hosts: # connect to server from connected hostname (name -> hostname) (optional) play: play.localhost diff --git a/src/main.rs b/src/main.rs index 65f5249..7df4f6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,91 +1,18 @@ -use log::debug; -use meexprox::{ - EventListener, MeexProx, MeexProxMutex, ProxyConfig, - ProxyEvent::{self, *}, - ProxyPlayer, -}; -use rust_mc_proto::DataBufferReader; -use simplelog::{ - ColorChoice, CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode, WriteLogger, -}; -use std::{ - error::Error, - fs::{self, File}, - path::Path, - sync::atomic::Ordering, -}; +use std::{fs::{self, File}, path::Path}; -pub struct MyEventListener {} +use log::LevelFilter; +use meexprox::{config::ProxyConfig, MeexProx}; +use simplelog::{ColorChoice, CombinedLogger, Config, TermLogger, TerminalMode, WriteLogger}; -impl EventListener for MyEventListener { - fn on_event( - &mut self, - this: MeexProxMutex, - event: &mut ProxyEvent, - ) -> Result<(), Box> { - match event { - RecvServerPacketEvent { packet, player } => { - // debug!("recv server packet event"); - } - SendServerPacketEvent { - packet, - player, - cancel, - } => { - // debug!("send server packet event"); - } - SendClientPacketEvent { - packet, - player, - cancel, - } => { - // debug!("send client packet event"); - } - RecvClientPacketEvent { packet, player } => { - // debug!("recv client packet event"); - if packet.id() == 0x03 || packet.id() == 0x04 { - let command = packet.read_string()?; - if command == "reconnect" { - println!("reconnect wow"); - ProxyPlayer::reconnect(player.clone(), this.clone(), "localhost", 25565) - .unwrap(); - } - } - } - PlayerConnectedEvent { player } => { - debug!("player connected"); - } - PlayerConnectingServerEvent { - player, - server, - cancel, - } => { - debug!("player connecting server"); - } - PlayerConnectingIPEvent { player, ip, cancel } => { - debug!("player connecting ip"); - } - PlayerDisconnectedEvent { player } => { - debug!("player disconnected"); - } - StatusRequestEvent { - status, - client_address, - server_address, - server_port, - cancel, - } => { - debug!("status request"); - } - } +// pub struct MyEventListener {} - Ok(()) - } -} +// impl EventListener for MyEventListener { -fn main() { +// } + +pub fn main() { CombinedLogger::init(vec![ TermLogger::new( LevelFilter::Debug, @@ -104,15 +31,13 @@ fn main() { let config_path = Path::new("config.yml"); if !config_path.exists() { - fs::write(config_path, include_bytes!("../default_config.yml")) + fs::write(config_path, include_bytes!("../config.yml")) .expect("config write error"); } let config = ProxyConfig::load(config_path).expect("config parse error"); - let mut meexprox = MeexProx::new(config); - - meexprox.add_event_listener(Box::new(MyEventListener {})); - + let meexprox = MeexProx::new(config); + // meexprox.add_event_listener(Box::new(MyEventListener {})); meexprox.start(); } diff --git a/src/meexprox/config.rs b/src/meexprox/config.rs index 774dce0..48aac27 100644 --- a/src/meexprox/config.rs +++ b/src/meexprox/config.rs @@ -1,45 +1,32 @@ -use super::ProxyError; - use serde_yml::Value; use std::fs; use std::path::Path; +use super::error::ProxyError; + #[derive(Clone, Debug)] -pub struct ProxyServer { - name: String, - host: String, - forced_host: Option, +pub struct ServerInfo { + pub name: String, + pub host: String, + pub forced_host: Option, } -impl ProxyServer { - pub fn new(name: String, host: String, forced_host: Option) -> ProxyServer { - ProxyServer { +impl ServerInfo { + pub fn new(name: String, host: String, forced_host: Option) -> ServerInfo { + ServerInfo { name, host, forced_host, } } - pub fn name(&self) -> &str { - &self.name - } - - pub fn host(&self) -> &str { - &self.host - } - - pub fn forced_host(&self) -> Option<&String> { - self.forced_host.as_ref() - } -} - -macro_rules! extract_string { - ($data:expr, $key:expr) => { - match $data.get(&Value::String($key.to_string())) { - Some(Value::String(val)) => Some(val.clone()), - _ => None, + pub fn from_host(host: String) -> ServerInfo { + ServerInfo { + name: host.clone(), + host, + forced_host: None, } - }; + } } #[derive(Clone)] @@ -50,20 +37,20 @@ pub enum PlayerForwarding { #[derive(Clone)] pub struct ProxyConfig { - host: String, - servers: Vec, - default_server: Option, - talk_host: Option, - talk_secret: Option, - player_forwarding: PlayerForwarding, - no_pf_for_ip_connect: bool, + pub host: String, + pub servers: Vec, + pub default_server: Option, + pub talk_host: Option, + pub talk_secret: Option, + pub player_forwarding: PlayerForwarding, + pub no_pf_for_ip_connect: bool, } impl ProxyConfig { pub fn new( host: String, - servers: Vec, - default_server: Option, + servers: Vec, + default_server: Option, talk_host: Option, talk_secret: Option, player_forwarding: PlayerForwarding, @@ -80,42 +67,15 @@ impl ProxyConfig { } } - pub fn host(&self) -> &str { - &self.host - } - - pub fn servers(&self) -> &Vec { - &self.servers - } - - pub fn talk_host(&self) -> Option<&String> { - self.talk_host.as_ref() - } - - pub fn talk_secret(&self) -> Option<&String> { - self.talk_secret.as_ref() - } - pub fn default_server(&self) -> Option<&ProxyServer> { - self.default_server.as_ref() - } - - pub fn player_forwarding(&self) -> &PlayerForwarding { - &self.player_forwarding - } - - pub fn no_pf_for_ip_connect(&self) -> bool { - self.no_pf_for_ip_connect - } - - pub fn load_data(data: String) -> Result> { + pub fn load_yml(data: String) -> Result> { let data = serde_yml::from_str::(&data)?; let data = data.as_mapping().ok_or(ProxyError::ConfigParse)?; - let host = extract_string!(data, "host").ok_or(ProxyError::ConfigParse)?; - let talk_host = extract_string!(data, "talk_host"); - let talk_secret = extract_string!(data, "talk_secret"); - let player_forwarding = match extract_string!(data, "player_forwarding") { - Some(pf) => match pf.as_str() { + let host = data.get("host").map(|o| o.as_str()).flatten().ok_or(ProxyError::ConfigParse)?.to_string(); + let talk_host = data.get("talk_host").map(|o| o.as_str()).flatten().map(|o| o.to_string()); + let talk_secret = data.get("talk_secret").map(|o| o.as_str()).flatten().map(|o| o.to_string()); + let player_forwarding = match data.get("player_forwarding").map(|o| o.as_str()).flatten() { + Some(pf) => match pf { "disabled" => PlayerForwarding::Disabled, _ => PlayerForwarding::Handshake, }, @@ -135,7 +95,7 @@ impl ProxyConfig { { for (name, addr) in servers_map { if let (Value::String(name), Value::String(addr)) = (name, addr) { - servers.push(ProxyServer::new(name.clone(), addr.clone(), None)); + servers.push(ServerInfo::new(name.clone(), addr.clone(), None)); } } } @@ -153,7 +113,8 @@ impl ProxyConfig { } } - let default_server = extract_string!(data, "default_server") + let default_server = data.get("default_server") + .map(|o| o.as_str()).flatten() .and_then(|ds| servers.iter().find(|s| s.name == ds).cloned()); Ok(ProxyConfig::new( @@ -168,10 +129,10 @@ impl ProxyConfig { } pub fn load(path: impl AsRef) -> Result> { - Self::load_data(fs::read_to_string(path)?) + Self::load_yml(fs::read_to_string(path)?) } - pub fn get_server_by_name(&self, name: &str) -> Option { + pub fn get_server_by_name(&self, name: &str) -> Option { for server in &self.servers { if &server.name == name { return Some(server.clone()); @@ -180,7 +141,7 @@ impl ProxyConfig { None } - pub fn get_server_by_forced_host(&self, forced_host: &str) -> Option { + pub fn get_server_by_forced_host(&self, forced_host: &str) -> Option { for server in &self.servers { if let Some(server_forced_host) = &server.forced_host { if server_forced_host == forced_host { diff --git a/src/meexprox/connection.rs b/src/meexprox/connection.rs new file mode 100644 index 0000000..79ffaf1 --- /dev/null +++ b/src/meexprox/connection.rs @@ -0,0 +1,180 @@ +use std::{net::TcpStream, sync::{Arc, Mutex}, thread}; + +use ignore_result::Ignore; +use rust_mc_proto::{DataBufferReader, MCConnTcp, Packet}; +use uuid::Uuid; + +use super::{config::{ProxyConfig, ServerInfo}, error::{AsProxyResult, ProxyError}}; + +#[derive(Clone, Debug)] +pub struct LoginInfo { + protocol_version: u16, + server_address: String, + server_port: u16, + name: String, + uuid: Uuid, + shared_secret: Option>, + verify_token: Option> +} + +impl LoginInfo { + pub fn write(&self, config: &ProxyConfig, stream: &mut MCConnTcp) { + todo!() // TODO: write login packets sending + } +} + +pub struct Player { + client_conn: Arc>, + server_conn: Arc>, + login_info: Option, + pub name: String, + pub uuid: Uuid, + pub server: Option, + pub protocol_version: u16 +} + +impl Player { + pub fn read( + protocol_version: u16, + server_address: String, + server_port: u16, + server: ServerInfo, + mut client_conn: MCConnTcp, + mut server_conn: MCConnTcp + ) -> Result { + let mut packet = client_conn.read_packet().as_proxy()?; + + if packet.id() != 0x00 { return Err(ProxyError::LoginPacket); } + + let name = packet.read_string().as_proxy()?; + let uuid = packet.read_uuid().as_proxy()?; + + server_conn.write_packet(&packet).as_proxy()?; + + let mut player = Player { + client_conn: Arc::new(Mutex::new(client_conn)), + server_conn: Arc::new(Mutex::new(server_conn)), + login_info: None, + name: name.clone(), + uuid, + server: Some(server), + protocol_version + }; + + let mut shared_secret = None; + let mut verify_token = None; + + loop { + let mut packet = player.read_server_packet()?; + match packet.id() { + 0x01 => { + player.write_client_packet(&packet)?; + let mut packet = player.read_client_packet()?; + let i = packet.read_usize_varint().as_proxy()?; + shared_secret = Some(packet.read_bytes(i).as_proxy()?); + let i = packet.read_usize_varint().as_proxy()?; + verify_token = Some(packet.read_bytes(i).as_proxy()?); + player.write_server_packet(&packet)?; + } + 0x02 => { + player.write_client_packet(&packet)?; + break; + } + 0x03 => { + player.write_client_packet(&packet)?; + let compression = Some(packet.read_usize_varint().as_proxy()?); + player.set_server_compression(compression); + player.set_client_compression(compression); + } + _ => { + return Err(ProxyError::LoginPacket); + }, + } + } + + player.login_info = Some(LoginInfo { + protocol_version, + server_address, + server_port, + name, + uuid, + shared_secret, + verify_token + }); + + player.write_server_packet(&player.read_client_packet()?)?; + + player.client_recv_loop(); + + Ok(player) + } + + pub fn client_recv_loop(&self) { + let mut client: rust_mc_proto::MinecraftConnection = self.client_conn.clone().lock().unwrap().try_clone().unwrap(); + let server = self.server_conn.clone(); + + thread::spawn(move || { + while let Ok(packet) = client.read_packet() { + while !server.lock().unwrap().is_alive() {} + server.lock().unwrap().write_packet(&packet).ignore(); + } + }); + } + + pub fn server_recv_loop(&self) { + let mut server = self.server_conn.clone().lock().unwrap().try_clone().unwrap(); + let client = self.client_conn.clone(); + + thread::spawn(move || { + while let Ok(packet) = server.read_packet() { + client.lock().unwrap().write_packet(&packet).ignore(); + } + }); + } + + pub fn connect(&self, config: &ProxyConfig, server_conn: TcpStream) -> Result<(), ProxyError> { + self.server_conn.lock().unwrap().close(); + let mut server_conn = MCConnTcp::new(server_conn); + if let Some(login_info) = &self.login_info { + login_info.write(config, &mut server_conn); + } + self.server_recv_loop(); + Ok(()) + } + + pub fn connect_server(&self, config: &ProxyConfig, server: ServerInfo) -> Result<(), ProxyError> { + self.connect(config, TcpStream::connect(&server.host).map_err(|_| ProxyError::ServerConnect)?) + } + + pub fn write_client_packet(&self, packet: &Packet) -> Result<(), ProxyError> { + self.client_conn.lock().unwrap().write_packet(packet).as_proxy() + } + + pub fn write_server_packet(&self, packet: &Packet) -> Result<(), ProxyError> { + self.server_conn.lock().unwrap().write_packet(packet).as_proxy() + } + + fn read_client_packet(&self) -> Result { + self.client_conn.lock().unwrap().read_packet().as_proxy() + } + + fn read_server_packet(&self) -> Result { + self.server_conn.lock().unwrap().read_packet().as_proxy() + } + + fn set_server_compression(&self, threshold: Option) { + self.server_conn.lock().unwrap().set_compression(threshold); + } + + fn set_client_compression(&self, threshold: Option) { + self.client_conn.lock().unwrap().set_compression(threshold); + } + + pub fn server_compression(&self) -> Option { + self.server_conn.lock().unwrap().compression() + } + + pub fn client_compression(&self) -> Option { + self.client_conn.lock().unwrap().compression() + } +} \ No newline at end of file diff --git a/src/meexprox/error.rs b/src/meexprox/error.rs index 6693b5f..7e9dfcf 100644 --- a/src/meexprox/error.rs +++ b/src/meexprox/error.rs @@ -1,8 +1,14 @@ +use rust_mc_proto::ProtocolError; + #[derive(Debug)] pub enum ProxyError { ConfigParse, ServerConnect, EventChanged, + HandshakePacket, + LoginPacket, + PeerAddr, + ProtocolError(ProtocolError) } impl std::fmt::Display for ProxyError { @@ -12,3 +18,23 @@ impl std::fmt::Display for ProxyError { } impl std::error::Error for ProxyError {} + +pub trait AsProxyError { + fn as_proxy(self) -> ProxyError; +} + +pub trait AsProxyResult { + fn as_proxy(self) -> Result; +} + +impl AsProxyError for ProtocolError { + fn as_proxy(self) -> ProxyError { + ProxyError::ProtocolError(self) + } +} + +impl AsProxyResult for Result { + fn as_proxy(self) -> Result { + self.map_err(|o| o.as_proxy()) + } +} \ No newline at end of file diff --git a/src/meexprox/event.rs b/src/meexprox/event.rs index a4135c2..366cdfb 100644 --- a/src/meexprox/event.rs +++ b/src/meexprox/event.rs @@ -1,252 +1,59 @@ -use super::{MeexProx, MeexProxMutex, PlayerMutex, ProxyServer}; +use std::net::SocketAddr; + use rust_mc_proto::Packet; -use std::{ - error::Error, - net::SocketAddr, - sync::atomic::{AtomicBool, Ordering}, -}; -pub enum ProxyEvent { - /// client <- proxy <- server \ - ///   | \ - ///   RecvServerPacketEvent - RecvServerPacketEvent { - packet: Packet, - player: PlayerMutex, - }, - - /// client -> proxy -> server \ - ///   | \ - ///   SendServerPacketEvent - SendServerPacketEvent { - packet: Packet, - player: PlayerMutex, - cancel: AtomicBool, - }, - - /// client <- proxy <- server \ - ///   | \ - ///   SendClientPacketEvent - SendClientPacketEvent { - packet: Packet, - player: PlayerMutex, - cancel: AtomicBool, - }, - - /// client -> proxy -> server \ - ///   | \ - ///   RecvClientPacketEvent - RecvClientPacketEvent { - packet: Packet, - player: PlayerMutex, - }, - - PlayerConnectedEvent { - player: PlayerMutex, - }, - - PlayerDisconnectedEvent { - player: PlayerMutex, - }, - - PlayerConnectingServerEvent { - player: PlayerMutex, - server: ProxyServer, - cancel: AtomicBool, - }, - - PlayerConnectingIPEvent { - player: PlayerMutex, - ip: String, - cancel: AtomicBool, - }, - - StatusRequestEvent { - status: String, - client_address: SocketAddr, - server_address: String, - server_port: u16, - cancel: AtomicBool, - }, -} - -impl ProxyEvent { - pub fn status_request( - meexprox: MeexProxMutex, - status: String, - client_address: SocketAddr, - server_address: String, - server_port: u16, - ) -> (String, bool) { - let ProxyEvent::StatusRequestEvent { - status, - client_address: _, - server_address: _, - server_port: _, - cancel, - } = MeexProx::trigger_event( - meexprox, - ProxyEvent::StatusRequestEvent { - status: status.clone(), - client_address, - server_address, - server_port, - cancel: AtomicBool::from(false), - }, - ) - else { - return (status, false); - }; - (status, cancel.load(Ordering::Relaxed)) - } - - pub fn player_connecting_ip( - meexprox: MeexProxMutex, - player: PlayerMutex, - ip: String, - ) -> (String, bool) { - let ProxyEvent::PlayerConnectingIPEvent { - ip, - player: _, - cancel, - } = MeexProx::trigger_event( - meexprox, - ProxyEvent::PlayerConnectingIPEvent { - ip: ip.clone(), - player, - cancel: AtomicBool::from(false), - }, - ) - else { - return (ip, false); - }; - (ip, cancel.load(Ordering::Relaxed)) - } - - pub fn player_connecting_server( - meexprox: MeexProxMutex, - player: PlayerMutex, - server: ProxyServer, - ) -> (ProxyServer, bool) { - let ProxyEvent::PlayerConnectingServerEvent { - server, - player: _, - cancel, - } = MeexProx::trigger_event( - meexprox, - ProxyEvent::PlayerConnectingServerEvent { - server: server.clone(), - player, - cancel: AtomicBool::from(false), - }, - ) - else { - return (server, false); - }; - (server, cancel.load(Ordering::Relaxed)) - } - - pub fn player_disconnected(meexprox: MeexProxMutex, player: PlayerMutex) -> () { - let ProxyEvent::PlayerDisconnectedEvent { player: _ } = - MeexProx::trigger_event(meexprox, ProxyEvent::PlayerDisconnectedEvent { player }) - else { - return; - }; - } - - pub fn player_connected(meexprox: MeexProxMutex, player: PlayerMutex) -> () { - let ProxyEvent::PlayerConnectedEvent { player: _ } = - MeexProx::trigger_event(meexprox, ProxyEvent::PlayerConnectedEvent { player }) - else { - return; - }; - } - - pub fn send_client_packet( - meexprox: MeexProxMutex, - packet: Packet, - player: PlayerMutex, - ) -> (Packet, bool) { - let ProxyEvent::SendClientPacketEvent { - packet, - player: _, - cancel, - } = MeexProx::trigger_event( - meexprox, - ProxyEvent::SendClientPacketEvent { - packet: packet.clone(), - player, - cancel: AtomicBool::from(false), - }, - ) - else { - return (packet, false); - }; - (packet, cancel.load(Ordering::Relaxed)) - } - - pub fn send_server_packet( - meexprox: MeexProxMutex, - packet: Packet, - player: PlayerMutex, - ) -> (Packet, bool) { - let ProxyEvent::SendServerPacketEvent { - packet, - player: _, - cancel, - } = MeexProx::trigger_event( - meexprox, - ProxyEvent::SendServerPacketEvent { - packet: packet.clone(), - player, - cancel: AtomicBool::from(false), - }, - ) - else { - return (packet, false); - }; - (packet, cancel.load(Ordering::Relaxed)) - } - - pub fn recv_server_packet( - meexprox: MeexProxMutex, - packet: Packet, - player: PlayerMutex, - ) -> Packet { - let ProxyEvent::RecvServerPacketEvent { packet, player: _ } = MeexProx::trigger_event( - meexprox, - ProxyEvent::RecvServerPacketEvent { - packet: packet.clone(), - player, - }, - ) else { - return packet; - }; - packet - } - - pub fn recv_client_packet( - meexprox: MeexProxMutex, - packet: Packet, - player: PlayerMutex, - ) -> Packet { - let ProxyEvent::RecvClientPacketEvent { packet, player: _ } = MeexProx::trigger_event( - meexprox, - ProxyEvent::RecvClientPacketEvent { - packet: packet.clone(), - player, - }, - ) else { - return packet; - }; - packet - } -} +use super::{config::ServerInfo, connection::Player, error::ProxyError}; pub trait EventListener { - fn on_event( - &mut self, - meexprox: MeexProxMutex, - event: &mut ProxyEvent, - ) -> Result<(), Box>; -} + fn on_server_recv_packet( + &self, + packet: &mut Packet, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_server_send_packet( + &self, + packet: &mut Packet, + cancel: &mut bool, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_client_send_packet( + &self, + packet: &mut Packet, + cancel: &mut bool, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_client_recv_packet( + &self, + packet: &mut Packet, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_player_connected( + &self, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_player_disconnected( + &self, + player: &Player, + ) -> Result<(), ProxyError>; + + fn on_player_connecting_server( + &self, + player: &Player, + cancel: &mut bool, + server: &mut ServerInfo + ) -> Result<(), ProxyError>; + + fn on_status_request( + &self, + status: String, + client_address: SocketAddr, + server_address: String, + server_port: u16, + cancel: &mut bool, + ) -> Result<(), ProxyError>; +} \ No newline at end of file diff --git a/src/meexprox/meexprox.rs b/src/meexprox/meexprox.rs index 8f4c943..a8acc13 100644 --- a/src/meexprox/meexprox.rs +++ b/src/meexprox/meexprox.rs @@ -1,512 +1,74 @@ -use super::{EventListener, PlayerForwarding, ProxyConfig, ProxyError, ProxyEvent, ProxyServer}; -use derivative::Derivative; -use log::{debug, info}; -use no_deadlocks::Mutex; +use log::{error, info}; +// use no_deadlocks::Mutex; use rust_mc_proto::{ - DataBufferReader, DataBufferWriter, MinecraftConnection, Packet, ProtocolError, Zigzag, + read_packet, write_packet, DataBufferReader, DataBufferWriter, MCConnTcp, Packet }; use std::{ - error::Error, net::{SocketAddr, TcpListener, TcpStream}, sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, - thread, + Arc, RwLock, RwLockReadGuard + }, thread, }; -use tokio::task::AbortHandle; -use uuid::Uuid; -#[derive(Derivative)] -#[derivative(Debug)] -pub struct ProxyPlayer { - #[derivative(Debug = "ignore")] - client_conn: MinecraftConnection, - #[derivative(Debug = "ignore")] - server_conn: MinecraftConnection, - connection_threads: Vec, - name: Option, - uuid: Option, - protocol_version: u16, - server: Option, - shared_secret: Option>, - verify_token: Option>, -} +use super::{config::{PlayerForwarding, ProxyConfig}, connection::Player, error::{AsProxyResult, ProxyError}, event::EventListener}; -impl ProxyPlayer { - pub fn new( - client_conn: MinecraftConnection, - server_conn: MinecraftConnection, - connection_threads: Vec, - name: Option, - uuid: Option, - protocol_version: u16, - server: Option, - shared_secret: Option>, - verify_token: Option>, - ) -> ProxyPlayer { - ProxyPlayer { - client_conn, - server_conn, - name, - uuid, - protocol_version, - server, - shared_secret, - verify_token, - connection_threads, - } - } - - pub fn client_conn(&self) -> &MinecraftConnection { - &self.client_conn - } - - pub fn server_conn(&self) -> &MinecraftConnection { - &self.server_conn - } - - pub fn client_conn_mut(&mut self) -> &mut MinecraftConnection { - &mut self.client_conn - } - - pub fn server_conn_mut(&mut self) -> &mut MinecraftConnection { - &mut self.server_conn - } - - pub fn name(&self) -> Option<&String> { - self.name.as_ref() - } - - pub fn uuid(&self) -> Option<&Uuid> { - self.uuid.as_ref() - } - - pub fn protocol_version(&self) -> u16 { - self.protocol_version - } - - pub fn server(&self) -> Option<&ProxyServer> { - self.server.as_ref() - } - - pub fn shared_secret(&self) -> Option<&Vec> { - self.shared_secret.as_ref() - } - - pub fn verify_token(&self) -> Option<&Vec> { - self.verify_token.as_ref() - } - - pub fn connection_threads(&mut self) -> &mut Vec { - &mut self.connection_threads - } - - pub fn connect_to_ip( - this: PlayerMutex, - meexprox: MeexProxMutex, - ip: &str, - server_address: &str, - server_port: u16, - ) -> Result<(), Box> { - let (ip, cancel) = - ProxyEvent::player_connecting_ip(meexprox.clone(), this.clone(), ip.to_string()); - let ip = &ip; - - if cancel { - return Ok(()); - } - - for thread in &mut this.lock().unwrap().connection_threads { - thread.abort(); - } - - this.lock().unwrap().server_conn.close(); - this.lock().unwrap().server_conn = MinecraftConnection::connect(ip)?; - - thread::spawn({ - let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone(); - let server_address = server_address.to_string(); - - move || { - let _ = ProxyPlayer::connect( - this, - meexprox, - player_forwarding, - &server_address, - server_port, - false, - ); - } - }); - - Ok(()) - } - - pub fn connect_to_server( - this: PlayerMutex, - meexprox: MeexProxMutex, - server: ProxyServer, - server_address: &str, - server_port: u16, - ) -> Result<(), Box> { - let (server, cancel) = - ProxyEvent::player_connecting_server(meexprox.clone(), this.clone(), server); - - if cancel { - return Ok(()); - } - - for thread in &mut this.lock().unwrap().connection_threads { - thread.abort(); - } - this.lock().unwrap().server_conn.close(); - - this.lock().unwrap().server = Some(server.clone()); - this.lock().unwrap().server_conn = MinecraftConnection::connect(server.host())?; - - thread::spawn({ - let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone(); - let server_address = server_address.to_string(); - - move || { - let _ = ProxyPlayer::connect( - this, - meexprox, - player_forwarding, - &server_address, - server_port, - false, - ); - } - }); - - Ok(()) - } - - pub fn reconnect( - this: PlayerMutex, - meexprox: MeexProxMutex, - server_address: &str, - server_port: u16, - ) -> Result<(), Box> { - for thread in &mut this.lock().unwrap().connection_threads { - thread.abort(); - } - this.lock().unwrap().server_conn.close(); - - let server_host = this.lock().unwrap().server().unwrap().host().to_string(); - this.lock().unwrap().server_conn = MinecraftConnection::connect(&server_host)?; - - thread::spawn({ - let player_forwarding = meexprox.lock().unwrap().config.player_forwarding().clone(); - let server_address = server_address.to_string(); - - move || { - let _ = ProxyPlayer::connect( - this, - meexprox, - player_forwarding, - &server_address, - server_port, - false, - ); - } - }); - - Ok(()) - } - - fn send_handshake( - this: PlayerMutex, - meexprox: MeexProxMutex, - player_forwarding: PlayerForwarding, - addr: SocketAddr, - server_address: &str, - server_port: u16, - ) -> Result<(), ProtocolError> { - let protocol_version = this.lock().unwrap().protocol_version; - - let packet = Packet::build(0x00, move |packet| { - packet.write_u16_varint(protocol_version)?; - packet.write_string(&server_address)?; - packet.write_unsigned_short(server_port)?; - packet.write_u8_varint(2)?; - - if let PlayerForwarding::Handshake = player_forwarding { - if let SocketAddr::V4(addr) = addr { - packet.write_boolean(false)?; // is ipv6 - packet.write_unsigned_short(addr.port())?; // port - packet.write_bytes(&addr.ip().octets())?; // octets - } else if let SocketAddr::V6(addr) = addr { - packet.write_boolean(true)?; - packet.write_unsigned_short(addr.port())?; - packet.write_bytes(&addr.ip().octets())?; - } - } - - Ok(()) - })?; - - let (packet, cancel) = ProxyEvent::send_server_packet(meexprox, packet, this.clone()); - - if !cancel { - this.lock().unwrap().server_conn.write_packet(&packet)?; - } - - Ok(()) - } - - fn send_login(this: PlayerMutex, meexprox: MeexProxMutex) -> Result<(), ProtocolError> { - if let Some(player_name) = this.lock().unwrap().name.as_ref() { - if let Some(player_uuid) = this.lock().unwrap().uuid.as_ref() { - let packet = Packet::build(0x00, move |packet| { - packet.write_string(&player_name)?; - packet.write_uuid(&player_uuid)?; - Ok(()) - })?; - - let (packet, cancel) = - ProxyEvent::send_server_packet(meexprox, packet, this.clone()); - - if !cancel { - this.lock().unwrap().server_conn.write_packet(&packet)?; - } - } - } - - Ok(()) - } - - fn connect( - this: PlayerMutex, - meexprox: MeexProxMutex, - player_forwarding: PlayerForwarding, - server_address: &str, - server_port: u16, - logged: bool, - ) -> Result<(), Box> { - let mut client_conn = this.lock().unwrap().client_conn.try_clone().unwrap(); - let mut server_conn = this.lock().unwrap().server_conn.try_clone().unwrap(); - - let addr = client_conn.get_ref().peer_addr().unwrap(); - let Some(name) = this.lock().unwrap().name.clone() else { - return Ok(()); - }; - - if !logged { - ProxyPlayer::send_handshake( - this.clone(), - meexprox.clone(), - player_forwarding, - addr, - server_address, - server_port, - )?; - - ProxyPlayer::send_login(this.clone(), meexprox.clone())?; - - while let Ok(mut packet) = server_conn.read_packet() { - if packet.id() == 0x01 { - if let Some(shared_secret) = this.lock().unwrap().shared_secret.clone() { - if let Some(verify_token) = this.lock().unwrap().verify_token.clone() { - let mut enc_response = Packet::empty(0x01); - - enc_response.write_usize_varint(shared_secret.len())?; - enc_response.write_bytes(&shared_secret)?; - enc_response.write_usize_varint(shared_secret.len())?; - enc_response.write_bytes(&verify_token)?; - - let (enc_response, cancel) = ProxyEvent::send_server_packet( - meexprox.clone(), - enc_response, - this.clone(), - ); - - if !cancel { - server_conn.write_packet(&enc_response)?; - } - } - } - } - - if packet.id() == 0x03 { - let threshold = packet.read_isize_varint()?; - if threshold >= 0 { - let threshold = threshold.zigzag(); - - server_conn.set_compression(Some(threshold)); - client_conn.set_compression(Some(threshold)); - } else { - server_conn.set_compression(None); - client_conn.set_compression(None); - } - } - - if packet.id() == 0x02 { - break; - } - } - - let login_ack = Packet::empty(0x03); - - let (login_ack, cancel) = - ProxyEvent::send_server_packet(meexprox.clone(), login_ack, this.clone()); - - if !cancel { - server_conn.write_packet(&login_ack)?; - } - } - - let mut handles = Vec::new(); - - handles.push( - tokio::spawn({ - let mut client_conn = client_conn.try_clone().unwrap(); - let mut server_conn = server_conn.try_clone().unwrap(); - - let this = this.clone(); - let meexprox = meexprox.clone(); - let name = name.clone(); - let addr = addr.clone(); - - async move { - while let Ok(packet) = client_conn.read_packet() { - let packet = - ProxyEvent::recv_client_packet(meexprox.clone(), packet, this.clone()); - - let (packet, cancel) = - ProxyEvent::send_server_packet(meexprox.clone(), packet, this.clone()); - - if !cancel { - match server_conn.write_packet(&packet) { - Ok(_) => {} - Err(_) => { - break; - } - }; - } - } - - if meexprox.lock().unwrap().remove_player(this.clone()) { - info!("{} disconnected player {}", addr.to_string(), name); - ProxyEvent::player_disconnected(meexprox.clone(), this.clone()); - } - } - }) - .abort_handle(), - ); - - handles.push( - tokio::spawn({ - let this = this.clone(); - - async move { - while let Ok(packet) = server_conn.read_packet() { - let packet = - ProxyEvent::recv_server_packet(meexprox.clone(), packet, this.clone()); - - let (packet, cancel) = - ProxyEvent::send_client_packet(meexprox.clone(), packet, this.clone()); - - if !cancel { - match client_conn.write_packet(&packet) { - Ok(_) => {} - Err(_) => { - break; - } - }; - } - } - - if meexprox.lock().unwrap().remove_player(this.clone()) { - info!("{} disconnected player {}", addr.to_string(), name); - ProxyEvent::player_disconnected(meexprox.clone(), this.clone()); - } - } - }) - .abort_handle(), - ); - - this.lock().unwrap().connection_threads = handles; - - Ok(()) - } -} pub struct MeexProx { config: ProxyConfig, - players: Vec, - event_listeners: Vec>, + players: RwLock>, + event_listeners: Vec> } impl MeexProx { pub fn new(config: ProxyConfig) -> MeexProx { MeexProx { config, - players: Vec::new(), + players: RwLock::new(Vec::new()), event_listeners: Vec::new(), } } - pub fn add_event_listener(&mut self, event_listener: Box) { + pub fn add_event_listener( + &mut self, + event_listener: Box, + ) { self.event_listeners.push(event_listener); } - pub fn trigger_event(this: MeexProxMutex, mut event: ProxyEvent) -> ProxyEvent { - for event_listener in &mut this.lock().unwrap().event_listeners { - let _ = event_listener.on_event(this.clone(), &mut event); + pub fn trigger_event( + &self, + trigger: fn(&dyn EventListener) -> Result<(), ProxyError> + ) -> Result<(), ProxyError> { + for event_listener in &self.event_listeners { + trigger(event_listener.as_ref())? } - event + Ok(()) } - pub fn get_player(&self, uuid: Uuid) -> Option { - for player in &self.players { - if let Some(player_uuid) = player.lock().unwrap().uuid { - if player_uuid == uuid { - return Some(player.clone()); - } - } - } - None + pub async fn get_players(&self) -> RwLockReadGuard<'_, Vec> { + self.players.read().unwrap() } - pub fn remove_player(&mut self, player: PlayerMutex) -> bool { - match self.players.iter().position(|x| Arc::ptr_eq(x, &player)) { - Some(i) => { - self.players.remove(i); - true - } - None => false, - } - } + pub fn accept_client(&self, mut client_conn: TcpStream) -> Result<(), ProxyError> { + let addr = client_conn.peer_addr().map_err(|_| ProxyError::PeerAddr)?; - pub fn accept_client(this: MeexProxMutex, stream: TcpStream) -> Result<(), Box> { - let Ok(addr) = stream.peer_addr() else { - return Ok(()); - }; - - let server_config = this.lock().unwrap().config.clone(); - - let mut client_conn = MinecraftConnection::new(stream); - - let mut handshake = client_conn.read_packet()?; + let mut handshake = read_packet(&mut client_conn, None).as_proxy()?; if handshake.id() != 0x00 { - return Ok(()); + return Err(ProxyError::HandshakePacket); } - let protocol_version = handshake.read_u16_varint()?; - let server_address = handshake.read_string()?; - let server_port = handshake.read_unsigned_short()?; - let next_state = handshake.read_u8_varint()?; + let protocol_version = handshake.read_u16_varint().as_proxy()?; + let server_address = handshake.read_string().as_proxy()?; + let server_port = handshake.read_unsigned_short().as_proxy()?; + let next_state = handshake.read_u8_varint().as_proxy()?; - let server = server_config + let server = self.config .get_server_by_forced_host(&server_address) - .or(server_config.default_server().cloned()) + .or(self.config.default_server.clone()) .ok_or(ProxyError::ConfigParse)?; - let mut server_conn = MinecraftConnection::connect(&server.host())?; + let mut server_conn = TcpStream::connect(&server.host).map_err(|_| ProxyError::ServerConnect)?; let handshake = Packet::build(0x00, |handshake| { handshake.write_u16_varint(protocol_version)?; @@ -514,7 +76,7 @@ impl MeexProx { handshake.write_unsigned_short(server_port)?; handshake.write_u8_varint(next_state)?; - if let PlayerForwarding::Handshake = server_config.player_forwarding() { + if let PlayerForwarding::Handshake = self.config.player_forwarding { if let SocketAddr::V4(addr) = addr { handshake.write_boolean(false)?; // is ipv6 handshake.write_unsigned_short(addr.port())?; // port @@ -527,155 +89,51 @@ impl MeexProx { } Ok(()) - })?; + }).as_proxy()?; - server_conn.write_packet(&handshake)?; + write_packet(&mut server_conn, None, 0, &handshake).as_proxy()?; + + let mut client_conn = MCConnTcp::new(client_conn); + let mut server_conn = MCConnTcp::new(server_conn); if next_state == 1 { loop { - let client_packet = client_conn.read_packet()?; - - server_conn.write_packet(&client_packet)?; - - let mut server_packet = server_conn.read_packet()?; - - if client_packet.id() == 0x00 { - let server_status = server_packet.read_string()?; - - let (status, cancel) = ProxyEvent::status_request( - this.clone(), - server_status.clone(), - addr.clone(), - server_address.clone(), - server_port, - ); - - if cancel { - break; - } - - server_packet = Packet::build(0x00, |p| p.write_string(&status))?; - } - - client_conn.write_packet(&server_packet)?; + server_conn.write_packet(&client_conn.read_packet().as_proxy()?).as_proxy()?; + client_conn.write_packet(&server_conn.read_packet().as_proxy()?).as_proxy()?; } } else if next_state == 2 { - let player = Arc::new(Mutex::new(ProxyPlayer::new( - client_conn.try_clone().unwrap(), - server_conn.try_clone().unwrap(), - Vec::new(), - None, - None, - protocol_version, - Some(server.clone()), - None, - None, - ))); - - let (server, cancel) = - ProxyEvent::player_connecting_server(this.clone(), player.clone(), server.clone()); - - if cancel { - return Ok(()); - } - - player.lock().unwrap().server = Some(server); - - this.lock().unwrap().players.push(player.clone()); - - let mut login_start = client_conn.read_packet()?; - - player.lock().unwrap().name = Some(login_start.read_string()?); - player.lock().unwrap().uuid = Some(login_start.read_uuid()?); - - server_conn.write_packet(&login_start)?; - - while let Ok(mut packet) = server_conn.read_packet() { - client_conn.write_packet(&packet)?; - - if packet.id() == 0x01 { - let mut enc_response = client_conn.read_packet()?; - - let shared_secret_length = enc_response.read_usize_varint()?; - player.lock().unwrap().shared_secret = - Some(enc_response.read_bytes(shared_secret_length)?); - let verify_token_length = enc_response.read_usize_varint()?; - player.lock().unwrap().verify_token = - Some(enc_response.read_bytes(verify_token_length)?); - - server_conn.write_packet(&enc_response)?; - } - - if packet.id() == 0x03 { - let threshold = packet.read_isize_varint()?; - - if threshold >= 0 { - let threshold = threshold.zigzag(); - - server_conn.set_compression(Some(threshold)); - client_conn.set_compression(Some(threshold)); - } else { - server_conn.set_compression(None); - client_conn.set_compression(None); - } - } - - if packet.id() == 0x02 { - break; - } - } - - // println!("lac re"); - // let login_ack = client_conn.read_packet()?; - // println!("lac {}", login_ack.id()); - // if login_ack.id() != 0x03 { - // return Ok(()); - // } - - let this = this.clone(); - - info!( - "{} connected player {}", - addr.to_string(), - player.lock().unwrap().name.clone().unwrap() - ); - ProxyEvent::player_connected(this.clone(), player.clone()); - - let _ = ProxyPlayer::connect( - player, - this, - server_config.player_forwarding().clone(), - &server_address, - server_port, - true, - ); + self.players.write().unwrap().push(Player::read( + protocol_version, + server_address, + server_port, + server, + client_conn, + server_conn + )?); } Ok(()) } pub fn start(self) { - let listener = TcpListener::bind(self.config.host()).expect("invalid host"); + let listener = TcpListener::bind(&self.config.host).expect("invalid host"); - info!("meexprox started on {}", self.config.host()); + info!("meexprox started on {}", &self.config.host); - let mutex_self = Arc::new(Mutex::new(self)); + let self_arc = Arc::new(self); for client in listener.incoming() { if let Ok(client) = client { - let mutex_self_clone = mutex_self.clone(); + let self_arc = self_arc.clone(); thread::spawn(move || { - match Self::accept_client(mutex_self_clone, client) { + match self_arc.accept_client(client) { Ok(_) => {} - Err(_) => { - // error!("connection error: {:?}", e); + Err(e) => { + error!("connection error: {:?}", e); } }; }); } } } -} - -pub type PlayerMutex = Arc>; -pub type MeexProxMutex = Arc>; +} \ No newline at end of file diff --git a/src/meexprox/mod.rs b/src/meexprox/mod.rs index 9bf03bf..0165848 100644 --- a/src/meexprox/mod.rs +++ b/src/meexprox/mod.rs @@ -2,8 +2,6 @@ pub mod config; pub mod error; pub mod event; pub mod meexprox; +pub mod connection; -pub use config::*; -pub use error::*; -pub use event::*; pub use meexprox::*;