diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2023-09-21 11:16:29 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-21 11:16:29 -0500 |
| commit | 7b3e2e4bf793466a351510c7fbbd08234e93bb0e (patch) | |
| tree | 7177a919de9982d9e3c7f36a76d2025696f465b6 /azalea-protocol/src/connect.rs | |
| parent | 83cce236145cdab1872a472a70943b669a880965 (diff) | |
| download | azalea-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-x | azalea-protocol/src/connect.rs | 200 |
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) } } |
