From 4d928973a6fb1de0d383489d97c848dcab79ecfd Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Tue, 19 Apr 2022 09:09:30 -0600 Subject: [PATCH] Login complete --- src/lib.rs | 1 + src/net/mod.rs | 9 ++++- src/net/packets.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++-- src/server/mod.rs | 26 ++++++++++++-- 4 files changed, 117 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5598efc..6729dce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,6 +98,7 @@ pub mod prelude { pub use log::*; pub use serde::{Deserialize, Serialize}; pub use serde_json::json; + pub use uuid::Uuid; pub type JSON = serde_json::Value; pub type NBT = fastnbt::Value; pub use std::collections::VecDeque; diff --git a/src/net/mod.rs b/src/net/mod.rs index 95cbd48..7f1856c 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -77,6 +77,8 @@ impl NetworkClient { Ok(()) } pub async fn send_packet(&mut self, packet: Packet) -> Result<(), tokio::io::Error> { + trace!("NetworkClient.send_packet()"); + debug!("Sending packet {:?} to client {}", packet, self.id); let bytes = packet.serialize(); self.stream.write(&bytes).await?; Ok(()) @@ -90,7 +92,12 @@ impl NetworkClient { let _ = self.read_data().await; let _ = self.read_packet(); } - pub fn disconnect(&mut self) { + pub async fn disconnect(&mut self, reason: Option) { + if let Some(reason) = reason { + if self.state == NetworkClientState::Login { + let _ = self.send_packet(Packet::CL00Disconnect { reason }).await; + } + } self.state = NetworkClientState::Disconnected; } } diff --git a/src/net/packets.rs b/src/net/packets.rs index ab8db5b..5cd382d 100644 --- a/src/net/packets.rs +++ b/src/net/packets.rs @@ -26,7 +26,40 @@ pub enum Packet { SS01Ping { payload: i64, }, + // Login + CL00Disconnect { + reason: JSON, + }, + CL01EncryptionRequest { + server_id: String, + public_key: Vec, + verify_token: Vec, + }, + CL02LoginSuccess { + uuid: u128, + username: String, + }, + CL03SetCompression { + threshold: usize, + }, + CL04LoginPluginRequest { + message_id: i32, + channel: String, + data: Vec, + }, + SL00LoginStart { + username: String, + }, + SL01EncryptionResponse { + shared_secret: Vec, + verify_token: Vec, + }, + SL02LoginPluginResponse { + message_id: i32, + successful: bool, + data: Option>, + }, // Play } impl Packet { @@ -90,7 +123,46 @@ impl Packet { } _ => Err(ParseError::InvalidData), }, - Login => unimplemented!("Parse Login packet"), + Login => match id { + 0x00 => { + if serverbound { + let (username, offset_delta) = parse_string(&data[offset..])?; + offset += offset_delta; + Ok((SL00LoginStart { username }, offset)) + } else { + unimplemented!("Parse CL00Disconnect") + } + } + 0x01 => { + if serverbound { + unimplemented!("Parse SL01EncryptionResponse") + } else { + unimplemented!("Parse CL01EncryptionRequest") + } + } + 0x02 => { + if serverbound { + unimplemented!("Parse SL02LoginPluginResponse") + } else { + unimplemented!("Parse CL02LoginSuccess") + } + } + 0x03 => { + if serverbound { + Err(ParseError::InvalidData) + } else { + unimplemented!("Parse CL03SetCompression") + } + } + 0x04 => { + if serverbound { + Err(ParseError::InvalidData) + } else { + unimplemented!("Parse CL04LoginPluginRequest") + } + } + _ => Err(ParseError::InvalidData), + }, Play => unimplemented!("Parse Play packet"), } } @@ -105,7 +177,7 @@ impl Packet { description, } => ( 0x00, - serialize_json(serde_json::json!({ + serialize_json(json!({ "version": { "name": version_name, "protocol": protocol_version, @@ -120,7 +192,17 @@ impl Packet { })), ), CS01Pong { payload } => (0x01, serialize_long(*payload).to_vec()), - _ => unimplemented!(), + CL00Disconnect { reason } => (0x00, serialize_json(reason.clone())), + // CL01EncryptionRequest + CL02LoginSuccess { uuid, username } => (0x02, { + let mut out = vec![]; + out.extend(uuid.to_be_bytes()); + out.extend(serialize_string(username)); + out + }), + // CL03SetCompression + // CL04LoginPluginRequest + _ => unimplemented!("Serializing unknown packet"), }; let mut id_and_body = serialize_varint(id as i32); id_and_body.append(&mut body); diff --git a/src/server/mod.rs b/src/server/mod.rs index fcc06f5..0138d05 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -93,7 +93,6 @@ impl Server { current_players += 1; } } - // TODO: Make this count the number in the play state. let client = &mut self.clients[client_index]; match packet { SH00Handshake { @@ -107,7 +106,7 @@ impl Server { "Disconnecting client {} for mismatched protocols: {} (expected {})", client.id, protocol_version, PROTOCOL_VERSION ); - client.disconnect(); + client.disconnect(None).await; return Err(()); } client.state = next_state; @@ -128,7 +127,28 @@ impl Server { SS01Ping { payload } => { let _ = client.send_packet(CS01Pong { payload }).await; debug!("Disconnecting client {}, SLP completed", client.id); - client.disconnect(); + client.disconnect(None).await; + } + SL00LoginStart { username } => { + debug!( + "Client {} is connecting with username {}", + client.id, username + ); + if current_players >= CONFIG.max_players { + client + .disconnect(Some(json!({ "text": "Server full!" }))) + .await; + } + // TODO: Authentication + // TODO: Encryption + // TODO: Compression + let _ = client + .send_packet(CL02LoginSuccess { + uuid: client.id, + username, + }) + .await; + client.state = NetworkClientState::Play; } _ => unimplemented!("Handling unknown packet"), }