From c750dbd8f1ff2179024123f118a70f63d8d243bf Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 10 Mar 2025 22:56:58 +0100 Subject: [PATCH] testing --- .gitignore | 20 +++++++++++++++- Cargo.lock | 23 ++++++++++++++++++ Cargo.toml | 3 ++- src/main.rs | 37 +++++++++++++++++++--------- src/methods/mod.rs | 60 ++++++++++++++++++++++++++++++++++++---------- src/parser.rs | 8 +++---- src/response.rs | 12 ++++++---- 7 files changed, 129 insertions(+), 34 deletions(-) diff --git a/.gitignore b/.gitignore index ea8c4bf..67ca772 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,19 @@ -/target +# Generated by Cargo +# will have compiled files and executables +debug/ +target/ + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# RustRover +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + +token.key \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 784bcfb..ae56909 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,6 +60,7 @@ dependencies = [ name = "auraclient-api" version = "0.1.0" dependencies = [ + "minreq", "mongodb", "serde", ] @@ -952,6 +953,22 @@ dependencies = [ "adler2", ] +[[package]] +name = "minreq" +version = "2.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0c420feb01b9fb5061f8c8f452534361dd783756dcf38ec45191ce55e7a161" +dependencies = [ + "log", + "once_cell", + "rustls", + "rustls-webpki", + "serde", + "serde_json", + "urlencoding", + "webpki-roots", +] + [[package]] name = "mio" version = "1.0.3" @@ -1739,6 +1756,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf16_iter" version = "1.0.5" diff --git a/Cargo.toml b/Cargo.toml index d9e8f2c..7b3b142 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,5 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] +minreq = { version = "2.13.2", features = ["https", "urlencoding", "json-using-serde"] } mongodb = { version = "3.2.1", features = ["sync"] } -serde = "1.0.218" +serde = { version ="1.0.218", features = ["derive"] } diff --git a/src/main.rs b/src/main.rs index f4adb78..3fcebc7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,18 +23,33 @@ fn main() -> std::io::Result<()> { move || { let mut stream = stream.unwrap(); let mut reader = BufReader::new(stream.try_clone().unwrap()); - let session = methods::Session::new(&mut reader, database).unwrap(); - loop { - let mut request_string = String::new(); - match reader.read_line(&mut request_string).unwrap() { - 0 => break, - _ => { - let (method, params) = parser::parse(&request_string).unwrap(); - let response = session.handle_request(&method, ¶ms); - stream.write_all(response.to_string().as_bytes()).unwrap(); - } - }; + match methods::Session::new(&mut reader, database) { + Ok(session) => loop { + let mut request_string = String::new(); + match reader.read_line(&mut request_string).unwrap() { + 0 => break, + _ => { + let (method, params) = parser::parse(&request_string).unwrap(); + let response = session.handle_request(&method, ¶ms); + stream + .write_all( + match response { + Ok(response) => response.to_string(), + Err(e) => format!("!{e}"), + } + .as_bytes(), + ) + .unwrap(); + } + }; + }, + Err(e) => { + stream.write_all(format!("!{e}").as_bytes()).unwrap(); + stream + .shutdown(std::net::Shutdown::Both) + .expect("shutdown call failed"); + } } } }); diff --git a/src/methods/mod.rs b/src/methods/mod.rs index 9b49ef5..bd6d420 100644 --- a/src/methods/mod.rs +++ b/src/methods/mod.rs @@ -1,38 +1,72 @@ +mod set_cloak; + use std::{ collections::HashMap, - io::{self, BufRead, BufReader}, + io::{BufRead, BufReader}, net::TcpStream, sync::Arc, }; +use serde::{Deserialize, Serialize}; + +use crate::{ + parser::ParamMap, + response::{Response, Result}, +}; + +#[derive(Debug, Deserialize, Serialize)] +pub struct LocalPlayer { + pub id: String, + pub name: String, +} + pub struct Session { - pub session_id: String, + pub session_token: String, pub database: Arc, + pub player: LocalPlayer, } impl Session { pub fn new( reader: &mut BufReader, database: Arc, - ) -> io::Result { - let mut session_id = String::new(); - reader.read_line(&mut session_id)?; + ) -> Result { + // Read the session token + let mut session_token = String::new(); + reader + .read_line(&mut session_token) + .map_err(|_| crate::response::Error::InvalidHandshake)?; + + // Validate session id + let response = minreq::get("https://api.minecraftservices.com/minecraft/profile") + .with_header("Authorization", &format!("Bearer {session_token}")) + .send() + .map_err(|_| crate::response::Error::InvalidSession)?; + + // If the session is invalid, return an error + if response.status_code != 200 { + return Err(crate::response::Error::InvalidSession); + } + + // Parse the player data + let player: LocalPlayer = response + .json() + .map_err(|_| crate::response::Error::InvalidSession)?; Ok(Self { - session_id, + session_token, database, + player, }) } - pub fn handle_request( - &self, - method: &str, - params: &HashMap, - ) -> crate::response::Response { + pub fn handle_request(&self, method: &str, params: &HashMap) -> Result { match method { - "ping" => crate::response::Response::Pong, + "ping" => Ok(Response::Pong), - _ => crate::response::Response::Error(crate::response::Error::InvalidRequest), + "set_cloak" => set_cloak::set_cloak(self, params.parse_param("cloak")?), + + _ => Err(crate::response::Error::InvalidRequest), } } } diff --git a/src/parser.rs b/src/parser.rs index 2c08df6..341ea10 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,14 +1,14 @@ use std::{collections::HashMap, str::FromStr}; pub trait ParamMap { - fn parse_param(&self, param: &str) -> Result; + fn parse_param(&self, param: &str) -> Result; } impl ParamMap for HashMap { - fn parse_param(&self, param: &str) -> Result { + fn parse_param(&self, param: &str) -> Result { match self.get(param) { - Some(value) => T::from_str(value).map_err(|_| format!("Invalid parameter: {}", param)), - None => Err(format!("Parameter not found: {}", param)), + Some(value) => T::from_str(value).map_err(|_| crate::response::Error::InvalidParameter), + None => Err(crate::response::Error::InvalidParameter), } } } diff --git a/src/response.rs b/src/response.rs index 06392c9..0c0978c 100644 --- a/src/response.rs +++ b/src/response.rs @@ -1,14 +1,16 @@ +pub type Result = std::result::Result; + #[derive(Debug, Clone)] pub enum Response { Pong, - Error(Error), + Success, } impl std::fmt::Display for Response { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Response::Pong => write!(f, "Pong"), - Response::Error(error) => write!(f, "!{}", error), + Response::Success => write!(f, "Success"), } } } @@ -19,7 +21,8 @@ pub enum Error { InvalidMethod, InvalidParameter, ParameterNotFound, - InvalidSessionToken, + InvalidSession, + InvalidHandshake, } impl std::fmt::Display for Error { @@ -29,7 +32,8 @@ impl std::fmt::Display for Error { Error::InvalidMethod => write!(f, "Invalid method"), Error::InvalidParameter => write!(f, "Invalid parameter"), Error::ParameterNotFound => write!(f, "Parameter not found"), - Error::InvalidSessionToken => write!(f, "Invalid session token"), + Error::InvalidSession => write!(f, "Invalid session"), + Error::InvalidHandshake => write!(f, "Invalid handshake"), } } }