try to fix some status response stuff

This commit is contained in:
OMGeeky
2024-11-14 18:04:53 +01:00
parent c6d703f167
commit df1908bfaa
9 changed files with 193 additions and 63 deletions

46
Cargo.lock generated
View File

@@ -123,6 +123,12 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.162" version = "0.2.162"
@@ -145,6 +151,8 @@ version = "0.1.0"
dependencies = [ dependencies = [
"num-derive", "num-derive",
"num-traits", "num-traits",
"serde",
"serde_json",
"tokio", "tokio",
"tokio-stream", "tokio-stream",
"tokio-util", "tokio-util",
@@ -274,12 +282,50 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.2.0" version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.215"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.2" version = "1.4.2"

View File

@@ -10,3 +10,5 @@ tokio = { version = "1.41.1", features = ["rt", "rt-multi-thread", "macros", "fu
tokio-util = { version = "0.7.0", features = ["full"] } tokio-util = { version = "0.7.0", features = ["full"] }
tokio-stream = "0.1" tokio-stream = "0.1"
serde = "1.0"
serde_json = "1.0"

View File

@@ -1,3 +1,4 @@
#![allow(unused)]
pub mod protocols; pub mod protocols;
pub mod types; pub mod types;
pub mod utils; pub mod utils;
@@ -5,10 +6,10 @@ pub mod utils;
use crate::types::string::McString; use crate::types::string::McString;
use crate::types::var_int::VarInt; use crate::types::var_int::VarInt;
use crate::types::{McRead, McRustRepr}; use crate::types::{McRead, McRustRepr};
use crate::utils::RWStreamWithLimit; use crate::utils::{MyAsyncReadExt, RWStreamWithLimit};
use num_derive::FromPrimitive; use num_derive::FromPrimitive;
use num_traits::{FromPrimitive, ToPrimitive}; use num_traits::{FromPrimitive, ToPrimitive};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpStream; use tokio::net::TcpStream;
#[tokio::main] #[tokio::main]
@@ -38,6 +39,7 @@ enum ConnectionState {
Status = 1, Status = 1,
Login = 2, Login = 2,
Transfer = 3, Transfer = 3,
///Internal use
Closed = -1, Closed = -1,
} }
struct Connection { struct Connection {
@@ -87,6 +89,7 @@ impl Connection {
} }
Err(e) => { Err(e) => {
self.connection_state = ConnectionState::Closed; self.connection_state = ConnectionState::Closed;
dbg!(&self.tcp_stream.shutdown().await);
println!("Got an error during package handling: {e}"); println!("Got an error during package handling: {e}");
} }
} }
@@ -106,7 +109,7 @@ impl Connection {
.await .await
.map_err(|_| "Could not read string".to_string())?; .map_err(|_| "Could not read string".to_string())?;
println!("address: '{}'", address.as_rs()); println!("address: '{}'", address.as_rs());
stream.read_exact(&mut [0, 2]).await.unwrap(); //server port. Unused stream.discard(2).await.unwrap(); //server port. Unused
let next_state_id = VarInt::read_stream(stream).await?; let next_state_id = VarInt::read_stream(stream).await?;
println!("next state: {}", next_state_id.as_rs()); println!("next state: {}", next_state_id.as_rs());
let next_state = FromPrimitive::from_i32(next_state_id.to_rs()); let next_state = FromPrimitive::from_i32(next_state_id.to_rs());

View File

@@ -3,22 +3,23 @@ use num_derive::FromPrimitive;
use tokio::io::{AsyncRead, AsyncWrite}; use tokio::io::{AsyncRead, AsyncWrite};
#[derive(FromPrimitive)] #[derive(FromPrimitive)]
pub enum Protocols { pub enum Protocol {
Status = 0x00, Status = 0x00,
Ping = 0x01, Ping = 0x01,
CustomReportDetails = 0x7a, CustomReportDetails = 0x7a,
} }
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>( pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
protocol: Protocols, protocol: Protocol,
stream: &mut RWStreamWithLimit<'_, T>, stream: &mut RWStreamWithLimit<'_, T>,
// bytes_left_in_package: &mut i32, // bytes_left_in_package: &mut i32,
) -> Result<(), bool> { ) -> Result<(), bool> {
match protocol { match protocol {
Protocols::Status => status::Protocol::handle(stream).await?, Protocol::Status => status::Protocol::handle(stream).await?,
Protocols::Ping => {} Protocol::Ping => ping::Protocol::handle(stream).await?,
Protocols::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?, Protocol::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?,
}; };
Ok(()) Ok(())
} }
mod custom_report_details; mod custom_report_details;
mod ping;
mod status; mod status;

View File

@@ -1,3 +1,4 @@
use crate::types::string::McString;
use crate::types::var_int::VarInt; use crate::types::var_int::VarInt;
use crate::types::McRead; use crate::types::McRead;
use crate::utils::RWStreamWithLimit; use crate::utils::RWStreamWithLimit;
@@ -10,33 +11,22 @@ impl Protocol {
stream: &mut RWStreamWithLimit<'_, T>, stream: &mut RWStreamWithLimit<'_, T>,
// bytes_left_in_package: &mut i32, // bytes_left_in_package: &mut i32,
) -> Result<(), bool> { ) -> Result<(), bool> {
println!("Some custom report detail stuff...");
let count = VarInt::read_stream(stream).await.map_err(|x| { let count = VarInt::read_stream(stream).await.map_err(|x| {
dbg!(x); dbg!(x);
true true
})?; })?;
dbg!(&count); dbg!(&count);
let string_size = VarInt::read_stream(stream).await.map_err(|x| { for i in 0..*count {
dbg!(x); McString::<128>::read_stream(stream).await.map_err(|x| {
true dbg!(x);
})?; true
dbg!(&string_size); })?;
stream.discard_unread().await.map_err(|x| { McString::<4096>::read_stream(stream).await.map_err(|x| {
dbg!(x); dbg!(x);
true true
})?; })?;
// for i in 0..*count { }
// let title = McString::read_stream(stream).await.map_err(|x| { Err(true)
// dbg!(x);
// })?;
// let description = McString::read_stream(stream).await.map_err(|x| {
// dbg!(x);
// })?;
// println!(
// "Read title & description fo some custom report ({i}): {}\n{}",
// title.as_rs(),
// description.as_rs()
// );
// }
Ok(())
} }
} }

29
src/protocols/ping.rs Normal file
View File

@@ -0,0 +1,29 @@
use crate::types::var_int::VarInt;
use crate::types::var_long::VarLong;
use crate::types::{McRead, McWrite};
use crate::utils::RWStreamWithLimit;
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
pub struct Protocol {}
impl Protocol {
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
stream: &mut RWStreamWithLimit<'_, T>,
) -> Result<(), bool> {
println!("Ping");
let v = stream.read_i64().await.map_err(|e| {
dbg!(e);
false
})?;
VarInt(0x01).write_stream(stream).await.map_err(|x| {
dbg!(x);
false
})?;
stream.write_i64(v).await.map_err(|e| {
dbg!(e);
false
})?;
Ok(())
}
}

View File

@@ -1,58 +1,83 @@
use crate::types::string::McString; use crate::types::string::McString;
use crate::types::var_int::VarInt; use crate::types::var_int::VarInt;
use crate::types::var_long::VarLong;
use crate::types::McWrite; use crate::types::McWrite;
use crate::utils::RWStreamWithLimit; use crate::utils::RWStreamWithLimit;
use tokio::io::{AsyncRead, AsyncWrite}; use serde_json::json;
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufWriter};
pub struct Protocol {} pub struct Protocol {}
impl Protocol { impl Protocol {
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>( pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
stream: &mut RWStreamWithLimit<'_, T>, stream: &mut RWStreamWithLimit<'_, T>,
// bytes_left_in_package: &mut i32,
) -> Result<(), bool> { ) -> Result<(), bool> {
println!("Status"); println!("Status");
VarInt(0x01).write_stream(stream).await.map_err(|x| { stream.discard_unread().await.map_err(|x| {
dbg!(x);
false
})?;
let string = Self::get_sample_result();
let mut total_size = 0;
let mut v = Vec::new();
let mut writer = BufWriter::new(&mut v);
//Package ID
total_size += VarInt(0x00).write_stream(&mut writer).await.map_err(|x| {
dbg!(x); dbg!(x);
false false
})?; })?;
McString::<32767>::from_string(Self::get_sample_result()) //Status JSON
total_size += McString::<32767>::from_string(string)
.write_stream(&mut writer)
.await
.map_err(|x| {
dbg!(x);
false
})?;
writer.flush().await.unwrap();
println!("total size: {}: {:?}", total_size, &v);
//Size in front
VarInt(total_size as i32)
.write_stream(stream) .write_stream(stream)
.await .await
.map_err(|x| { .map_err(|x| {
dbg!(x); dbg!(x);
false false
})?; })?;
// stream.discard_unread().await.map_err(|x| { //actually write the content to the stream, not just a local buffer
// dbg!(x); stream.write_all(&v).await.map_err(|x| {
// false dbg!(x);
// })?; false
// *bytes_left_in_package = 0; })?;
Ok(()) Ok(())
} }
fn get_sample_result() -> String { fn get_sample_result() -> String {
"{ json!({
\"version\": { "version": {
\"name\": \"1.21.2\", "name": "1.21.2",
\"protocol\": 768 "protocol": 768
}, },
\"players\": { "players": {
\"max\": 100, "max": 100,
\"online\": 5, "online": 5,
\"sample\": [ "sample": [
{ {
\"name\": \"thinkofdeath\", "name": "thinkofdeath",
\"id\": \"4566e69f-c907-48ee-8d71-d7ba5aa00d20\" "id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20",
} },
] ],
}, },
\"description\": { "description": {
\"text\": \"Hello, world!\" "text": "Hello, world!"
}, },
\"favicon\": \"data:image/png;base64,<data>\", // "favicon": "data:image/png;base64,<data>",
\"enforcesSecureChat\": false "enforcesSecureChat": false,
}" })
.to_string() .to_string()
} }
} }

View File

@@ -7,8 +7,17 @@ pub struct McString<const MAX_SIZE: usize> {
pub value: String, pub value: String,
} }
impl<const MAX_SIZE: usize> McString<MAX_SIZE> { impl<const MAX_SIZE: usize> McString<MAX_SIZE> {
fn measure_size(s: &str) -> usize { pub fn measure_size(s: &str) -> usize {
s.len() // 3. UTF-8 encoded byte length
let utf8_len = s.bytes().len();
// 5. Calculate total length (including VarInt prefix)
let varint_size = VarInt(utf8_len as i32).get_size();
if varint_size > 3 {
//TODO: This is not allowed
}
// println!("strlen: {}+({}?{})", varint_size, utf8_len, utf16_len);
varint_size + utf8_len
} }
pub fn from_string(s: String) -> Self { pub fn from_string(s: String) -> Self {
Self { value: s } Self { value: s }
@@ -25,6 +34,7 @@ impl<const MAX_SIZE: usize> McRead for McString<MAX_SIZE> {
dbg!(x); dbg!(x);
})?; })?;
let size = *max_size as usize; let size = *max_size as usize;
println!("Reading string of length: {}", size);
// Check if the size exceeds the maximum allowed length (n) // Check if the size exceeds the maximum allowed length (n)
if size > (MAX_SIZE * 3) + 3 { if size > (MAX_SIZE * 3) + 3 {
@@ -35,10 +45,14 @@ impl<const MAX_SIZE: usize> McRead for McString<MAX_SIZE> {
let actual_size = b.read(&mut bytes).await.map_err(|x| { let actual_size = b.read(&mut bytes).await.map_err(|x| {
dbg!(x); dbg!(x);
})?; })?;
assert_eq!(size, actual_size);
let value = String::from_utf8(bytes).map_err(|x| { let value = String::from_utf8(bytes).map_err(|x| {
dbg!(x); dbg!(x);
})?; })?;
assert_eq!(
size, actual_size,
"Did not read all that was to read {}",
value
);
Ok(Self { value }) Ok(Self { value })
} }
} }
@@ -54,10 +68,12 @@ impl<const MAX_SIZE: usize> McWrite for McString<MAX_SIZE> {
{ {
let buf = self.value.as_bytes(); let buf = self.value.as_bytes();
let length = Self::measure_size(&self.value); let length = Self::measure_size(&self.value);
VarInt(length as i32).write_stream(stream).await?; println!("string length: {}", length);
let length_var_int = VarInt(length as i32);
let written = length_var_int.write_stream(stream).await?;
println!("Writing String to stream: '{}'", self.value);
stream.write_all(buf).await?; stream.write_all(buf).await?;
Ok(length) Ok(buf.len() + written)
} }
} }
impl<const MAX_SIZE: usize> McRustRepr for McString<MAX_SIZE> { impl<const MAX_SIZE: usize> McRustRepr for McString<MAX_SIZE> {

View File

@@ -1,3 +1,4 @@
use std::cmp::min;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::pin::Pin; use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
@@ -8,6 +9,23 @@ pub struct RWStreamWithLimit<'a, T: AsyncRead + AsyncWrite> {
read_bytes_left: usize, read_bytes_left: usize,
} }
impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> {
pub(crate) async fn discard(&mut self, bytes: usize) -> std::io::Result<usize> {
let bytes = min(bytes, self.read_bytes_left);
let read = self.stream.read_exact(&mut vec![0; bytes]).await?;
self.read_bytes_left -= read;
Ok(read)
}
}
pub(crate) trait MyAsyncReadExt {
async fn discard(&mut self, bytes: usize) -> std::io::Result<usize>;
}
impl<T: AsyncRead + Unpin> MyAsyncReadExt for T {
async fn discard(&mut self, bytes: usize) -> std::io::Result<usize> {
self.read_exact(&mut vec![0; bytes]).await
}
}
impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> { impl<'a, T: AsyncRead + AsyncWrite + Unpin> RWStreamWithLimit<'a, T> {
pub(crate) fn new(stream: &'a mut T, read_limit: usize) -> Self { pub(crate) fn new(stream: &'a mut T, read_limit: usize) -> Self {
Self { Self {