use std::{
io::{Read, Write},
net::TcpStream,
};
use bytes::{BufMut, Bytes, BytesMut};
use miniz_oxide::{deflate, inflate};
use crate::{
error::TypeError,
minecraft::{
encrypt::{Aes128CfbDec, Aes128CfbEnc, decrypt_packet, encrypt_packet},
intents::legacy_ping::compare_init_bytes,
var_int::VarInt,
},
};
#[derive(Debug, Clone)]
pub struct Packet {
pub length: VarInt,
pub id: VarInt,
pub data: Bytes,
}
impl Packet {
pub(crate) const PACKET_LIMIT: usize = 2097151;
pub fn new(id: i32, data: Bytes) -> Self {
Self {
length: VarInt(data.len() as i32),
id: VarInt(id),
data,
}
}
pub fn read_init(stream: &mut TcpStream) -> Result<InitPacket, TypeError> {
let mut packet_ident = [0u8; 3];
stream
.read(&mut packet_ident)
.map_err(|e| TypeError::ReadError(e))?;
if let Some(legacy) = compare_init_bytes(packet_ident) {
return Ok(legacy);
}
let mut packet_ident = packet_ident.to_vec();
let len = VarInt::read_via_stream(stream, &mut packet_ident)?;
let buf_len = len.0 as usize - packet_ident.len();
if len.0 > Self::PACKET_LIMIT as i32 {
return Err(TypeError::PacketSizeExceedsLimit(len.0));
}
let mut data = vec![0u8; buf_len];
stream
.read_exact(&mut data)
.map_err(|e| TypeError::ReadError(e))?;
packet_ident.append(&mut data);
let data = packet_ident;
let mut data = Bytes::from_owner(data);
let id = VarInt::read(&mut data)?;
Ok(InitPacket::V1_7Above(Self {
length: len,
id,
data,
}))
}
pub fn from_stream(stream: &mut TcpStream, expected_id: i32) -> Result<Self, TypeError> {
let len = VarInt::read_via_stream(stream, &mut Vec::new())?;
if len.0 > Self::PACKET_LIMIT as i32 {
return Err(TypeError::PacketSizeExceedsLimit(len.0));
}
let mut data = vec![0u8; len.0 as usize];
stream.read_exact(&mut data).unwrap();
let mut data = Bytes::from_owner(data);
let id = VarInt::read(&mut data)?;
if id.0 != expected_id {
return Err(TypeError::UnexpectedPacketId(expected_id, id.0));
}
Ok(Self {
length: len,
id,
data,
})
}
#[must_use]
pub fn write_stream(self, stream: &mut TcpStream) -> Result<(), TypeError> {
let mut data = BytesMut::new();
self.write(&mut data);
stream
.write_all(&data)
.map_err(|e| TypeError::WriteError(e))?;
Ok(())
}
#[must_use]
pub fn write_encrypted_stream(
self,
stream: &mut TcpStream,
enc: &mut Aes128CfbEnc,
) -> Result<(), TypeError> {
let mut data = BytesMut::new();
self.write(&mut data);
let mut data = data.to_vec();
encrypt_packet(enc, &mut data)?;
stream
.write_all(&data)
.map_err(|e| TypeError::WriteError(e))?;
Ok(())
}
#[must_use]
pub fn write_compressed_encrypted_stream(
self,
stream: &mut TcpStream,
enc: &mut Aes128CfbEnc,
) -> Result<(), TypeError> {
let mut packet_data = BytesMut::new();
self.id.write(&mut packet_data);
packet_data.extend_from_slice(&self.data);
let comp_packet = &deflate::compress_to_vec_zlib(&packet_data[..], 4);
let uncomp_len = self.id.byte_len() + self.data.len();
let data_len = VarInt(uncomp_len as i32).byte_len() + comp_packet.len();
let mut packet = BytesMut::new();
VarInt(data_len as i32).write(&mut packet);
VarInt(uncomp_len as i32).write(&mut packet);
packet.extend_from_slice(comp_packet);
let mut packet = packet.to_vec();
encrypt_packet(enc, &mut packet)?;
stream
.write_all(&packet)
.map_err(|e| TypeError::WriteError(e))?;
Ok(())
}
pub fn from_compressed_encrypted_stream(
stream: &mut TcpStream,
dec: &mut Aes128CfbDec,
expected_id: i32,
) -> Result<Self, TypeError> {
let len = VarInt::read_via_encrypted_stream(stream, dec)?;
let mut data = vec![0u8; len.0 as usize];
stream.read_exact(&mut data).unwrap();
decrypt_packet(dec, &mut data)?;
let mut data = Bytes::from_owner(data);
let data_len = VarInt::read(&mut data)?;
let mut data = Bytes::from_owner(
inflate::decompress_to_vec_zlib(&data).map_err(|e| TypeError::DecompressError(e))?,
);
let id = VarInt::read(&mut data)?;
if id.0 != expected_id {
return Err(TypeError::UnexpectedPacketId(expected_id, id.0));
}
Ok(Self {
length: data_len,
id,
data,
})
}
}
impl WritePacketData for Packet {
fn write(mut self, data: &mut BytesMut) {
let mut len = 0;
len += self.id.byte_len();
len += self.data.len();
self.length = VarInt(len as i32);
self.length.write(data);
self.id.write(data);
data.put(self.data);
}
}
pub trait ReadPacketData {
fn read(data: &mut Bytes) -> Result<Self, TypeError>
where
Self: Sized;
}
pub trait WritePacketData {
fn write(self, data: &mut BytesMut);
fn byte_len(self) -> usize
where
Self: Sized,
{
let mut data = BytesMut::new();
self.write(&mut data);
data.len()
}
}
impl WritePacketData for u8 {
fn write(self, data: &mut BytesMut) {
data.put_u8(self);
}
}
#[derive(Debug, Clone)]
pub enum InitPacket {
V1_6,
V1_4To1_5,
Vbeta1_8To1_3,
V1_7Above(Packet),
}