kojacoord_protocol/versions/v1_7_10/handshake/
mod.rs1use 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}