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"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "libc"
version = "0.2.162"
@@ -145,6 +151,8 @@ version = "0.1.0"
dependencies = [
"num-derive",
"num-traits",
"serde",
"serde_json",
"tokio",
"tokio-stream",
"tokio-util",
@@ -274,12 +282,50 @@ version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
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]]
name = "signal-hook-registry"
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-stream = "0.1"
serde = "1.0"
serde_json = "1.0"

View File

@@ -1,3 +1,4 @@
#![allow(unused)]
pub mod protocols;
pub mod types;
pub mod utils;
@@ -5,10 +6,10 @@ pub mod utils;
use crate::types::string::McString;
use crate::types::var_int::VarInt;
use crate::types::{McRead, McRustRepr};
use crate::utils::RWStreamWithLimit;
use crate::utils::{MyAsyncReadExt, RWStreamWithLimit};
use num_derive::FromPrimitive;
use num_traits::{FromPrimitive, ToPrimitive};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt};
use tokio::net::TcpStream;
#[tokio::main]
@@ -38,6 +39,7 @@ enum ConnectionState {
Status = 1,
Login = 2,
Transfer = 3,
///Internal use
Closed = -1,
}
struct Connection {
@@ -87,6 +89,7 @@ impl Connection {
}
Err(e) => {
self.connection_state = ConnectionState::Closed;
dbg!(&self.tcp_stream.shutdown().await);
println!("Got an error during package handling: {e}");
}
}
@@ -106,7 +109,7 @@ impl Connection {
.await
.map_err(|_| "Could not read string".to_string())?;
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?;
println!("next state: {}", next_state_id.as_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};
#[derive(FromPrimitive)]
pub enum Protocols {
pub enum Protocol {
Status = 0x00,
Ping = 0x01,
CustomReportDetails = 0x7a,
}
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
protocol: Protocols,
protocol: Protocol,
stream: &mut RWStreamWithLimit<'_, T>,
// bytes_left_in_package: &mut i32,
) -> Result<(), bool> {
match protocol {
Protocols::Status => status::Protocol::handle(stream).await?,
Protocols::Ping => {}
Protocols::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?,
Protocol::Status => status::Protocol::handle(stream).await?,
Protocol::Ping => ping::Protocol::handle(stream).await?,
Protocol::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?,
};
Ok(())
}
mod custom_report_details;
mod ping;
mod status;

View File

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

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::var_int::VarInt;
use crate::types::var_long::VarLong;
use crate::types::McWrite;
use crate::utils::RWStreamWithLimit;
use tokio::io::{AsyncRead, AsyncWrite};
use serde_json::json;
use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufWriter};
pub struct Protocol {}
impl Protocol {
pub async fn handle<T: AsyncRead + AsyncWrite + Unpin>(
stream: &mut RWStreamWithLimit<'_, T>,
// bytes_left_in_package: &mut i32,
) -> Result<(), bool> {
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);
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)
.await
.map_err(|x| {
dbg!(x);
false
})?;
// stream.discard_unread().await.map_err(|x| {
// dbg!(x);
// false
// })?;
// *bytes_left_in_package = 0;
//actually write the content to the stream, not just a local buffer
stream.write_all(&v).await.map_err(|x| {
dbg!(x);
false
})?;
Ok(())
}
fn get_sample_result() -> String {
"{
\"version\": {
\"name\": \"1.21.2\",
\"protocol\": 768
json!({
"version": {
"name": "1.21.2",
"protocol": 768
},
\"players\": {
\"max\": 100,
\"online\": 5,
\"sample\": [
"players": {
"max": 100,
"online": 5,
"sample": [
{
\"name\": \"thinkofdeath\",
\"id\": \"4566e69f-c907-48ee-8d71-d7ba5aa00d20\"
}
]
"name": "thinkofdeath",
"id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20",
},
],
},
\"description\": {
\"text\": \"Hello, world!\"
"description": {
"text": "Hello, world!"
},
\"favicon\": \"data:image/png;base64,<data>\",
\"enforcesSecureChat\": false
}"
// "favicon": "data:image/png;base64,<data>",
"enforcesSecureChat": false,
})
.to_string()
}
}

View File

@@ -7,8 +7,17 @@ pub struct McString<const MAX_SIZE: usize> {
pub value: String,
}
impl<const MAX_SIZE: usize> McString<MAX_SIZE> {
fn measure_size(s: &str) -> usize {
s.len()
pub fn measure_size(s: &str) -> usize {
// 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 {
Self { value: s }
@@ -25,6 +34,7 @@ impl<const MAX_SIZE: usize> McRead for McString<MAX_SIZE> {
dbg!(x);
})?;
let size = *max_size as usize;
println!("Reading string of length: {}", size);
// Check if the size exceeds the maximum allowed length (n)
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| {
dbg!(x);
})?;
assert_eq!(size, actual_size);
let value = String::from_utf8(bytes).map_err(|x| {
dbg!(x);
})?;
assert_eq!(
size, actual_size,
"Did not read all that was to read {}",
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 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?;
Ok(length)
Ok(buf.len() + written)
}
}
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::pin::Pin;
use std::task::{Context, Poll};
@@ -8,6 +9,23 @@ pub struct RWStreamWithLimit<'a, T: AsyncRead + AsyncWrite> {
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> {
pub(crate) fn new(stream: &'a mut T, read_limit: usize) -> Self {
Self {