From fb795df5e877dd2e1e6d2a3ddeaf0ed50b989af3 Mon Sep 17 00:00:00 2001 From: Alvsch Date: Wed, 16 Oct 2024 23:44:45 +0200 Subject: [PATCH] Fixed velocity support --- pumpkin-protocol/src/bytebuf/mod.rs | 1 + pumpkin/src/client/client_packet.rs | 6 ++-- pumpkin/src/client/mod.rs | 47 +++++++++++++++++------------ pumpkin/src/entity/player.rs | 2 +- pumpkin/src/proxy/velocity.rs | 43 ++++++++++++++++++++------ 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/pumpkin-protocol/src/bytebuf/mod.rs b/pumpkin-protocol/src/bytebuf/mod.rs index 3b46f2f90..9901615de 100644 --- a/pumpkin-protocol/src/bytebuf/mod.rs +++ b/pumpkin-protocol/src/bytebuf/mod.rs @@ -370,6 +370,7 @@ impl ByteBuffer { if self.buffer.len() >= len { Ok(self.buffer.copy_to_bytes(len)) } else { + dbg!("{:?} < {:?}", self.buffer.len(), len); Err(DeserializerError::Message( "Unable to copy bytes".to_string(), )) diff --git a/pumpkin/src/client/client_packet.rs b/pumpkin/src/client/client_packet.rs index d185438e6..4ee37cf4b 100644 --- a/pumpkin/src/client/client_packet.rs +++ b/pumpkin/src/client/client_packet.rs @@ -20,7 +20,7 @@ use uuid::Uuid; use crate::{ client::authentication::{self, validate_textures, GameProfile}, entity::player::{ChatMode, Hand}, - proxy::velocity::velocity_login, + proxy::velocity::{self, velocity_login}, server::{Server, CURRENT_MC_VERSION}, }; @@ -180,7 +180,9 @@ impl Client { Err(AuthError::MissingAuthClient) } - pub fn handle_plugin_response(&self, _plugin_response: SLoginPluginResponse) {} + pub fn handle_plugin_response(&self, plugin_response: SLoginPluginResponse) { + velocity::receive_plugin_response(self, &ADVANCED_CONFIG.proxy.velocity, plugin_response); + } pub fn handle_login_acknowledged( &self, diff --git a/pumpkin/src/client/mod.rs b/pumpkin/src/client/mod.rs index 83e61abaa..b18b1f064 100644 --- a/pumpkin/src/client/mod.rs +++ b/pumpkin/src/client/mod.rs @@ -1,10 +1,8 @@ use std::{ - io::{self, Write}, - net::SocketAddr, - sync::{ + collections::VecDeque, io::{self, Write}, net::SocketAddr, sync::{ atomic::{AtomicBool, AtomicI32}, Arc, - }, + } }; use crate::{ @@ -110,7 +108,7 @@ pub struct Client { /// The packet decoder for incoming packets. dec: Arc>, /// A queue of raw packets received from the client, waiting to be processed. - pub client_packets_queue: Arc>>, + pub client_packets_queue: Arc>>, /// Indicates whether the client should be converted into a player. pub make_player: AtomicBool, @@ -140,7 +138,7 @@ impl Client { dec: Arc::new(Mutex::new(PacketDecoder::default())), encryption: AtomicBool::new(false), closed: AtomicBool::new(false), - client_packets_queue: Arc::new(Mutex::new(Vec::new())), + client_packets_queue: Arc::new(Mutex::new(VecDeque::new())), make_player: AtomicBool::new(false), keep_alive_sender, last_alive_received: AtomicCell::new(std::time::Instant::now()), @@ -150,7 +148,7 @@ impl Client { /// Adds a Incoming packet to the queue pub fn add_packet(&self, packet: RawPacket) { let mut client_packets_queue = self.client_packets_queue.lock(); - client_packets_queue.push(packet); + client_packets_queue.push_back(packet); } /// Sets the Packet encryption @@ -206,8 +204,9 @@ impl Client { /// Processes all packets send by the client pub async fn process_packets(&self, server: &Arc) { - while let Some(mut packet) = self.client_packets_queue.lock().pop() { + while let Some(mut packet) = self.client_packets_queue.lock().pop_front() { let _ = self.handle_packet(server, &mut packet).await.map_err(|e| { + dbg!("{:?}", packet.id); let text = format!("Error while reading incoming packet {}", e); log::error!("{}", text); self.kick(&text) @@ -221,22 +220,24 @@ impl Client { server: &Arc, packet: &mut RawPacket, ) -> Result<(), DeserializerError> { + println!("{:?}", self.connection_state.load()); match self.connection_state.load() { - pumpkin_protocol::ConnectionState::HandShake => self.handle_handshake_packet(packet), - pumpkin_protocol::ConnectionState::Status => self.handle_status_packet(server, packet), + pumpkin_protocol::ConnectionState::HandShake => self.handle_handshake_packet(packet).unwrap(), + pumpkin_protocol::ConnectionState::Status => self.handle_status_packet(server, packet).unwrap(), // TODO: Check config if transfer is enabled pumpkin_protocol::ConnectionState::Login | pumpkin_protocol::ConnectionState::Transfer => { - self.handle_login_packet(server, packet).await + self.handle_login_packet(server, packet).await.unwrap() } pumpkin_protocol::ConnectionState::Config => { - self.handle_config_packet(server, packet).await + self.handle_config_packet(server, packet).await.unwrap() } _ => { log::error!("Invalid Connection state {:?}", self.connection_state); - Ok(()) + // Ok(()) } - } + }; + Ok(()) } fn handle_handshake_packet(&self, packet: &mut RawPacket) -> Result<(), DeserializerError> { @@ -378,13 +379,21 @@ impl Client { if !received_data.is_empty() { let mut dec = self.dec.lock(); dec.queue_slice(&received_data); - match dec.decode() { - Ok(packet) => { - if let Some(packet) = packet { - self.add_packet(packet); + loop { + match dec.decode() { + Ok(packet) => { + if let Some(packet) = packet { + self.add_packet(packet); + } else { + break; + } } + Err(err) => { + dbg!("a"); + self.kick(&err.to_string()); + break; + }, } - Err(err) => self.kick(&err.to_string()), } dec.clear(); } diff --git a/pumpkin/src/entity/player.rs b/pumpkin/src/entity/player.rs index e51e2ad32..865c8a58a 100644 --- a/pumpkin/src/entity/player.rs +++ b/pumpkin/src/entity/player.rs @@ -276,7 +276,7 @@ impl Player { impl Player { pub async fn process_packets(&self, server: &Arc) { let mut packets = self.client.client_packets_queue.lock(); - while let Some(mut packet) = packets.pop() { + while let Some(mut packet) = packets.pop_back() { match self.handle_play_packet(server, &mut packet).await { Ok(_) => {} Err(e) => { diff --git a/pumpkin/src/proxy/velocity.rs b/pumpkin/src/proxy/velocity.rs index e97e84c97..453e4471b 100644 --- a/pumpkin/src/proxy/velocity.rs +++ b/pumpkin/src/proxy/velocity.rs @@ -4,7 +4,7 @@ use bytes::{BufMut, BytesMut}; use hmac::{Hmac, Mac}; use pumpkin_config::proxy::VelocityConfig; use pumpkin_protocol::{ - bytebuf::ByteBuffer, client::login::CLoginPluginRequest, server::login::SLoginPluginResponse, + bytebuf::ByteBuffer, client::login::{CLoginPluginRequest, CLoginSuccess}, server::login::SLoginPluginResponse, Property }; use sha2::Sha256; @@ -27,7 +27,7 @@ pub fn velocity_login(client: &Client) { )); } -pub fn check_integrity(data: (&[u8], &[u8]), secret: String) -> bool { +pub fn check_integrity(data: (&[u8], &[u8]), secret: &str) -> bool { let (signature, data_without_signature) = data; let mut mac = HmacSha256::new_from_slice(secret.as_bytes()).expect("HMAC can take key of any size"); @@ -37,14 +37,14 @@ pub fn check_integrity(data: (&[u8], &[u8]), secret: String) -> bool { pub fn receive_plugin_response( client: &Client, - config: VelocityConfig, + config: &VelocityConfig, response: SLoginPluginResponse, ) { dbg!("velocity response"); if let Some(data) = response.data { let (signature, data_without_signature) = data.split_at(32); - if !check_integrity((signature, data_without_signature), config.secret) { + if !check_integrity((signature, data_without_signature), &config.secret) { client.kick("Unable to verify player details"); return; } @@ -60,11 +60,36 @@ pub fn receive_plugin_response( )); return; } - // TODO: no unwrap - let addr: SocketAddr = buf.get_string().unwrap().parse().unwrap(); + // TODO: dont default to localhost + let addr: SocketAddr = buf.get_string().unwrap().parse() + .unwrap_or_else(|_| ([127, 0, 0, 1], 25565).into()); + *client.address.lock() = addr; - todo!() - } else { - client.kick("This server requires you to connect with Velocity.") + + let uuid = buf.get_uuid().unwrap(); + + let username = buf.get_string().unwrap(); + + // Read game profile properties + let properties = buf.get_list(|data| { + let name = data.get_string()?; + let value = data.get_string()?; + let signature = data.get_option(|data| { + data.get_string() + })?; + + Ok(Property { + name, + value, + signature, + }) + }).unwrap(); + + client.send_packet(&CLoginSuccess { + uuid: &uuid, + username: &username, + properties: &properties, + strict_error_handling: false, + }); } }