aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-16 17:51:05 -0600
committermat <github@matdoes.dev>2021-12-16 17:51:05 -0600
commit227ba5511d50af8c7c46a47e09db7f55a0ed84b7 (patch)
tree1067828ee2082e0f073a4d16b201b2888c55b6e8
parent999116ed7c5edf113e12aae150c2e23974d539dc (diff)
downloadazalea-drasl-227ba5511d50af8c7c46a47e09db7f55a0ed84b7.tar.xz
add a few more login packets
-rw-r--r--Cargo.lock9
-rw-r--r--Cargo.toml1
-rw-r--r--azalea-auth/Cargo.toml9
-rw-r--r--azalea-auth/src/game_profile.rs20
-rw-r--r--azalea-auth/src/lib.rs3
-rw-r--r--azalea-chat/src/component.rs2
-rw-r--r--azalea-core/src/resource_location.rs20
-rw-r--r--azalea-core/src/serializable_uuid.rs2
-rw-r--r--azalea-protocol/Cargo.toml2
-rw-r--r--azalea-protocol/src/mc_buf.rs18
-rw-r--r--azalea-protocol/src/packets/login/clientbound_custom_query_packet.rs15
-rw-r--r--azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs39
-rw-r--r--azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs32
-rw-r--r--azalea-protocol/src/packets/login/mod.rs25
-rw-r--r--azalea-protocol/src/write.rs8
15 files changed, 181 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e999fcc1..1f6baa86 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -31,6 +31,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
+name = "azalea-auth"
+version = "0.1.0"
+dependencies = [
+ "uuid",
+]
+
+[[package]]
name = "azalea-chat"
version = "0.1.0"
dependencies = [
@@ -59,7 +66,9 @@ version = "0.1.0"
dependencies = [
"async-recursion",
"async-trait",
+ "azalea-auth",
"azalea-chat",
+ "azalea-core",
"byteorder",
"bytes",
"serde",
diff --git a/Cargo.toml b/Cargo.toml
index 22f3e5a8..0cf441eb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,5 @@ members = [
"azalea-protocol",
"azalea-chat",
"azalea-core",
+ "azalea-auth",
]
diff --git a/azalea-auth/Cargo.toml b/azalea-auth/Cargo.toml
new file mode 100644
index 00000000..aa9b7bdb
--- /dev/null
+++ b/azalea-auth/Cargo.toml
@@ -0,0 +1,9 @@
+[package]
+edition = "2021"
+name = "azalea-auth"
+version = "0.1.0"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+uuid = "^0.8.2"
diff --git a/azalea-auth/src/game_profile.rs b/azalea-auth/src/game_profile.rs
new file mode 100644
index 00000000..a186a208
--- /dev/null
+++ b/azalea-auth/src/game_profile.rs
@@ -0,0 +1,20 @@
+use std::collections::HashMap;
+
+use uuid::Uuid;
+
+#[derive(Hash, Clone, Debug)]
+pub struct GameProfile {
+ pub uuid: Uuid,
+ pub name: String,
+ pub properties: HashMap<String, String>,
+}
+
+impl GameProfile {
+ pub fn new(uuid: Uuid, name: String) -> Self {
+ GameProfile {
+ uuid,
+ name,
+ properties: HashMap::new(),
+ }
+ }
+}
diff --git a/azalea-auth/src/lib.rs b/azalea-auth/src/lib.rs
new file mode 100644
index 00000000..773ea1d9
--- /dev/null
+++ b/azalea-auth/src/lib.rs
@@ -0,0 +1,3 @@
+//! Handle Minecraft authentication.
+
+pub mod game_profile;
diff --git a/azalea-chat/src/component.rs b/azalea-chat/src/component.rs
index 1ed1f836..9f065c47 100644
--- a/azalea-chat/src/component.rs
+++ b/azalea-chat/src/component.rs
@@ -22,8 +22,6 @@ lazy_static! {
/// A chat component
impl Component {
- // TODO: is it possible to use a macro so this doesn't have to be duplicated?
-
pub fn get_base_mut(&mut self) -> &mut BaseComponent {
match self {
Self::Text(c) => &mut c.base,
diff --git a/azalea-core/src/resource_location.rs b/azalea-core/src/resource_location.rs
index df706e7a..c1fed451 100644
--- a/azalea-core/src/resource_location.rs
+++ b/azalea-core/src/resource_location.rs
@@ -1,14 +1,15 @@
//! A resource, like minecraft:stone
-pub struct ResourceLocation<'a> {
- pub namespace: &'a str,
- pub path: &'a str,
+#[derive(Hash, Clone, Debug)]
+pub struct ResourceLocation {
+ pub namespace: String,
+ pub path: String,
}
static DEFAULT_NAMESPACE: &str = "minecraft";
// static REALMS_NAMESPACE: &str = "realms";
-impl<'a> ResourceLocation<'a> {
+impl ResourceLocation {
pub fn new(resource_string: &str) -> Result<ResourceLocation, String> {
let sep_byte_position_option = resource_string.chars().position(|c| c == ':');
let (namespace, path) = if let Some(sep_byte_position) = sep_byte_position_option {
@@ -23,7 +24,16 @@ impl<'a> ResourceLocation<'a> {
} else {
(DEFAULT_NAMESPACE, resource_string)
};
- Ok(ResourceLocation { namespace, path })
+ Ok(ResourceLocation {
+ namespace: namespace.to_string(),
+ path: path.to_string(),
+ })
+ }
+}
+
+impl std::fmt::Display for ResourceLocation {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ write!(f, "{}:{}", self.namespace, self.path)
}
}
diff --git a/azalea-core/src/serializable_uuid.rs b/azalea-core/src/serializable_uuid.rs
index 473d8254..f8c03b60 100644
--- a/azalea-core/src/serializable_uuid.rs
+++ b/azalea-core/src/serializable_uuid.rs
@@ -26,7 +26,7 @@ impl SerializableUuid for Uuid {
let most = ((array[0] as u64) << 32) | ((array[1] as u64) & 0xFFFFFFFF);
let least = ((array[2] as u64) << 32) | ((array[3] as u64) & 0xFFFFFFFF);
- Uuid::from_u128((((most as u128) << 64) | least as u128).into())
+ Uuid::from_u128(((most as u128) << 64) | least as u128)
}
}
diff --git a/azalea-protocol/Cargo.toml b/azalea-protocol/Cargo.toml
index 2b8a97f2..cf97f089 100644
--- a/azalea-protocol/Cargo.toml
+++ b/azalea-protocol/Cargo.toml
@@ -8,7 +8,9 @@ version = "0.1.0"
[dependencies]
async-recursion = "^0.3.2"
async-trait = "0.1.51"
+azalea-auth = {path = "../azalea-auth"}
azalea-chat = {path = "../azalea-chat"}
+azalea-core = {path = "../azalea-core"}
byteorder = "^1.4.3"
bytes = "^1.1.0"
serde = {version = "1.0.130", features = ["serde_derive"]}
diff --git a/azalea-protocol/src/mc_buf.rs b/azalea-protocol/src/mc_buf.rs
index 5a1ac274..0a47f637 100644
--- a/azalea-protocol/src/mc_buf.rs
+++ b/azalea-protocol/src/mc_buf.rs
@@ -1,6 +1,6 @@
//! Utilities for reading and writing for the Minecraft protocol
-use std::{future::Future, io::Write};
+use std::io::Write;
use async_trait::async_trait;
use byteorder::{BigEndian, WriteBytesExt};
@@ -35,6 +35,7 @@ pub trait Writable {
fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error>;
fn write_short(&mut self, n: u16) -> Result<(), std::io::Error>;
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
+ fn write_int(&mut self, n: i32) -> Result<(), std::io::Error>;
}
#[async_trait]
@@ -79,7 +80,8 @@ impl Writable for Vec<u8> {
}
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
- Ok(self.extend_from_slice(bytes))
+ self.extend_from_slice(bytes);
+ Ok(())
}
fn write_varint(&mut self, mut value: i32) -> Result<(), std::io::Error> {
@@ -122,6 +124,10 @@ impl Writable for Vec<u8> {
self.write_varint(bytes.len() as i32)?;
self.write_bytes(bytes)
}
+
+ fn write_int(&mut self, n: i32) -> Result<(), std::io::Error> {
+ WriteBytesExt::write_i32::<BigEndian>(self, n)
+ }
}
#[async_trait]
@@ -133,6 +139,7 @@ pub trait Readable {
async fn read_utf(&mut self) -> Result<String, String>;
async fn read_utf_with_len(&mut self, max_length: u32) -> Result<String, String>;
async fn read_byte(&mut self) -> Result<u8, String>;
+ async fn read_int(&mut self) -> Result<i32, String>;
}
#[async_trait]
@@ -225,6 +232,13 @@ where
Err(_) => Err("Error reading byte".to_string()),
}
}
+
+ async fn read_int(&mut self) -> Result<i32, String> {
+ match AsyncReadExt::read_i32(self).await {
+ Ok(r) => Ok(r),
+ Err(_) => Err("Error reading int".to_string()),
+ }
+ }
}
#[cfg(test)]
diff --git a/azalea-protocol/src/packets/login/clientbound_custom_query_packet.rs b/azalea-protocol/src/packets/login/clientbound_custom_query_packet.rs
index 8f501fc9..2c66bfa3 100644
--- a/azalea-protocol/src/packets/login/clientbound_custom_query_packet.rs
+++ b/azalea-protocol/src/packets/login/clientbound_custom_query_packet.rs
@@ -1,15 +1,13 @@
+use super::LoginPacket;
+use crate::mc_buf::{Readable, Writable};
+use azalea_core::resource_location::ResourceLocation;
use std::hash::Hash;
use tokio::io::BufReader;
-use crate::mc_buf::{Readable, Writable};
-
-use super::LoginPacket;
-
#[derive(Hash, Clone, Debug)]
pub struct ClientboundCustomQueryPacket {
pub transaction_id: u32,
- // TODO: this should be a resource location
- pub identifier: String,
+ pub identifier: ResourceLocation,
pub data: Vec<u8>,
}
@@ -20,7 +18,7 @@ impl ClientboundCustomQueryPacket {
pub fn write(&self, buf: &mut Vec<u8>) {
buf.write_varint(self.transaction_id as i32).unwrap();
- buf.write_utf(&self.identifier).unwrap();
+ buf.write_utf(self.identifier.to_string().as_str()).unwrap();
buf.write_bytes(&self.data).unwrap();
}
@@ -28,8 +26,7 @@ impl ClientboundCustomQueryPacket {
buf: &mut BufReader<T>,
) -> Result<LoginPacket, String> {
let transaction_id = buf.read_varint().await? as u32;
- // TODO: this should be a resource location
- let identifier = buf.read_utf().await?;
+ let identifier = ResourceLocation::new(&buf.read_utf().await?)?;
let data = buf.read_bytes(1048576).await?;
Ok(ClientboundCustomQueryPacket {
transaction_id,
diff --git a/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs b/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs
new file mode 100644
index 00000000..88166c54
--- /dev/null
+++ b/azalea-protocol/src/packets/login/clientbound_game_profile_packet.rs
@@ -0,0 +1,39 @@
+use super::LoginPacket;
+use crate::mc_buf::{Readable, Writable};
+use azalea_auth::game_profile::GameProfile;
+use azalea_core::{resource_location::ResourceLocation, serializable_uuid::SerializableUuid};
+use std::hash::Hash;
+use tokio::io::BufReader;
+
+#[derive(Hash, Clone, Debug)]
+pub struct ClientboundGameProfilePacket {
+ pub game_profile: GameProfile,
+}
+
+impl ClientboundGameProfilePacket {
+ pub fn get(self) -> LoginPacket {
+ LoginPacket::ClientboundGameProfilePacket(self)
+ }
+
+ pub fn write(&self, buf: &mut Vec<u8>) {
+ for n in self.game_profile.uuid.to_int_array() {
+ buf.write_int(n as i32).unwrap();
+ }
+ buf.write_utf(self.game_profile.name.as_str()).unwrap();
+ }
+
+ pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
+ buf: &mut BufReader<T>,
+ ) -> Result<LoginPacket, String> {
+ let uuid = SerializableUuid::from_int_array(
+ buf.read_int().await?,
+ buf.read_int().await?,
+ buf.read_int().await?,
+ buf.read_int().await?,
+ );
+ let name = buf.read_utf(16).await?;
+ ClientboundGameProfilePacket {
+ game_profile: GameProfile::new(uuid, name),
+ }
+ }
+}
diff --git a/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs b/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs
new file mode 100644
index 00000000..87fc6e03
--- /dev/null
+++ b/azalea-protocol/src/packets/login/clientbound_login_compression_packet.rs
@@ -0,0 +1,32 @@
+use std::hash::Hash;
+use tokio::io::BufReader;
+
+use crate::mc_buf::Readable;
+
+use super::LoginPacket;
+
+#[derive(Hash, Clone, Debug)]
+pub struct ClientboundLoginCompressionPacket {
+ pub compression_threshold: i32,
+}
+
+impl ClientboundLoginCompressionPacket {
+ pub fn get(self) -> LoginPacket {
+ LoginPacket::ClientboundLoginCompressionPacket(self)
+ }
+
+ pub fn write(&self, buf: &mut Vec<u8>) {
+ buf.write_varint(self.compression_threshold).unwrap();
+ }
+
+ pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(
+ buf: &mut BufReader<T>,
+ ) -> Result<LoginPacket, String> {
+ let compression_threshold = buf.read_varint().await?;
+
+ Ok(ClientboundLoginCompressionPacket {
+ compression_threshold
+ }
+ .get())
+ }
+}
diff --git a/azalea-protocol/src/packets/login/mod.rs b/azalea-protocol/src/packets/login/mod.rs
index f0ed6717..7fee684a 100644
--- a/azalea-protocol/src/packets/login/mod.rs
+++ b/azalea-protocol/src/packets/login/mod.rs
@@ -1,5 +1,7 @@
pub mod clientbound_custom_query_packet;
+pub mod clientbound_game_profile_packet;
pub mod clientbound_hello_packet;
+pub mod clientbound_login_compression_packet;
pub mod serverbound_hello_packet;
use async_trait::async_trait;
@@ -15,8 +17,12 @@ where
Self: Sized,
{
ClientboundCustomQueryPacket(clientbound_custom_query_packet::ClientboundCustomQueryPacket),
- ServerboundHelloPacket(serverbound_hello_packet::ServerboundHelloPacket),
+ ClientboundGameProfilePacket(clientbound_game_profile_packet::ClientboundGameProfilePacket),
ClientboundHelloPacket(clientbound_hello_packet::ClientboundHelloPacket),
+ ClientboundLoginCompressionPacket(
+ clientbound_login_compression_packet::ClientboundLoginCompressionPacket,
+ ),
+ ServerboundHelloPacket(serverbound_hello_packet::ServerboundHelloPacket),
}
#[async_trait]
@@ -24,16 +30,20 @@ impl ProtocolPacket for LoginPacket {
fn id(&self) -> u32 {
match self {
LoginPacket::ClientboundCustomQueryPacket(_packet) => 0x04,
- LoginPacket::ServerboundHelloPacket(_packet) => 0x00,
+ LoginPacket::ClientboundGameProfilePacket(_packet) => 0x02,
LoginPacket::ClientboundHelloPacket(_packet) => 0x01,
+ LoginPacket::ClientboundLoginCompressionPacket(_packet) => 0x03,
+ LoginPacket::ServerboundHelloPacket(_packet) => 0x00,
}
}
fn write(&self, buf: &mut Vec<u8>) {
match self {
LoginPacket::ClientboundCustomQueryPacket(packet) => packet.write(buf),
- LoginPacket::ServerboundHelloPacket(packet) => packet.write(buf),
+ LoginPacket::ClientboundGameProfilePacket(packet) => packet.write(buf),
LoginPacket::ClientboundHelloPacket(packet) => packet.write(buf),
+ LoginPacket::ClientboundLoginCompressionPacket(packet) => packet.write(buf),
+ LoginPacket::ServerboundHelloPacket(packet) => packet.write(buf),
}
}
@@ -49,9 +59,18 @@ impl ProtocolPacket for LoginPacket {
Ok(match flow {
PacketFlow::ServerToClient => match id {
0x01 => clientbound_hello_packet::ClientboundHelloPacket::read(buf).await?,
+ 0x02 => {
+ clientbound_game_profile_packet::ClientboundGameProfilePacket::read(buf).await?
+ }
0x04 => {
clientbound_custom_query_packet::ClientboundCustomQueryPacket::read(buf).await?
}
+ 0x03 => {
+ clientbound_login_compression_packet::ClientboundLoginCompressionPacket::read(
+ buf,
+ )
+ .await?
+ }
_ => return Err(format!("Unknown ServerToClient status packet id: {}", id)),
},
PacketFlow::ClientToServer => match id {
diff --git a/azalea-protocol/src/write.rs b/azalea-protocol/src/write.rs
index 3d8540eb..bf9fd0aa 100644
--- a/azalea-protocol/src/write.rs
+++ b/azalea-protocol/src/write.rs
@@ -10,7 +10,9 @@ pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
// write the packet id
let mut id_and_data_buf = vec![];
- id_and_data_buf.write_varint(packet.id() as i32);
+ id_and_data_buf
+ .write_varint(packet.id() as i32)
+ .expect("Writing packet id failed");
packet.write(&mut id_and_data_buf);
// write the packet data
@@ -18,7 +20,9 @@ pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
// make a new buffer that has the length at the beginning
// and id+data at the end
let mut complete_buf: Vec<u8> = Vec::new();
- complete_buf.write_varint(id_and_data_buf.len() as i32);
+ complete_buf
+ .write_varint(id_and_data_buf.len() as i32)
+ .expect("Writing packet length failed");
complete_buf.append(&mut id_and_data_buf);
// finally, write and flush to the stream