Pumpkin/pumpkin-protocol/src/packet_decoder.rs
2024-08-23 07:54:40 -04:00

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);
}
}