From 7a78fccd7dd97ea67ac80b83ff42d1ad4d21f6aa Mon Sep 17 00:00:00 2001 From: MeexReay Date: Thu, 22 Aug 2024 13:03:41 +0300 Subject: [PATCH] atomic_compression feature --- Cargo.toml | 8 ++- README.md | 17 +++++++ src/lib.rs | 147 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 134 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3afc0ed..c71f3f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,10 @@ version = "0.1.15" edition = "2021" [dependencies] -flate2 = "1.0.30" -bytebuffer = "2.2.0" +flate2 = "1.0.32" +bytebuffer = "2.3.0" uuid = "1.10.0" + +[features] +# default = [ "atomic_compression" ] +atomic_compression = [] \ No newline at end of file diff --git a/README.md b/README.md index 9895c69..e81bc4b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,23 @@ all types of packets you can find on [wiki.vg](https://wiki.vg/) \ [crates](https://crates.io/crates/rust_mc_proto) [github](https://github.com/MeexReay/rust_mc_proto) +## setup + +stable + +```toml +rust_mc_proto = "0.1.15" +``` + +unstable + +```toml +rust_mc_proto = { git = "https://github.com/MeexReay/rust_mc_proto" } +``` + +features: +- atomic_compression (default) + ## how to use it for reference: diff --git a/src/lib.rs b/src/lib.rs index f0b9cd9..99fa468 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,10 +17,13 @@ use std::{ fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, - sync::{ - atomic::{AtomicUsize, Ordering}, - Arc, - }, + usize, +}; + +#[cfg(feature = "atomic_compression")] +use sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, }; /// Minecraft protocol error @@ -49,7 +52,10 @@ impl Error for ProtocolError {} /// Minecraft connection, wrapper for stream with compression pub struct MinecraftConnection { stream: T, + #[cfg(feature = "atomic_compression")] compression: Arc, + #[cfg(not(feature = "atomic_compression"))] + compression: Option, compression_type: u32, } @@ -71,7 +77,10 @@ impl MinecraftConnection { Ok(MinecraftConnection { stream, + #[cfg(feature = "atomic_compression")] compression: Arc::new(AtomicUsize::new(usize::MAX)), + #[cfg(not(feature = "atomic_compression"))] + compression: None, compression_type: 1, }) } @@ -87,7 +96,7 @@ impl MinecraftConnection { Ok(stream) => Ok(MinecraftConnection { stream, compression: self.compression.clone(), - compression_type: 1, + compression_type: self.compression_type, }), _ => Err(ProtocolError::CloneError), } @@ -118,13 +127,17 @@ impl MinecraftConnection { pub fn new(stream: T) -> MinecraftConnection { MinecraftConnection { stream, + #[cfg(feature = "atomic_compression")] compression: Arc::new(AtomicUsize::new(usize::MAX)), + #[cfg(not(feature = "atomic_compression"))] + compression: None, compression_type: 1, } } /// Set compression threshold pub fn set_compression(&mut self, threshold: Option) { + #[cfg(feature = "atomic_compression")] self.compression.store( match threshold { Some(t) => t, @@ -132,15 +145,26 @@ impl MinecraftConnection { }, Ordering::Relaxed, ); + #[cfg(not(feature = "atomic_compression"))] + { + self.compression = threshold; + } } /// Get compression threshold pub fn compression(&self) -> Option { - let threshold = self.compression.load(Ordering::Relaxed); - if threshold == usize::MAX { - None - } else { - Some(threshold) + #[cfg(feature = "atomic_compression")] + { + let threshold = self.compression.load(Ordering::Relaxed); + if threshold == usize::MAX { + return None + } else { + return Some(threshold) + } + } + #[cfg(not(feature = "atomic_compression"))] + { + self.compression } } @@ -174,22 +198,36 @@ impl MinecraftConnection { /// Read [`Packet`](Packet) from connection pub fn read_packet(&mut self) -> Result { - read_packet_atomic( - &mut self.stream, - self.compression.clone(), - Ordering::Relaxed, - ) + #[cfg(feature = "atomic_compression")] + { + return read_packet_atomic( + &mut self.stream, + self.compression.clone(), + Ordering::Relaxed, + ) + } + + #[cfg(not(feature = "atomic_compression"))] + read_packet(&mut self.stream, self.compression) } /// Write [`Packet`](Packet) to connection pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> { - write_packet_atomic( - &mut self.stream, - self.compression.clone(), - Ordering::Relaxed, - self.compression_type, - packet, - ) + #[cfg(feature = "atomic_compression")] + { + return write_packet_atomic( + &mut self.stream, + self.compression.clone(), + Ordering::Relaxed, + self.compression_type, + packet, + ) + } + + #[cfg(not(feature = "atomic_compression"))] + { + write_packet(&mut self.stream, self.compression, self.compression_type, packet) + } } } @@ -225,24 +263,22 @@ pub type MCConn = MinecraftConnection; /// MinecraftConnection\ shorter alias pub type MCConnTcp = MinecraftConnection; + /// Read [`Packet`](Packet) from stream /// /// `compression` here is atomic usize /// usize::MAX means that compression is disabled /// /// `ordering` is order how to load atomic -pub fn read_packet_atomic( +pub fn read_packet( stream: &mut T, - compression: Arc, - ordering: Ordering, + compression: Option ) -> Result { let mut data: Vec; let packet_length = stream.read_usize_varint_size()?; - let compress_threashold = compression.load(ordering); - - if compress_threashold != usize::MAX { + if compression.is_some() { let data_length = stream.read_usize_varint_size()?; data = stream.read_bytes(packet_length.0 - data_length.1)?; @@ -259,7 +295,7 @@ pub fn read_packet_atomic( /// Write [`Packet`](Packet) to stream /// -/// `compression` here is atomic usize +/// `compression` here is usize /// usize::MAX means that compression is disabled /// /// `ordering` is order how to load atomic @@ -267,10 +303,9 @@ pub fn read_packet_atomic( /// `compression_type` is integer from 0 (none) to 9 (longest) /// 1 is fast compression /// 6 is normal compression -pub fn write_packet_atomic( +pub fn write_packet( stream: &mut T, - compression: Arc, - ordering: Ordering, + compression: Option, compression_type: u32, packet: &Packet, ) -> Result<(), ProtocolError> { @@ -280,12 +315,10 @@ pub fn write_packet_atomic( data_buf.write_u8_varint(packet.id())?; data_buf.write_buffer(packet.buffer())?; - let compress_threshold = compression.load(ordering); - - if compress_threshold != usize::MAX { + if let Some(compression) = compression { let mut packet_buf = ByteBuffer::new(); - if data_buf.len() >= compress_threshold { + if data_buf.len() >= compression { let compressed_data = compress_zlib(data_buf.as_bytes(), compression_type)?; packet_buf.write_usize_varint(data_buf.len())?; packet_buf @@ -307,3 +340,45 @@ pub fn write_packet_atomic( Ok(()) } + +/// Read [`Packet`](Packet) from stream +/// +/// `compression` here is atomic usize +/// usize::MAX means that compression is disabled +/// +/// `ordering` is order how to load atomic +#[cfg(feature = "atomic_compression")] +pub fn read_packet_atomic( + stream: &mut T, + compression: Arc, + ordering: Ordering, +) -> Result { + read_packet(stream, match compression.load(ordering) { + usize::MAX => None, + i => Some(i), + }) +} + +/// Write [`Packet`](Packet) to stream +/// +/// `compression` here is atomic usize +/// usize::MAX means that compression is disabled +/// +/// `ordering` is order how to load atomic +/// +/// `compression_type` is integer from 0 (none) to 9 (longest) +/// 1 is fast compression +/// 6 is normal compression +#[cfg(feature = "atomic_compression")] +pub fn write_packet_atomic( + stream: &mut T, + compression: Arc, + ordering: Ordering, + compression_type: u32, + packet: &Packet, +) -> Result<(), ProtocolError> { + write_packet(stream, match compression.load(ordering) { + usize::MAX => None, + i => Some(i), + }, compression_type, packet) +}