diff options
| author | mat <github@matdoes.dev> | 2021-12-15 13:43:57 -0600 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2021-12-15 13:43:57 -0600 |
| commit | 732de94d7b9f1bf2bc9239c8138a37c53242b470 (patch) | |
| tree | eaeaddbf73bf5379fbb1924e57a28b8dad5be48b /minecraft-protocol/src | |
| parent | ace140500734d33fe53126086a8d9278fa861e21 (diff) | |
| download | azalea-drasl-732de94d7b9f1bf2bc9239c8138a37c53242b470.tar.xz | |
oh yeah it compiles
Diffstat (limited to 'minecraft-protocol/src')
| -rw-r--r-- | minecraft-protocol/src/connect.rs | 121 | ||||
| -rw-r--r-- | minecraft-protocol/src/lib.rs | 2 | ||||
| -rw-r--r-- | minecraft-protocol/src/packets/game/mod.rs | 41 | ||||
| -rw-r--r-- | minecraft-protocol/src/packets/handshake/mod.rs | 2 | ||||
| -rw-r--r-- | minecraft-protocol/src/read.rs | 28 | ||||
| -rw-r--r-- | minecraft-protocol/src/write.rs | 27 |
6 files changed, 168 insertions, 53 deletions
diff --git a/minecraft-protocol/src/connect.rs b/minecraft-protocol/src/connect.rs index 5b750802..7c6a5f18 100644 --- a/minecraft-protocol/src/connect.rs +++ b/minecraft-protocol/src/connect.rs @@ -1,6 +1,12 @@ //! parse sending and receiving packets with a server. -use crate::packets::ConnectionProtocol; +use crate::packets::game::GamePacket; +use crate::packets::handshake::HandshakePacket; +use crate::packets::login::LoginPacket; +use crate::packets::status::StatusPacket; +use crate::packets::{ConnectionProtocol, ProtocolPacket}; +use crate::read::read_packet; +use crate::write::write_packet; use crate::{mc_buf, packets::Packet, ServerIpAddress}; use tokio::io::AsyncWriteExt; use tokio::{ @@ -13,15 +19,32 @@ pub enum PacketFlow { ServerToClient, } -pub struct Connection { - pub state: ConnectionProtocol, +pub struct HandshakeConnection { pub flow: PacketFlow, /// The buffered writer pub stream: TcpStream, } -impl Connection { - pub async fn new(address: &ServerIpAddress) -> Result<Connection, String> { +pub struct GameConnection { + pub flow: PacketFlow, + /// The buffered writer + pub stream: TcpStream, +} + +pub struct StatusConnection { + pub flow: PacketFlow, + /// The buffered writer + pub stream: TcpStream, +} + +pub struct LoginConnection { + pub flow: PacketFlow, + /// The buffered writer + pub stream: TcpStream, +} + +impl HandshakeConnection { + pub async fn new(address: &ServerIpAddress) -> Result<HandshakeConnection, String> { let ip = address.ip; let port = address.port; @@ -34,67 +57,65 @@ impl Connection { .set_nodelay(true) .expect("Error enabling tcp_nodelay"); - Ok(Connection { - state: ConnectionProtocol::Handshake, + Ok(HandshakeConnection { flow: PacketFlow::ServerToClient, stream, }) } - pub fn switch_state(&mut self, state: ConnectionProtocol) { - self.state = state; + pub fn login(self) -> LoginConnection { + LoginConnection { + flow: self.flow, + stream: self.stream, + } } - pub async fn read_packet(&mut self) -> Result<Packet, String> { - // what this does: - // 1. reads the first 5 bytes, probably only some of this will be used to get the packet length - // 2. how much we should read = packet length - 5 - // 3. read the rest of the packet and add it to the cursor - // 4. figure out what packet this is and parse it - - // the first thing minecraft sends us is the length as a varint, which can be up to 5 bytes long - let mut buf = BufReader::with_capacity(4 * 1024 * 1024, &mut self.stream); - - let (_packet_size, _packet_size_varint_size) = mc_buf::read_varint(&mut buf).await?; - - // then, minecraft tells us the packet id as a varint - let (packet_id, _packet_id_size) = mc_buf::read_varint(&mut buf).await?; + pub fn status(self) -> StatusConnection { + StatusConnection { + flow: self.flow, + stream: self.stream, + } + } - // if we recognize the packet id, parse it + pub async fn read(&mut self) -> Result<HandshakePacket, String> { + read_packet::<HandshakePacket>(&self.flow, &mut self.stream).await + } - let packet = Packet::read( - packet_id.try_into().unwrap(), - &self.state, - &self.flow, - &mut buf, - ) - .await?; + /// Write a packet to the server + pub async fn write(&mut self, packet: HandshakePacket) { + write_packet(packet, &mut self.stream).await; + } +} - Ok(packet) +impl GameConnection { + pub async fn read(&mut self) -> Result<GamePacket, String> { + read_packet::<GamePacket>(&self.flow, &mut self.stream).await } /// Write a packet to the server - pub async fn send_packet(&mut self, packet: Packet) { - // TODO: implement compression - - // packet structure: - // length (varint) + id (varint) + data + pub async fn write(&mut self, packet: GamePacket) { + write_packet(packet, &mut self.stream).await; + } +} - // write the packet id - let mut id_and_data_buf = vec![]; - mc_buf::write_varint(&mut id_and_data_buf, packet.id() as i32); - packet.write(&mut id_and_data_buf); +impl StatusConnection { + pub async fn read(&mut self) -> Result<StatusPacket, String> { + read_packet::<StatusPacket>(&self.flow, &mut self.stream).await + } - // write the packet data + /// Write a packet to the server + pub async fn write(&mut self, packet: StatusPacket) { + write_packet(packet, &mut self.stream).await; + } +} - // make a new buffer that has the length at the beginning - // and id+data at the end - let mut complete_buf: Vec<u8> = Vec::new(); - mc_buf::write_varint(&mut complete_buf, id_and_data_buf.len() as i32); - complete_buf.append(&mut id_and_data_buf); +impl LoginConnection { + pub async fn read(&mut self) -> Result<LoginPacket, String> { + read_packet::<LoginPacket>(&self.flow, &mut self.stream).await + } - // finally, write and flush to the stream - self.stream.write_all(&complete_buf).await.unwrap(); - self.stream.flush().await.unwrap(); + /// Write a packet to the server + pub async fn write(&mut self, packet: LoginPacket) { + write_packet(packet, &mut self.stream).await; } } diff --git a/minecraft-protocol/src/lib.rs b/minecraft-protocol/src/lib.rs index 31b50164..684add45 100644 --- a/minecraft-protocol/src/lib.rs +++ b/minecraft-protocol/src/lib.rs @@ -6,7 +6,9 @@ use std::str::FromStr; pub mod connect; pub mod mc_buf; pub mod packets; +pub mod read; pub mod resolver; +pub mod write; #[derive(Debug)] pub struct ServerAddress { diff --git a/minecraft-protocol/src/packets/game/mod.rs b/minecraft-protocol/src/packets/game/mod.rs index 08444697..06d8ae4c 100644 --- a/minecraft-protocol/src/packets/game/mod.rs +++ b/minecraft-protocol/src/packets/game/mod.rs @@ -1,2 +1,41 @@ +use async_trait::async_trait; +use tokio::io::BufReader; + +use crate::connect::PacketFlow; + +use super::ProtocolPacket; + #[derive(Clone, Debug)] -pub enum GamePacket {} +pub enum GamePacket +where + Self: Sized, {} + +#[async_trait] +impl ProtocolPacket for GamePacket { + fn id(&self) -> u32 { + match self { + _ => 0x00, + } + } + + fn write(&self, buf: &mut Vec<u8>) { + match self { + _ => (), + } + } + + /// Read a packet by its id, ConnectionProtocol, and flow + async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>( + id: u32, + flow: &PacketFlow, + buf: &mut BufReader<T>, + ) -> Result<GamePacket, String> + where + Self: Sized, + { + match flow { + PacketFlow::ServerToClient => Err("HandshakePacket::read not implemented".to_string()), + PacketFlow::ClientToServer => Err("HandshakePacket::read not implemented".to_string()), + } + } +} diff --git a/minecraft-protocol/src/packets/handshake/mod.rs b/minecraft-protocol/src/packets/handshake/mod.rs index 792588b5..01010e1e 100644 --- a/minecraft-protocol/src/packets/handshake/mod.rs +++ b/minecraft-protocol/src/packets/handshake/mod.rs @@ -1,7 +1,5 @@ pub mod client_intention_packet; -use std::f32::consts::E; - use async_trait::async_trait; use tokio::io::BufReader; diff --git a/minecraft-protocol/src/read.rs b/minecraft-protocol/src/read.rs new file mode 100644 index 00000000..7f4eeaac --- /dev/null +++ b/minecraft-protocol/src/read.rs @@ -0,0 +1,28 @@ +use tokio::{io::BufReader, net::TcpStream}; + +use crate::{connect::PacketFlow, mc_buf, packets::ProtocolPacket}; + +pub async fn read_packet<P: ProtocolPacket>( + flow: &PacketFlow, + stream: &mut TcpStream, +) -> Result<P, String> { + // what this does: + // 1. reads the first 5 bytes, probably only some of this will be used to get the packet length + // 2. how much we should read = packet length - 5 + // 3. read the rest of the packet and add it to the cursor + // 4. figure out what packet this is and parse it + + // the first thing minecraft sends us is the length as a varint, which can be up to 5 bytes long + let mut buf = BufReader::with_capacity(4 * 1024 * 1024, stream); + + let (_packet_size, _packet_size_varint_size) = mc_buf::read_varint(&mut buf).await?; + + // then, minecraft tells us the packet id as a varint + let (packet_id, _packet_id_size) = mc_buf::read_varint(&mut buf).await?; + + // if we recognize the packet id, parse it + + let packet = P::read(packet_id.try_into().unwrap(), &flow, &mut buf).await?; + + Ok(packet) +} diff --git a/minecraft-protocol/src/write.rs b/minecraft-protocol/src/write.rs new file mode 100644 index 00000000..529bb210 --- /dev/null +++ b/minecraft-protocol/src/write.rs @@ -0,0 +1,27 @@ +use tokio::{io::AsyncWriteExt, net::TcpStream}; + +use crate::{mc_buf, packets::ProtocolPacket}; + +pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) { + // TODO: implement compression + + // packet structure: + // length (varint) + id (varint) + data + + // write the packet id + let mut id_and_data_buf = vec![]; + mc_buf::write_varint(&mut id_and_data_buf, packet.id() as i32); + packet.write(&mut id_and_data_buf); + + // write the packet data + + // make a new buffer that has the length at the beginning + // and id+data at the end + let mut complete_buf: Vec<u8> = Vec::new(); + mc_buf::write_varint(&mut complete_buf, id_and_data_buf.len() as i32); + complete_buf.append(&mut id_and_data_buf); + + // finally, write and flush to the stream + stream.write_all(&complete_buf).await.unwrap(); + stream.flush().await.unwrap(); +} |
