aboutsummaryrefslogtreecommitdiff
path: root/azalea-protocol/src/connect.rs
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2023-09-21 11:16:29 -0500
committerGitHub <noreply@github.com>2023-09-21 11:16:29 -0500
commit7b3e2e4bf793466a351510c7fbbd08234e93bb0e (patch)
tree7177a919de9982d9e3c7f36a76d2025696f465b6 /azalea-protocol/src/connect.rs
parent83cce236145cdab1872a472a70943b669a880965 (diff)
downloadazalea-drasl-7b3e2e4bf793466a351510c7fbbd08234e93bb0e.tar.xz
1.20.2 (#99)
* add configuration state * start updating to 23w31a * implement a bit more of 23w31a * chunk batching * start adding configuration state * ioasfhjgsd * almost works * configuration state mostly implemented * handle other packets in configuration state and fix keepalive * cleanup, fix warnings * 23w32a * fix some doctests * 23w33a * 23w35a * 1.20.2-pre2 * fix system conflicts * 1.20.2-pre4 * make tests compile * tests pass * 1.20.2-rc2 * 1.20.2 * Revert "1.20.2" This reverts commit dd152fd265332ead333c919e585ded6d609d7468. * didn't mean to commit that code --------- Co-authored-by: mat <git@matdoes.dev>
Diffstat (limited to 'azalea-protocol/src/connect.rs')
-rwxr-xr-xazalea-protocol/src/connect.rs200
1 files changed, 133 insertions, 67 deletions
diff --git a/azalea-protocol/src/connect.rs b/azalea-protocol/src/connect.rs
index 5df1d874..9c573506 100755
--- a/azalea-protocol/src/connect.rs
+++ b/azalea-protocol/src/connect.rs
@@ -1,19 +1,23 @@
//! Connect to remote servers/clients.
+use crate::packets::configuration::{
+ ClientboundConfigurationPacket, ServerboundConfigurationPacket,
+};
use crate::packets::game::{ClientboundGamePacket, ServerboundGamePacket};
-use crate::packets::handshake::{ClientboundHandshakePacket, ServerboundHandshakePacket};
+use crate::packets::handshaking::{ClientboundHandshakePacket, ServerboundHandshakePacket};
use crate::packets::login::clientbound_hello_packet::ClientboundHelloPacket;
use crate::packets::login::{ClientboundLoginPacket, ServerboundLoginPacket};
use crate::packets::status::{ClientboundStatusPacket, ServerboundStatusPacket};
use crate::packets::ProtocolPacket;
-use crate::read::{read_packet, try_read_packet, ReadPacketError};
-use crate::write::write_packet;
+use crate::read::{deserialize_packet, read_raw_packet, try_read_raw_packet, ReadPacketError};
+use crate::write::{serialize_packet, write_raw_packet};
use azalea_auth::game_profile::GameProfile;
use azalea_auth::sessionserver::{ClientSessionServerError, ServerSessionServerError};
use azalea_crypto::{Aes128CfbDec, Aes128CfbEnc};
use bytes::BytesMut;
use log::{error, info};
use std::fmt::Debug;
+use std::io::Cursor;
use std::marker::PhantomData;
use std::net::SocketAddr;
use thiserror::Error;
@@ -22,20 +26,28 @@ use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf, ReuniteError};
use tokio::net::TcpStream;
use uuid::Uuid;
-/// The read half of a connection.
-pub struct ReadConnection<R: ProtocolPacket> {
+pub struct RawReadConnection {
pub read_stream: OwnedReadHalf,
pub buffer: BytesMut,
pub compression_threshold: Option<u32>,
pub dec_cipher: Option<Aes128CfbDec>,
- _reading: PhantomData<R>,
}
-/// The write half of a connection.
-pub struct WriteConnection<W: ProtocolPacket> {
+pub struct RawWriteConnection {
pub write_stream: OwnedWriteHalf,
pub compression_threshold: Option<u32>,
pub enc_cipher: Option<Aes128CfbEnc>,
+}
+
+/// The read half of a connection.
+pub struct ReadConnection<R: ProtocolPacket> {
+ pub raw: RawReadConnection,
+ _reading: PhantomData<R>,
+}
+
+/// The write half of a connection.
+pub struct WriteConnection<W: ProtocolPacket> {
+ pub raw: RawWriteConnection,
_writing: PhantomData<W>,
}
@@ -55,7 +67,7 @@ pub struct WriteConnection<W: ProtocolPacket> {
/// serverbound_hello_packet::ServerboundHelloPacket,
/// serverbound_key_packet::ServerboundKeyPacket
/// },
-/// handshake::client_intention_packet::ClientIntentionPacket
+/// handshaking::client_intention_packet::ClientIntentionPacket
/// }
/// };
///
@@ -82,7 +94,7 @@ pub struct WriteConnection<W: ProtocolPacket> {
/// conn.write(
/// ServerboundHelloPacket {
/// name: "bot".to_string(),
-/// profile_id: None,
+/// profile_id: uuid::Uuid::nil(),
/// }
/// .get(),
/// )
@@ -108,7 +120,7 @@ pub struct WriteConnection<W: ProtocolPacket> {
/// conn.set_compression_threshold(p.compression_threshold);
/// }
/// ClientboundLoginPacket::GameProfile(p) => {
-/// break (conn.game(), p.game_profile);
+/// break (conn.configuration(), p.game_profile);
/// }
/// ClientboundLoginPacket::LoginDisconnect(p) => {
/// eprintln!("login disconnect: {}", p.reason);
@@ -126,13 +138,9 @@ pub struct Connection<R: ProtocolPacket, W: ProtocolPacket> {
pub writer: WriteConnection<W>,
}
-impl<R> ReadConnection<R>
-where
- R: ProtocolPacket + Debug,
-{
- /// Read a packet from the stream.
- pub async fn read(&mut self) -> Result<R, Box<ReadPacketError>> {
- read_packet::<R, _>(
+impl RawReadConnection {
+ pub async fn read(&mut self) -> Result<Vec<u8>, Box<ReadPacketError>> {
+ read_raw_packet::<_>(
&mut self.read_stream,
&mut self.buffer,
self.compression_threshold,
@@ -141,10 +149,8 @@ where
.await
}
- /// Try to read a packet from the stream, or return Ok(None) if there's no
- /// packet.
- pub fn try_read(&mut self) -> Result<Option<R>, Box<ReadPacketError>> {
- try_read_packet::<R, _>(
+ pub fn try_read(&mut self) -> Result<Option<Vec<u8>>, Box<ReadPacketError>> {
+ try_read_raw_packet::<_>(
&mut self.read_stream,
&mut self.buffer,
self.compression_threshold,
@@ -152,14 +158,11 @@ where
)
}
}
-impl<W> WriteConnection<W>
-where
- W: ProtocolPacket + Debug,
-{
- /// Write a packet to the server.
- pub async fn write(&mut self, packet: W) -> std::io::Result<()> {
- if let Err(e) = write_packet(
- &packet,
+
+impl RawWriteConnection {
+ pub async fn write(&mut self, packet: &[u8]) -> std::io::Result<()> {
+ if let Err(e) = write_raw_packet(
+ packet,
&mut self.write_stream,
self.compression_threshold,
&mut self.enc_cipher,
@@ -184,6 +187,42 @@ where
}
}
+impl<R> ReadConnection<R>
+where
+ R: ProtocolPacket + Debug,
+{
+ /// Read a packet from the stream.
+ pub async fn read(&mut self) -> Result<R, Box<ReadPacketError>> {
+ let raw_packet = self.raw.read().await?;
+ deserialize_packet(&mut Cursor::new(raw_packet.as_slice()))
+ }
+
+ /// Try to read a packet from the stream, or return Ok(None) if there's no
+ /// packet.
+ pub fn try_read(&mut self) -> Result<Option<R>, Box<ReadPacketError>> {
+ let Some(raw_packet) = self.raw.try_read()? else {
+ return Ok(None);
+ };
+ Ok(Some(deserialize_packet(&mut Cursor::new(
+ raw_packet.as_slice(),
+ ))?))
+ }
+}
+impl<W> WriteConnection<W>
+where
+ W: ProtocolPacket + Debug,
+{
+ /// Write a packet to the server.
+ pub async fn write(&mut self, packet: W) -> std::io::Result<()> {
+ self.raw.write(&serialize_packet(&packet).unwrap()).await
+ }
+
+ /// End the connection.
+ pub async fn shutdown(&mut self) -> std::io::Result<()> {
+ self.raw.shutdown().await
+ }
+}
+
impl<R, W> Connection<R, W>
where
R: ProtocolPacket + Debug,
@@ -230,16 +269,20 @@ impl Connection<ClientboundHandshakePacket, ServerboundHandshakePacket> {
Ok(Connection {
reader: ReadConnection {
- read_stream,
- buffer: BytesMut::new(),
- compression_threshold: None,
- dec_cipher: None,
+ raw: RawReadConnection {
+ read_stream,
+ buffer: BytesMut::new(),
+ compression_threshold: None,
+ dec_cipher: None,
+ },
_reading: PhantomData,
},
writer: WriteConnection {
- write_stream,
- compression_threshold: None,
- enc_cipher: None,
+ raw: RawWriteConnection {
+ write_stream,
+ compression_threshold: None,
+ enc_cipher: None,
+ },
_writing: PhantomData,
},
})
@@ -267,11 +310,11 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
pub fn set_compression_threshold(&mut self, threshold: i32) {
// if you pass a threshold of less than 0, compression is disabled
if threshold >= 0 {
- self.reader.compression_threshold = Some(threshold as u32);
- self.writer.compression_threshold = Some(threshold as u32);
+ self.reader.raw.compression_threshold = Some(threshold as u32);
+ self.writer.raw.compression_threshold = Some(threshold as u32);
} else {
- self.reader.compression_threshold = None;
- self.writer.compression_threshold = None;
+ self.reader.raw.compression_threshold = None;
+ self.writer.raw.compression_threshold = None;
}
}
@@ -279,14 +322,16 @@ impl Connection<ClientboundLoginPacket, ServerboundLoginPacket> {
/// the same for both reading and writing.
pub fn set_encryption_key(&mut self, key: [u8; 16]) {
let (enc_cipher, dec_cipher) = azalea_crypto::create_cipher(&key);
- self.reader.dec_cipher = Some(dec_cipher);
- self.writer.enc_cipher = Some(enc_cipher);
+ self.reader.raw.dec_cipher = Some(dec_cipher);
+ self.writer.raw.enc_cipher = Some(enc_cipher);
}
- /// Change our state from login to game. This is the state that's used when
- /// you're actually in the game.
+ /// Change our state from login to configuration. This is the state where
+ /// the server sends us the registries and resource pack and stuff.
#[must_use]
- pub fn game(self) -> Connection<ClientboundGamePacket, ServerboundGamePacket> {
+ pub fn configuration(
+ self,
+ ) -> Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
Connection::from(self)
}
@@ -384,11 +429,11 @@ impl Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
pub fn set_compression_threshold(&mut self, threshold: i32) {
// if you pass a threshold of less than 0, compression is disabled
if threshold >= 0 {
- self.reader.compression_threshold = Some(threshold as u32);
- self.writer.compression_threshold = Some(threshold as u32);
+ self.reader.raw.compression_threshold = Some(threshold as u32);
+ self.writer.raw.compression_threshold = Some(threshold as u32);
} else {
- self.reader.compression_threshold = None;
- self.writer.compression_threshold = None;
+ self.reader.raw.compression_threshold = None;
+ self.writer.raw.compression_threshold = None;
}
}
@@ -396,8 +441,8 @@ impl Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
/// the same for both reading and writing.
pub fn set_encryption_key(&mut self, key: [u8; 16]) {
let (enc_cipher, dec_cipher) = azalea_crypto::create_cipher(&key);
- self.reader.dec_cipher = Some(dec_cipher);
- self.writer.enc_cipher = Some(enc_cipher);
+ self.reader.raw.dec_cipher = Some(dec_cipher);
+ self.writer.raw.enc_cipher = Some(enc_cipher);
}
/// Change our state from login to game. This is the state that's used when
@@ -421,6 +466,25 @@ impl Connection<ServerboundLoginPacket, ClientboundLoginPacket> {
}
}
+impl Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
+ /// Change our state from configuration to game. This is the state that's
+ /// used when the client is actually in the world.
+ #[must_use]
+ pub fn game(self) -> Connection<ClientboundGamePacket, ServerboundGamePacket> {
+ Connection::from(self)
+ }
+}
+
+impl Connection<ClientboundGamePacket, ServerboundGamePacket> {
+ /// Change our state back to configuration.
+ #[must_use]
+ pub fn configuration(
+ self,
+ ) -> Connection<ClientboundConfigurationPacket, ServerboundConfigurationPacket> {
+ Connection::from(self)
+ }
+}
+
// rust doesn't let us implement From because allegedly it conflicts with
// `core`'s "impl<T> From<T> for T" so we do this instead
impl<R1, W1> Connection<R1, W1>
@@ -438,16 +502,11 @@ where
{
Connection {
reader: ReadConnection {
- read_stream: connection.reader.read_stream,
- buffer: connection.reader.buffer,
- compression_threshold: connection.reader.compression_threshold,
- dec_cipher: connection.reader.dec_cipher,
+ raw: connection.reader.raw,
_reading: PhantomData,
},
writer: WriteConnection {
- compression_threshold: connection.writer.compression_threshold,
- write_stream: connection.writer.write_stream,
- enc_cipher: connection.writer.enc_cipher,
+ raw: connection.writer.raw,
_writing: PhantomData,
},
}
@@ -459,16 +518,20 @@ where
Connection {
reader: ReadConnection {
- read_stream,
- buffer: BytesMut::new(),
- compression_threshold: None,
- dec_cipher: None,
+ raw: RawReadConnection {
+ read_stream,
+ buffer: BytesMut::new(),
+ compression_threshold: None,
+ dec_cipher: None,
+ },
_reading: PhantomData,
},
writer: WriteConnection {
- write_stream,
- compression_threshold: None,
- enc_cipher: None,
+ raw: RawWriteConnection {
+ write_stream,
+ compression_threshold: None,
+ enc_cipher: None,
+ },
_writing: PhantomData,
},
}
@@ -476,6 +539,9 @@ where
/// Convert from a `Connection` into a `TcpStream`. Useful for servers.
pub fn unwrap(self) -> Result<TcpStream, ReuniteError> {
- self.reader.read_stream.reunite(self.writer.write_stream)
+ self.reader
+ .raw
+ .read_stream
+ .reunite(self.writer.raw.write_stream)
}
}