diff --git a/Cargo.toml b/Cargo.toml index 8867dd9..6c6e6ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,8 @@ version = "0.1.0" edition = "2024" [dependencies] -tokio = {version = "1.45.0", features = ["full"]} \ No newline at end of file +# async-trait = {version = "0.1.88", optional = true} +tokio = {version = "1.45.0", features = ["full"]} + +# [features] +# async = ["async-trait"] \ No newline at end of file diff --git a/src/data.rs b/src/data.rs index cee7423..4ffa7ef 100644 --- a/src/data.rs +++ b/src/data.rs @@ -1,12 +1,10 @@ -use std::io::{Read, Write}; +use std::io::{Cursor, Read, Write}; use tokio::io::{AsyncRead, AsyncReadExt}; use crate::inet::InetError; - - - +#[derive(Debug)] pub enum DataError { ReadError, WriteError, @@ -15,37 +13,65 @@ pub enum DataError { Inet(InetError), } -pub trait ReadLike { - type Output; - fn _read_bytes(self, size: usize) -> Self::Output; -} +pub trait DataReader { + async fn read_bytes(&mut self, size: usize) -> Result, DataError>; -impl ReadLike for &mut R { - type Output = Result, DataError>; + async fn read_byte(&mut self) -> Result { + Ok(self.read_bytes(1).await?[0]) + } - fn _read_bytes(self, size: usize) -> Self::Output { - let mut buf = vec![0; size]; - let mut read = 0; - while read < size { - match self.read(&mut buf[read..]) { - Ok(0) => return Err(DataError::Inet(InetError::ConnectionClosed)), - Ok(n) => read+=n, - Err(_) => return Err(DataError::ReadError) - } - }; Ok(buf) + async fn read_signed_byte(&mut self) -> Result { + Ok(self.read_byte().await? as i8) + } + + async fn read_short(&mut self) -> Result { + Ok(u16::from_be_bytes( + self.read_bytes(2).await?.try_into().unwrap(), + )) + } + + async fn read_signed_short(&mut self) -> Result { + Ok(self.read_short().await? as i16) + } + + async fn read_varint_size(&mut self) -> Result<(i32, usize), DataError> { + let mut value = 0; + let mut position = 0; + loop { + let byte = self.read_byte().await?; + value |= ((byte & 0x7F) as i32) << (position * 7); + if (byte & 0x80) == 0 { + return Ok((value, position as usize)); + }; + position += 1; + if position >= 5 { + return Err(DataError::VarIntIsSoBig); + }; + } + } + + async fn read_varint(&mut self) -> Result { + Ok(self.read_varint_size().await?.0) + } + + // async fn read_packet(&mut self, threshold: Option) -> Result>, DataError> { + // let size = self.read_varint().await?; + // let mut buf = self.read_bytes(size).await?; + // } + + async fn read_string(&mut self) -> Result { + let size = self.read_varint().await?; + let vec = self.read_bytes(size as usize).await?; + String::from_utf8(vec).map_err(|_| DataError::StringDecodeError) } } -#[cfg(feature = "async")] -#[async_trait] -impl ReadLike for &mut R { - type Output = Result, DataError>; - - async fn _read_bytes(self, size: usize) -> Self::Output { +impl DataReader for R { + async fn read_bytes(&mut self, size: usize) -> Result, DataError> { let mut buf = vec![0; size]; let mut read = 0; while read < size { - match AsyncReadExt::read(&mut self, &mut buf[read..]).await { + match AsyncReadExt::read(self, &mut buf[read..]).await { Ok(0) => return Err(DataError::Inet(InetError::ConnectionClosed)), Ok(n) => read += n, Err(_) => return Err(DataError::ReadError), @@ -54,73 +80,3 @@ impl ReadLike for &mut R { Ok(buf) } } - -#[cfg_attr(feature = "async", async_trait)] -pub trait DataReader { - #[cfg(not(feature = "async"))] - fn read_bytes(&mut self, size: usize) -> Result, DataError>; - - #[cfg(feature = "async")] - async fn read_bytes(&mut self, size: usize) -> Result, DataError>; - - fn read_byte(&mut self) -> Result { - Ok(self.read_bytes(1)?[0]) - } - - fn read_signed_byte(&mut self) -> Result { - Ok(self.read_byte()? as i8) - } - - fn read_short(&mut self) -> Result { - Ok(u16::from_be_bytes(self.read_bytes(2)?.try_into().unwrap())) - } - - fn read_signed_short(&mut self) -> Result { - Ok(self.read_short()? as i16) - } - - fn read_varint(&mut self) -> Result { - let mut value = 0; - let mut position = 0; - loop { - let byte = self.read_byte()?; - value |= ((byte & 0x7F) << position) as i32; - if (byte & 0x80) == 0 {return Ok(value)}; - position += 7; - if position >= 32 {return Err(DataError::VarIntIsSoBig)}; - } - } - - fn read_string(&mut self) -> Result { - let size = self.read_varint()?; - let vec = self.read_bytes(size as usize)?; - String::from_utf8(vec).map_err(|_| DataError::StringDecodeError) - } -} - -impl DataReader for R { - #[cfg(not(feature = "async"))] - fn read_bytes(&mut self, size: usize) -> Result, DataError> { - self._read_bytes(size) - } -} - -#[cfg(feature = "async")] -#[async_trait] -impl DataReader for R { - async fn _read_bytes(&mut self, size: usize) -> Result, DataError> { - self.read_bytes(size).await - } -} - - - -pub trait DataWriter { - fn write_bytes(&mut self, buf: Vec) -> Result<(), DataError>; -} - -impl DataWriter for W { - fn write_bytes(&mut self, buf: Vec) -> Result<(), DataError> { - self.write_all(&buf).map_err(|_| DataError::WriteError) - } -} \ No newline at end of file diff --git a/src/inet.rs b/src/inet.rs index 3da0e05..bec63e4 100644 --- a/src/inet.rs +++ b/src/inet.rs @@ -2,7 +2,7 @@ use tokio::net::{TcpListener, TcpStream}; - +#[derive(Debug)] pub enum InetError { BindError, ConnectionClosed diff --git a/src/main.rs b/src/main.rs index b0baffa..a28e4d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,20 +1,18 @@ -use std::{io::Cursor, sync::Arc, time::Duration}; + +use std::{io::Cursor, net::Shutdown}; use data::{DataError, DataReader}; use inet::Server; -use tokio::{io::AsyncReadExt, net::TcpStream, time::sleep}; +use tokio::{io::AsyncWriteExt, net::TcpStream}; - - -mod inet; mod data; - - +mod inet; #[tokio::main] async fn main() { let Ok(server) = Server::new("127.0.0.1:25565").await else { - println!("Не удалось забиндить сервер"); return; + println!("Не удалось забиндить сервер"); + return; }; loop { @@ -23,10 +21,30 @@ async fn main() { } } -async fn test(stream: TcpStream) { - let Ok(addr) = stream.peer_addr() else {return;}; +async fn test(mut stream: TcpStream) { + let Ok(addr) = stream.peer_addr() else { + return; + }; println!("Подключение: {addr}"); // читаем первый пакет - let size = stream.read_varint(); + match read_first_packet(&mut stream).await { + Ok(_) => {}, Err(e) => println!("Ошибка во время обработки пакета: {e:?}") + } println!("Отключение: {addr}"); -} \ No newline at end of file + println!(); +} + +async fn read_first_packet(stream: &mut TcpStream) -> Result<(), DataError> { + let size = stream.read_varint().await?; + let mut buf = Cursor::new(stream.read_bytes(size as usize).await?); + let id = buf.read_varint().await?; + let version = buf.read_varint().await?; + let host = buf.read_string().await?; + let port = buf.read_short().await?; + let ns = buf.read_varint().await?; + println!("Айди пакета: {id}"); + println!("Версия протокола: {version}"); + println!("Адрес сервера: {host}:{port}"); + println!("Следующее состояние: {ns}"); + Ok(()) +}