nurtex_protocol/connection/
reader.rs1use std::fmt::Debug;
2use std::io::{Cursor, Read};
3use std::sync::Arc;
4use std::sync::atomic::{AtomicI8, AtomicI32, Ordering};
5
6use bytes::{Buf, Bytes, BytesMut};
7use flate2::read::ZlibDecoder;
8use futures::StreamExt;
9use nurtex_codec::types::variable::VarI32;
10use nurtex_encrypt::AesDecryptor;
11use tokio::io::AsyncRead;
12use tokio::net::tcp::OwnedReadHalf;
13use tokio::sync::Mutex;
14use tokio_util::codec::{BytesCodec, FramedRead};
15
16use crate::ProtocolPacket;
17use crate::connection::{ClientsidePacket, ConnectionState};
18use crate::packets::configuration::ClientsideConfigurationPacket;
19use crate::packets::handshake::ClientsideHandshakePacket;
20use crate::packets::login::ClientsideLoginPacket;
21use crate::packets::play::ClientsidePlayPacket;
22use crate::packets::status::ClientsideStatusPacket;
23
24pub struct ConnectionReader {
26 pub read_stream: Option<OwnedReadHalf>,
28
29 pub buffer: BytesMut,
31
32 pub decryptor: Arc<Mutex<Option<AesDecryptor>>>,
34
35 pub state: Arc<AtomicI8>,
37
38 pub compression_threshold: Arc<AtomicI32>,
40}
41
42impl ConnectionReader {
43 pub async fn read_packet(&mut self) -> Option<ClientsidePacket> {
45 let Some(read_half) = &mut self.read_stream else {
46 return None;
47 };
48
49 let compression_threshold = self.compression_threshold.load(Ordering::SeqCst);
50 let state = ConnectionState::from(self.state.load(Ordering::SeqCst));
51 let mut decryptor_guard = self.decryptor.lock().await;
52
53 let raw_packet = read_raw_packet(read_half, &mut self.buffer, compression_threshold, &mut *decryptor_guard).await?;
54 let mut cursor = Cursor::new(&raw_packet[..]);
55
56 match state {
57 ConnectionState::Handshake => deserialize_packet::<ClientsideHandshakePacket>(&mut cursor).map(ClientsidePacket::Handshake),
58 ConnectionState::Status => deserialize_packet::<ClientsideStatusPacket>(&mut cursor).map(ClientsidePacket::Status),
59 ConnectionState::Login => deserialize_packet::<ClientsideLoginPacket>(&mut cursor).map(ClientsidePacket::Login),
60 ConnectionState::Configuration => deserialize_packet::<ClientsideConfigurationPacket>(&mut cursor).map(ClientsidePacket::Configuration),
61 ConnectionState::Play => deserialize_packet::<ClientsidePlayPacket>(&mut cursor).map(ClientsidePacket::Play),
62 }
63 }
64}
65
66fn parse_frame(buf: &mut BytesMut) -> Option<Bytes> {
68 let mut temp_buf = Cursor::new(&buf[..]);
69
70 let length = i32::read_var(&mut temp_buf)? as usize;
71 let varint_length = temp_buf.position() as usize;
72
73 if buf.len() < varint_length + length {
74 return None;
75 }
76
77 buf.advance(varint_length);
78
79 let data = buf.split_to(length).freeze();
80
81 if buf.is_empty() && buf.capacity() > 64 * 1024 {
82 buf.clear();
83 buf.reserve(64 * 1024);
84 }
85
86 Some(data)
87}
88
89pub fn deserialize_packet<P: ProtocolPacket + Debug>(buf: &mut Cursor<&[u8]>) -> Option<P> {
91 let packet_id = i32::read_var(buf)? as u32;
92 P::read(packet_id, buf)
93}
94
95pub fn compression_decoder(data: &[u8], compression_threshold: i32) -> Option<Bytes> {
97 let mut cursor = Cursor::new(data);
98 let n = i32::read_var(&mut cursor)?;
99
100 if n == 0 {
101 let remaining = &data[cursor.position() as usize..];
102 return Some(Bytes::copy_from_slice(remaining));
103 }
104
105 if n < compression_threshold || n > 8388608 {
106 return None;
107 }
108
109 let mut buf = Vec::with_capacity(n as usize);
110 let mut decoder = ZlibDecoder::new(&data[cursor.position() as usize..]);
111 decoder.read_to_end(&mut buf).ok()?;
112
113 Some(Bytes::from(buf))
114}
115
116pub async fn read_packet<P: ProtocolPacket + Debug, R>(stream: &mut R, buf: &mut BytesMut, compression_threshold: i32, cipher: &mut Option<AesDecryptor>) -> Option<P>
118where
119 R: AsyncRead + Unpin + Send + Sync,
120{
121 let raw_packet = read_raw_packet(stream, buf, compression_threshold, cipher).await?;
122 let packet = deserialize_packet(&mut Cursor::new(&raw_packet[..]))?;
123 Some(packet)
124}
125
126pub async fn read_raw_packet<R>(stream: &mut R, buf: &mut BytesMut, compression_threshold: i32, cipher: &mut Option<AesDecryptor>) -> Option<Bytes>
128where
129 R: AsyncRead + Unpin + Send + Sync,
130{
131 loop {
132 if let Some(packet) = read_raw_packet_from_buffer(buf, compression_threshold) {
133 return Some(packet);
134 };
135
136 let bytes = read_and_decrypt_frame(stream, cipher).await?;
137 buf.extend_from_slice(&bytes);
138 }
139}
140
141async fn read_and_decrypt_frame<R>(stream: &mut R, cipher: &mut Option<AesDecryptor>) -> Option<Bytes>
143where
144 R: AsyncRead + Unpin + Send + Sync,
145{
146 let mut framed = FramedRead::new(stream, BytesCodec::new());
147
148 let mut bytes = framed.next().await?.ok()?;
149
150 if let Some(cipher) = cipher {
151 nurtex_encrypt::decrypt_data(cipher, &mut bytes);
152 }
153
154 Some(bytes.freeze())
155}
156
157pub fn read_raw_packet_from_buffer(buf: &mut BytesMut, compression_threshold: i32) -> Option<Bytes> {
159 let frame = parse_frame(buf)?;
160
161 if compression_threshold >= 0 {
162 compression_decoder(&frame, compression_threshold)
163 } else {
164 Some(frame)
165 }
166}