From f09dadecbd403f80c7bea9ebd250068fef4c6c83 Mon Sep 17 00:00:00 2001 From: OMGeeky Date: Fri, 15 Nov 2024 00:54:41 +0100 Subject: [PATCH] create package structs for easier handling of individual packages & finally fix status. It finally works in the client to list the server --- src/main.rs | 89 ++++++++++--- src/protocols.rs | 26 ++-- src/protocols/custom_report_details.rs | 57 ++++++-- src/protocols/handshake.rs | 47 +++++++ src/protocols/ping.rs | 36 ++++- src/protocols/status.rs | 118 ++++++++++++----- src/types.rs | 5 +- src/types/long.rs | 49 +++++++ src/types/package.rs | 174 +++++++++++++++++++++++++ src/types/string.rs | 16 ++- src/types/var_int.rs | 8 +- src/types/var_long.rs | 3 +- 12 files changed, 537 insertions(+), 91 deletions(-) create mode 100644 src/protocols/handshake.rs create mode 100644 src/types/long.rs create mode 100644 src/types/package.rs diff --git a/src/main.rs b/src/main.rs index f8e8d9e..66cd513 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,6 +58,10 @@ impl Connection { self.connection_state = ConnectionState::Closed; continue; } + // else if size == 0xFE { + // // Legacy Ping (see https://wiki.vg/Server_List_Ping#1.6) + // handle_legacy_ping(&mut self.tcp_stream).await?; + // } } Err(_) => { println!("could not peek if we reached the end of the stream."); @@ -65,6 +69,16 @@ impl Connection { } let length = VarInt::read_stream(&mut self.tcp_stream).await?; + if *length == 0xFE { + //Legacy Ping (see https://wiki.vg/Server_List_Ping#1.6) + let x = handle_legacy_ping(&mut self.tcp_stream).await; + self.connection_state = ConnectionState::Closed; + self.tcp_stream.shutdown().await.map_err(|e| { + dbg!(e); + "?" + })?; + continue; + } println!("packet length: {}", length.as_rs()); let bytes_left_in_package = length.to_rs(); @@ -102,24 +116,26 @@ impl Connection { _compression: bool, // bytes_left_in_package: &mut i32, ) -> Result { - println!("Handshake"); - let protocol_version = VarInt::read_stream(stream).await?; - println!("protocol version: {}", protocol_version.as_rs()); - let address: McString<255> = McString::read_stream(stream) - .await - .map_err(|_| "Could not read string".to_string())?; - println!("address: '{}'", address.as_rs()); - 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()); - match next_state { - Some(next_state) => Ok(next_state), - None => Err(format!( - "Got an unknown next state: {}", - next_state_id.as_rs() - )), - } + let handshake_data = protocols::handshake::Data::read_stream(stream).await?; + // dbg!(&handshake_data); + Ok(handshake_data.next_state) + // let protocol_version = VarInt::read_stream(stream).await?; + // println!("protocol version: {}", protocol_version.as_rs()); + // let address: McString<255> = McString::read_stream(stream) + // .await + // .map_err(|_| "Could not read string".to_string())?; + // println!("address: '{}'", address.as_rs()); + // 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()); + // match next_state { + // Some(next_state) => Ok(next_state), + // None => Err(format!( + // "Got an unknown next state: {}", + // next_state_id.as_rs() + // )), + // } } async fn handle_package( stream: &mut RWStreamWithLimit<'_, T>, @@ -128,13 +144,17 @@ impl Connection { ) -> Result { let packet_id = VarInt::read_stream(stream).await?; - println!("id: {:0>2x}", packet_id.as_rs()); + println!( + "Handling new Package with id: {:0>2x} =======================", + packet_id.as_rs() + ); if connection_state == ConnectionState::NotConnected && packet_id.to_rs() == 0x00 { return Self::handshake(stream, compression).await; } match FromPrimitive::from_i32(packet_id.to_rs()) { Some(protocol) => { - let res = protocols::handle(protocol, stream).await; + let res = types::package::Package::handle(protocol, stream).await; + // let res = protocols::handle(protocol, stream).await; match res { Ok(_) => { println!("Success!"); @@ -159,6 +179,35 @@ impl Connection { Ok(connection_state) } } + +async fn handle_legacy_ping(stream: &mut TcpStream) -> Result<(), String> { + println!("handling legacy ping"); + let id = stream.read_u8().await.map_err(|e| e.to_string())?; + let payload = stream.read_u8().await.map_err(|e| e.to_string())?; + let plugin_message_ident = stream.read_u8().await.map_err(|e| e.to_string())?; + + stream + .write_all(&[ + 0xfe, // 1st packet id: 0xfe for server list ping + 0x01, // payload: always 1 + 0xfa, // 2nd packet id: 0xfa for plugin message + 0x00, 0x0b, // length of following string: always 11 as short, + 0x00, 0x4d, 0x00, 0x43, 0x00, 0x7c, 0x00, 0x50, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, + 0x00, 0x48, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x74, + // ^^ MC|PingHost as UTF16-BE + + // length of the rest of the data + 13, // ^^ + // protocol version: 127 for the invalid version, to signal, client is too old + 0, 49, 0, 50, 0, 55, // ^^ + 0x00, 0x00, // length of hostname: 0 as short + 0x00, 0x00, 0x00, 0x00, // port: 0 as int + ]) + .await + .map_err(|e| e.to_string())?; + Ok(()) +} + async fn handle_connection(stream: TcpStream) { let mut connection = Connection { connection_state: ConnectionState::NotConnected, diff --git a/src/protocols.rs b/src/protocols.rs index d0f2534..837c174 100644 --- a/src/protocols.rs +++ b/src/protocols.rs @@ -1,25 +1,31 @@ use crate::utils::RWStreamWithLimit; -use num_derive::FromPrimitive; +use num_derive::{FromPrimitive, ToPrimitive}; use tokio::io::{AsyncRead, AsyncWrite}; -#[derive(FromPrimitive)] -pub enum Protocol { +#[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone)] +pub enum ProtocolId { Status = 0x00, Ping = 0x01, CustomReportDetails = 0x7a, } +#[derive(FromPrimitive, ToPrimitive, Debug, Copy, Clone)] +pub enum ProtocolResponseId { + Status = 0x00, + Ping = 0x01, +} pub async fn handle( - protocol: Protocol, + protocol: ProtocolId, stream: &mut RWStreamWithLimit<'_, T>, // bytes_left_in_package: &mut i32, ) -> Result<(), bool> { match protocol { - Protocol::Status => status::Protocol::handle(stream).await?, - Protocol::Ping => ping::Protocol::handle(stream).await?, - Protocol::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?, + ProtocolId::Status => status::Protocol::handle(stream).await?, + ProtocolId::Ping => ping::Protocol::handle(stream).await?, + ProtocolId::CustomReportDetails => custom_report_details::Protocol::handle(stream).await?, }; Ok(()) } -mod custom_report_details; -mod ping; -mod status; +pub(crate) mod custom_report_details; +pub(crate) mod handshake; +pub(crate) mod ping; +pub(crate) mod status; diff --git a/src/protocols/custom_report_details.rs b/src/protocols/custom_report_details.rs index 7000f58..88a1203 100644 --- a/src/protocols/custom_report_details.rs +++ b/src/protocols/custom_report_details.rs @@ -1,11 +1,50 @@ +use crate::types::long::Long; use crate::types::string::McString; use crate::types::var_int::VarInt; use crate::types::McRead; use crate::utils::RWStreamWithLimit; -use tokio::io::{AsyncRead, AsyncWrite}; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, BufWriter}; pub struct Protocol {} +#[derive(Debug, Clone)] +pub struct Data { + details: Vec<(McString<128>, McString<4096>)>, +} +impl McRead for Data { + async fn read_stream(stream: &mut T) -> Result + where + Self: Sized, + { + // let size = stream. + // let mut v = vec![0; size]; + // let mut writer = BufWriter::new(&mut v); + + // let x = stream.read_buf(&mut v) + println!(); + loop { + let byte = stream.read_u8().await.map_err(|e| { + dbg!(e); + "idk" + })?; + print!(" '{:0>2x}' ", byte); + dbg!(byte); + } + // println!("x"); + // println!("{:?}", v); + // dbg!(&v); + // let count = VarInt::read_stream(stream).await?; + let details = vec![]; + // let string = format!("Still need to get details from stream ({})", *count); + // dbg!(string); + // for i in 0..*count { + // let title = McString::<128>::read_stream(stream).await?; + // let description = McString::<128>::read_stream(stream).await?; + // } + + Ok(Self { details }) + } +} impl Protocol { pub async fn handle( stream: &mut RWStreamWithLimit<'_, T>, @@ -18,14 +57,14 @@ impl Protocol { })?; dbg!(&count); 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 - })?; + // 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) } diff --git a/src/protocols/handshake.rs b/src/protocols/handshake.rs new file mode 100644 index 0000000..86c3c04 --- /dev/null +++ b/src/protocols/handshake.rs @@ -0,0 +1,47 @@ +use crate::types::long::Long; +use crate::types::string::McString; +use crate::types::var_int::{read_stream, VarInt}; +use crate::types::var_long::VarLong; +use crate::types::{McRead, McRustRepr, McWrite}; +use crate::utils::RWStreamWithLimit; +use crate::ConnectionState; +use num_traits::FromPrimitive; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; + +#[derive(Debug, Clone)] +pub struct Data { + protocol_version: VarInt, + server_address: McString<255>, + server_port: u16, + pub(crate) next_state: ConnectionState, +} +impl McRead for Data { + async fn read_stream(b: &mut T) -> Result { + println!("Reading Handshake"); + let protocol_version = VarInt::read_stream(b).await?; + let server_address = McString::read_stream(b).await?; + let server_port = b + .read_u16() + .await + .map_err(|e| format!("Error reading port:{e}"))?; + + let next_state_id = VarInt::read_stream(b).await?; + println!("next state: {}", next_state_id.as_rs()); + let next_state = FromPrimitive::from_i32(next_state_id.to_rs()); + let next_state = match next_state { + Some(next_state) => next_state, + None => { + return Err(format!( + "Got an unknown next state: {}", + next_state_id.as_rs() + )) + } + }; + Ok(Self { + server_port, + server_address, + next_state, + protocol_version, + }) + } +} diff --git a/src/protocols/ping.rs b/src/protocols/ping.rs index 11afc10..c94a126 100644 --- a/src/protocols/ping.rs +++ b/src/protocols/ping.rs @@ -1,11 +1,45 @@ +use crate::types::long::Long; +use crate::types::string::McString; 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 {} +pub struct Protocol(); +#[derive(Debug, Clone)] +pub struct Data { + pub timespan: Long, +} +impl McRead for Data { + async fn read_stream(stream: &mut T) -> Result + where + Self: Sized, + { + Ok(Self { + timespan: Long::read_stream(stream).await?, + }) + } +} + +#[derive(Debug, Clone)] +pub struct ResponseData { + pub(crate) timespan: Long, +} +impl McWrite for ResponseData { + type Error = String; + + async fn write_stream( + &self, + stream: &mut T, + ) -> Result { + self.timespan + .write_stream(stream) + .await + .map_err(|e| e.to_string()) + } +} impl Protocol { pub async fn handle( stream: &mut RWStreamWithLimit<'_, T>, diff --git a/src/protocols/status.rs b/src/protocols/status.rs index 099accd..b1ee56e 100644 --- a/src/protocols/status.rs +++ b/src/protocols/status.rs @@ -1,13 +1,51 @@ +use crate::types::long::Long; +use crate::types::package::{OutgoingPackage, OutgoingPackageContent, Package}; use crate::types::string::McString; use crate::types::var_int::VarInt; use crate::types::var_long::VarLong; -use crate::types::McWrite; +use crate::types::{McRead, McWrite}; use crate::utils::RWStreamWithLimit; use serde_json::json; use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufWriter}; pub struct Protocol {} +#[derive(Debug, Clone)] +pub struct Data {} + +impl McRead for Data { + async fn read_stream(stream: &mut T) -> Result + where + Self: Sized, + { + Ok(Self {}) + } +} + +#[derive(Debug, Clone)] +pub struct ResponseData { + json_response: McString<32767>, +} +impl Default for ResponseData { + fn default() -> Self { + Self { + json_response: McString::from_string(Protocol::get_sample_result()), + } + } +} +impl McWrite for ResponseData { + type Error = String; + + async fn write_stream( + &self, + stream: &mut T, + ) -> Result { + self.json_response + .write_stream(stream) + .await + .map_err(|e| e.to_string()) + } +} impl Protocol { pub async fn handle( stream: &mut RWStreamWithLimit<'_, T>, @@ -18,40 +56,48 @@ impl Protocol { 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 - })?; - - //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 - })?; - //actually write the content to the stream, not just a local buffer - stream.write_all(&v).await.map_err(|x| { - dbg!(x); - false - })?; + let response = ResponseData { + json_response: McString::from_string(string), + }; + let x = Package::Outgoing(OutgoingPackage { + protocol: crate::protocols::ProtocolResponseId::Status, + content: OutgoingPackageContent::StatusResponse(response), + }); + // + // 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 + // })?; + // + // //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 + // })?; + // //actually write the content to the stream, not just a local buffer + // stream.write_all(&v).await.map_err(|x| { + // dbg!(x); + // false + // })?; Ok(()) } @@ -63,7 +109,7 @@ impl Protocol { "protocol": 768 }, "players": { - "max": 100, + "max": 1000000000, "online": 5, "sample": [ { diff --git a/src/types.rs b/src/types.rs index 58101fb..b0b9d56 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,8 +1,7 @@ use tokio::io::{AsyncRead, AsyncWrite}; pub(crate) trait McRead { - type Error; - async fn read_stream(stream: &mut T) -> Result + async fn read_stream(stream: &mut T) -> Result where Self: Sized; } @@ -21,6 +20,8 @@ pub trait McRustRepr { fn to_rs(&self) -> Self::RustRepresentation; fn as_rs(&self) -> &Self::RustRepresentation; } +pub mod long; +pub mod package; pub mod string; pub mod var_int; pub mod var_long; diff --git a/src/types/long.rs b/src/types/long.rs new file mode 100644 index 0000000..2b4ffdf --- /dev/null +++ b/src/types/long.rs @@ -0,0 +1,49 @@ +use crate::types::var_int::{read_stream, VarInt}; +use crate::types::{McRead, McRustRepr, McWrite}; +use std::ops::Deref; +use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; + +#[derive(Debug, Copy, Clone)] +pub struct Long(pub i64); +impl Deref for Long { + type Target = i64; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl McWrite for Long { + type Error = std::io::Error; + + async fn write_stream( + &self, + stream: &mut T, + ) -> Result + where + Self: Sized, + { + stream.write_i64(self.0).await?; + Ok(8) + } +} +impl McRead for Long { + async fn read_stream(b: &mut T) -> Result { + Ok(Self(b.read_i64().await.map_err(|e| e.to_string())?)) + } +} +impl McRustRepr for Long { + type RustRepresentation = i64; + + fn into_rs(self) -> Self::RustRepresentation { + self.0 + } + + fn to_rs(&self) -> Self::RustRepresentation { + self.0 + } + + fn as_rs(&self) -> &Self::RustRepresentation { + &self.0 + } +} diff --git a/src/types/package.rs b/src/types/package.rs new file mode 100644 index 0000000..e0f3957 --- /dev/null +++ b/src/types/package.rs @@ -0,0 +1,174 @@ +use crate::protocols::{self, ProtocolId, ProtocolResponseId}; +use crate::types::string::McString; +use crate::types::var_int::VarInt; +use crate::types::{McRead, McWrite}; +use crate::utils::RWStreamWithLimit; +use num_traits::ToPrimitive; +use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt, BufWriter}; + +#[derive(Debug, Clone)] +pub enum Package { + Incoming(IncomingPackage), + Outgoing(OutgoingPackage), +} +#[derive(Debug, Clone)] +pub struct IncomingPackage { + pub(crate) protocol: ProtocolId, + pub(crate) content: IncomingPackageContent, +} +#[derive(Debug, Clone)] +pub struct OutgoingPackage { + pub(crate) protocol: ProtocolResponseId, + pub(crate) content: OutgoingPackageContent, +} +impl OutgoingPackage { + pub fn empty() {} +} +#[derive(Debug, Clone)] +pub enum IncomingPackageContent { + Handshake(crate::protocols::handshake::Data), + Status(crate::protocols::status::Data), + Ping(crate::protocols::ping::Data), + CustomReportDetails(crate::protocols::custom_report_details::Data), +} +#[derive(Debug, Clone)] +pub enum OutgoingPackageContent { + StatusResponse(crate::protocols::status::ResponseData), + PingResponse(crate::protocols::ping::ResponseData), +} +impl McWrite for OutgoingPackageContent { + type Error = String; + + async fn write_stream( + &self, + stream: &mut T, + ) -> Result + where + Self: Sized, + { + match self { + OutgoingPackageContent::StatusResponse(x) => x.write_stream(stream).await, + OutgoingPackageContent::PingResponse(x) => x.write_stream(stream).await, + } + } +} +impl McWrite for OutgoingPackage { + type Error = String; + + async fn write_stream( + &self, + stream: &mut T, + ) -> Result + where + Self: Sized, + { + let id = self.protocol; + let mut total_size = 0; + + //write the content to a local buffer first to determine size + let mut v = Vec::new(); + println!("total size: {}: {:?}", total_size, &v); + + let mut writer = BufWriter::new(&mut v); + total_size += + VarInt(ToPrimitive::to_i32(&id).expect("All the ids should be hard coded to work...")) + .write_stream(&mut writer) + .await + .map_err(|e| e.to_string())?; + writer.flush().await.map_err(|e| e.to_string())?; + println!("total size: {}: {:?}", total_size, &v); + + let mut writer = BufWriter::new(&mut v); + total_size += self.content.write_stream(&mut writer).await?; + writer.flush().await.map_err(|e| e.to_string())?; + println!("total size: {}: {:?}", total_size, &v); + + // //Size in front + let x = VarInt(total_size as i32) + .write_stream(stream) + .await + .map_err(|x| { + dbg!(&x); + format!("Error writing the size: {:?}", x).to_string() + })?; + // //actually write the content to the stream, not just a local buffer + stream.write_all(&v).await.map_err(|x| { + dbg!(&x); + format!("Error writing the bytes: {:?}", x).to_string() + })?; + stream.flush().await.map_err(|e| e.to_string())?; + Ok(total_size + x) + } +} +impl IncomingPackage { + async fn answer( + &self, + stream: &mut RWStreamWithLimit<'_, T>, + ) -> Result<(), bool> { + let answer = match (&self.protocol, &self.content) { + (ProtocolId::Status, _) => Some(OutgoingPackage { + protocol: ProtocolResponseId::Status, + content: OutgoingPackageContent::StatusResponse( + protocols::status::ResponseData::default(), + ), + }), + (ProtocolId::Ping, IncomingPackageContent::Ping(ping_data)) => Some(OutgoingPackage { + protocol: ProtocolResponseId::Ping, + content: OutgoingPackageContent::PingResponse(protocols::ping::ResponseData { + timespan: ping_data.timespan, + }), + }), + (ProtocolId::Ping, _) => unreachable!(), + (ProtocolId::CustomReportDetails, _) => None, + }; + if let Some(outgoing_package) = answer { + outgoing_package.write_stream(stream).await.map_err(|e| { + dbg!(e); + false + })?; + } + Ok(()) + } +} +impl Package { + pub async fn handle( + protocol_id: ProtocolId, + stream: &mut RWStreamWithLimit<'_, T>, + ) -> Result<(), bool> { + let incoming_content = read_data(protocol_id, stream).await.map_err(|e| { + dbg!(e); + true + })?; + let incoming = IncomingPackage { + protocol: protocol_id, + content: incoming_content, + }; + incoming.answer(stream).await?; + Ok(()) + } +} + +pub async fn read_data( + protocol_id: ProtocolId, + stream: &mut RWStreamWithLimit<'_, T>, +) -> Result { + Ok(match protocol_id { + ProtocolId::Status => { + IncomingPackageContent::Status(protocols::status::Data::read_stream(stream).await?) + } + ProtocolId::Ping => { + IncomingPackageContent::Ping(protocols::ping::Data::read_stream(stream).await?) + } + ProtocolId::CustomReportDetails => { + // return Err("Not implemented".to_string()); + let x = IncomingPackageContent::CustomReportDetails( + protocols::custom_report_details::Data::read_stream(stream).await?, + ); + stream.discard_unread().await.map_err(|e| { + dbg!(e); + "Could not discard unused stuff" + })?; + x + } + }) +} diff --git a/src/types/string.rs b/src/types/string.rs index cc45d1e..33a56f9 100644 --- a/src/types/string.rs +++ b/src/types/string.rs @@ -3,13 +3,15 @@ use crate::types::{McRead, McRustRepr, McWrite}; use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt}; +#[derive(Debug, Clone)] pub struct McString { pub value: String, } impl McString { pub fn measure_size(s: &str) -> usize { // 3. UTF-8 encoded byte length - let utf8_len = s.bytes().len(); + let utf8_len = s.len(); + // let utf8_len = s.bytes().len(); // 5. Calculate total length (including VarInt prefix) let varint_size = VarInt(utf8_len as i32).get_size(); @@ -17,36 +19,38 @@ impl McString { //TODO: This is not allowed } // println!("strlen: {}+({}?{})", varint_size, utf8_len, utf16_len); - varint_size + utf8_len + // varint_size + + utf8_len } pub fn from_string(s: String) -> Self { Self { value: s } } } impl McRead for McString { - type Error = (); - - async fn read_stream(b: &mut T) -> Result + async fn read_stream(b: &mut T) -> Result where Self: Sized, { let max_size = VarInt::read_stream(b).await.map_err(|x| { dbg!(x); + "could not read size" })?; 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 { - return Err(()); // Or a more specific error type + return Err("Too big string".to_string()); // Or a more specific error type } let mut bytes = vec![0u8; size]; let actual_size = b.read(&mut bytes).await.map_err(|x| { dbg!(x); + "Error reading" })?; let value = String::from_utf8(bytes).map_err(|x| { dbg!(x); + "Error parsing UTF8 string" })?; assert_eq!( size, actual_size, diff --git a/src/types/var_int.rs b/src/types/var_int.rs index efc544a..0a57da7 100644 --- a/src/types/var_int.rs +++ b/src/types/var_int.rs @@ -27,8 +27,7 @@ impl McWrite for VarInt { } } impl McRead for VarInt { - type Error = String; - async fn read_stream(b: &mut T) -> Result { + async fn read_stream(b: &mut T) -> Result { let value = read_stream(b, 32).await? as i32; Ok(Self(value)) } @@ -81,14 +80,13 @@ async fn write_varint( loop { written += 1; if (value & !SEGMENT_BITS) == 0 { - writer.write_u8(value as u8).await.unwrap(); + writer.write_u8(value as u8).await?; break; } writer .write_u8(((value & SEGMENT_BITS) | CONTINUE_BIT) as u8) - .await - .unwrap(); + .await?; value = (value as u32 >> 7) as i32; // Simulate Java's >>> } diff --git a/src/types/var_long.rs b/src/types/var_long.rs index 2bce607..7847588 100644 --- a/src/types/var_long.rs +++ b/src/types/var_long.rs @@ -34,8 +34,7 @@ impl McWrite for VarLong { } } impl McRead for VarLong { - type Error = String; - async fn read_stream(b: &mut T) -> Result { + async fn read_stream(b: &mut T) -> Result { let value = crate::types::var_int::read_stream(b, 64).await? as i64; Ok(Self(value)) }