Skip to main content

kojacoord_protocol/versions/v1_7_10/handshake/
mod.rs

1use bytes::{Buf, BufMut, Bytes, BytesMut};
2
3use crate::codec::{Decode, Encode, PacketId};
4use crate::error::ProtocolError;
5use crate::types::VarInt;
6
7pub use self::serverbound::ServerboundHandshake;
8
9mod serverbound {
10    use super::*;
11
12    #[derive(Debug, Clone, PartialEq)]
13    pub struct ServerboundHandshake {
14        pub protocol_version: VarInt,
15        pub server_address: String,
16        pub server_port: u16,
17        pub next_state: VarInt,
18    }
19
20    impl PacketId for ServerboundHandshake {
21        fn packet_id(_ver: u32) -> u8 {
22            0x00
23        }
24    }
25
26    impl Encode for ServerboundHandshake {
27        fn encode(&self, dst: &mut BytesMut) -> Result<(), ProtocolError> {
28            self.protocol_version.encode(dst)?;
29
30            let addr_bytes = self.server_address.as_bytes();
31            VarInt(addr_bytes.len() as i32).encode(dst)?;
32            dst.put_slice(addr_bytes);
33
34            dst.put_u16(self.server_port);
35
36            self.next_state.encode(dst)
37        }
38    }
39
40    impl Decode for ServerboundHandshake {
41        fn decode(src: &mut Bytes) -> Result<Self, ProtocolError> {
42            let protocol_version = VarInt::decode(src)?;
43
44            let addr_len = VarInt::decode(src)?.0 as usize;
45            if src.remaining() < addr_len {
46                return Err(ProtocolError::Io(std::io::Error::new(
47                    std::io::ErrorKind::UnexpectedEof,
48                    "Missing bytes for ServerboundHandshake server_address",
49                )));
50            }
51            let mut addr_bytes = vec![0u8; addr_len];
52            src.copy_to_slice(&mut addr_bytes);
53            let server_address = String::from_utf8(addr_bytes).map_err(|_| {
54                ProtocolError::Io(std::io::Error::new(
55                    std::io::ErrorKind::InvalidData,
56                    "Invalid UTF-8 in ServerboundHandshake server_address",
57                ))
58            })?;
59
60            if src.remaining() < 2 {
61                return Err(ProtocolError::Io(std::io::Error::new(
62                    std::io::ErrorKind::UnexpectedEof,
63                    "Missing bytes for ServerboundHandshake server_port",
64                )));
65            }
66            let server_port = src.get_u16();
67
68            let next_state = VarInt::decode(src)?;
69
70            Ok(Self {
71                protocol_version,
72                server_address,
73                server_port,
74                next_state,
75            })
76        }
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    fn roundtrip(pkt: ServerboundHandshake) -> ServerboundHandshake {
85        let mut buf = BytesMut::new();
86        pkt.encode(&mut buf).unwrap();
87        let mut bytes = buf.freeze();
88        ServerboundHandshake::decode(&mut bytes).unwrap()
89    }
90
91    #[test]
92    fn handshake_login() {
93        let p = ServerboundHandshake {
94            protocol_version: VarInt(5),
95            server_address: "localhost".to_string(),
96            server_port: 25565,
97            next_state: VarInt(2),
98        };
99        assert_eq!(roundtrip(p.clone()), p);
100    }
101
102    #[test]
103    fn handshake_status() {
104        let p = ServerboundHandshake {
105            protocol_version: VarInt(5),
106            server_address: "play.example.com".to_string(),
107            server_port: 25565,
108            next_state: VarInt(1),
109        };
110        assert_eq!(roundtrip(p.clone()), p);
111    }
112
113    #[test]
114    fn packet_id_is_zero() {
115        assert_eq!(ServerboundHandshake::packet_id(5), 0x00);
116    }
117}