compression_type and more comments
This commit is contained in:
parent
93e392ff22
commit
1651c9828c
446
src/lib.rs
446
src/lib.rs
@ -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 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;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub trait Zigzag<T> { fn zigzag(&self) -> T; }
|
||||
impl Zigzag<u8> for i8 { fn zigzag(&self) -> u8 { ((self << 1) ^ (self >> 7)) as u8 } }
|
||||
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<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)) } }
|
||||
pub trait Zigzag<T> {
|
||||
fn zigzag(&self) -> T;
|
||||
}
|
||||
impl Zigzag<u8> for i8 {
|
||||
fn zigzag(&self) -> u8 {
|
||||
((self << 1) ^ (self >> 7)) as u8
|
||||
}
|
||||
}
|
||||
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<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)]
|
||||
pub enum ProtocolError {
|
||||
AddressParseError,
|
||||
@ -31,7 +91,7 @@ pub enum ProtocolError {
|
||||
WriteError,
|
||||
ZlibError,
|
||||
UnsignedShortError,
|
||||
CloneError
|
||||
CloneError,
|
||||
}
|
||||
|
||||
impl fmt::Display for ProtocolError {
|
||||
@ -46,7 +106,7 @@ impl Error for ProtocolError {}
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Packet {
|
||||
id: u8,
|
||||
buffer: ByteBuffer
|
||||
buffer: ByteBuffer,
|
||||
}
|
||||
|
||||
macro_rules! size_varint {
|
||||
@ -111,7 +171,8 @@ macro_rules! write_varint {
|
||||
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))
|
||||
}
|
||||
}};
|
||||
}
|
||||
@ -134,7 +195,7 @@ pub trait DataBufferReader {
|
||||
let size = self.read_usize_varint()?;
|
||||
match String::from_utf8(self.read_bytes(size)?) {
|
||||
Ok(i) => Ok(i),
|
||||
Err(_) => Err(ProtocolError::StringParseError)
|
||||
Err(_) => Err(ProtocolError::StringParseError),
|
||||
}
|
||||
}
|
||||
/// Read Unsigned Short as u16
|
||||
@ -192,58 +253,123 @@ pub trait DataBufferReader {
|
||||
}
|
||||
|
||||
/// 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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> { read_varint!(usize, self) }
|
||||
/// Read VarInt as u8
|
||||
fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> { read_varint!(u8, self) }
|
||||
/// Read VarInt as u16
|
||||
fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> { read_varint!(u16, self) }
|
||||
/// Read VarInt as u32
|
||||
fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> { read_varint!(u32, self) }
|
||||
/// Read VarInt as u64
|
||||
fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> { read_varint!(u64, self) }
|
||||
/// Read VarInt as u128
|
||||
fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> { read_varint!(u128, self) }
|
||||
|
||||
/// Read VarInt as isize
|
||||
fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> { Ok(self.read_usize_varint()?.zigzag()) }
|
||||
/// Read VarInt as i8
|
||||
fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> { Ok(self.read_u8_varint()?.zigzag()) }
|
||||
/// Read VarInt as i16
|
||||
fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> { Ok(self.read_u16_varint()?.zigzag()) }
|
||||
/// Read VarInt as i32
|
||||
fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> { Ok(self.read_u32_varint()?.zigzag()) }
|
||||
/// Read VarInt as i64
|
||||
fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> { Ok(self.read_u64_varint()?.zigzag()) }
|
||||
/// Read VarInt as i128
|
||||
fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> { Ok(self.read_u128_varint()?.zigzag()) }
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
fn read_usize_varint(&mut self) -> Result<usize, ProtocolError> {
|
||||
read_varint!(usize, self)
|
||||
}
|
||||
/// Read VarInt as u8
|
||||
fn read_u8_varint(&mut self) -> Result<u8, ProtocolError> {
|
||||
read_varint!(u8, self)
|
||||
}
|
||||
/// Read VarInt as u16
|
||||
fn read_u16_varint(&mut self) -> Result<u16, ProtocolError> {
|
||||
read_varint!(u16, self)
|
||||
}
|
||||
/// Read VarInt as u32
|
||||
fn read_u32_varint(&mut self) -> Result<u32, ProtocolError> {
|
||||
read_varint!(u32, self)
|
||||
}
|
||||
/// Read VarInt as u64
|
||||
fn read_u64_varint(&mut self) -> Result<u64, ProtocolError> {
|
||||
read_varint!(u64, self)
|
||||
}
|
||||
/// Read VarInt as u128
|
||||
fn read_u128_varint(&mut self) -> Result<u128, ProtocolError> {
|
||||
read_varint!(u128, self)
|
||||
}
|
||||
|
||||
/// Read VarInt as isize
|
||||
fn read_isize_varint(&mut self) -> Result<isize, ProtocolError> {
|
||||
Ok(self.read_usize_varint()?.zigzag())
|
||||
}
|
||||
/// Read VarInt as i8
|
||||
fn read_i8_varint(&mut self) -> Result<i8, ProtocolError> {
|
||||
Ok(self.read_u8_varint()?.zigzag())
|
||||
}
|
||||
/// Read VarInt as i16
|
||||
fn read_i16_varint(&mut self) -> Result<i16, ProtocolError> {
|
||||
Ok(self.read_u16_varint()?.zigzag())
|
||||
}
|
||||
/// Read VarInt as i32
|
||||
fn read_i32_varint(&mut self) -> Result<i32, ProtocolError> {
|
||||
Ok(self.read_u32_varint()?.zigzag())
|
||||
}
|
||||
/// Read VarInt as i64
|
||||
fn read_i64_varint(&mut self) -> Result<i64, ProtocolError> {
|
||||
Ok(self.read_u64_varint()?.zigzag())
|
||||
}
|
||||
/// Read VarInt as i128
|
||||
fn read_i128_varint(&mut self) -> Result<i128, ProtocolError> {
|
||||
Ok(self.read_u128_varint()?.zigzag())
|
||||
}
|
||||
}
|
||||
|
||||
/// Packet data writer trait
|
||||
pub trait DataBufferWriter {
|
||||
@ -319,30 +445,54 @@ pub trait DataBufferWriter {
|
||||
}
|
||||
|
||||
/// 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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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 {
|
||||
@ -367,10 +517,7 @@ impl<W: Write> DataBufferWriter for W {
|
||||
impl Packet {
|
||||
/// Create new packet from id and buffer
|
||||
pub fn new(id: u8, buffer: ByteBuffer) -> Packet {
|
||||
Packet {
|
||||
id,
|
||||
buffer
|
||||
}
|
||||
Packet { id, buffer }
|
||||
}
|
||||
|
||||
/// Create new packet from packet data
|
||||
@ -378,12 +525,12 @@ impl Packet {
|
||||
let mut buf = ByteBuffer::from_bytes(data);
|
||||
|
||||
let (packet_id, packet_id_size) = buf.read_u8_varint_size()?;
|
||||
let packet_data = DataBufferReader::read_bytes(
|
||||
&mut buf, data.len() - packet_id_size as usize)?;
|
||||
let packet_data =
|
||||
DataBufferReader::read_bytes(&mut buf, data.len() - packet_id_size as usize)?;
|
||||
|
||||
Ok(Packet {
|
||||
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 {
|
||||
Packet {
|
||||
id,
|
||||
buffer: ByteBuffer::from_bytes(data)
|
||||
buffer: ByteBuffer::from_bytes(data),
|
||||
}
|
||||
}
|
||||
|
||||
@ -399,16 +546,15 @@ impl Packet {
|
||||
pub fn empty(id: u8) -> Packet {
|
||||
Packet {
|
||||
id,
|
||||
buffer: ByteBuffer::new()
|
||||
buffer: ByteBuffer::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Build packet with lambda
|
||||
pub fn build<F>(
|
||||
id: u8,
|
||||
builder: F
|
||||
) -> Result<Packet, ProtocolError>
|
||||
where F: FnOnce(&mut Packet) -> Result<(), ProtocolError> {
|
||||
pub fn build<F>(id: u8, builder: F) -> Result<Packet, ProtocolError>
|
||||
where
|
||||
F: FnOnce(&mut Packet) -> Result<(), ProtocolError>,
|
||||
{
|
||||
let mut packet = Self::empty(id);
|
||||
builder(&mut packet)?;
|
||||
Ok(packet)
|
||||
@ -464,30 +610,33 @@ impl DataBufferWriter for Packet {
|
||||
}
|
||||
}
|
||||
|
||||
/// Minecraft connection, wrapper for stream with compression
|
||||
pub struct MinecraftConnection<T: Read + Write> {
|
||||
stream: T,
|
||||
compression: Arc<AtomicUsize>
|
||||
compression: Arc<AtomicUsize>,
|
||||
compression_type: u32,
|
||||
}
|
||||
|
||||
impl MinecraftConnection<TcpStream> {
|
||||
/// Connect to Minecraft Server with TcpStream
|
||||
pub fn connect(addr: &str) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
||||
let addr = match addr.to_socket_addrs() {
|
||||
Ok(mut i) => { match i.next() {
|
||||
Some(i) => { i },
|
||||
None => { return Err(ProtocolError::AddressParseError) },
|
||||
} },
|
||||
Err(_) => { return Err(ProtocolError::AddressParseError) },
|
||||
Ok(mut i) => match i.next() {
|
||||
Some(i) => i,
|
||||
None => return Err(ProtocolError::AddressParseError),
|
||||
},
|
||||
Err(_) => return Err(ProtocolError::AddressParseError),
|
||||
};
|
||||
|
||||
let stream: TcpStream = match TcpStream::connect(&addr) {
|
||||
Ok(i) => i,
|
||||
Err(_) => { return Err(ProtocolError::StreamConnectError) },
|
||||
Err(_) => return Err(ProtocolError::StreamConnectError),
|
||||
};
|
||||
|
||||
Ok(MinecraftConnection {
|
||||
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
|
||||
pub fn try_clone(&mut self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
|
||||
match self.stream.try_clone() {
|
||||
Ok(stream) => {
|
||||
Ok(MinecraftConnection {
|
||||
stream: stream,
|
||||
compression: self.compression.clone()
|
||||
})
|
||||
},
|
||||
_ => {
|
||||
Err(ProtocolError::CloneError)
|
||||
},
|
||||
Ok(stream) => Ok(MinecraftConnection {
|
||||
stream,
|
||||
compression: self.compression.clone(),
|
||||
compression_type: 1,
|
||||
}),
|
||||
_ => Err(ProtocolError::CloneError),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -537,22 +682,21 @@ impl<T: Read + Write> MinecraftConnection<T> {
|
||||
pub fn new(stream: T) -> MinecraftConnection<T> {
|
||||
MinecraftConnection {
|
||||
stream,
|
||||
compression: Arc::new(AtomicUsize::new(usize::MAX))
|
||||
compression: Arc::new(AtomicUsize::new(usize::MAX)),
|
||||
compression_type: 1,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set compression threshold
|
||||
pub fn set_compression(&mut self, threshold: Option<usize>) {
|
||||
self.compression = Arc::new(AtomicUsize::new(
|
||||
match threshold {
|
||||
self.compression = Arc::new(AtomicUsize::new(match threshold {
|
||||
Some(t) => t,
|
||||
None => usize::MAX,
|
||||
}
|
||||
));
|
||||
}));
|
||||
}
|
||||
|
||||
/// Get compression threshold
|
||||
pub fn get_compression(&self) -> Option<usize> {
|
||||
pub fn compression(&self) -> Option<usize> {
|
||||
let threshold = self.compression.load(Ordering::Relaxed);
|
||||
if threshold == usize::MAX {
|
||||
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
|
||||
pub fn get_mut(&mut self) -> &mut T {
|
||||
&mut self.stream
|
||||
@ -576,7 +738,8 @@ impl<T: Read + Write> MinecraftConnection<T> {
|
||||
read_packet_atomic(
|
||||
&mut self.stream,
|
||||
self.compression.clone(),
|
||||
Ordering::Relaxed)
|
||||
Ordering::Relaxed,
|
||||
)
|
||||
}
|
||||
|
||||
/// Write [`Packet`](Packet) to connection
|
||||
@ -585,7 +748,9 @@ impl<T: Read + Write> MinecraftConnection<T> {
|
||||
&mut self.stream,
|
||||
self.compression.clone(),
|
||||
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> {
|
||||
MinecraftConnection {
|
||||
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> {
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::default());
|
||||
fn compress_zlib(bytes: &[u8], compression: u32) -> Result<Vec<u8>, ProtocolError> {
|
||||
let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression));
|
||||
encoder.write_all(bytes).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> {
|
||||
let mut decoder = ZlibDecoder::new(bytes);
|
||||
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)
|
||||
}
|
||||
|
||||
@ -618,8 +786,17 @@ pub type MCConn<T> = MinecraftConnection<T>;
|
||||
/// MinecraftConnection\<TcpStream\> shorter alias
|
||||
pub type MCConnTcp = MinecraftConnection<TcpStream>;
|
||||
|
||||
/// Read [`Packet`](Packet) from stream, if compression is usize::MAX, compression is disabled
|
||||
pub fn read_packet_atomic<T: Read>(stream: &mut T, compression: Arc<AtomicUsize>, ordering: Ordering) -> Result<Packet, ProtocolError> {
|
||||
/// 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<T: Read>(
|
||||
stream: &mut T,
|
||||
compression: Arc<AtomicUsize>,
|
||||
ordering: Ordering,
|
||||
) -> Result<Packet, ProtocolError> {
|
||||
let mut data: Vec<u8>;
|
||||
|
||||
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)?)
|
||||
}
|
||||
|
||||
/// Write [`Packet`](Packet) to stream, if compression is usize::MAX, compression is disabled
|
||||
pub fn write_packet_atomic<T: Write>(stream: &mut T, compression: Arc<AtomicUsize>, ordering: Ordering, packet: &Packet) -> Result<(), ProtocolError> {
|
||||
/// 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
|
||||
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 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();
|
||||
|
||||
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_all(&compressed_data).or(Err(ProtocolError::WriteError))?;
|
||||
packet_buf
|
||||
.write_all(&compressed_data)
|
||||
.or(Err(ProtocolError::WriteError))?;
|
||||
} else {
|
||||
packet_buf.write_usize_varint(0)?;
|
||||
packet_buf.write_buffer(&data_buf)?;
|
||||
|
30
src/tests.rs
30
src/tests.rs
@ -4,7 +4,9 @@ use std::{net::TcpListener, thread};
|
||||
#[test]
|
||||
fn test_compression_server_client() -> Result<(), 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));
|
||||
|
||||
let mut packet = Packet::empty(0x12);
|
||||
@ -22,7 +24,8 @@ fn test_compression_server_client() -> 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() {
|
||||
let mut stream = MCConnTcp::new(stream.or(Err(ProtocolError::StreamConnectError))?);
|
||||
@ -45,22 +48,19 @@ fn test_compression_server_client() -> Result<(), ProtocolError> {
|
||||
|
||||
#[test]
|
||||
fn test_compression_atomic_bytebuffer() -> Result<(), ProtocolError> {
|
||||
let packet_1 = Packet::build(0x12, |p| {
|
||||
p.write_bytes(b"1234567890qwertyuiopasdfghjklzxcvbnm")
|
||||
})?;
|
||||
let mut conn = MCConn::new(ByteBuffer::new());
|
||||
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)?;
|
||||
|
||||
buffer.set_rpos(0);
|
||||
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");
|
||||
assert_eq!(
|
||||
packet_2.read_bytes(36)?,
|
||||
b"1234567890qwertyuiopasdfghjklzxcvbnm"
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue
Block a user