/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* client.rs :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: tomoron +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/05/07 17:23:09 by tomoron #+# #+# */ /* Updated: 2026/05/19 18:57:29 by tomoron ### ########.fr */ /* */ /* ************************************************************************** */ use json::object; use tokio::net::TcpStream; use std::collections::VecDeque; use crate::minecraft::handshake::Handshake; use crate::minecraft::varint::{varint_read, varint_write}; use std::{fmt, io}; pub struct Client { pub in_stream: TcpStream, buffer: Vec, out_stream: Option, handshake: Option } impl Client { pub fn create(stream: TcpStream) -> Self { Self { in_stream: stream, buffer: vec![], out_stream: None, handshake: None } } pub async fn in_read(&mut self) -> Result { let mut buf = vec![0 as u8; 100]; loop { match self.in_stream.try_read(&mut buf) { Ok(n) => { println!("[{}] read {} bytes",self, n); println!("[{}] {:?}", self, &buf[..n]); self.buffer_append((&buf[..n]).to_vec()).await?; if n == 0 { return Ok(0) } } Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { return Ok(1); } Err(_e) => { println!("[{}] error", self); return Err("read failed".to_string()) } } } } pub async fn out_readable(&self) { if let Some(stream) = &self.out_stream { stream.readable().await.expect("readable call failed"); } else { std::future::pending::<()>().await; }; } pub async fn out_read(&mut self) -> Result { let mut buf = vec![0 as u8; 1024]; if let None = self.out_stream { return Ok(1); } match self.out_stream.as_mut().unwrap().try_read(&mut buf) { Ok(n) => { let _ = self.in_stream.writable().await; let _ = self.in_stream.try_write(&buf[..n]); if n == 0 { Ok(0) } else { Ok(1) } } Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { Ok(1) } Err(_e) => { println!("try_read returned an error"); Err("Failed to read".to_string()) } } } pub async fn buffer_append(&mut self, data: Vec) -> Result { if data.len() == 0 { return Ok(0); } println!("[{}] buffer handling", self); if let Some(out_stream) = &self.out_stream { println!("[{}] out stream present passing buffer", self); let _ = out_stream.writable().await; let _ = out_stream.try_write(&data); return Ok(0); } if self.buffer.len() + data.len() > 65536 { return Err("buffer full".to_string()); } let _ = self.buffer.extend(data); if self.buffer[0] == 0 { return Err("invalid packet".to_string()); } if self.buffer.len() - 1 >= self.buffer[0] as usize { println!("[{}] valid packet received", self); let len = varint_read(&mut self.buffer.clone().into())? as usize; self.handle_packet(self.buffer[1..=len].to_vec().into()).await?; self.buffer.drain(..len + 1); return Ok(1); } Ok(0) } async fn send_packet(&self, data: Vec) { let mut sent_data: Vec = varint_write(data.len() as i32); sent_data.extend(data); let _ = self.in_stream.writable().await; match self.in_stream.try_write(sent_data.as_slice()) { Err(e) => { eprintln!("error while sending response {:?}", e); }, _ => { } } } async fn handle_packet(&mut self, mut packet: VecDeque) -> Result<(), String> { let packet_id = varint_read(&mut packet)?; if self.handshake.is_none() { if packet_id != 0 { return Err("packet 0 expected. invalid packet received".to_string()); } self.handshake = Some(Handshake::from_packet(&mut packet)?); use std::os::unix::io::AsRawFd; let fd = self.in_stream.as_raw_fd(); println!("{} => {}", fd, self); println!("[{}] got {}",self, self.handshake.as_ref().unwrap()); return Ok(()); } let intent = self.handshake.as_ref().unwrap().intent; if intent == 1 { self.status_intent_handle(&mut packet, packet_id).await?; } else if intent == 2 { self.login_intent_handle(&mut packet, packet_id).await?; } Ok(()) } async fn status_intent_handle(&self, packet: &mut VecDeque, packet_id: i32) -> Result<(),String> { let status_response = object! { "version": { "name": "idk", "protocol" : self.handshake.as_ref().unwrap().protocol_version, }, "players": { "max": 420, "online": 69 }, "description": "§c".to_string() + &self.handshake.as_ref().unwrap().server_address.clone() + "§r:§a" + &self.handshake.as_ref().unwrap().server_port.to_string(), }; if packet_id == 0 { let mut response : Vec = vec![]; let response_json = json::stringify(status_response); let mut response_json_len = varint_write(response_json.len() as i32); let mut response_packet_id = varint_write(0); response.append(&mut response_packet_id); response.append(&mut response_json_len); response.append(&mut response_json.as_bytes().into()); println!("[{}] sent status response to client", self); self.send_packet(response).await; } else if packet_id == 1 { let mut response = varint_write(1); response.extend(packet.drain(..)); self.send_packet(response).await; println!("[{}] sent ping response to client", self); } Ok(()) } async fn login_intent_handle(&mut self, mut _packet: &mut VecDeque, _packet_id: i32) -> Result<(),String> { let stream = TcpStream::connect("localhost:25566").await.map_err(|_| "failed to connect to remote host".to_string())?; let mut new_handshake = self.handshake.as_ref().unwrap().clone(); new_handshake.server_address = "localhost".to_string(); new_handshake.server_port = 25566; println!("{}", new_handshake); let handshake_packet = new_handshake.to_packet(); let mut packet = Vec::new(); packet.extend(varint_write(handshake_packet.len() as i32)); packet.extend(handshake_packet); self.out_stream = Some(stream); let _ = self.out_stream.as_ref().unwrap().writable().await; let _ = self.out_stream.as_ref().unwrap().try_write(packet.as_slice()); println!("[{}] sent handshake to server", self); Ok(()) } } impl fmt::Display for Client { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(handshake) = &self.handshake { write!(f, "{}", handshake.server_address) } else { use std::os::unix::io::AsRawFd; write!(f, "{}", self.in_stream.as_raw_fd()) } } }