deepslate_protocol/packet/
handshake.rs1use bytes::{Buf, BufMut};
4
5use crate::types::{self, ProtocolError};
6use crate::varint;
7
8use super::Packet;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum HandshakeIntent {
13 Status = 1,
15 Login = 2,
17 Transfer = 3,
19}
20
21impl HandshakeIntent {
22 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#[derive(Debug, Clone, PartialEq, Eq)]
41pub struct HandshakePacket {
42 pub protocol_version: i32,
44 pub server_address: String,
46 pub server_port: u16,
48 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}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use proptest::prelude::*;
85
86 fn handshake_intent_strategy() -> impl Strategy<Value = HandshakeIntent> {
87 prop_oneof![
88 Just(HandshakeIntent::Status),
89 Just(HandshakeIntent::Login),
90 Just(HandshakeIntent::Transfer),
91 ]
92 }
93
94 proptest! {
95 #[test]
96 fn handshake_roundtrip(
97 protocol_version: i32,
98 server_address: String,
99 server_port: u16,
100 next_state in handshake_intent_strategy()
101 ) {
102 let server_address = if server_address.len() > 255 { server_address[..255].to_string() } else { server_address };
103 let packet = HandshakePacket {
104 protocol_version,
105 server_address,
106 server_port,
107 next_state,
108 };
109 let mut buf = Vec::new();
110 packet.encode(&mut buf);
111 let decoded = HandshakePacket::decode(&mut &buf[..]).unwrap();
112 prop_assert_eq!(decoded, packet);
113 }
114 }
115}