diff options
author | Joey Sacchini <joey@sacchini.net> | 2020-12-03 16:27:58 -0500 |
---|---|---|
committer | Joey Sacchini <joey@sacchini.net> | 2020-12-03 16:27:58 -0500 |
commit | 64272b9938ffe84a196b00fd4f14125bcaf9f832 (patch) | |
tree | 156b82869e02476ec686be2ffb0b089fcf17929c /src | |
parent | d3e6ebc20b26a1863f1443884413b72e3605ec3d (diff) | |
download | craftio-rs-64272b9938ffe84a196b00fd4f14125bcaf9f832.tar.gz craftio-rs-64272b9938ffe84a196b00fd4f14125bcaf9f832.tar.bz2 craftio-rs-64272b9938ffe84a196b00fd4f14125bcaf9f832.zip |
make compression and encryption optional features
Diffstat (limited to 'src')
-rw-r--r-- | src/connection.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 2 | ||||
-rw-r--r-- | src/reader.rs | 29 | ||||
-rw-r--r-- | src/wrapper.rs | 6 | ||||
-rw-r--r-- | src/writer.rs | 191 |
5 files changed, 157 insertions, 74 deletions
diff --git a/src/connection.rs b/src/connection.rs index 4da97bb..c061c85 100644 --- a/src/connection.rs +++ b/src/connection.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "encryption")] use crate::cfb8::CipherError; use crate::reader::{CraftReader, CraftSyncReader, ReadResult}; use crate::wrapper::{CraftIo, CraftWrapper}; @@ -27,11 +28,13 @@ impl<R, W> CraftIo for CraftConnection<R, W> { self.writer.set_state(next); } + #[cfg(feature = "compression")] fn set_compression_threshold(&mut self, threshold: Option<i32>) { self.reader.set_compression_threshold(threshold); self.writer.set_compression_threshold(threshold); } + #[cfg(feature = "encryption")] fn enable_encryption(&mut self, key: &[u8], iv: &[u8]) -> Result<(), CipherError> { self.reader.enable_encryption(key, iv)?; self.writer.enable_encryption(key, iv)?; @@ -1,5 +1,6 @@ #![feature(backtrace)] +#[cfg(feature = "encryption")] mod cfb8; mod connection; mod reader; @@ -8,6 +9,7 @@ mod util; mod wrapper; mod writer; +#[cfg(feature = "encryption")] pub use cfb8::CipherError; pub use connection::CraftConnection; pub use reader::*; diff --git a/src/reader.rs b/src/reader.rs index 5b302aa..886ecfe 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -1,6 +1,8 @@ +#[cfg(feature = "encryption")] use crate::cfb8::{setup_craft_cipher, CipherError, CraftCipher}; use crate::util::{get_sized_buf, VAR_INT_BUF_SIZE}; use crate::wrapper::{CraftIo, CraftWrapper}; +#[cfg(feature = "compression")] use flate2::{DecompressError, FlushDecompress, Status}; use mcproto_rs::protocol::{Id, PacketDirection, RawPacket, State}; use mcproto_rs::types::VarInt; @@ -32,6 +34,7 @@ pub enum ReadError { err: mcproto_rs::protocol::PacketErr, backtrace: Backtrace, }, + #[cfg(feature = "compression")] #[error("failed to decompress packet")] DecompressFailed { #[from] @@ -40,6 +43,7 @@ pub enum ReadError { }, } +#[cfg(feature = "compression")] #[derive(Debug, Error)] pub enum DecompressErr { #[error("buf error")] @@ -83,10 +87,13 @@ pub struct CraftReader<R> { raw_buf: Option<Vec<u8>>, raw_ready: usize, raw_offset: usize, + #[cfg(feature = "compression")] decompress_buf: Option<Vec<u8>>, + #[cfg(feature = "compression")] compression_threshold: Option<i32>, state: State, direction: PacketDirection, + #[cfg(feature = "encryption")] encryption: Option<CraftCipher>, } @@ -101,10 +108,12 @@ impl<R> CraftIo for CraftReader<R> { self.state = next; } + #[cfg(feature = "compression")] fn set_compression_threshold(&mut self, threshold: Option<i32>) { self.compression_threshold = threshold; } + #[cfg(feature = "encryption")] fn enable_encryption(&mut self, key: &[u8], iv: &[u8]) -> Result<(), CipherError> { setup_craft_cipher(&mut self.encryption, key, iv) } @@ -292,10 +301,13 @@ impl<R> CraftReader<R> { raw_buf: None, raw_ready: 0, raw_offset: 0, + #[cfg(feature = "compression")] decompress_buf: None, + #[cfg(feature = "compression")] compression_threshold: None, state, direction, + #[cfg(feature = "encryption")] encryption: None, } } @@ -314,9 +326,8 @@ impl<R> CraftReader<R> { let buf = &mut self.raw_buf.as_mut().expect("should exist right now")[offset..offset + size]; // decrypt the packet if encryption is enabled - if let Some(encryption) = self.encryption.as_mut() { - encryption.decrypt(buf); - } + #[cfg(feature = "encryption")] + handle_decryption(self.encryption.as_mut(), buf); // try to get the packet body bytes... this boils down to: // * check if compression enabled, @@ -327,6 +338,7 @@ impl<R> CraftReader<R> { // which contains this packet's data // * if compression not enabled, then the buf contains only the packet body bytes + #[cfg(feature = "compression")] let packet_buf = if let Some(_) = self.compression_threshold { let (data_len, rest) = dsz_unwrap!(buf, VarInt); let data_len = data_len.0 as usize; @@ -339,6 +351,9 @@ impl<R> CraftReader<R> { buf }; + #[cfg(not(feature = "compression"))] + let packet_buf = buf; + let (raw_id, body_buf) = dsz_unwrap!(packet_buf, VarInt); let id = Id { @@ -373,6 +388,13 @@ impl<R> CraftReader<R> { } } +#[cfg(feature = "encryption")] +fn handle_decryption(cipher: Option<&mut CraftCipher>, buf: &mut[u8]) { + if let Some(encryption) = cipher { + encryption.decrypt(buf); + } +} + fn deserialize_raw_packet<'a, P>(raw: ReadResult<P>) -> ReadResult<P::Packet> where P: RawPacket<'a>, @@ -394,6 +416,7 @@ fn deserialize_varint(buf: &[u8]) -> ReadResult<(VarInt, usize)> { } } +#[cfg(feature = "compression")] fn decompress<'a>( src: &'a [u8], target: &'a mut Option<Vec<u8>>, diff --git a/src/wrapper.rs b/src/wrapper.rs index 06f451b..71ff7da 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -1,3 +1,4 @@ +#[cfg(feature = "encryption")] use crate::cfb8::CipherError; use mcproto_rs::protocol::State; @@ -6,7 +7,12 @@ pub trait CraftWrapper<I> { } pub trait CraftIo { + fn set_state(&mut self, next: State); + + #[cfg(feature = "compression")] fn set_compression_threshold(&mut self, threshold: Option<i32>); + + #[cfg(feature = "encryption")] fn enable_encryption(&mut self, key: &[u8], iv: &[u8]) -> Result<(), CipherError>; } diff --git a/src/writer.rs b/src/writer.rs index e1f71c3..ef97043 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -1,6 +1,8 @@ +#[cfg(feature = "encryption")] use crate::cfb8::{setup_craft_cipher, CipherError, CraftCipher}; use crate::util::{get_sized_buf, move_data_rightwards, VAR_INT_BUF_SIZE}; use crate::wrapper::{CraftIo, CraftWrapper}; +#[cfg(feature = "compression")] use flate2::{CompressError, Compression, FlushCompress, Status}; use mcproto_rs::protocol::{Id, Packet, PacketDirection, RawPacket, State}; use mcproto_rs::types::VarInt; @@ -21,12 +23,14 @@ pub enum WriteError { backtrace: Backtrace, }, #[error("failed to compress packet")] + #[cfg(feature = "compression")] CompressFail { #[from] err: CompressError, backtrace: Backtrace, }, #[error("compression gave buf error")] + #[cfg(feature = "compression")] CompressBufError { backtrace: Backtrace }, #[error("io error while writing data")] IoFail { @@ -114,12 +118,14 @@ pub trait CraftSyncWriter { pub struct CraftWriter<W> { inner: W, - raw_buf: Option<Vec<u8>>, + #[cfg(feature = "compression")] compress_buf: Option<Vec<u8>>, + #[cfg(feature = "compression")] compression_threshold: Option<i32>, state: State, direction: PacketDirection, + #[cfg(feature = "encryption")] encryption: Option<CraftCipher>, } @@ -134,10 +140,12 @@ impl<W> CraftIo for CraftWriter<W> { self.state = next; } + #[cfg(feature = "compression")] fn set_compression_threshold(&mut self, threshold: Option<i32>) { self.compression_threshold = threshold; } + #[cfg(feature = "encryption")] fn enable_encryption(&mut self, key: &[u8], iv: &[u8]) -> Result<(), CipherError> { setup_craft_cipher(&mut self.encryption, key, iv) } @@ -250,10 +258,13 @@ impl<W> CraftWriter<W> { Self { inner, raw_buf: None, + #[cfg(feature = "compression")] compression_threshold: None, + #[cfg(feature = "compression")] compress_buf: None, state, direction, + #[cfg(feature = "encryption")] encryption: None, } } @@ -266,83 +277,22 @@ impl<W> CraftWriter<W> { let body_size = prepared.id_size + prepared.data_size; let buf = get_sized_buf(&mut self.raw_buf, 0, HEADER_OFFSET + body_size); + #[cfg(feature = "compression")] let packet_data = if let Some(threshold) = self.compression_threshold { if threshold >= 0 && (threshold as usize) <= body_size { - let compressed_size = compress(buf, &mut self.compress_buf, HEADER_OFFSET)?.len(); - let compress_buf = - get_sized_buf(&mut self.compress_buf, 0, compressed_size + HEADER_OFFSET); - - let data_len_target = &mut compress_buf[VAR_INT_BUF_SIZE..HEADER_OFFSET]; - let mut data_len_serializer = SliceSerializer::create(data_len_target); - VarInt(body_size as i32) - .mc_serialize(&mut data_len_serializer) - .map_err(move |err| PacketSerializeFail::Header(err))?; - let data_len_bytes = data_len_serializer.finish().len(); - - let packet_len_target = &mut compress_buf[..VAR_INT_BUF_SIZE]; - let mut packet_len_serializer = SliceSerializer::create(packet_len_target); - VarInt((compressed_size + data_len_bytes) as i32) - .mc_serialize(&mut packet_len_serializer) - .map_err(move |err| PacketSerializeFail::Header(err))?; - let packet_len_bytes = packet_len_serializer.finish().len(); - - let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; - move_data_rightwards( - &mut compress_buf[..HEADER_OFFSET], - packet_len_bytes, - n_shift_packet_len, - ); - let n_shift_data_len = VAR_INT_BUF_SIZE - data_len_bytes; - move_data_rightwards( - &mut compress_buf[n_shift_packet_len..HEADER_OFFSET], - packet_len_bytes + data_len_bytes, - n_shift_data_len, - ); - let start_offset = n_shift_data_len + n_shift_packet_len; - let end_at = start_offset + data_len_bytes + packet_len_bytes + compressed_size; - &mut compress_buf[start_offset..end_at] + prepare_packet_compressed(buf, &mut self.compress_buf, body_size)? } else { - let packet_len_start_at = VAR_INT_BUF_SIZE - 1; - let packet_len_target = &mut buf[packet_len_start_at..HEADER_OFFSET - 1]; - let mut packet_len_serializer = SliceSerializer::create(packet_len_target); - VarInt((body_size + 1) as i32) - .mc_serialize(&mut packet_len_serializer) - .map_err(move |err| PacketSerializeFail::Header(err))?; - - let packet_len_bytes = packet_len_serializer.finish().len(); - let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; - move_data_rightwards( - &mut buf[packet_len_start_at..HEADER_OFFSET - 1], - packet_len_bytes, - n_shift_packet_len, - ); - - let start_offset = packet_len_start_at + n_shift_packet_len; - let end_at = start_offset + packet_len_bytes + 1 + body_size; - buf[start_offset + packet_len_bytes] = 0; // data_len = 0 - &mut buf[start_offset..end_at] + prepare_packet_compressed_below_threshold(buf, body_size)? } } else { - let packet_len_target = &mut buf[VAR_INT_BUF_SIZE..HEADER_OFFSET]; - let mut packet_len_serializer = SliceSerializer::create(packet_len_target); - VarInt(body_size as i32) - .mc_serialize(&mut packet_len_serializer) - .map_err(move |err| PacketSerializeFail::Header(err))?; - let packet_len_bytes = packet_len_serializer.finish().len(); - let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; - move_data_rightwards( - &mut buf[VAR_INT_BUF_SIZE..HEADER_OFFSET], - packet_len_bytes, - n_shift_packet_len, - ); - let start_offset = VAR_INT_BUF_SIZE + n_shift_packet_len; - let end_at = start_offset + packet_len_bytes + body_size; - &mut buf[start_offset..end_at] + prepare_packet_normally(buf, body_size)? }; - if let Some(encryption) = &mut self.encryption { - encryption.encrypt(packet_data); - } + #[cfg(not(feature = "compression"))] + let packet_data = prepare_packet_normally(buf, body_size)?; + + #[cfg(feature = "encryption")] + handle_encryption(self.encryption.as_mut(), packet_data); Ok((packet_data, &mut self.inner)) } @@ -408,6 +358,104 @@ impl<W> CraftWriter<W> { } } +fn prepare_packet_normally( + buf: &mut [u8], + body_size: usize, +) -> WriteResult<&mut [u8]> +{ + let packet_len_target = &mut buf[VAR_INT_BUF_SIZE..HEADER_OFFSET]; + let mut packet_len_serializer = SliceSerializer::create(packet_len_target); + VarInt(body_size as i32) + .mc_serialize(&mut packet_len_serializer) + .map_err(move |err| PacketSerializeFail::Header(err))?; + let packet_len_bytes = packet_len_serializer.finish().len(); + let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; + move_data_rightwards( + &mut buf[VAR_INT_BUF_SIZE..HEADER_OFFSET], + packet_len_bytes, + n_shift_packet_len, + ); + let start_offset = VAR_INT_BUF_SIZE + n_shift_packet_len; + let end_at = start_offset + packet_len_bytes + body_size; + Ok(&mut buf[start_offset..end_at]) +} + +#[cfg(feature = "compression")] +fn prepare_packet_compressed<'a>( + buf: &'a mut [u8], + compress_buf: &'a mut Option<Vec<u8>>, + body_size: usize, +) -> WriteResult<&'a mut [u8]> { + let compressed_size = compress(buf, compress_buf, HEADER_OFFSET)?.len(); + let compress_buf = + get_sized_buf(compress_buf, 0, compressed_size + HEADER_OFFSET); + + let data_len_target = &mut compress_buf[VAR_INT_BUF_SIZE..HEADER_OFFSET]; + let mut data_len_serializer = SliceSerializer::create(data_len_target); + VarInt(body_size as i32) + .mc_serialize(&mut data_len_serializer) + .map_err(move |err| PacketSerializeFail::Header(err))?; + let data_len_bytes = data_len_serializer.finish().len(); + + let packet_len_target = &mut compress_buf[..VAR_INT_BUF_SIZE]; + let mut packet_len_serializer = SliceSerializer::create(packet_len_target); + VarInt((compressed_size + data_len_bytes) as i32) + .mc_serialize(&mut packet_len_serializer) + .map_err(move |err| PacketSerializeFail::Header(err))?; + let packet_len_bytes = packet_len_serializer.finish().len(); + + let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; + move_data_rightwards( + &mut compress_buf[..HEADER_OFFSET], + packet_len_bytes, + n_shift_packet_len, + ); + let n_shift_data_len = VAR_INT_BUF_SIZE - data_len_bytes; + move_data_rightwards( + &mut compress_buf[n_shift_packet_len..HEADER_OFFSET], + packet_len_bytes + data_len_bytes, + n_shift_data_len, + ); + let start_offset = n_shift_data_len + n_shift_packet_len; + let end_at = start_offset + data_len_bytes + packet_len_bytes + compressed_size; + + Ok(&mut compress_buf[start_offset..end_at]) +} + +#[cfg(feature = "compression")] +fn prepare_packet_compressed_below_threshold( + buf: &mut [u8], + body_size: usize, +) -> WriteResult<&mut [u8]> +{ + let packet_len_start_at = VAR_INT_BUF_SIZE - 1; + let packet_len_target = &mut buf[packet_len_start_at..HEADER_OFFSET - 1]; + let mut packet_len_serializer = SliceSerializer::create(packet_len_target); + VarInt((body_size + 1) as i32) + .mc_serialize(&mut packet_len_serializer) + .map_err(move |err| PacketSerializeFail::Header(err))?; + + let packet_len_bytes = packet_len_serializer.finish().len(); + let n_shift_packet_len = VAR_INT_BUF_SIZE - packet_len_bytes; + move_data_rightwards( + &mut buf[packet_len_start_at..HEADER_OFFSET - 1], + packet_len_bytes, + n_shift_packet_len, + ); + + let start_offset = packet_len_start_at + n_shift_packet_len; + let end_at = start_offset + packet_len_bytes + 1 + body_size; + buf[start_offset + packet_len_bytes] = 0; // data_len = 0 + Ok(&mut buf[start_offset..end_at]) +} + +#[cfg(feature = "encryption")] +fn handle_encryption(encryption: Option<&mut CraftCipher>, buf: &mut [u8]) { + if let Some(encryption) = encryption { + encryption.encrypt(buf); + } +} + #[derive(Debug)] struct GrowVecSerializer<'a> { target: &'a mut Option<Vec<u8>>, @@ -474,6 +522,7 @@ impl<'a> SliceSerializer<'a> { } } +#[cfg(feature = "compression")] fn compress<'a, 'b>( src: &'b [u8], output: &'a mut Option<Vec<u8>>, |