Cactus/net/packet/
mod.rs

1//! This module abstracts away a Minecraft packet, so that it can be used in a simple and
2//! standardized way.
3
4pub mod data_types;
5pub mod packet_types;
6pub mod utils;
7
8use bytes::BytesMut;
9use core::fmt;
10use data_types::{CodecError, Encodable, StringProtocol, VarInt};
11use log::debug;
12use std::{collections::VecDeque, fmt::Debug};
13use thiserror::Error;
14
15// It is true that I could lazily evaluate the length, and Id for more performance but I chose to do it eagerly.
16
17/// An abstraction for a Minecraft packet.
18///
19/// Structure of a normal uncompressed Packet:
20///
21/// Length (VarInt): Length of Packet ID + Data
22/// P): An ID each packet has
23/// Data (Byte Aacket ID (VarIntrray): Actual data bytes
24#[derive(Clone, Eq, PartialEq)]
25pub struct Packet {
26    /// Length of `id` + `data`
27    length: usize,
28
29    /// An ID that each Packet has, varint-decoded.
30    id: VarInt,
31
32    /// The raw bytes making the packet. (so it contains ALL the packet, Length, Packet ID and
33    /// the data bytes)
34    data: BytesMut,
35
36    /// The raw bytes making the PAYLOAD of the packet. (so this slice does not contain the length
37    /// and acket ID)
38    payload: BytesMut,
39
40    /// For debugging purposes, the type of the packet, like 'Handshake (handshaking)'.
41    name: Option<String>,
42}
43
44// TODO: Implement printing functions to see the bytes in hexadecimal in order and in the reverse
45// order.
46
47// TODO: Implement `Iterator` trait to iterate over the packet's bytes in order to then implement
48// encoding/decoding functions for VarInts and such.
49
50// TODO: A PACKET BUILDER!!!!!!!!!!!
51
52impl Packet {
53    /// Initializes a new `Packet` by parsing the `data` buffer.
54    pub fn new<T: AsRef<[u8]>>(data: T) -> Result<Self, PacketError> {
55        let parsed = Self::parse_packet(data.as_ref())?;
56        Ok(Self {
57            length: parsed.0,
58            id: parsed.1,
59            data: data.as_ref().into(),
60            payload: parsed.2.into(),
61            name: None,
62        })
63    }
64
65    /// This is the WHOLE packet.
66    pub fn get_full_packet(&self) -> &[u8] {
67        &self.data
68    }
69
70    /// This is the PAYLOAD. So the bytes except the Packet Length and the Packet ID.
71    pub fn get_payload(&self) -> &[u8] {
72        // TODO: del this debug
73        debug!("PACKET: payload: {}", utils::get_dec_repr(&self.payload));
74        &self.payload
75    }
76
77    /// Sets the name of the current packet.
78    pub fn set_name(&mut self, name: &str) {
79        self.name = Some(name.to_string());
80    }
81
82    /// Returns the name of the current packet.
83    pub fn get_name(&self) -> &Option<String> {
84        &self.name
85    }
86
87    /// Returns a reference to the packet ID `VarInt`.
88    pub fn get_id(&self) -> &VarInt {
89        &self.id
90    }
91
92    /// Returns the `Packet` `length` attribute. From protocol.
93    pub fn get_length(&self) -> usize {
94        self.length
95    }
96
97    /// Returns the number of bytes in the payload.
98    pub fn len_payload(&self) -> usize {
99        self.data.len()
100    }
101
102    /// Returns the number of bytes in the packet.
103    /// To be clear, this is the length of the received TCP packet.
104    pub fn len(&self) -> usize {
105        self.data.len()
106    }
107
108    /// Tries to parse raw bytes and return in order:
109    /// (Packet Length, Packet ID, Packet payload bytes)
110    fn parse_packet(data: &[u8]) -> Result<(usize, VarInt, &[u8]), PacketError> {
111        let packet_len_varint = VarInt::from_bytes(data, ())?;
112        let packet_len_len: usize = packet_len_varint.get_bytes().len();
113
114        // We don't add + 1 because we're dealing with 0-indexing.
115        // ALL but the Length (VarInt).
116        // ID and Payload.
117        let except_length = &data[packet_len_len..];
118
119        let packet_id_varint = VarInt::from_bytes(except_length, ())?;
120
121        // So this is essentially "except_length_and_id", the continuation of `except_length`
122        let payload = &except_length[packet_id_varint.get_bytes().len()..];
123
124        Ok((
125            packet_len_varint.get_value() as usize,
126            packet_id_varint,
127            payload,
128        ))
129    }
130}
131
132/// Allows making a `Packet` object with defaults.
133/// Usage:
134/// ```rust
135/// let packet = Packet::default();
136/// ```
137impl Default for Packet {
138    fn default() -> Self {
139        Self {
140            length: usize::default(),
141            id: VarInt::default(),
142            payload: BytesMut::new(),
143            data: BytesMut::new(),
144            name: Option::default(),
145        }
146    }
147}
148
149impl fmt::Display for Packet {
150    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151        let name = self.get_name().clone().unwrap_or("Unknown".to_string()); // no allocation
152        let len = self.len();
153        let id = self.id.get_value();
154
155        write!(f, "{{ name={name:?}; len={len}; id={id} }}")
156        // {name:?} quotes/escapes odd names; drop ? if you truly want bare text.
157    }
158}
159
160/// For :? and :#?
161/// Debug displays the all the BYTES.
162impl Debug for Packet {
163    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
164        let name = self.get_name().clone().unwrap_or("Unknown".to_string()); // no allocation
165        let len = self.len();
166        let id = self.id.get_value();
167        let bytes: String = utils::get_dec_repr(self.get_full_packet());
168
169        write!(f, "{{ name={name:?}; len={len}; id={id}; bytes={bytes} }}")
170        // {name:?} quotes/escapes odd names; drop ? if you truly want bare text.
171    }
172}
173
174impl AsRef<[u8]> for Packet {
175    fn as_ref(&self) -> &[u8] {
176        &self.data
177    }
178}
179
180#[derive(Error, Debug)]
181pub enum PacketError {
182    #[error("Failed to decode the packet length")]
183    LengthDecodingError,
184
185    #[error("Failed to build the packet: {0}")]
186    BuildPacket(String),
187
188    #[error("Failed to decode from the payload: {0}")]
189    PayloadDecodeError(String),
190
191    #[error("Codec error: {0}")]
192    Codec(#[from] CodecError),
193}
194
195/// Represents the different actions that the PacketBuilder will do to construct the packet payload.
196pub enum BuildAction {
197    /// Appends raw bytes to the packet payload.
198    AppendBytes(Vec<u8>),
199
200    /// Appends an integer as a VarInt to the packet payload.
201    AppendVarInt(i32),
202
203    /// Appends a UTF-8 string to the packet payload.
204    AppendString(String),
205}
206
207/// A builder to build a packet.
208#[derive(Default)]
209pub struct PacketBuilder {
210    /// Queue of actions to process
211    actions: VecDeque<BuildAction>,
212}
213
214impl PacketBuilder {
215    /// Returns an empty Self, Self::default().
216    ///
217    /// Then use chained method calls to build your `Packet`.
218    ///
219    /// # Example
220    ///
221    /// let packet: Packet = PacketBuilder::new().append_varint(3).build()?;
222    pub fn new() -> Self {
223        Self::default()
224    }
225
226    /// Builds a packet
227    pub fn build(&self, packet_id: i32, name: Option<String>) -> Result<Packet, PacketError> {
228        let id = VarInt::from_value(packet_id)?;
229
230        let mut payload = BytesMut::with_capacity(64);
231        for action in &self.actions {
232            match action {
233                BuildAction::AppendBytes(bytes) => payload.extend_from_slice(bytes),
234                BuildAction::AppendVarInt(value) => {
235                    let varint = VarInt::from_value(*value)?;
236                    payload.extend_from_slice(varint.get_bytes());
237                }
238                BuildAction::AppendString(string) => {
239                    let string_protocol = StringProtocol::from_value(string.clone())?;
240                    payload.extend_from_slice(string_protocol.get_bytes());
241                }
242            }
243        }
244
245        let length = id.size() + payload.len();
246        let length_varint = VarInt::from_value(length as i32)?;
247
248        // Future self: Why "+ 10"?
249        let mut data = BytesMut::with_capacity(length + 10);
250        data.extend(length_varint.get_bytes());
251        data.extend(id.get_bytes());
252        data.extend_from_slice(&payload);
253
254        Ok(Packet {
255            length,
256            id,
257            data,
258            payload,
259            name,
260        })
261    }
262
263    /// Appends bytes to the back of the packet payload.
264    pub fn append_bytes<T: AsRef<[u8]>>(&mut self, data: T) -> &mut Self {
265        self.actions
266            .push_back(BuildAction::AppendBytes(data.as_ref().to_vec()));
267        self
268    }
269
270    /// Appends `value` as a VarInt to the back of the packet payload.
271    pub fn append_varint(&mut self, value: i32) -> &mut Self {
272        self.actions.push_back(BuildAction::AppendVarInt(value));
273        self
274    }
275
276    /// Appends `string` as a String to the back of the packet payload.
277    pub fn append_string<T: AsRef<str>>(&mut self, string: T) -> &mut Self {
278        self.actions
279            .push_back(BuildAction::AppendString(string.as_ref().to_string()));
280        self
281    }
282}
283
284// TODO: I wonder if having "invalid" value, like a too short/long Length should propagate an error
285// when creating a Packet.
286
287/// Represents a response to the Minecraft client.
288pub struct Response {
289    /// The packet to respond
290    packet: Option<Packet>,
291    /// Whether the server should close the connection after sending this response.
292    close_after_response: bool,
293}
294
295impl Response {
296    pub fn new(packet: Option<Packet>) -> Self {
297        Self {
298            packet,
299            close_after_response: false,
300        }
301    }
302
303    /// Returns a reference to the packet
304    pub fn get_packet(&self) -> Option<&Packet> {
305        self.packet.as_ref()
306    }
307
308    /// Consumes the Response and returns the packet
309    pub fn take_packet(self) -> Option<Packet> {
310        self.packet
311    }
312
313    /// Sets the `close_after_response` to true, which should make the server close the connection
314    /// with the Minecraft client after sending this response.
315    pub fn close_conn(mut self) -> Self {
316        self.close_after_response = true;
317        self
318    }
319
320    /// Returns whether or not the connection with the Minecraft client should be closed.
321    pub fn does_close_conn(&self) -> bool {
322        self.close_after_response
323    }
324}
325
326#[cfg(test)]
327mod tests {
328    use super::*;
329
330    #[test]
331    fn test_packet_creation_valid() {
332        // Length = ID + Data = 4
333        // ID = 4
334        // Data = &[1, 2, 3]
335        let init_data = &[4, 4, 1, 2, 3];
336
337        let mut packet: Packet = Packet::new(init_data).expect("Failed to create packet");
338        packet.set_name("test packet");
339
340        // 1 = 4
341        assert_eq!(packet.get_length(), 4);
342        assert_eq!(
343            packet.get_name().clone().unwrap(),
344            "test packet".to_string()
345        );
346        assert_eq!(packet.len(), init_data.len());
347        assert_eq!(packet.get_id().get_value(), 4);
348        assert_eq!(packet.get_payload(), &[1, 2, 3]);
349        assert_eq!(packet.get_full_packet(), init_data);
350    }
351
352    #[test]
353    fn test_packet_creation_invalid_length_too_short() {
354        // Length = 1
355        // ID = 4
356        // Data = &[1, 2, 3]
357        let init_data = &[1, 4, 1, 2, 3];
358
359        let packet: Packet = Packet::new(init_data).expect("Failed to create packet");
360
361        assert_eq!(packet.get_length(), 1);
362        assert_eq!(packet.len(), init_data.len());
363        assert_eq!(packet.get_id().get_value(), 4);
364        assert_eq!(packet.get_payload(), &[1, 2, 3]);
365        assert_eq!(packet.get_full_packet(), init_data);
366    }
367
368    #[test]
369    fn test_packet_creation_invalid_length_too_long() {
370        // Length = 2048
371        // ID = 4
372        // Data = &[1, 2, 3]
373
374        let mut init_data: Vec<u8> = VarInt::from_value(2048).unwrap().get_bytes().to_vec(); // Length
375        init_data.push(4); // ID
376        init_data.push(1); // Data
377        init_data.push(2);
378        init_data.push(3);
379
380        let packet: Packet = Packet::new(&init_data).expect("Failed to create packet");
381
382        assert_eq!(packet.get_length(), 2048);
383        assert_eq!(packet.get_id().get_value(), 4);
384        assert_eq!(packet.get_payload(), &[1, 2, 3]);
385
386        assert_eq!(packet.get_full_packet(), init_data);
387        assert_eq!(packet.len(), init_data.len());
388    }
389
390    #[test]
391    fn test_packet_creation_valid_varint_length() {
392        // Length = 256
393        // ID = 4
394        // Data = &[255; u8], 255 because it's + 1 with the ID
395
396        let mut init_data: Vec<u8> = VarInt::from_value(256).unwrap().get_bytes().to_vec(); // Length
397        init_data.push(4);
398        let data: &[u8] = &(1..=255).collect::<Vec<u8>>()[..];
399        init_data.extend(data);
400
401        let packet: Packet = Packet::new(&init_data).expect("Failed to create packet");
402
403        assert_eq!(packet.get_length(), 256);
404        assert_eq!(packet.get_id().get_value(), 4);
405        assert_eq!(packet.get_payload(), data);
406
407        assert_eq!(packet.get_full_packet(), init_data);
408        assert_eq!(packet.len(), init_data.len());
409    }
410
411    #[test]
412    fn test_packet_creation_valid_varint_length_id() {
413        // Length = ID(varint) + Data = ?
414        // ID = 1000
415        // Data = &[1, 2, 3]
416
417        let id: Vec<u8> = VarInt::from_value(1000).unwrap().get_bytes().to_vec(); // Length
418        let data = &[1, 2, 3];
419        let length = VarInt::from_value((id.len() + data.len()) as i32)
420            .unwrap()
421            .get_bytes()
422            .to_vec();
423
424        let mut init_data = Vec::new();
425        init_data.extend(length);
426        init_data.extend(&id);
427        init_data.extend(data);
428
429        let packet: Packet = Packet::new(&init_data).expect("Failed to create packet");
430
431        assert_eq!(packet.get_length(), id.len() + data.len());
432        assert_eq!(packet.get_id().get_value(), 1000);
433        assert_eq!(packet.get_payload(), data);
434
435        assert_eq!(packet.get_full_packet(), init_data);
436        assert_eq!(packet.len(), init_data.len());
437    }
438}