compression_type and more comments

This commit is contained in:
MeexReay 2024-07-16 02:09:05 +03:00
parent 93e392ff22
commit 1651c9828c
2 changed files with 328 additions and 134 deletions

View File

@ -1,25 +1,85 @@
use std::{error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, sync::{Arc, atomic::{AtomicUsize, Ordering}}};
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
use bytebuffer::ByteBuffer; use bytebuffer::ByteBuffer;
use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
use std::{
error::Error,
fmt,
io::{Read, Write},
net::{TcpStream, ToSocketAddrs},
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
};
use uuid::Uuid; use uuid::Uuid;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
pub trait Zigzag<T> { fn zigzag(&self) -> T; } pub trait Zigzag<T> {
impl Zigzag<u8> for i8 { fn zigzag(&self) -> u8 { ((self << 1) ^ (self >> 7)) as u8 } } fn zigzag(&self) -> T;
impl Zigzag<i8> for u8 { fn zigzag(&self) -> i8 { ((self >> 1) as i8) ^ (-((self & 1) as i8)) } } }
impl Zigzag<u16> for i16 { fn zigzag(&self) -> u16 { ((self << 1) ^ (self >> 15)) as u16 } } impl Zigzag<u8> for i8 {
impl Zigzag<i16> for u16 { fn zigzag(&self) -> i16 { ((self >> 1) as i16) ^ (-((self & 1) as i16)) } } fn zigzag(&self) -> u8 {
impl Zigzag<u32> for i32 { fn zigzag(&self) -> u32 { ((self << 1) ^ (self >> 31)) as u32 } } ((self << 1) ^ (self >> 7)) as u8
impl Zigzag<i32> for u32 { fn zigzag(&self) -> i32 { ((self >> 1) as i32) ^ (-((self & 1) as i32)) } } }
impl Zigzag<u64> for i64 { fn zigzag(&self) -> u64 { ((self << 1) ^ (self >> 63)) as u64 } } }
impl Zigzag<i64> for u64 { fn zigzag(&self) -> i64 { ((self >> 1) as i64) ^ (-((self & 1) as i64)) } } impl Zigzag<i8> for u8 {
impl Zigzag<u128> for i128 { fn zigzag(&self) -> u128 { ((self << 1) ^ (self >> 127)) as u128 } } fn zigzag(&self) -> i8 {
impl Zigzag<i128> for u128 { fn zigzag(&self) -> i128 { ((self >> 1) as i128) ^ (-((self & 1) as i128)) } } ((self >> 1) as i8) ^ (-((self & 1) as i8))
impl Zigzag<usize> for isize { fn zigzag(&self) -> usize { ((self << 1) ^ (self >> std::mem::size_of::<usize>()-1)) as usize } } }
impl Zigzag<isize> for usize { fn zigzag(&self) -> isize { ((self >> 1) as isize) ^ (-((self & 1) as isize)) } } }
impl Zigzag<u16> for i16 {
fn zigzag(&self) -> u16 {
((self << 1) ^ (self >> 15)) as u16
}
}
impl Zigzag<i16> for u16 {
fn zigzag(&self) -> i16 {
((self >> 1) as i16) ^ (-((self & 1) as i16))
}
}
impl Zigzag<u32> for i32 {
fn zigzag(&self) -> u32 {
((self << 1) ^ (self >> 31)) as u32
}
}
impl Zigzag<i32> for u32 {
fn zigzag(&self) -> i32 {
((self >> 1) as i32) ^ (-((self & 1) as i32))
}
}
impl Zigzag<u64> for i64 {
fn zigzag(&self) -> u64 {
((self << 1) ^ (self >> 63)) as u64
}
}
impl Zigzag<i64> for u64 {
fn zigzag(&self) -> i64 {
((self >> 1) as i64) ^ (-((self & 1) as i64))
}
}
impl Zigzag<u128> for i128 {
fn zigzag(&self) -> u128 {
((self << 1) ^ (self >> 127)) as u128
}
}
impl Zigzag<i128> for u128 {
fn zigzag(&self) -> i128 {
((self >> 1) as i128) ^ (-((self & 1) as i128))
}
}
impl Zigzag<usize> for isize {
fn zigzag(&self) -> usize {
((self << 1) ^ (self >> std::mem::size_of::<usize>() - 1)) as usize
}
}
impl Zigzag<isize> for usize {
fn zigzag(&self) -> isize {
((self >> 1) as isize) ^ (-((self & 1) as isize))
}
}
/// Minecraft protocol error
#[derive(Debug)] #[derive(Debug)]
pub enum ProtocolError { pub enum ProtocolError {
AddressParseError, AddressParseError,
@ -31,7 +91,7 @@ pub enum ProtocolError {
WriteError, WriteError,
ZlibError, ZlibError,
UnsignedShortError, UnsignedShortError,
CloneError CloneError,
} }
impl fmt::Display for ProtocolError { impl fmt::Display for ProtocolError {
@ -46,7 +106,7 @@ impl Error for ProtocolError {}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Packet { pub struct Packet {
id: u8, id: u8,
buffer: ByteBuffer buffer: ByteBuffer,
} }
macro_rules! size_varint { macro_rules! size_varint {
@ -111,12 +171,13 @@ macro_rules! write_varint {
DataBufferWriter::write_byte($self, next).or(Err(ProtocolError::VarIntError))?; DataBufferWriter::write_byte($self, next).or(Err(ProtocolError::VarIntError))?;
} }
DataBufferWriter::write_byte($self, (value & 0b01111111) as u8).or(Err(ProtocolError::VarIntError)) DataBufferWriter::write_byte($self, (value & 0b01111111) as u8)
.or(Err(ProtocolError::VarIntError))
} }
}}; }};
} }
/// Packet data reader trait /// Packet data reader trait
pub trait DataBufferReader { pub trait DataBufferReader {
/// Read bytes /// Read bytes
fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, ProtocolError>; fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, ProtocolError>;
@ -134,7 +195,7 @@ pub trait DataBufferReader {
let size = self.read_usize_varint()?; let size = self.read_usize_varint()?;
match String::from_utf8(self.read_bytes(size)?) { match String::from_utf8(self.read_bytes(size)?) {
Ok(i) => Ok(i), Ok(i) => Ok(i),
Err(_) => Err(ProtocolError::StringParseError) Err(_) => Err(ProtocolError::StringParseError),
} }
} }
/// Read Unsigned Short as u16 /// Read Unsigned Short as u16
@ -192,60 +253,125 @@ pub trait DataBufferReader {
} }
/// Read VarInt as usize with size in bytes (varint, size) /// Read VarInt as usize with size in bytes (varint, size)
fn read_usize_varint_size(&mut self) -> Result<(usize, usize), ProtocolError> { size_varint!(usize, self) } fn read_usize_varint_size(&mut self) -> Result<(usize, usize), ProtocolError> {
size_varint!(usize, self)
}
/// Read VarInt as u8 with size in bytes (varint, size) /// Read VarInt as u8 with size in bytes (varint, size)
fn read_u8_varint_size(&mut self) -> Result<(u8, u8), ProtocolError> { size_varint!(u8, self) } fn read_u8_varint_size(&mut self) -> Result<(u8, u8), ProtocolError> {
size_varint!(u8, self)
}
/// Read VarInt as u16 with size in bytes (varint, size) /// Read VarInt as u16 with size in bytes (varint, size)
fn read_u16_varint_size(&mut self) -> Result<(u16, u16), ProtocolError> { size_varint!(u16, self) } fn read_u16_varint_size(&mut self) -> Result<(u16, u16), ProtocolError> {
size_varint!(u16, self)
}
/// Read VarInt as u32 with size in bytes (varint, size) /// Read VarInt as u32 with size in bytes (varint, size)
fn read_u32_varint_size(&mut self) -> Result<(u32, u32), ProtocolError> { size_varint!(u32, self) } fn read_u32_varint_size(&mut self) -> Result<(u32, u32), ProtocolError> {
size_varint!(u32, self)
}
/// Read VarInt as u64 with size in bytes (varint, size) /// Read VarInt as u64 with size in bytes (varint, size)
fn read_u64_varint_size(&mut self) -> Result<(u64, u64), ProtocolError> { size_varint!(u64, self) } fn read_u64_varint_size(&mut self) -> Result<(u64, u64), ProtocolError> {
size_varint!(u64, self)
}
/// Read VarInt as u128 with size in bytes (varint, size) /// Read VarInt as u128 with size in bytes (varint, size)
fn read_u128_varint_size(&mut self) -> Result<(u128, u128), ProtocolError> { size_varint!(u128, self) } fn read_u128_varint_size(&mut self) -> Result<(u128, u128), ProtocolError> {
size_varint!(u128, self)
}
/// Read VarInt as isize with size in bytes (varint, size) /// Read VarInt as isize with size in bytes (varint, size)
fn read_isize_varint_size(&mut self) -> Result<(isize, isize), ProtocolError> { Ok({let i = self.read_usize_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_isize_varint_size(&mut self) -> Result<(isize, isize), ProtocolError> {
Ok({
let i = self.read_usize_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as i8 with size in bytes (varint, size) /// Read VarInt as i8 with size in bytes (varint, size)
fn read_i8_varint_size(&mut self) -> Result<(i8, i8), ProtocolError> { Ok({let i = self.read_u8_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_i8_varint_size(&mut self) -> Result<(i8, i8), ProtocolError> {
Ok({
let i = self.read_u8_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as i16 with size in bytes (varint, size) /// Read VarInt as i16 with size in bytes (varint, size)
fn read_i16_varint_size(&mut self) -> Result<(i16, i16), ProtocolError> { Ok({let i = self.read_u16_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_i16_varint_size(&mut self) -> Result<(i16, i16), ProtocolError> {
Ok({
let i = self.read_u16_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as i32 with size in bytes (varint, size) /// Read VarInt as i32 with size in bytes (varint, size)
fn read_i32_varint_size(&mut self) -> Result<(i32, i32), ProtocolError> { Ok({let i = self.read_u32_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_i32_varint_size(&mut self) -> Result<(i32, i32), ProtocolError> {
Ok({
let i = self.read_u32_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as i64 with size in bytes (varint, size) /// Read VarInt as i64 with size in bytes (varint, size)
fn read_i64_varint_size(&mut self) -> Result<(i64, i64), ProtocolError> { Ok({let i = self.read_u64_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_i64_varint_size(&mut self) -> Result<(i64, i64), ProtocolError> {
Ok({
let i = self.read_u64_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as i128 with size in bytes (varint, size) /// Read VarInt as i128 with size in bytes (varint, size)
fn read_i128_varint_size(&mut self) -> Result<(i128, i128), ProtocolError> { Ok({let i = self.read_u128_varint_size()?; (i.0.zigzag(), i.1.zigzag())}) } fn read_i128_varint_size(&mut self) -> Result<(i128, i128), ProtocolError> {
Ok({
let i = self.read_u128_varint_size()?;
(i.0.zigzag(), i.1.zigzag())
})
}
/// Read VarInt as usize /// Read VarInt as usize
fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> { read_varint!(usize, self) } fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> {
read_varint!(usize, self)
}
/// Read VarInt as u8 /// Read VarInt as u8
fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> { read_varint!(u8, self) } fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> {
read_varint!(u8, self)
}
/// Read VarInt as u16 /// Read VarInt as u16
fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> { read_varint!(u16, self) } fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> {
read_varint!(u16, self)
}
/// Read VarInt as u32 /// Read VarInt as u32
fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> { read_varint!(u32, self) } fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> {
read_varint!(u32, self)
}
/// Read VarInt as u64 /// Read VarInt as u64
fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> { read_varint!(u64, self) } fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> {
read_varint!(u64, self)
}
/// Read VarInt as u128 /// Read VarInt as u128
fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> { read_varint!(u128, self) } fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> {
read_varint!(u128, self)
}
/// Read VarInt as isize /// Read VarInt as isize
fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> { Ok(self.read_usize_varint()?.zigzag()) } fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> {
Ok(self.read_usize_varint()?.zigzag())
}
/// Read VarInt as i8 /// Read VarInt as i8
fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> { Ok(self.read_u8_varint()?.zigzag()) } fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> {
Ok(self.read_u8_varint()?.zigzag())
}
/// Read VarInt as i16 /// Read VarInt as i16
fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> { Ok(self.read_u16_varint()?.zigzag()) } fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> {
Ok(self.read_u16_varint()?.zigzag())
}
/// Read VarInt as i32 /// Read VarInt as i32
fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> { Ok(self.read_u32_varint()?.zigzag()) } fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> {
Ok(self.read_u32_varint()?.zigzag())
}
/// Read VarInt as i64 /// Read VarInt as i64
fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> { Ok(self.read_u64_varint()?.zigzag()) } fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> {
Ok(self.read_u64_varint()?.zigzag())
}
/// Read VarInt as i128 /// Read VarInt as i128
fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> { Ok(self.read_u128_varint()?.zigzag()) } fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> {
Ok(self.read_u128_varint()?.zigzag())
}
} }
/// Packet data writer trait
/// Packet data writer trait
pub trait DataBufferWriter { pub trait DataBufferWriter {
/// Write bytes /// Write bytes
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError>; fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError>;
@ -319,30 +445,54 @@ pub trait DataBufferWriter {
} }
/// Write VarInt as usize /// Write VarInt as usize
fn write_usize_varint(&mut self, val: usize) -> Result<(), ProtocolError> { write_varint!(usize, self, val) } fn write_usize_varint(&mut self, val: usize) -> Result<(), ProtocolError> {
write_varint!(usize, self, val)
}
/// Write VarInt as u8 /// Write VarInt as u8
fn write_u8_varint(&mut self, val: u8) -> Result<(), ProtocolError> { write_varint!(u8, self, val) } fn write_u8_varint(&mut self, val: u8) -> Result<(), ProtocolError> {
write_varint!(u8, self, val)
}
/// Write VarInt as u16 /// Write VarInt as u16
fn write_u16_varint(&mut self, val: u16) -> Result<(), ProtocolError> { write_varint!(u16, self, val) } fn write_u16_varint(&mut self, val: u16) -> Result<(), ProtocolError> {
write_varint!(u16, self, val)
}
/// Write VarInt as u32 /// Write VarInt as u32
fn write_u32_varint(&mut self, val: u32) -> Result<(), ProtocolError> { write_varint!(u32, self, val) } fn write_u32_varint(&mut self, val: u32) -> Result<(), ProtocolError> {
write_varint!(u32, self, val)
}
/// Write VarInt as u64 /// Write VarInt as u64
fn write_u64_varint(&mut self, val: u64) -> Result<(), ProtocolError> { write_varint!(u64, self, val) } fn write_u64_varint(&mut self, val: u64) -> Result<(), ProtocolError> {
write_varint!(u64, self, val)
}
/// Write VarInt as u128 /// Write VarInt as u128
fn write_u128_varint(&mut self, val: u128) -> Result<(), ProtocolError> { write_varint!(u128, self, val) } fn write_u128_varint(&mut self, val: u128) -> Result<(), ProtocolError> {
write_varint!(u128, self, val)
}
/// Write VarInt as isize /// Write VarInt as isize
fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> { self.write_usize_varint(val.zigzag()) } fn write_isize_varint(&mut self, val: isize) -> Result<(), ProtocolError> {
self.write_usize_varint(val.zigzag())
}
/// Write VarInt as i8 /// Write VarInt as i8
fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> { self.write_u8_varint(val.zigzag()) } fn write_i8_varint(&mut self, val: i8) -> Result<(), ProtocolError> {
self.write_u8_varint(val.zigzag())
}
/// Write VarInt as i16 /// Write VarInt as i16
fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> { self.write_u16_varint(val.zigzag()) } fn write_i16_varint(&mut self, val: i16) -> Result<(), ProtocolError> {
self.write_u16_varint(val.zigzag())
}
/// Write VarInt as i32 /// Write VarInt as i32
fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> { self.write_u32_varint(val.zigzag()) } fn write_i32_varint(&mut self, val: i32) -> Result<(), ProtocolError> {
self.write_u32_varint(val.zigzag())
}
/// Write VarInt as i64 /// Write VarInt as i64
fn write_i64_varint(&mut self, val: i64) -> Result<(), ProtocolError> { self.write_u64_varint(val.zigzag()) } fn write_i64_varint(&mut self, val: i64) -> Result<(), ProtocolError> {
self.write_u64_varint(val.zigzag())
}
/// Write VarInt as i128 /// Write VarInt as i128
fn write_i128_varint(&mut self, val: i128) -> Result<(), ProtocolError> { self.write_u128_varint(val.zigzag()) } fn write_i128_varint(&mut self, val: i128) -> Result<(), ProtocolError> {
self.write_u128_varint(val.zigzag())
}
} }
impl<R: Read> DataBufferReader for R { impl<R: Read> DataBufferReader for R {
@ -367,10 +517,7 @@ impl<W: Write> DataBufferWriter for W {
impl Packet { impl Packet {
/// Create new packet from id and buffer /// Create new packet from id and buffer
pub fn new(id: u8, buffer: ByteBuffer) -> Packet { pub fn new(id: u8, buffer: ByteBuffer) -> Packet {
Packet { Packet { id, buffer }
id,
buffer
}
} }
/// Create new packet from packet data /// Create new packet from packet data
@ -378,12 +525,12 @@ impl Packet {
let mut buf = ByteBuffer::from_bytes(data); let mut buf = ByteBuffer::from_bytes(data);
let (packet_id, packet_id_size) = buf.read_u8_varint_size()?; let (packet_id, packet_id_size) = buf.read_u8_varint_size()?;
let packet_data = DataBufferReader::read_bytes( let packet_data =
&mut buf, data.len() - packet_id_size as usize)?; DataBufferReader::read_bytes(&mut buf, data.len() - packet_id_size as usize)?;
Ok(Packet { Ok(Packet {
id: packet_id, id: packet_id,
buffer: ByteBuffer::from_bytes(&packet_data) buffer: ByteBuffer::from_bytes(&packet_data),
}) })
} }
@ -391,7 +538,7 @@ impl Packet {
pub fn from_bytes(id: u8, data: &[u8]) -> Packet { pub fn from_bytes(id: u8, data: &[u8]) -> Packet {
Packet { Packet {
id, id,
buffer: ByteBuffer::from_bytes(data) buffer: ByteBuffer::from_bytes(data),
} }
} }
@ -399,16 +546,15 @@ impl Packet {
pub fn empty(id: u8) -> Packet { pub fn empty(id: u8) -> Packet {
Packet { Packet {
id, id,
buffer: ByteBuffer::new() buffer: ByteBuffer::new(),
} }
} }
/// Build packet with lambda /// Build packet with lambda
pub fn build<F>( pub fn build<F>(id: u8, builder: F) -> Result<Packet, ProtocolError>
id: u8, where
builder: F F: FnOnce(&mut Packet) -> Result<(), ProtocolError>,
) -> Result<Packet, ProtocolError> {
where F: FnOnce(&mut Packet) -> Result<(), ProtocolError> {
let mut packet = Self::empty(id); let mut packet = Self::empty(id);
builder(&mut packet)?; builder(&mut packet)?;
Ok(packet) Ok(packet)
@ -464,30 +610,33 @@ impl DataBufferWriter for Packet {
} }
} }
/// Minecraft connection, wrapper for stream with compression
pub struct MinecraftConnection<T: Read + Write> { pub struct MinecraftConnection<T: Read + Write> {
stream: T, stream: T,
compression: Arc<AtomicUsize> compression: Arc<AtomicUsize>,
compression_type: u32,
} }
impl MinecraftConnection<TcpStream> { impl MinecraftConnection<TcpStream> {
/// Connect to Minecraft Server with TcpStream /// Connect to Minecraft Server with TcpStream
pub fn connect(addr: &str) -> Result<MinecraftConnection<TcpStream>, ProtocolError> { pub fn connect(addr: &str) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
let addr = match addr.to_socket_addrs() { let addr = match addr.to_socket_addrs() {
Ok(mut i) => { match i.next() { Ok(mut i) => match i.next() {
Some(i) => { i }, Some(i) => i,
None => { return Err(ProtocolError::AddressParseError) }, None => return Err(ProtocolError::AddressParseError),
} }, },
Err(_) => { return Err(ProtocolError::AddressParseError) }, Err(_) => return Err(ProtocolError::AddressParseError),
}; };
let stream: TcpStream = match TcpStream::connect(&addr) { let stream: TcpStream = match TcpStream::connect(&addr) {
Ok(i) => i, Ok(i) => i,
Err(_) => { return Err(ProtocolError::StreamConnectError) }, Err(_) => return Err(ProtocolError::StreamConnectError),
}; };
Ok(MinecraftConnection { Ok(MinecraftConnection {
stream, stream,
compression: Arc::new(AtomicUsize::new(usize::MAX)) compression: Arc::new(AtomicUsize::new(usize::MAX)),
compression_type: 1,
}) })
} }
@ -499,17 +648,13 @@ impl MinecraftConnection<TcpStream> {
/// Try clone MinecraftConnection with compression and stream /// Try clone MinecraftConnection with compression and stream
pub fn try_clone(&mut self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> { pub fn try_clone(&mut self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
match self.stream.try_clone() { match self.stream.try_clone() {
Ok(stream) => { Ok(stream) => Ok(MinecraftConnection {
Ok(MinecraftConnection { stream,
stream: stream, compression: self.compression.clone(),
compression: self.compression.clone() compression_type: 1,
}) }),
}, _ => Err(ProtocolError::CloneError),
_ => {
Err(ProtocolError::CloneError)
},
} }
} }
} }
@ -535,24 +680,23 @@ impl<T: Read + Write> DataBufferWriter for MinecraftConnection<T> {
impl<T: Read + Write> MinecraftConnection<T> { impl<T: Read + Write> MinecraftConnection<T> {
/// Create new MinecraftConnection from stream /// Create new MinecraftConnection from stream
pub fn new(stream: T) -> MinecraftConnection<T> { pub fn new(stream: T) -> MinecraftConnection<T> {
MinecraftConnection { MinecraftConnection {
stream, stream,
compression: Arc::new(AtomicUsize::new(usize::MAX)) compression: Arc::new(AtomicUsize::new(usize::MAX)),
compression_type: 1,
} }
} }
/// Set compression threshold /// Set compression threshold
pub fn set_compression(&mut self, threshold: Option<usize>) { pub fn set_compression(&mut self, threshold: Option<usize>) {
self.compression = Arc::new(AtomicUsize::new( self.compression = Arc::new(AtomicUsize::new(match threshold {
match threshold { Some(t) => t,
Some(t) => t, None => usize::MAX,
None => usize::MAX, }));
}
));
} }
/// Get compression threshold /// Get compression threshold
pub fn get_compression(&self) -> Option<usize> { pub fn compression(&self) -> Option<usize> {
let threshold = self.compression.load(Ordering::Relaxed); let threshold = self.compression.load(Ordering::Relaxed);
if threshold == usize::MAX { if threshold == usize::MAX {
None None
@ -561,6 +705,24 @@ impl<T: Read + Write> MinecraftConnection<T> {
} }
} }
/// Set compression type
///
/// `compression_type` is integer from 0 (none) to 9 (longest)
/// 1 is fast compression
/// 6 is normal compression
pub fn set_compression_type(&mut self, compression_type: u32) {
self.compression_type = compression_type;
}
/// Get compression type
///
/// `compression_type` is integer from 0 (none) to 9 (longest)
/// 1 is fast compression
/// 6 is normal compression
pub fn compression_type(&self) -> u32 {
self.compression_type
}
/// Get mutable reference of stream /// Get mutable reference of stream
pub fn get_mut(&mut self) -> &mut T { pub fn get_mut(&mut self) -> &mut T {
&mut self.stream &mut self.stream
@ -574,18 +736,21 @@ impl<T: Read + Write> MinecraftConnection<T> {
/// Read [`Packet`](Packet) from connection /// Read [`Packet`](Packet) from connection
pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> { pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
read_packet_atomic( read_packet_atomic(
&mut self.stream, &mut self.stream,
self.compression.clone(), self.compression.clone(),
Ordering::Relaxed) Ordering::Relaxed,
)
} }
/// Write [`Packet`](Packet) to connection /// Write [`Packet`](Packet) to connection
pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> { pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
write_packet_atomic( write_packet_atomic(
&mut self.stream, &mut self.stream,
self.compression.clone(), self.compression.clone(),
Ordering::Relaxed, Ordering::Relaxed,
packet) self.compression_type,
packet,
)
} }
} }
@ -594,13 +759,14 @@ impl<T: Read + Write + Clone> MinecraftConnection<T> {
pub fn clone(&mut self) -> MinecraftConnection<T> { pub fn clone(&mut self) -> MinecraftConnection<T> {
MinecraftConnection { MinecraftConnection {
stream: self.stream.clone(), stream: self.stream.clone(),
compression: self.compression.clone() compression: self.compression.clone(),
compression_type: self.compression_type,
} }
} }
} }
fn compress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> { fn compress_zlib(bytes: &[u8], compression: u32) -> Result<Vec<u8>, ProtocolError> {
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default()); let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression));
encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?; encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?;
encoder.finish().or(Err(ProtocolError::ZlibError)) encoder.finish().or(Err(ProtocolError::ZlibError))
} }
@ -608,7 +774,9 @@ fn compress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> {
fn decompress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> { fn decompress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> {
let mut decoder = ZlibDecoder::new(bytes); let mut decoder = ZlibDecoder::new(bytes);
let mut output = Vec::new(); let mut output = Vec::new();
decoder.read_to_end(&mut output).or(Err(ProtocolError::ZlibError))?; decoder
.read_to_end(&mut output)
.or(Err(ProtocolError::ZlibError))?;
Ok(output) Ok(output)
} }
@ -618,8 +786,17 @@ pub type MCConn<T> = MinecraftConnection<T>;
/// MinecraftConnection\<TcpStream\> shorter alias /// MinecraftConnection\<TcpStream\> shorter alias
pub type MCConnTcp = MinecraftConnection<TcpStream>; pub type MCConnTcp = MinecraftConnection<TcpStream>;
/// Read [`Packet`](Packet) from stream, if compression is usize::MAX, compression is disabled /// Read [`Packet`](Packet) from stream
pub fn read_packet_atomic<T: Read>(stream: &mut T, compression: Arc<AtomicUsize>, ordering: Ordering) -> Result<Packet, ProtocolError> { ///
/// `compression` here is atomic usize
/// usize::MAX means that compression is disabled
///
/// `ordering` is order how to load atomic
pub fn read_packet_atomic<T: Read>(
stream: &mut T,
compression: Arc<AtomicUsize>,
ordering: Ordering,
) -> Result<Packet, ProtocolError> {
let mut data: Vec<u8>; let mut data: Vec<u8>;
let packet_length = stream.read_usize_varint_size()?; let packet_length = stream.read_usize_varint_size()?;
@ -641,8 +818,23 @@ pub fn read_packet_atomic<T: Read>(stream: &mut T, compression: Arc<AtomicUsize>
Ok(Packet::from_data(&data)?) Ok(Packet::from_data(&data)?)
} }
/// Write [`Packet`](Packet) to stream, if compression is usize::MAX, compression is disabled /// Write [`Packet`](Packet) to stream
pub fn write_packet_atomic<T: Write>(stream: &mut T, compression: Arc<AtomicUsize>, ordering: Ordering, packet: &Packet) -> Result<(), ProtocolError> { ///
/// `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
pub fn write_packet_atomic<T: Write>(
stream: &mut T,
compression: Arc<AtomicUsize>,
ordering: Ordering,
compression_type: u32,
packet: &Packet,
) -> Result<(), ProtocolError> {
let mut buf = ByteBuffer::new(); let mut buf = ByteBuffer::new();
let mut data_buf = ByteBuffer::new(); let mut data_buf = ByteBuffer::new();
@ -655,9 +847,11 @@ pub fn write_packet_atomic<T: Write>(stream: &mut T, compression: Arc<AtomicUsiz
let mut packet_buf = ByteBuffer::new(); let mut packet_buf = ByteBuffer::new();
if data_buf.len() >= compress_threshold { if data_buf.len() >= compress_threshold {
let compressed_data = compress_zlib(data_buf.as_bytes())?; let compressed_data = compress_zlib(data_buf.as_bytes(), compression_type)?;
packet_buf.write_usize_varint(data_buf.len())?; packet_buf.write_usize_varint(data_buf.len())?;
packet_buf.write_all(&compressed_data).or(Err(ProtocolError::WriteError))?; packet_buf
.write_all(&compressed_data)
.or(Err(ProtocolError::WriteError))?;
} else { } else {
packet_buf.write_usize_varint(0)?; packet_buf.write_usize_varint(0)?;
packet_buf.write_buffer(&data_buf)?; packet_buf.write_buffer(&data_buf)?;
@ -673,4 +867,4 @@ pub fn write_packet_atomic<T: Write>(stream: &mut T, compression: Arc<AtomicUsiz
stream.write_buffer(&buf)?; stream.write_buffer(&buf)?;
Ok(()) Ok(())
} }

View File

@ -4,9 +4,11 @@ use std::{net::TcpListener, thread};
#[test] #[test]
fn test_compression_server_client() -> Result<(), ProtocolError> { fn test_compression_server_client() -> Result<(), ProtocolError> {
fn test(first_text: &str) -> Result<bool, ProtocolError> { fn test(first_text: &str) -> Result<bool, ProtocolError> {
let Ok(mut conn) = MCConnTcp::connect("localhost:44447") else { return test(first_text) }; let Ok(mut conn) = MCConnTcp::connect("localhost:44447") else {
return test(first_text);
};
conn.set_compression(Some(5)); conn.set_compression(Some(5));
let mut packet = Packet::empty(0x12); let mut packet = Packet::empty(0x12);
packet.write_string(first_text)?; packet.write_string(first_text)?;
conn.write_packet(&packet)?; conn.write_packet(&packet)?;
@ -22,7 +24,8 @@ fn test_compression_server_client() -> Result<(), ProtocolError> {
} }
thread::spawn(move || -> Result<(), ProtocolError> { thread::spawn(move || -> Result<(), ProtocolError> {
let listener = TcpListener::bind("localhost:44447").or(Err(ProtocolError::StreamConnectError))?; let listener =
TcpListener::bind("localhost:44447").or(Err(ProtocolError::StreamConnectError))?;
for stream in listener.incoming() { for stream in listener.incoming() {
let mut stream = MCConnTcp::new(stream.or(Err(ProtocolError::StreamConnectError))?); let mut stream = MCConnTcp::new(stream.or(Err(ProtocolError::StreamConnectError))?);
@ -45,22 +48,19 @@ fn test_compression_server_client() -> Result<(), ProtocolError> {
#[test] #[test]
fn test_compression_atomic_bytebuffer() -> Result<(), ProtocolError> { fn test_compression_atomic_bytebuffer() -> Result<(), ProtocolError> {
let packet_1 = Packet::build(0x12, |p| { let mut conn = MCConn::new(ByteBuffer::new());
p.write_bytes(b"1234567890qwertyuiopasdfghjklzxcvbnm") conn.set_compression(Some(5));
})?;
let compression = Arc::new(AtomicUsize::new(5)); let mut packet_1 = Packet::empty(0x12);
packet_1.write_bytes(b"1234567890qwertyuiopasdfghjklzxcvbnm")?;
conn.write_packet(&packet_1)?;
let mut buffer = ByteBuffer::new(); let mut packet_2 = conn.read_packet()?;
write_packet_atomic(&mut buffer, compression.clone(), Ordering::Acquire, &packet_1)?; assert_eq!(
packet_2.read_bytes(36)?,
buffer.set_rpos(0); b"1234567890qwertyuiopasdfghjklzxcvbnm"
buffer.set_wpos(0); );
let mut packet_2 = read_packet_atomic(&mut buffer, compression.clone(), Ordering::Acquire)?;
assert_eq!(packet_2.read_bytes(36)?, b"1234567890qwertyuiopasdfghjklzxcvbnm");
Ok(()) Ok(())
} }