From e3c0aec9670523cab6517ceb8a16de6d200dea62 Mon Sep 17 00:00:00 2001 From: Jenya705 <51133999+Jenya705@users.noreply.github.com> Date: Sat, 27 May 2023 20:01:42 +0200 Subject: [PATCH] Bungeecord join bug fix (#345) ## Description Fixes issue #344 --- crates/valence_core/src/packet/decode.rs | 3 +- crates/valence_network/src/connect.rs | 49 +++++++++++++++++------- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/crates/valence_core/src/packet/decode.rs b/crates/valence_core/src/packet/decode.rs index d5203e0..f6c8c7a 100644 --- a/crates/valence_core/src/packet/decode.rs +++ b/crates/valence_core/src/packet/decode.rs @@ -138,7 +138,8 @@ impl PacketDecoder { self.cipher = Some(cipher); } - /// Decrypts the provided byte slice in place using the cipher, without consuming the cipher. + /// Decrypts the provided byte slice in place using the cipher, without + /// consuming the cipher. #[cfg(feature = "encryption")] fn decrypt_bytes(cipher: &mut Cipher, bytes: &mut [u8]) { for chunk in bytes.chunks_mut(Cipher::block_size()) { diff --git a/crates/valence_network/src/connect.rs b/crates/valence_network/src/connect.rs index 0339f21..877a399 100644 --- a/crates/valence_network/src/connect.rs +++ b/crates/valence_network/src/connect.rs @@ -4,7 +4,7 @@ use std::io; use std::net::SocketAddr; use std::time::Duration; -use anyhow::{anyhow, bail, ensure, Context}; +use anyhow::{bail, ensure, Context}; use base64::prelude::*; use hmac::digest::Update; use hmac::{Hmac, Mac}; @@ -230,7 +230,9 @@ async fn handle_login( let info = match shared.connection_mode() { ConnectionMode::Online { .. } => login_online(shared, conn, remote_addr, username).await?, ConnectionMode::Offline => login_offline(remote_addr, username)?, - ConnectionMode::BungeeCord => login_bungeecord(&handshake.server_address, username)?, + ConnectionMode::BungeeCord => { + login_bungeecord(remote_addr, &handshake.server_address, username)? + } ConnectionMode::Velocity { secret } => login_velocity(conn, username, secret).await?, }; @@ -375,11 +377,15 @@ fn auth_digest(bytes: &[u8]) -> String { BigInt::from_signed_bytes_be(bytes).to_str_radix(16) } +fn offline_uuid(username: &str) -> anyhow::Result { + Uuid::from_slice(&Sha256::digest(username)[..16]).map_err(Into::into) +} + /// Login procedure for offline mode. fn login_offline(remote_addr: SocketAddr, username: String) -> anyhow::Result { Ok(NewClientInfo { // Derive the client's UUID from a hash of their username. - uuid: Uuid::from_slice(&Sha256::digest(username.as_str())[..16])?, + uuid: offline_uuid(username.as_str())?, username, properties: vec![].into(), ip: remote_addr.ip(), @@ -387,24 +393,39 @@ fn login_offline(remote_addr: SocketAddr, username: String) -> anyhow::Result anyhow::Result { +fn login_bungeecord( + remote_addr: SocketAddr, + server_address: &str, + username: String, +) -> anyhow::Result { // Get data from server_address field of the handshake - let [_, client_ip, uuid, properties]: [&str; 4] = server_address - .split('\0') - .take(4) - .collect::>() - .try_into() - .map_err(|_| anyhow!("malformed BungeeCord server address data"))?; + let data = server_address.split('\0').take(4).collect::>(); + + // Ip of player, only given if ip_forward on bungee is true + let ip = match data.get(1) { + Some(ip) => ip.parse()?, + None => remote_addr.ip(), + }; + + // Uuid of player, only given if ip_forward on bungee is true + let uuid = match data.get(2) { + Some(uuid) => uuid.parse()?, + None => offline_uuid(username.as_str())?, + }; // Read properties and get textures - let properties: Vec = - serde_json::from_str(properties).context("failed to parse BungeeCord player properties")?; + // Properties of player's game profile, only given if ip_forward and online_mode on bungee both are true + let properties: Vec = match data.get(3) { + Some(properties) => serde_json::from_str(properties) + .context("failed to parse BungeeCord player properties")?, + None => vec![], + }; Ok(NewClientInfo { - uuid: uuid.parse()?, + uuid, username, properties: properties.into(), - ip: client_ip.parse()?, + ip, }) }