steel_protocol/
packet_traits.rs1use std::{
5 io::{Cursor, Write},
6 num::NonZeroU32,
7 sync::Arc,
8};
9
10use flate2::{Compression, write::ZlibEncoder};
11use serde::Deserialize;
12use steel_utils::{
13 FrontVec,
14 codec::VarInt,
15 serial::{ReadFrom, WriteTo},
16};
17
18use crate::utils::{ConnectionProtocol, MAX_PACKET_DATA_SIZE, MAX_PACKET_SIZE, PacketError};
19
20pub trait ServerPacket: ReadFrom {
23 fn read_packet(data: &mut Cursor<&[u8]>) -> Result<Self, PacketError> {
25 Self::read(data).map_err(PacketError::from)
26 }
27}
28
29pub trait ClientPacket: WriteTo {
31 fn write_packet(
37 &self,
38 writer: &mut impl Write,
39 protocol: ConnectionProtocol,
40 ) -> Result<(), PacketError> {
41 let packet_id = self
42 .get_id(protocol)
43 .ok_or(PacketError::InvalidProtocol(format!(
44 "Invalid protocol {protocol:?}"
45 )))?;
46 VarInt(packet_id).write(writer)?;
47 self.write(writer).map_err(PacketError::from)
48 }
49
50 fn get_id(&self, protocol: ConnectionProtocol) -> Option<i32>;
52}
53
54#[derive(Copy, Clone, Debug, Deserialize)]
56pub struct CompressionInfo {
57 pub threshold: NonZeroU32,
60 pub level: i32,
64}
65
66impl CompressionInfo {
67 pub const DEFAULT_THRESHOLD: u32 = 256;
69 pub const DEFAULT_LEVEL: i32 = 4;
71}
72
73impl Default for CompressionInfo {
74 #[expect(
75 clippy::unwrap_used,
76 reason = "the default threshold is a known nonzero compression threshold"
77 )]
78 fn default() -> Self {
79 Self {
80 threshold: NonZeroU32::new(Self::DEFAULT_THRESHOLD).unwrap(),
81 level: Self::DEFAULT_LEVEL,
82 }
83 }
84}
85
86#[derive(Clone)]
122pub struct EncodedPacket {
123 pub encoded_data: Arc<FrontVec>,
126}
127
128impl EncodedPacket {
129 fn from_data_uncompressed(mut packet_data: FrontVec) -> Result<Self, PacketError> {
130 let data_len = packet_data.len();
131 let varint_size = VarInt::written_size(data_len as i32);
132
133 let complete_len = varint_size + data_len;
134 if complete_len > MAX_PACKET_SIZE {
135 return Err(PacketError::TooLong(complete_len));
136 }
137
138 VarInt(data_len as i32).set_in_front(&mut packet_data, varint_size);
139
140 Ok(Self {
141 encoded_data: Arc::new(packet_data),
142 })
143 }
144
145 fn from_packet_data(
146 mut packet_data: FrontVec,
147 compression: CompressionInfo,
148 ) -> Result<Self, PacketError> {
149 let data_len = packet_data.len();
150 if data_len + VarInt::MAX_SIZE * 2 > MAX_PACKET_DATA_SIZE {
152 Err(PacketError::TooLong(data_len))?;
153 }
154
155 if data_len >= compression.threshold.get() as _ {
156 let mut buf = FrontVec::new(10);
157 let mut compressor =
158 ZlibEncoder::new(&mut buf, Compression::new(compression.level as u32));
159
160 compressor
161 .write_all(&packet_data)
162 .map_err(|e| PacketError::CompressionFailed(e.to_string()))?;
163 compressor
164 .finish()
165 .map_err(|e| PacketError::CompressionFailed(e.to_string()))?;
166
167 let varint_size = VarInt::written_size(data_len as i32);
169 let full_len = varint_size + buf.len();
170 let full_varint_size = VarInt::written_size(full_len as i32);
171
172 VarInt(data_len as i32).set_in_front(&mut buf, varint_size);
173 VarInt(full_len as i32).set_in_front(&mut buf, full_varint_size);
174 log::trace!(
175 "data length: {data_len}, full length: {full_len}, varint size: {varint_size}, full varint size: {full_varint_size}"
176 );
177
178 Ok(Self {
179 encoded_data: Arc::new(buf),
180 })
181 } else {
182 let data_len_with_header = data_len + 1;
187 let varint_size = VarInt::written_size(data_len_with_header as i32);
188
189 VarInt(0).set_in_front(&mut packet_data, 1);
190 VarInt(data_len_with_header as i32).set_in_front(&mut packet_data, varint_size);
191
192 Ok(Self {
193 encoded_data: Arc::new(packet_data),
194 })
195 }
196 }
197
198 pub fn from_bare<P: ClientPacket>(
204 packet: P,
205 compression: Option<CompressionInfo>,
206 protocol: ConnectionProtocol,
207 ) -> Result<Self, PacketError> {
208 let buf = Self::write_vec(packet, protocol)?;
209 Self::from_data(buf, compression)
210 }
211
212 fn write_vec<P: ClientPacket>(
213 packet: P,
214 protocol: ConnectionProtocol,
215 ) -> Result<FrontVec, PacketError> {
216 let mut buf = FrontVec::new(6);
217 packet.write_packet(&mut buf, protocol)?;
218 Ok(buf)
219 }
220
221 fn from_data(buf: FrontVec, compression: Option<CompressionInfo>) -> Result<Self, PacketError> {
222 if let Some(compression) = compression {
223 Self::from_packet_data(buf, compression)
224 } else {
225 Self::from_data_uncompressed(buf)
226 }
227 }
228}