aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoey Sacchini <joey@sacchini.net>2020-12-03 16:27:58 -0500
committerJoey Sacchini <joey@sacchini.net>2020-12-03 16:27:58 -0500
commit64272b9938ffe84a196b00fd4f14125bcaf9f832 (patch)
tree156b82869e02476ec686be2ffb0b089fcf17929c /src
parentd3e6ebc20b26a1863f1443884413b72e3605ec3d (diff)
downloadcraftio-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.rs3
-rw-r--r--src/lib.rs2
-rw-r--r--src/reader.rs29
-rw-r--r--src/wrapper.rs6
-rw-r--r--src/writer.rs191
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)?;
diff --git a/src/lib.rs b/src/lib.rs
index 16d26a7..5789dd5 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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>>,