Skip to main content

deepslate_protocol/packet/
handshake.rs

1//! Handshake packet (serverbound).
2
3use bytes::{Buf, BufMut};
4
5use crate::types::{self, ProtocolError};
6use crate::varint;
7
8use super::Packet;
9
10/// The intent declared in the handshake, determining the next protocol state.
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum HandshakeIntent {
13    /// Server list ping (STATUS).
14    Status = 1,
15    /// Player login (LOGIN).
16    Login = 2,
17    /// Server transfer (1.20.5+).
18    Transfer = 3,
19}
20
21impl HandshakeIntent {
22    /// Parse from the protocol integer value.
23    ///
24    /// # Errors
25    ///
26    /// Returns `ProtocolError::InvalidData` if the value is not recognized.
27    pub fn from_id(id: i32) -> Result<Self, ProtocolError> {
28        match id {
29            1 => Ok(Self::Status),
30            2 => Ok(Self::Login),
31            3 => Ok(Self::Transfer),
32            _ => Err(ProtocolError::InvalidData(format!(
33                "unknown handshake intent: {id}"
34            ))),
35        }
36    }
37}
38
39/// Serverbound handshake packet (packet ID 0x00 in HANDSHAKE state).
40#[derive(Debug, Clone)]
41pub struct HandshakePacket {
42    /// The protocol version the client is using.
43    pub protocol_version: i32,
44    /// The server address the client connected to.
45    pub server_address: String,
46    /// The server port the client connected to.
47    pub server_port: u16,
48    /// The intended next state.
49    pub next_state: HandshakeIntent,
50}
51
52impl Packet for HandshakePacket {
53    const PACKET_ID: i32 = 0x00;
54
55    fn decode(buf: &mut impl Buf) -> Result<Self, ProtocolError> {
56        let protocol_version = varint::read_var_int(buf)?;
57        let server_address = types::read_string_max(buf, 255)?;
58        if buf.remaining() < 2 {
59            return Err(ProtocolError::UnexpectedEof);
60        }
61        let server_port = buf.get_u16();
62        let next_state_id = varint::read_var_int(buf)?;
63        let next_state = HandshakeIntent::from_id(next_state_id)?;
64
65        Ok(Self {
66            protocol_version,
67            server_address,
68            server_port,
69            next_state,
70        })
71    }
72
73    fn encode(&self, buf: &mut impl BufMut) {
74        varint::write_var_int(buf, self.protocol_version);
75        types::write_string(buf, &self.server_address);
76        buf.put_u16(self.server_port);
77        varint::write_var_int(buf, self.next_state as i32);
78    }
79}