1#[cfg(test)]
2mod tests;
3
4pub mod data;
5pub mod packet;
6
7pub mod prelude {
8 pub use crate::{DataReader, DataWriter};
9}
10
11pub use crate::{
12 data::{DataReader, DataWriter},
13 packet::Packet,
14};
15
16use flate2::{read::ZlibDecoder, write::ZlibEncoder, Compression};
17use std::{
18 error::Error, fmt, io::{Read, Write}, net::{TcpStream, ToSocketAddrs}, usize
19};
20
21#[derive(Debug)]
23pub enum ProtocolError {
24 AddressParseError,
25 DataRanOutError,
26 StringParseError,
27 StreamConnectError,
28 VarIntError,
29 ReadError,
30 WriteError,
31 ZlibError,
32 CloneError,
33 ConnectionClosedError
34}
35
36impl fmt::Display for ProtocolError {
37 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38 write!(f, "An protocol error occured")
39 }
40}
41
42impl Error for ProtocolError {}
43
44pub struct MinecraftConnection<T: Read + Write> {
46 stream: T,
47 compression: Option<usize>,
48 compression_type: u32
49}
50
51impl<T: Read + Write> DataReader for MinecraftConnection<T> {
52 fn read_bytes(&mut self, size: usize) -> Result<Vec<u8>, ProtocolError> {
53 let mut buf = vec![0; size];
54 match self.stream.read_exact(&mut buf) {
55 Ok(_) => Ok(buf),
56 Err(_) => Err(ProtocolError::ReadError),
57 }
58 }
59}
60
61impl<T: Read + Write> DataWriter for MinecraftConnection<T> {
62 fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), ProtocolError> {
63 self.stream.write_all(bytes).map_err(|_| ProtocolError::WriteError)
64 }
65}
66
67impl<T: Read + Write> MinecraftConnection<T> {
68 pub fn new(stream: T) -> MinecraftConnection<T> {
70 MinecraftConnection {
71 stream,
72 compression: None,
73 compression_type: 1,
74 }
75 }
76
77 pub fn set_compression(&mut self, threshold: Option<usize>) {
79 self.compression = threshold;
80 }
81
82 pub fn compression(&self) -> Option<usize> {
84 self.compression
85 }
86
87 pub fn set_compression_type(&mut self, compression_type: u32) {
93 self.compression_type = compression_type;
94 }
95
96 pub fn compression_type(&self) -> u32 {
102 self.compression_type
103 }
104
105 pub fn get_mut(&mut self) -> &mut T {
107 &mut self.stream
108 }
109
110 pub fn get_ref(&self) -> &T {
112 &self.stream
113 }
114
115 pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
117 read_packet(&mut self.stream, self.compression)
118 }
119
120 pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
122 write_packet(&mut self.stream, self.compression, self.compression_type, packet)
123 }
124}
125
126impl<T: Read + Write + Clone> MinecraftConnection<T> {
127 pub fn clone(&mut self) -> MinecraftConnection<T> {
129 MinecraftConnection {
130 stream: self.stream.clone(),
131 compression: self.compression,
132 compression_type: self.compression_type,
133 }
134 }
135}
136
137impl MinecraftConnection<TcpStream> {
138 pub fn connect(addr: impl ToSocketAddrs) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
140 let addr = match addr.to_socket_addrs() {
141 Ok(mut i) => match i.next() {
142 Some(i) => i,
143 None => return Err(ProtocolError::AddressParseError),
144 },
145 Err(_) => return Err(ProtocolError::AddressParseError),
146 };
147
148 let stream: TcpStream = match TcpStream::connect(&addr) {
149 Ok(i) => i,
150 Err(_) => return Err(ProtocolError::StreamConnectError),
151 };
152
153 Ok(MinecraftConnection {
154 stream,
155 compression: None,
156 compression_type: 1,
157 })
158 }
159
160 pub fn close(&mut self) {
162 let _ = self.stream.shutdown(std::net::Shutdown::Both);
163 }
164
165 pub fn try_clone(&self) -> Result<MinecraftConnection<TcpStream>, ProtocolError> {
167 match self.stream.try_clone() {
168 Ok(stream) => Ok(MinecraftConnection {
169 stream,
170 compression: self.compression,
171 compression_type: self.compression_type,
172 }),
173 _ => Err(ProtocolError::CloneError),
174 }
175 }
176}
177
178fn compress_zlib(bytes: &[u8], compression: u32) -> Result<Vec<u8>, ProtocolError> {
179 let mut encoder = ZlibEncoder::new(Vec::new(), Compression::new(compression));
180 encoder.write_all(bytes).or(Err(ProtocolError::ZlibError))?;
181 encoder.finish().or(Err(ProtocolError::ZlibError))
182}
183
184fn decompress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> {
185 let mut decoder = ZlibDecoder::new(bytes);
186 let mut output = Vec::new();
187 decoder
188 .read_to_end(&mut output)
189 .or(Err(ProtocolError::ZlibError))?;
190 Ok(output)
191}
192
193pub type MCConn<T> = MinecraftConnection<T>;
195
196pub type MCConnTcp = MinecraftConnection<TcpStream>;
198
199
200pub fn read_packet<T: Read>(
207 stream: &mut T,
208 compression: Option<usize>
209) -> Result<Packet, ProtocolError> {
210 let mut data: Vec<u8>;
211
212 let packet_length = stream.read_usize_varint_size()?;
213
214 if compression.is_some() {
215 let data_length = stream.read_usize_varint_size()?;
216
217 data = stream.read_bytes(packet_length.0 - data_length.1)?;
218
219 if data_length.0 != 0 {
220 data = decompress_zlib(&data)?;
221 }
222 } else {
223 data = stream.read_bytes(packet_length.0 as usize)?;
224 }
225
226 Ok(Packet::from_data(&data)?)
227}
228
229pub fn write_packet<T: Write>(
240 stream: &mut T,
241 compression: Option<usize>,
242 compression_type: u32,
243 packet: &Packet,
244) -> Result<(), ProtocolError> {
245 let mut buf = Vec::new();
246
247 let mut data_buf = Vec::new();
248 data_buf.write_varint(packet.id() as i32)?;
249 data_buf.write_bytes(packet.get_bytes())?;
250
251 if let Some(compression) = compression {
252 let mut packet_buf = Vec::new();
253
254 if data_buf.len() >= compression {
255 let compressed_data = compress_zlib(&data_buf, compression_type)?;
256 packet_buf.write_varint(data_buf.len() as i32)?;
257 packet_buf
258 .write_all(&compressed_data)
259 .or(Err(ProtocolError::WriteError))?;
260 } else {
261 packet_buf.write_varint(0)?;
262 packet_buf.write_bytes(&data_buf)?;
263 }
264
265 buf.write_varint(packet_buf.len() as i32)?;
266 buf.write_bytes(&packet_buf)?;
267 } else {
268 buf.write_varint(data_buf.len() as i32)?;
269 buf.write_bytes(&data_buf)?;
270 }
271
272 stream.write_bytes(&buf)?;
273
274 Ok(())
275}