aboutsummaryrefslogtreecommitdiff
path: root/minecraft-protocol/src
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-15 13:43:57 -0600
committermat <github@matdoes.dev>2021-12-15 13:43:57 -0600
commit732de94d7b9f1bf2bc9239c8138a37c53242b470 (patch)
treeeaeaddbf73bf5379fbb1924e57a28b8dad5be48b /minecraft-protocol/src
parentace140500734d33fe53126086a8d9278fa861e21 (diff)
downloadazalea-drasl-732de94d7b9f1bf2bc9239c8138a37c53242b470.tar.xz
oh yeah it compiles
Diffstat (limited to 'minecraft-protocol/src')
-rw-r--r--minecraft-protocol/src/connect.rs121
-rw-r--r--minecraft-protocol/src/lib.rs2
-rw-r--r--minecraft-protocol/src/packets/game/mod.rs41
-rw-r--r--minecraft-protocol/src/packets/handshake/mod.rs2
-rw-r--r--minecraft-protocol/src/read.rs28
-rw-r--r--minecraft-protocol/src/write.rs27
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();
+}