150 lines
4.3 KiB
Rust
150 lines
4.3 KiB
Rust
use aes::cipher::{generic_array::GenericArray, BlockDecryptMut, BlockSizeUser, KeyIvInit};
|
|
use bytes::{Buf, BytesMut};
|
|
|
|
use std::io::Write;
|
|
|
|
use bytes::BufMut;
|
|
use flate2::write::ZlibDecoder;
|
|
|
|
use crate::{
|
|
bytebuf::ByteBuffer, PacketError, RawPacket, VarInt, VarIntDecodeError, MAX_PACKET_SIZE,
|
|
};
|
|
|
|
type Cipher = cfb8::Decryptor<aes::Aes128>;
|
|
|
|
// Decoder: Client -> Server
|
|
#[derive(Default)]
|
|
pub struct PacketDecoder {
|
|
buf: BytesMut,
|
|
decompress_buf: BytesMut,
|
|
compression: Option<u32>,
|
|
cipher: Option<Cipher>,
|
|
}
|
|
|
|
impl PacketDecoder {
|
|
pub fn decode(&mut self) -> Result<Option<RawPacket>, PacketError> {
|
|
let mut r = &self.buf[..];
|
|
|
|
let packet_len = match VarInt::decode_partial(&mut r) {
|
|
Ok(len) => len,
|
|
Err(VarIntDecodeError::Incomplete) => return Ok(None),
|
|
Err(VarIntDecodeError::TooLarge) => Err(PacketError::MalformedLength)?,
|
|
};
|
|
|
|
if !(0..=MAX_PACKET_SIZE).contains(&packet_len) {
|
|
Err(PacketError::OutOfBounds)?
|
|
}
|
|
|
|
if r.len() < packet_len as usize {
|
|
// Not enough data arrived yet.
|
|
return Ok(None);
|
|
}
|
|
|
|
let packet_len_len = VarInt(packet_len).written_size();
|
|
|
|
let mut data;
|
|
if self.compression.is_some() {
|
|
r = &r[..packet_len as usize];
|
|
|
|
let data_len = VarInt::decode(&mut r).map_err(|_| PacketError::TooLong)?.0;
|
|
|
|
if !(0..=MAX_PACKET_SIZE).contains(&data_len) {
|
|
Err(PacketError::OutOfBounds)?
|
|
}
|
|
|
|
// Is this packet compressed?
|
|
if data_len > 0 {
|
|
debug_assert!(self.decompress_buf.is_empty());
|
|
|
|
self.decompress_buf.put_bytes(0, data_len as usize);
|
|
|
|
// TODO: use libdeflater or zune-inflate?
|
|
let mut z = ZlibDecoder::new(&mut self.decompress_buf[..]);
|
|
|
|
z.write_all(r).map_err(|_| PacketError::FailedWrite)?;
|
|
z.finish().map_err(|_| PacketError::FailedFinish)?;
|
|
|
|
let total_packet_len = VarInt(packet_len).written_size() + packet_len as usize;
|
|
|
|
self.buf.advance(total_packet_len);
|
|
|
|
data = self.decompress_buf.split();
|
|
} else {
|
|
debug_assert_eq!(data_len, 0);
|
|
|
|
let remaining_len = r.len();
|
|
|
|
self.buf.advance(packet_len_len + 1);
|
|
|
|
data = self.buf.split_to(remaining_len);
|
|
}
|
|
} else {
|
|
// no compression
|
|
self.buf.advance(packet_len_len);
|
|
data = self.buf.split_to(packet_len as usize);
|
|
}
|
|
|
|
r = &data[..];
|
|
let packet_id = VarInt::decode(&mut r).map_err(|_| PacketError::DecodeID)?;
|
|
|
|
data.advance(data.len() - r.len());
|
|
Ok(Some(RawPacket {
|
|
id: packet_id,
|
|
bytebuf: ByteBuffer::new(data),
|
|
}))
|
|
}
|
|
|
|
pub fn enable_encryption(&mut self, key: &[u8; 16]) {
|
|
assert!(self.cipher.is_none(), "encryption is already enabled");
|
|
|
|
let mut cipher = Cipher::new_from_slices(key, key).expect("invalid key");
|
|
|
|
// Don't forget to decrypt the data we already have.
|
|
Self::decrypt_bytes(&mut cipher, &mut self.buf);
|
|
|
|
self.cipher = Some(cipher);
|
|
}
|
|
|
|
pub fn set_compression(&mut self, compression: Option<u32>) {
|
|
self.compression = compression;
|
|
}
|
|
|
|
fn decrypt_bytes(cipher: &mut Cipher, bytes: &mut [u8]) {
|
|
for chunk in bytes.chunks_mut(Cipher::block_size()) {
|
|
let gen_arr = GenericArray::from_mut_slice(chunk);
|
|
cipher.decrypt_block_mut(gen_arr);
|
|
}
|
|
}
|
|
|
|
pub fn queue_bytes(&mut self, mut bytes: BytesMut) {
|
|
if let Some(cipher) = &mut self.cipher {
|
|
Self::decrypt_bytes(cipher, &mut bytes);
|
|
}
|
|
|
|
self.buf.unsplit(bytes);
|
|
}
|
|
|
|
pub fn queue_slice(&mut self, bytes: &[u8]) {
|
|
let len = self.buf.len();
|
|
|
|
self.buf.extend_from_slice(bytes);
|
|
|
|
if let Some(cipher) = &mut self.cipher {
|
|
let slice = &mut self.buf[len..];
|
|
Self::decrypt_bytes(cipher, slice);
|
|
}
|
|
}
|
|
|
|
pub fn take_capacity(&mut self) -> BytesMut {
|
|
self.buf.split_off(self.buf.len())
|
|
}
|
|
|
|
pub fn clear(&mut self) {
|
|
self.buf.clear()
|
|
}
|
|
|
|
pub fn reserve(&mut self, additional: usize) {
|
|
self.buf.reserve(additional);
|
|
}
|
|
}
|