Repository: azalea-rs/azalea (language: rust)

Issue:
ClientIntentionPacket incorrectly uses ConnectionProtocol for client intent
`ClientIntentionPacket` uses `ConnectionProtocol` as its type for the client's intention. Because of this, the transfer intent is not included in the enum and cannot be handled.


Discussion / hints:

Fix patch:
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 39cc504c4..1f9685ec3 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -51,7 +51,7 @@ use azalea_protocol::{
             serverbound_login_acknowledged_packet::ServerboundLoginAcknowledgedPacket,
             ClientboundLoginPacket,
         },
-        ConnectionProtocol, PROTOCOL_VERSION,
+        ConnectionProtocol, ClientIntention, PROTOCOL_VERSION,
     },
     resolver, ServerAddress,
 };
@@ -358,7 +358,7 @@ impl Client {
                 protocol_version: PROTOCOL_VERSION,
                 hostname: address.host.clone(),
                 port: address.port,
-                intention: ConnectionProtocol::Login,
+                intention: ClientIntention::Login,
             }
             .get(),
         )
diff --git a/azalea-client/src/ping.rs b/azalea-client/src/ping.rs
index c74a62be9..d06123923 100755
--- a/azalea-client/src/ping.rs
+++ b/azalea-client/src/ping.rs
@@ -12,7 +12,7 @@ use azalea_protocol::{
             serverbound_status_request_packet::ServerboundStatusRequestPacket,
             ClientboundStatusPacket,
         },
-        ConnectionProtocol, PROTOCOL_VERSION,
+        ClientIntention, PROTOCOL_VERSION,
     },
     resolver, ServerAddress,
 };
@@ -79,7 +79,7 @@ pub async fn ping_server_with_connection(
             protocol_version: PROTOCOL_VERSION,
             hostname: address.host.clone(),
             port: address.port,
-            intention: ConnectionProtocol::Status,
+            intention: ClientIntention::Status,
         }
         .get(),
     )
diff --git a/azalea-protocol/examples/handshake_proxy.rs b/azalea-protocol/examples/handshake_proxy.rs
index a7ac67c74..442db3869 100644
--- a/azalea-protocol/examples/handshake_proxy.rs
+++ b/azalea-protocol/examples/handshake_proxy.rs
@@ -16,7 +16,7 @@ use azalea_protocol::{
             },
             ServerboundStatusPacket,
         },
-        ConnectionProtocol, PROTOCOL_VERSION,
+        ClientIntention, PROTOCOL_VERSION,
     },
     read::ReadPacketError,
 };
@@ -95,7 +95,7 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
     match intent.intention {
         // If the client is pinging the proxy,
         // reply with the information below.
-        ConnectionProtocol::Status => {
+        ClientIntention::Status => {
             let mut conn = conn.status();
             loop {
                 match conn.read().await {
@@ -135,7 +135,7 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
         // wait for them to send the `Hello` packet to
         // log their username and uuid, then forward the
         // connection along to the proxy target.
-        ConnectionProtocol::Login => {
+        ClientIntention::Login => {
             let mut conn = conn.login();
             loop {
                 match conn.read().await {
@@ -169,8 +169,8 @@ async fn handle_connection(stream: TcpStream) -> anyhow::Result<()> {
                 }
             }
         }
-        _ => {
-            warn!("Client provided weird intent: {:?}", intent.intention);
+        ClientIntention::Transfer => {
+            warn!("Client attempted to join via transfer")
         }
     }
 
diff --git a/azalea-protocol/src/connect.rs b/azalea-protocol/src/connect.rs
index cf98e4194..691d25c06 100755
--- a/azalea-protocol/src/connect.rs
+++ b/azalea-protocol/src/connect.rs
@@ -61,7 +61,7 @@ pub struct WriteConnection<W: ProtocolPacket> {
 ///     resolver,
 ///     connect::Connection,
 ///     packets::{
-///         ConnectionProtocol, PROTOCOL_VERSION,
+///         ClientIntention, PROTOCOL_VERSION,
 ///         login::{
 ///             ClientboundLoginPacket,
 ///             serverbound_hello_packet::ServerboundHelloPacket,
@@ -82,7 +82,7 @@ pub struct WriteConnection<W: ProtocolPacket> {
 ///             protocol_version: PROTOCOL_VERSION,
 ///             hostname: resolved_address.ip().to_string(),
 ///             port: resolved_address.port(),
-///             intention: ConnectionProtocol::Login,
+///             intention: ClientIntention::Login,
 ///         }
 ///         .get(),
 ///     )
diff --git a/azalea-protocol/src/packets/handshaking/client_intention_packet.rs b/azalea-protocol/src/packets/handshaking/client_intention_packet.rs
index cac64a01e..82be621a3 100755
--- a/azalea-protocol/src/packets/handshaking/client_intention_packet.rs
+++ b/azalea-protocol/src/packets/handshaking/client_intention_packet.rs
@@ -1,4 +1,4 @@
-use crate::packets::ConnectionProtocol;
+use crate::packets::ClientIntention;
 use azalea_buf::McBuf;
 use azalea_protocol_macros::ServerboundHandshakePacket;
 use std::hash::Hash;
@@ -9,5 +9,5 @@ pub struct ClientIntentionPacket {
     pub protocol_version: i32,
     pub hostname: String,
     pub port: u16,
-    pub intention: ConnectionProtocol,
+    pub intention: ClientIntention,
 }
diff --git a/azalea-protocol/src/packets/mod.rs b/azalea-protocol/src/packets/mod.rs
index 63a0c1c93..044bb56c4 100755
--- a/azalea-protocol/src/packets/mod.rs
+++ b/azalea-protocol/src/packets/mod.rs
@@ -50,15 +50,44 @@ where
     fn write(&self, buf: &mut impl Write) -> Result<(), std::io::Error>;
 }
 
-impl azalea_buf::McBufReadable for ConnectionProtocol {
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ClientIntention {
+    Status = 1,
+    Login = 2,
+    Transfer = 3
+}
+
+impl TryFrom<i32> for ClientIntention {
+    type Error = ();
+
+    fn try_from(value: i32) -> Result<Self, Self::Error> {
+        match value {
+            1 => Ok(ClientIntention::Status),
+            2 => Ok(ClientIntention::Login),
+            3 => Ok(ClientIntention::Transfer),
+            _ => Err(()),
+        }
+    }
+}
+
+impl From<ClientIntention> for ConnectionProtocol {
+    fn from(intention: ClientIntention) -> Self {
+        match intention {
+            ClientIntention::Status => ConnectionProtocol::Status,
+            ClientIntention::Login | ClientIntention::Transfer => ConnectionProtocol::Login,
+        }
+    }
+}
+
+impl azalea_buf::McBufReadable for ClientIntention {
     fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> {
         let id = i32::var_read_from(buf)?;
-        ConnectionProtocol::from_i32(id).ok_or(BufReadError::UnexpectedEnumVariant { id })
+        id.try_into().map_err(|_| BufReadError::UnexpectedEnumVariant { id })
     }
 }
 
-impl McBufWritable for ConnectionProtocol {
+impl McBufWritable for ClientIntention {
     fn write_into(&self, buf: &mut impl Write) -> Result<(), std::io::Error> {
         (*self as i32).var_write_into(buf)
     }
-}
+}
\ No newline at end of file


Test patch: