diff --git a/src/main.rs b/src/main.rs index 289b1e2..2d2ab5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ use crate::mc_server::{MinecraftAPI, MinecraftServerHandle, ServerDeploymentStat use crate::opaque_error::OpaqueError; use crate::packets::clientbound::status::StatusStructNew; use crate::packets::serverbound::handshake::Handshake; +use crate::packets::serverbound::login::LoginStart; use crate::packets::{Packet, SendPacket}; mod kube_cache; @@ -111,7 +112,15 @@ async fn process_connection( packets::ProtocolState::Status => { handle_status(&mut client_stream, &handshake, api).await?; } - packets::ProtocolState::Login => handle_login(&mut client_stream, &handshake, api).await?, + packets::ProtocolState::Login => { + // This block of packet parsing is needed here, so the span with the + // username is correctly propagated due to the async nature of things + let packet = Packet::parse(&mut client_stream).await?; + let login_packet = packets::serverbound::login::LoginStart::parse(packet) + .await + .ok_or("Failed to parse login start packet".to_string())?; + handle_login(&mut client_stream, &handshake, login_packet, api).await? + } packets::ProtocolState::Transfer => { return Err(OpaqueError::create( "next state is transfer; Not yet implemented!", @@ -169,6 +178,7 @@ async fn handle_status( let _pong = Packet::new(9, vec![0; 8]) .ok_or("failed to create empty pong packet?")? .send_packet(client_stream) + .instrument(span.clone()) .await .map_err(|_| "failed to send pong packet")?; let _guard = span.enter(); @@ -176,7 +186,7 @@ async fn handle_status( match _ping { Ok(_) => tracing::info!("sent status with error"), Err(err) => { - tracing::warn!(err = OpaqueError::from(err).context) + tracing::error!(err = OpaqueError::from(err).context) } }; return Ok(()); @@ -212,10 +222,11 @@ async fn handle_status( return mc_server::handle_ping(client_stream).await; } -#[tracing::instrument(level = "info", fields(server_addr = handshake.get_server_address(),server_port = handshake.server_port.get_value()),skip(client_stream, handshake, api))] +#[tracing::instrument(level = "info", fields(server_addr = handshake.get_server_address(),server_port = handshake.server_port.get_value(),username = login_start.name.get_value()),skip(client_stream, handshake, api, login_start))] async fn handle_login( client_stream: &mut TcpStream, handshake: &Handshake, + login_start: LoginStart, api: impl MinecraftAPI, ) -> Result<(), OpaqueError> { let server = api @@ -244,6 +255,13 @@ async fn handle_login( .await .map_err(|_| "failed to forward handshake packet to minecraft server")?; + login_start + .send_packet(&mut server_stream) + .await + .map_err(|e| { + "failed to forward login packet to server before splicing".to_string() + })?; + tracing::info!("proxying with splice"); let traffic = tokio_splice2::io::SpliceBidiIo { io_sl2sr, io_sr2sl } .execute(client_stream, &mut server_stream) diff --git a/src/packets/serverbound/login.rs b/src/packets/serverbound/login.rs new file mode 100644 index 0000000..3f4f38e --- /dev/null +++ b/src/packets/serverbound/login.rs @@ -0,0 +1,34 @@ +use tokio::io::AsyncWriteExt; + +use crate::{ + packets::{Packet, SendPacket}, + types::VarString, +}; + +/// id: 0x00 +pub struct LoginStart { + all: Vec, + pub name: VarString, + // TODO: implement uuid parsing + // uuid: Vec, +} + +impl LoginStart { + pub async fn parse(packet: Packet) -> Option { + let mut reader = packet.data.clone(); + let name = VarString::parse(&mut reader).await?; + + Some(LoginStart { + all: packet.all, + name: name, + }) + } +} + +impl SendPacket for LoginStart { + async fn send_packet(&self, stream: &mut tokio::net::TcpStream) -> std::io::Result<()> { + stream.write_all(&self.all).await?; + stream.flush().await?; + Ok(()) + } +} diff --git a/src/packets/serverbound/mod.rs b/src/packets/serverbound/mod.rs index 9651198..acd006e 100644 --- a/src/packets/serverbound/mod.rs +++ b/src/packets/serverbound/mod.rs @@ -1,2 +1,3 @@ pub mod handshake; +pub mod login; pub mod status;