init commit??

This commit is contained in:
MeexReay 2024-05-12 00:11:25 +03:00
parent 32c09ce144
commit 39df5454a2
6 changed files with 444 additions and 0 deletions

73
Cargo.lock generated Normal file
View File

@ -0,0 +1,73 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "bytebuffer"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7bfaf7cd08cacd74cdc6b521c37ac39cbc92692e5ab5c21ed5657a749b577c"
dependencies = [
"byteorder",
]
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crc32fast"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
dependencies = [
"cfg-if",
]
[[package]]
name = "flate2"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "miniz_oxide"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
[[package]]
name = "rust_mc_proto"
version = "0.1.0"
dependencies = [
"bytebuffer",
"flate2",
"varint-rs",
]
[[package]]
name = "varint-rs"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"

15
Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "rust_mc_proto"
description = "Minecraft packets protocol in pure rust"
license-file = "LICENSE"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
varint-rs = "2.2.0"
flate2 = "1.0.30"
bytebuffer = "2.2.0"

13
LICENSE Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

View File

@ -1 +1,2 @@
# rust_mc_proto
Minecraft packets protocol in pure rust

305
src/lib.rs Normal file
View File

@ -0,0 +1,305 @@
use std::io::{Write, Read};
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use bytebuffer::ByteBuffer;
use varint_rs::{VarintWriter, VarintReader};
use flate2::{Compress, Compression, Decompress, FlushCompress, Status, FlushDecompress};
#[derive(Debug)]
pub enum ProtocolError {
AddressParseError,
DataRanOutError,
StringParseError,
StreamConnectError,
VarIntError,
ReadError,
WriteError,
ZlibError,
UnsignedShortError
}
#[derive(Debug)]
pub struct Packet {
pub id: u8,
pub buffer: ByteBuffer
}
impl VarintWriter for Packet {
type Error = ProtocolError;
fn write(&mut self, byte: u8) -> Result<(), Self::Error> {
match Write::write(&mut self.buffer, &[byte]) {
Ok(_) => Ok(()),
Err(_) => Err(ProtocolError::WriteError)
}
}
}
impl VarintReader for Packet {
type Error = ProtocolError;
fn read(&mut self) -> Result<u8, Self::Error> {
let mut buf = vec![0; 1];
match Read::read(&mut self.buffer, &mut buf) {
Ok(i) => {
if i == 1 {
Ok(buf[0])
} else {
Err(ProtocolError::ReadError)
}
},
Err(_) => Err(ProtocolError::ReadError),
}
}
}
impl Packet {
pub fn new(id: u8, buffer: ByteBuffer) -> Packet {
Packet {
id,
buffer
}
}
pub fn from_bytes(id: u8, data: &[u8]) -> Packet {
Packet {
id,
buffer: ByteBuffer::from_bytes(data)
}
}
pub fn empty(id: u8) -> Packet {
Packet {
id,
buffer: ByteBuffer::new()
}
}
pub fn write_string(&mut self, s: String) -> Result<(), ProtocolError> {
let bytes = s.as_bytes();
self.write_usize_varint(bytes.len())?;
for b in bytes {
self.write(*b)?;
}
Ok(())
}
pub fn read_string(&mut self) -> Result<String, ProtocolError> {
let size = self.read_usize_varint()?;
let mut bytes: Vec<u8> = vec![0; size];
for _ in 0..size {
bytes.push(self.read()?);
}
match String::from_utf8(bytes) {
Ok(i) => Ok(i),
Err(_) => Err(ProtocolError::StringParseError)
}
}
pub fn write_unsigned_short(&mut self, short: u16) -> Result<(), ProtocolError> {
match self.buffer.write_all(&short.to_be_bytes()) {
Ok(_) => Ok(()),
Err(_) => Err(ProtocolError::UnsignedShortError),
}
}
}
pub struct Connection {
pub stream: TcpStream,
pub addr: SocketAddr,
compress: bool,
compress_threashold: usize
}
impl Connection {
pub fn build(addr: &str) -> Result<Connection, ProtocolError> {
let addr = match addr.to_socket_addrs() {
Ok(mut i) => { match i.next() {
Some(i) => { i },
None => { return Err(ProtocolError::AddressParseError) },
} },
Err(_) => { return Err(ProtocolError::AddressParseError) },
};
let stream: TcpStream = match TcpStream::connect(&addr) {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::StreamConnectError) },
};
Ok(Connection {
stream,
addr,
compress: false,
compress_threashold: 0
})
}
pub fn new(addr: &str) -> Connection {
Self::build(addr).unwrap()
}
pub fn set_compression(&mut self, threashold: usize) {
self.compress = true;
self.compress_threashold = threashold;
}
pub fn read_packet(&mut self) -> Result<Packet, ProtocolError> {
if !self.compress {
let length = self.read_usize_varint()?;
let packet_id = self.read_u8_varint()?;
let mut data: Vec<u8> = vec![0; length - 1];
match self.stream.read_exact(&mut data) {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::ReadError) },
};
Ok(Packet::from_bytes(packet_id, &data))
} else {
let packet_length = self.read_usize_varint()?;
let data_length = self.read_usize_varint()?;
if data_length == 0 {
let mut data: Vec<u8> = vec![0; packet_length - 1];
match self.stream.read_exact(&mut data) {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::ReadError) },
};
let mut data_buf = ByteBuffer::from_vec(decompress_zlib(&data)?);
let packet_id = match data_buf.read_u8_varint() {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::VarIntError) },
};
let mut data: Vec<u8> = vec![0; data_length - 1];
match data_buf.read_exact(&mut data) {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::ReadError) },
};
Ok(Packet::from_bytes(packet_id, &data))
} else {
let packet_id = self.read_u8_varint()?;
let mut data: Vec<u8> = vec![0; data_length - 1];
match self.stream.read_exact(&mut data) {
Ok(i) => i,
Err(_) => { return Err(ProtocolError::ReadError) },
};
Ok(Packet::from_bytes(packet_id, &data))
}
}
}
pub fn write_packet(&mut self, packet: &Packet) -> Result<(), ProtocolError> {
let mut buf = ByteBuffer::new();
if !self.compress {
match buf.write_usize_varint(packet.buffer.len() + 1) {
Ok(_) => {},
Err(_) => { return Err(ProtocolError::WriteError) },
};
match buf.write_u8_varint(packet.id) {
Ok(_) => {},
Err(_) => { return Err(ProtocolError::WriteError) },
};
match buf.write_all(packet.buffer.as_bytes()) {
Ok(_) => {},
Err(_) => { return Err(ProtocolError::WriteError) },
};
} else {
let mut pack = ByteBuffer::new();
if packet.buffer.len() < self.compress_threashold {
pack.write_usize_varint(0).unwrap();
pack.write_u8_varint(packet.id).unwrap();
pack.write_all(packet.buffer.as_bytes()).unwrap();
} else {
let mut data = ByteBuffer::new();
data.write_u8_varint(packet.id).unwrap();
data.write_all(packet.buffer.as_bytes()).unwrap();
let data = compress_zlib(data.as_bytes())?;
pack.write_usize_varint(packet.buffer.len() + 1).unwrap();
pack.write_all(&data).unwrap();
}
buf.write_usize_varint(pack.len()).unwrap();
buf.write_all(pack.as_bytes()).unwrap();
}
self.stream.write_all(buf.as_bytes()).unwrap();
Ok(())
}
pub fn close(&mut self) {
self.stream.shutdown(std::net::Shutdown::Both).unwrap();
}
}
impl VarintWriter for Connection {
type Error = ProtocolError;
fn write(&mut self, byte: u8) -> Result<(), Self::Error> {
match Write::write(&mut self.stream, &[byte]) {
Ok(_) => Ok(()),
Err(_) => Err(ProtocolError::WriteError),
}
}
}
impl VarintReader for Connection {
type Error = ProtocolError;
fn read(&mut self) -> Result<u8, Self::Error> {
let mut buf = vec![0; 1];
match Read::read(&mut self.stream, &mut buf) {
Ok(i) => {
if i == 1 {
Ok(buf[0])
} else {
Err(ProtocolError::ReadError)
}
},
Err(_) => Err(ProtocolError::ReadError),
}
}
}
fn compress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> {
let mut compresser = Compress::new(Compression::best(), true);
let mut output: Vec<u8> = Vec::new();
match compresser.compress_vec(&bytes, &mut output, FlushCompress::Finish) {
Ok(i) => {
match i {
Status::Ok => Ok(output),
_ => Err(ProtocolError::ZlibError)
}
},
Err(_) => Err(ProtocolError::ZlibError)
}
}
fn decompress_zlib(bytes: &[u8]) -> Result<Vec<u8>, ProtocolError> {
let mut compresser = Decompress::new(true);
let mut output: Vec<u8> = Vec::new();
match compresser.decompress_vec(&bytes, &mut output, FlushDecompress::Finish) {
Ok(i) => {
match i {
Status::Ok => Ok(output),
_ => Err(ProtocolError::ZlibError)
}
},
Err(_) => Err(ProtocolError::ZlibError)
}
}

37
src/main.rs Normal file
View File

@ -0,0 +1,37 @@
use rust_mc_proto::{Connection, Packet, ProtocolError};
use varint_rs::{VarintReader, VarintWriter};
use std::io::Write;
fn send_handshake(conn: &mut Connection,
protocol_version: u16,
server_address: &str,
server_port: u16,
next_state: u8) -> Result<(), ProtocolError> {
let mut packet = Packet::empty(0x00);
packet.write_u16_varint(protocol_version)?;
packet.write_string(server_address.to_string())?;
packet.write_unsigned_short(server_port)?;
packet.write_u8_varint(next_state)?;
packet.buffer.set_rpos(0);
packet.buffer.set_wpos(0);
conn.write_packet(&packet)
}
fn send_status_request(conn: &mut Connection) -> Result<(), ProtocolError> {
conn.write_packet(&Packet::empty(0x00))
}
fn read_status_response(conn: &mut Connection) -> Result<String, ProtocolError> {
let mut packet = conn.read_packet()?;
packet.read_string()
}
fn main() {
let mut conn = Connection::new("localhost:25565");
send_handshake(&mut conn, 765, "localhost", 25565, 1).unwrap();
send_status_request(&mut conn).unwrap();
println!("{}", read_status_response(&mut conn).unwrap());
}