diff --git a/Cargo.lock b/Cargo.lock
index cdb1267..1684e11 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1165,9 +1165,9 @@ checksum = "502d53007c02d7605a05df1c1a73ee436952781653da5d0bf57ad608f66932c1"
[[package]]
name = "syn"
-version = "1.0.35"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb7f4c519df8c117855e19dd8cc851e89eb746fe7a73f0157e0d95fdec5369b0"
+checksum = "4cdb98bcb1f9d81d07b536179c269ea15999b5d14ea958196413869445bb5250"
dependencies = [
"proc-macro2",
"quote",
@@ -1186,6 +1186,12 @@ dependencies = [
"unicode-xid",
]
+[[package]]
+name = "take_mut"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60"
+
[[package]]
name = "tempfile"
version = "3.1.0"
@@ -1270,6 +1276,7 @@ dependencies = [
"serde",
"serde_json",
"sha-1",
+ "take_mut",
"tokio",
"uuid",
]
diff --git a/Cargo.toml b/Cargo.toml
index 768deba..75b0d84 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -32,6 +32,7 @@ async-trait = "0.1.36"
clap = { version = "2.33.1", features = ["yaml"] }
serde = { version = "1.0.114", features = ["derive"] }
serde_json = "1.0.56"
+take_mut = "0.2.2"
tokio = { version = "0.2.22", features = ["io-util", "macros", "net", "tcp", "rt-threaded"] }
uuid = { version = "0.8", features = ["serde"] }
diff --git a/rustfmt.toml b/rustfmt.toml
index 2b854ee..d070ec0 100644
--- a/rustfmt.toml
+++ b/rustfmt.toml
@@ -5,4 +5,3 @@ newline_style = "Native"
normalize_comments = true
normalize_doc_attributes = true
use_try_shorthand = true
-wrap_comments = true
diff --git a/src/main.rs b/src/main.rs
index 5657fce..aa13869 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -5,7 +5,7 @@
mod net;
use crate::net::chat::Chat;
-use crate::net::connection::Connection;
+use crate::net::packet_stream::{Client, PacketStream, PacketStreamMaps};
use crate::net::protocol::state::handshake::Handshake;
use crate::net::protocol::state::login::Login;
use crate::net::protocol::state::play::Play;
@@ -55,7 +55,7 @@ async fn listen(mut listener: TcpListener) {
}
async fn accept_connection(socket: TcpStream) {
- let con = Connection::new(socket);
+ let con = PacketStream::new(Box::new(socket));
eprintln!("Client connected.");
match interact_handshake(con).await {
@@ -72,10 +72,10 @@ fn mk_err>(str: S) -> io::Result {
Err(io::Error::new(io::ErrorKind::Other, str.borrow().to_string()))
}
-async fn interact_handshake(mut con: Connection) -> io::Result<()> {
+async fn interact_handshake(mut con: PacketStream) -> io::Result<()> {
use crate::net::protocol::state::handshake::*;
- match con.read().await? {
+ match con.recieve().await? {
Serverbound::HandshakePkt(handshake) => {
use HandshakeNextState::*;
@@ -87,13 +87,13 @@ async fn interact_handshake(mut con: Connection) -> io::Result<()> {
}
}
-async fn interact_status(mut con: Connection) -> io::Result<()> {
+async fn interact_status(mut con: PacketStream) -> io::Result<()> {
use crate::net::protocol::state::status::*;
loop {
- match con.read().await? {
+ match con.recieve().await? {
Serverbound::Request(Request {}) => {
- con.write(&Clientbound::Response(Response {
+ con.send(&Clientbound::Response(Response {
data: ResponseData {
version: ResponseVersion {
name: "1.16.1".to_string(),
@@ -113,7 +113,7 @@ async fn interact_status(mut con: Connection) -> io::Result<()> {
.await?;
},
Serverbound::Ping(ping) => {
- con.write(&Clientbound::Pong(Pong { payload: ping.payload })).await?;
+ con.send(&Clientbound::Pong(Pong { payload: ping.payload })).await?;
// The status ping is now over so the server ends the connection.
return Ok(());
@@ -122,13 +122,13 @@ async fn interact_status(mut con: Connection) -> io::Result<()> {
}
}
-async fn interact_login(mut con: Connection) -> io::Result<()> {
+async fn interact_login(mut con: PacketStream) -> io::Result<()> {
use crate::net::protocol::state::login::*;
- let name = match con.read().await? {
+ let name = match con.recieve().await? {
Serverbound::LoginStart(login_start) => login_start.name,
_ => {
- con.write(&Clientbound::Disconnect(Disconnect {
+ con.send(&Clientbound::Disconnect(Disconnect {
reason: Chat {
text: "Unexpected packet (expected Login Start).".to_string(),
},
@@ -164,14 +164,14 @@ async fn interact_login(mut con: Connection) -> io::Result<()> {
let server_id = "";
- con.write(&Clientbound::EncryptionRequest(EncryptionRequest {
+ con.send(&Clientbound::EncryptionRequest(EncryptionRequest {
server_id: server_id.to_string().into_boxed_str(),
public_key: public_key.clone().into_boxed_slice(),
verify_token: verify_token.clone().into_boxed_slice(),
}))
.await?;
- let secret = match con.read().await? {
+ let secret = match con.recieve().await? {
Serverbound::EncryptionResponse(encryption_response) => {
let token = key
.decrypt(PaddingScheme::PKCS1v15Encrypt, &encryption_response.verify_token)
@@ -188,7 +188,7 @@ async fn interact_login(mut con: Connection) -> io::Result<()> {
},
};
- con = con.set_encryption(&secret).expect("Failed to set encryption.");
+ con.enable_encryption(&secret).expect("Failed to set encryption.");
#[cfg(feature = "authentication")]
{
@@ -224,9 +224,15 @@ async fn interact_login(mut con: Connection) -> io::Result<()> {
}
#[cfg(feature = "compression")]
- con.set_compression(Some(64)).await?;
+ {
+ con.send(&Clientbound::SetCompression(SetCompression {
+ threshold: crate::net::serialize::VarInt(64),
+ }))
+ .await?;
+ con.set_compression(Some(64));
+ }
- con.write(&Clientbound::LoginSuccess(LoginSuccess {
+ con.send(&Clientbound::LoginSuccess(LoginSuccess {
uuid: uuid::Uuid::nil(),
username: name,
}))
@@ -235,10 +241,10 @@ async fn interact_login(mut con: Connection) -> io::Result<()> {
interact_play(con.into_play()).await
}
-async fn interact_play(mut con: Connection) -> io::Result<()> {
+async fn interact_play(mut con: PacketStream) -> io::Result<()> {
use crate::net::protocol::state::play::*;
- con.write(&Clientbound::Disconnect(Disconnect {
+ con.send(&Clientbound::Disconnect(Disconnect {
reason: Chat {
text: "Goodbye!".to_string(),
},
diff --git a/src/net/connection.rs b/src/net/connection.rs
deleted file mode 100644
index 2117934..0000000
--- a/src/net/connection.rs
+++ /dev/null
@@ -1,124 +0,0 @@
-mod packet_format;
-mod stream;
-
-use crate::net::connection::packet_format::default::DefaultPacketFormat;
-use crate::net::connection::packet_format::PacketFormat;
-use crate::net::connection::stream::Stream;
-use crate::net::protocol::packet_map::PacketMap;
-use crate::net::protocol::state::handshake::Handshake;
-use crate::net::protocol::state::login::Login;
-use crate::net::protocol::state::play::Play;
-use crate::net::protocol::state::status::Status;
-use crate::net::protocol::state::ProtocolState;
-use std::io;
-use std::marker::PhantomData;
-use tokio::io::BufStream;
-use tokio::net::TcpStream;
-
-pub struct Connection {
- rw: Box,
- fmt: Box,
- st: PhantomData,
-}
-
-impl Connection {
- pub async fn write(&mut self, pkt: &St::Clientbound) -> io::Result<()> {
- // Turn the packet into bytes.
- let mut contents = Vec::new();
- pkt.write(&mut contents);
-
- // Send the packet with the appropriate header.
- self.fmt.send(&mut self.rw, &contents).await
- }
-
- pub async fn read(&mut self) -> io::Result {
- use crate::net::serialize::VecPacketDeserializer;
-
- let buf = self.fmt.recieve(&mut self.rw).await?;
-
- St::Serverbound::read(&mut VecPacketDeserializer::new(buf.as_ref()))
- .map_err(|err| io::Error::new(io::ErrorKind::Other, err))
- }
-
- fn into_state(self) -> Connection {
- Connection {
- rw: self.rw,
- fmt: self.fmt,
- st: PhantomData,
- }
- }
-
- #[allow(dead_code)]
- pub fn into_disconnected(self) -> Connection {
- self.into_state()
- }
-}
-
-impl Connection {
- pub fn new(stream: TcpStream) -> Self {
- Connection {
- rw: Box::new(BufStream::new(stream)),
- fmt: Box::new(DefaultPacketFormat),
- st: PhantomData,
- }
- }
-
- pub fn into_status(self) -> Connection {
- self.into_state()
- }
-
- pub fn into_login(self) -> Connection {
- self.into_state()
- }
-}
-
-impl Connection {
- #[cfg(feature = "compression")]
- pub async fn set_compression(&mut self, threshold: Option) -> io::Result<()> {
- use crate::net::connection::packet_format::compressed::CompressedPacketFormat;
- use crate::net::protocol::state::login::{Clientbound, SetCompression};
- use crate::net::serialize::VarInt;
-
- // Tell the client about the new compression threshold,
- // using a packet compressed with the old compression threshold.
- self.write(&Clientbound::SetCompression(SetCompression {
- // A negative threshold will disable compression.
- threshold: VarInt(threshold.map(|x| x as i32).unwrap_or(-1)),
- }))
- .await?;
-
- // Further packets will use the new compression threshold.
- match threshold {
- Some(threshold) => {
- self.fmt = Box::new(CompressedPacketFormat::new(threshold as usize));
- },
- None => {
- self.fmt = Box::new(DefaultPacketFormat);
- },
- }
-
- Ok(())
- }
-
- /// WARNING: This function is not idempontent.
- /// Calling it twice will result in the underlying stream getting encrypted
- /// twice.
- #[cfg(feature = "encryption")]
- pub fn set_encryption(self, secret: &[u8]) -> Result {
- use crate::net::connection::stream::encrypted::EncryptedStream;
- use cfb8::stream_cipher::NewStreamCipher;
- use cfb8::Cfb8;
-
- let cipher: Cfb8 = Cfb8::new_var(secret, secret).map_err(|err| err.to_string())?;
-
- Ok(Connection {
- rw: Box::new(EncryptedStream::new(self.rw, cipher)),
- fmt: self.fmt,
- st: PhantomData,
- })
- }
-
- pub fn into_play(self) -> Connection {
- self.into_state()
- }
-}
diff --git a/src/net/connection/packet_format.rs b/src/net/connection/packet_format.rs
deleted file mode 100644
index 0c13955..0000000
--- a/src/net/connection/packet_format.rs
+++ /dev/null
@@ -1,36 +0,0 @@
-#[cfg(feature = "compression")]
-pub mod compressed;
-pub mod default;
-
-use async_trait::async_trait;
-use std::io;
-use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
-
-pub type Reader = dyn AsyncRead + Unpin + Send;
-pub type Writer = dyn AsyncWrite + Unpin + Send;
-
-#[async_trait]
-pub trait PacketFormat: Send + Sync {
- async fn recieve(&self, src: &mut Reader) -> io::Result>;
- async fn send(&self, dest: &mut Writer, data: &[u8]) -> io::Result<()>;
-}
-
-/// A completely arbitrary limitation on the maximum size of a recieved packet.
-pub const MAX_PACKET_SIZE: usize = 35565;
-
-pub async fn read_varint(src: &mut Reader) -> io::Result<(usize, i32)> {
- let mut num_read: usize = 0;
- let mut acc = 0;
- while num_read < 5 {
- let byte = src.read_u8().await?;
- acc |= ((byte & 0b01111111) as i32) << (num_read * 7);
-
- num_read += 1;
-
- if byte & 0b10000000 == 0 {
- return Ok((num_read, acc));
- }
- }
-
- Err(io::Error::new(io::ErrorKind::Other, "VarInt was too long.".to_string()))
-}
diff --git a/src/net/mod.rs b/src/net/mod.rs
index fca7f30..7d3a150 100644
--- a/src/net/mod.rs
+++ b/src/net/mod.rs
@@ -1,4 +1,4 @@
pub mod chat;
-pub mod connection;
+pub mod packet_stream;
pub mod protocol;
pub mod serialize;
diff --git a/src/net/packet_stream.rs b/src/net/packet_stream.rs
new file mode 100644
index 0000000..14379bd
--- /dev/null
+++ b/src/net/packet_stream.rs
@@ -0,0 +1,237 @@
+mod packet_format;
+mod stream;
+
+use crate::net::packet_stream::packet_format::{AutoPacketFormat, PacketFormat};
+use crate::net::packet_stream::stream::Stream;
+use crate::net::protocol::packet_map::PacketMap;
+use crate::net::protocol::state::handshake::Handshake;
+use crate::net::protocol::state::login::Login;
+use crate::net::protocol::state::play::Play;
+use crate::net::protocol::state::status::Status;
+use crate::net::protocol::state::ProtocolState;
+use async_trait::async_trait;
+use std::io;
+use std::marker::PhantomData;
+
+/// Prevents outside types from implementing a trait.
+mod sealed {
+ pub trait Sealed {}
+}
+use sealed::Sealed;
+
+/// A remote end of a connection: either a client or server.
+///
+/// It is impossible to implement this trait for other types.
+pub trait Remote: Sealed {}
+/// The remote end of a connection is a client.
+pub enum Client {}
+/// The remote end of a connection is a server.
+pub enum Server {}
+impl Sealed for Client {}
+impl Sealed for Server {}
+impl Remote for Client {}
+impl Remote for Server {}
+
+/// A packet compression theshold (i.e. the minimum packet size to compress).
+#[cfg(feature = "compression")]
+pub type CompressionThreshold = usize;
+#[cfg(not(feature = "compression"))]
+pub type CompressionThreshold = !;
+
+/// A shared secret used for packet encryption.
+#[cfg(feature = "encryption")]
+pub type SharedSecret = [u8];
+#[cfg(not(feature = "encryption"))]
+pub type SharedSecret = !;
+
+/// A stream of packets.
+///
+/// The type parameters are used to ensure using the type system
+/// that you can only send and recieve the correct type of packets.
+pub struct PacketStream {
+ inner: Box,
+ compression_threshold: Option,
+ encryption_enabled: bool,
+ remote: PhantomData,
+ state: PhantomData,
+}
+
+impl PacketStream {
+ /// Coerce the packet stream to any protocol state of your choosing.
+ /// This can be used to break PacketStream's type-enforced correctness guarantees,
+ /// so it should only be used internally.
+ ///
+ /// The purpose of this function is to reduce code duplication
+ /// for all the pre-defined safe protocol state transitions.
+ fn into_state(self) -> PacketStream {
+ PacketStream {
+ inner: self.inner,
+ compression_threshold: self.compression_threshold,
+ encryption_enabled: self.encryption_enabled,
+ remote: self.remote,
+ state: PhantomData,
+ }
+ }
+
+ /// Send any packet over the stream, ignoring the declared ProtocolState.
+ /// This can be used to break PacketStream's type-enforced correctness guarantees,
+ /// so it should only be used internally.
+ ///
+ /// The purpose of this function is to reduce code duplication
+ /// while implementing [`PacketStreamMaps`]'s send and recieve;
+ /// the sending and recieving code is always going to be the same,
+ /// but due to some shortcomings of Rust's type system
+ /// (specifically, because there's no way to approximate type-level functions;
+ /// in Haskell you could use multi-parameter type classes or type families),
+ /// we can't implement this generically safely over Remote/ProtocolState combinations.
+ async fn send_generic(&mut self, pkt: &Pkt) -> io::Result<()> {
+ let mut contents = Vec::new();
+ pkt.write(&mut contents);
+
+ AutoPacketFormat(self.compression_threshold)
+ .send(&mut self.inner, &contents)
+ .await
+ }
+
+ /// Recieve any packet from the stream, ignoring the declared ProtocolState.
+ /// This can be used to break PacketStream's type-enforced correctness guarantees,
+ /// so it should only be used internally.
+ ///
+ /// The purpose of this function is to reduce code duplication
+ /// while implementing [`PacketStreamMaps`]'s send and recieve;
+ /// the sending and recieving code is always going to be the same,
+ /// but due to some shortcomings of Rust's type system
+ /// (specifically, because there's no way to approximate type-level functions;
+ /// in Haskell you could use multi-parameter type classes or type families),
+ /// we can't implement this generically safely over Remote/ProtocolState combinations.
+ async fn recieve_generic(&mut self) -> io::Result {
+ use crate::net::serialize::VecPacketDeserializer;
+
+ let buf = AutoPacketFormat(self.compression_threshold)
+ .recieve(&mut self.inner)
+ .await?;
+
+ Pkt::read(&mut VecPacketDeserializer::new(buf.as_ref()))
+ .map_err(|err| io::Error::new(io::ErrorKind::Other, err))
+ }
+
+ /// Transition to the protocol disconnected state,
+ /// which prevents reading or writing any more packets.
+ #[allow(dead_code)]
+ pub fn into_disconnected(self) -> PacketStream {
+ self.into_state()
+ }
+}
+
+/// A valid combination of inbound and outbound packet maps,
+/// which are determined by the protocol state and remote.
+#[async_trait]
+pub trait PacketStreamMaps: Sealed {
+ /// The kind of packets that can be recieved from the remote.
+ type Inbound: PacketMap;
+ /// The kind of packets that can be sent to the remote.
+ type Outbound: PacketMap;
+
+ /// Recieve a packet from the remote.
+ async fn recieve(&mut self) -> io::Result;
+
+ /// Send a packet to the remote.
+ async fn send(&mut self, pkt: &Self::Outbound) -> io::Result<()>;
+}
+
+impl Sealed for PacketStream {}
+#[async_trait]
+impl PacketStreamMaps for PacketStream {
+ type Inbound = St::Serverbound;
+ type Outbound = St::Clientbound;
+
+ async fn recieve(&mut self) -> io::Result {
+ self.recieve_generic().await
+ }
+
+ async fn send(&mut self, pkt: &Self::Outbound) -> io::Result<()> {
+ self.send_generic(pkt).await
+ }
+}
+
+impl Sealed for PacketStream {}
+#[async_trait]
+impl PacketStreamMaps for PacketStream {
+ type Inbound = St::Clientbound;
+ type Outbound = St::Serverbound;
+
+ async fn recieve(&mut self) -> io::Result {
+ self.recieve_generic().await
+ }
+
+ async fn send(&mut self, pkt: &Self::Outbound) -> io::Result<()> {
+ self.send_generic(pkt).await
+ }
+}
+
+impl PacketStream {
+ pub fn new(inner: Box) -> Self {
+ Self {
+ inner,
+ compression_threshold: None,
+ encryption_enabled: false,
+ remote: PhantomData,
+ state: PhantomData,
+ }
+ }
+
+ /// Transition to the protocol status state.
+ pub fn into_status(self) -> PacketStream {
+ self.into_state()
+ }
+
+ /// Transition to the protocol login state.
+ pub fn into_login(self) -> PacketStream {
+ self.into_state()
+ }
+}
+
+#[cfg(feature = "encryption")]
+pub type InvalidKeyNonceLength = cfb8::stream_cipher::InvalidKeyNonceLength;
+#[cfg(not(feature = "encryption"))]
+pub type InvalidKeyNonceLength = !;
+
+impl PacketStream {
+ /// Transition to the protocol play state.
+ pub fn into_play(self) -> PacketStream {
+ self.into_state()
+ }
+
+ /// Set the compression threshold, i.e. the minimum size of packet to compress.
+ /// Setting the compression threshold to None disables compression.
+ pub fn set_compression(&mut self, threshold: Option) {
+ self.compression_threshold = threshold;
+ }
+
+ // I want to leave the function available even when encryption is disabled
+ // so that users of PacketStream can use the `Option` pattern
+ // to support encryption configuration without needing config features everywhere.
+
+ /// Sets the shared secret, which enables encryption.
+ /// Trying to enable encryption twice is an error, and the function will panic.
+ pub fn enable_encryption(&mut self, shared_secret: &SharedSecret) -> Result<(), InvalidKeyNonceLength> {
+ if self.encryption_enabled {
+ panic!("Tried to enable encryption twice!");
+ }
+
+ #[cfg(feature = "encryption")]
+ {
+ use crate::net::packet_stream::stream::encrypted::EncryptedStream;
+ use cfb8::stream_cipher::NewStreamCipher;
+ use cfb8::Cfb8;
+
+ let cipher: Cfb8 = Cfb8::new_var(shared_secret, shared_secret)?;
+ take_mut::take(&mut self.inner, |inner| Box::new(EncryptedStream::new(inner, cipher)));
+
+ Ok(())
+ }
+
+ #[cfg(not(feature = "encryption"))]
+ *shared_secret
+ }
+}
diff --git a/src/net/packet_stream/packet_format.rs b/src/net/packet_stream/packet_format.rs
new file mode 100644
index 0000000..5a7d013
--- /dev/null
+++ b/src/net/packet_stream/packet_format.rs
@@ -0,0 +1,75 @@
+#[cfg(feature = "compression")]
+mod compressed;
+mod default;
+
+use crate::net::packet_stream::packet_format::default::DefaultPacketFormat;
+use crate::net::packet_stream::CompressionThreshold;
+use async_trait::async_trait;
+use std::io;
+use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite};
+
+pub type Reader = dyn AsyncRead + Unpin + Send;
+pub type Writer = dyn AsyncWrite + Unpin + Send;
+
+/// A packet format describes how to read a packet header and retrieve its data.
+#[async_trait]
+pub trait PacketFormat: Send + Sync {
+ /// Recieve the bytes of a packet's body (its id and header) from the provided stream.
+ /// This involves reading the packet header and performing decompression if necessary.
+ async fn recieve(&self, src: &mut Reader) -> io::Result>;
+
+ /// Send the bytes of a packet's body (its id and header) through the provided stream.
+ /// This involves writing the packet header and performing compression if necessary.
+ async fn send(&self, dest: &mut Writer, data: &[u8]) -> io::Result<()>;
+}
+
+pub struct AutoPacketFormat(pub Option);
+
+#[async_trait]
+impl PacketFormat for AutoPacketFormat {
+ async fn recieve(&self, src: &mut Reader) -> io::Result> {
+ match self.0 {
+ #[cfg(not(feature = "compression"))]
+ Some(x) => x,
+ #[cfg(feature = "compression")]
+ Some(threshold) => {
+ use crate::net::packet_stream::packet_format::compressed::CompressedPacketFormat;
+ CompressedPacketFormat(threshold).recieve(src).await
+ },
+ None => DefaultPacketFormat.recieve(src).await,
+ }
+ }
+
+ async fn send(&self, dest: &mut Writer, data: &[u8]) -> io::Result<()> {
+ match self.0 {
+ #[cfg(not(feature = "compression"))]
+ Some(x) => x,
+ #[cfg(feature = "compression")]
+ Some(threshold) => {
+ use crate::net::packet_stream::packet_format::compressed::CompressedPacketFormat;
+ CompressedPacketFormat(threshold).send(dest, data).await
+ },
+ None => DefaultPacketFormat.send(dest, data).await,
+ }
+ }
+}
+
+/// A completely arbitrary limitation on the maximum size of a recieved packet.
+pub const MAX_PACKET_SIZE: usize = 35565;
+
+async fn read_varint(src: &mut Reader) -> io::Result<(usize, i32)> {
+ let mut num_read: usize = 0;
+ let mut acc = 0;
+ while num_read < 5 {
+ let byte = src.read_u8().await?;
+ acc |= ((byte & 0b01111111) as i32) << (num_read * 7);
+
+ num_read += 1;
+
+ if byte & 0b10000000 == 0 {
+ return Ok((num_read, acc));
+ }
+ }
+
+ Err(io::Error::new(io::ErrorKind::Other, "VarInt was too long.".to_string()))
+}
diff --git a/src/net/connection/packet_format/compressed.rs b/src/net/packet_stream/packet_format/compressed.rs
similarity index 94%
rename from src/net/connection/packet_format/compressed.rs
rename to src/net/packet_stream/packet_format/compressed.rs
index d8e6414..cbc9aea 100644
--- a/src/net/connection/packet_format/compressed.rs
+++ b/src/net/packet_stream/packet_format/compressed.rs
@@ -1,17 +1,10 @@
-use crate::net::connection::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
+use crate::net::packet_stream::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
use async_trait::async_trait;
use std::boxed::Box;
use std::io;
-pub struct CompressedPacketFormat {
- threshold: usize,
-}
-
-impl CompressedPacketFormat {
- pub fn new(threshold: usize) -> Self {
- Self { threshold }
- }
-}
+#[repr(transparent)]
+pub struct CompressedPacketFormat(pub usize);
// A compressed header is in this format:
//
@@ -76,7 +69,7 @@ impl PacketFormat for CompressedPacketFormat {
// If the length of the uncompressed data exceeds the threshold,
// then we will compress this packet.
- if data.len() >= self.threshold {
+ if data.len() >= self.0 {
// Now we compress the data.
use flate2::{Compress, FlushCompress};
diff --git a/src/net/connection/packet_format/default.rs b/src/net/packet_stream/packet_format/default.rs
similarity index 91%
rename from src/net/connection/packet_format/default.rs
rename to src/net/packet_stream/packet_format/default.rs
index d93b77f..ec61830 100644
--- a/src/net/connection/packet_format/default.rs
+++ b/src/net/packet_stream/packet_format/default.rs
@@ -1,4 +1,4 @@
-use crate::net::connection::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
+use crate::net::packet_stream::packet_format::{read_varint, PacketFormat, Reader, Writer, MAX_PACKET_SIZE};
use async_trait::async_trait;
use std::boxed::Box;
use std::io;
diff --git a/src/net/connection/stream.rs b/src/net/packet_stream/stream.rs
similarity index 100%
rename from src/net/connection/stream.rs
rename to src/net/packet_stream/stream.rs
diff --git a/src/net/connection/stream/encrypted.rs b/src/net/packet_stream/stream/encrypted.rs
similarity index 98%
rename from src/net/connection/stream/encrypted.rs
rename to src/net/packet_stream/stream/encrypted.rs
index 3ba0bf7..8066026 100644
--- a/src/net/connection/stream/encrypted.rs
+++ b/src/net/packet_stream/stream/encrypted.rs
@@ -1,4 +1,4 @@
-use crate::net::connection::stream::Stream;
+use crate::net::packet_stream::stream::Stream;
use aes::Aes128;
use cfb8::stream_cipher::StreamCipher;
use cfb8::Cfb8;
diff --git a/src/net/protocol/state.rs b/src/net/protocol/state.rs
index 849b38d..7fb1803 100644
--- a/src/net/protocol/state.rs
+++ b/src/net/protocol/state.rs
@@ -5,7 +5,7 @@ pub mod status;
use crate::net::protocol::packet_map::PacketMap;
-pub trait ProtocolState {
+pub trait ProtocolState: Send + Sync {
type Clientbound: PacketMap;
type Serverbound: PacketMap;
}