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; // Decoder: Client -> Server #[derive(Default)] pub struct PacketDecoder { buf: BytesMut, decompress_buf: BytesMut, compression: Option, cipher: Option, } impl PacketDecoder { pub fn decode(&mut self) -> Result, 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) { 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); } }