aboutsummaryrefslogtreecommitdiff
path: root/minecraft-protocol
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2021-12-06 19:59:20 +0000
committermat <github@matdoes.dev>2021-12-06 19:59:20 +0000
commit0b484df40c356cf4fe87f3d3a20eadf59eef42c9 (patch)
tree272b2ad58c7fc850378c5bc97eaae95a79277177 /minecraft-protocol
parent544c8a33940572eb7ad36eeafa94f8a64a1e23bc (diff)
downloadazalea-drasl-0b484df40c356cf4fe87f3d3a20eadf59eef42c9.tar.xz
implement new packet implementation
Diffstat (limited to 'minecraft-protocol')
-rw-r--r--minecraft-protocol/src/connection.rs33
-rw-r--r--minecraft-protocol/src/friendly_byte_buf.rs16
-rw-r--r--minecraft-protocol/src/packets/client_intention_packet.rs17
-rw-r--r--minecraft-protocol/src/packets/mod.rs14
-rw-r--r--minecraft-protocol/src/server_status_pinger.rs79
5 files changed, 65 insertions, 94 deletions
diff --git a/minecraft-protocol/src/connection.rs b/minecraft-protocol/src/connection.rs
index 4fa1cde7..79058a75 100644
--- a/minecraft-protocol/src/connection.rs
+++ b/minecraft-protocol/src/connection.rs
@@ -1,6 +1,9 @@
-use crate::ServerIpAddress;
+use crate::{friendly_byte_buf::FriendlyByteBuf, packets::Packet, ServerIpAddress};
use bytes::BytesMut;
-use tokio::{io::BufWriter, net::TcpStream};
+use tokio::{
+ io::{AsyncWriteExt, BufWriter},
+ net::TcpStream,
+};
pub enum PacketFlow {
ClientToServer,
@@ -35,4 +38,30 @@ impl Connection {
buffer: BytesMut::with_capacity(4 * 1024 * 1024),
})
}
+
+ /// Write a packet to the server
+ pub async fn send_packet(&mut self, packet: &dyn Packet) {
+ // packet structure:
+ // length + id + data
+
+ // Is this efficient? I have no idea, probably not.
+ // getting rid of the FriendlyByteBuffer struct might help
+
+ // write the packet id
+ let mut id_and_data_buf = vec![packet.get_id()];
+
+ // write the packet data
+ let mut id_and_data_friendly_buf = FriendlyByteBuf::new(&mut id_and_data_buf);
+ packet.write(&mut id_and_data_friendly_buf);
+
+ // add the packet length to the beginning
+ let mut complete_buf: Vec<u8> = Vec::new();
+ let mut complete_friendly_buf = FriendlyByteBuf::new(&mut complete_buf);
+ complete_friendly_buf.write_varint(id_and_data_buf.len() as u32);
+ complete_buf.append(&mut id_and_data_buf);
+
+ // finally, write and flush to the stream
+ self.stream.write_all(&complete_buf).await.unwrap();
+ self.stream.flush().await.unwrap();
+ }
}
diff --git a/minecraft-protocol/src/friendly_byte_buf.rs b/minecraft-protocol/src/friendly_byte_buf.rs
index 2babe398..586b0857 100644
--- a/minecraft-protocol/src/friendly_byte_buf.rs
+++ b/minecraft-protocol/src/friendly_byte_buf.rs
@@ -1,22 +1,24 @@
//! Minecraft calls it a "friendly byte buffer".
use byteorder::{BigEndian, WriteBytesExt};
-// use std::io::Write;
-const MAX_VARINT_SIZE: u32 = 5;
-const MAX_VARLONG_SIZE: u32 = 10;
-const DEFAULT_NBT_QUOTA: u32 = 2097152;
+// const MAX_VARINT_SIZE: u32 = 5;
+// const MAX_VARLONG_SIZE: u32 = 10;
+// const DEFAULT_NBT_QUOTA: u32 = 2097152;
const MAX_STRING_LENGTH: u16 = 32767;
-const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
+// const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
pub struct FriendlyByteBuf<'a> {
source: &'a mut Vec<u8>,
}
-impl FriendlyByteBuf<'_> {
+impl<'a> FriendlyByteBuf<'a> {
+ pub fn new(source: &'a mut Vec<u8>) -> FriendlyByteBuf<'a> {
+ FriendlyByteBuf { source }
+ }
+
pub fn write_byte(&mut self, n: u8) {
self.source.write_u8(n).unwrap();
- println!("write_byte: {}", n);
}
pub fn write_bytes(&mut self, bytes: &[u8]) {
diff --git a/minecraft-protocol/src/packets/client_intention_packet.rs b/minecraft-protocol/src/packets/client_intention_packet.rs
index a9a4d86a..30f76387 100644
--- a/minecraft-protocol/src/packets/client_intention_packet.rs
+++ b/minecraft-protocol/src/packets/client_intention_packet.rs
@@ -5,17 +5,19 @@ use crate::friendly_byte_buf::FriendlyByteBuf;
use super::{ConnectionProtocol, Packet};
#[derive(Hash)]
-pub struct ClientIntentionPacket {
- protocol_version: u32,
- hostname: String,
- port: u16,
+pub struct ClientIntentionPacket<'a> {
+ pub protocol_version: u32,
+ pub hostname: &'a String,
+ pub port: u16,
/// 1 for status, 2 for login
- intention: ConnectionProtocol,
+ pub intention: ConnectionProtocol,
}
// implement "Packet" for "ClientIntentionPacket"
-impl Packet for ClientIntentionPacket {
- const ID: u8 = 0x00;
+impl<'a> Packet for ClientIntentionPacket<'a> {
+ fn get_id(&self) -> u8 {
+ 0x00
+ }
// implement "from_reader" for "ClientIntentionPacket"
fn write(&self, buf: &mut FriendlyByteBuf) {
@@ -25,4 +27,3 @@ impl Packet for ClientIntentionPacket {
buf.write_varint(self.intention.clone() as u32);
}
}
-
diff --git a/minecraft-protocol/src/packets/mod.rs b/minecraft-protocol/src/packets/mod.rs
index 2ccdeb44..bdb80c2f 100644
--- a/minecraft-protocol/src/packets/mod.rs
+++ b/minecraft-protocol/src/packets/mod.rs
@@ -1,6 +1,7 @@
-pub mod client_intention_packet;
-
-use std::collections::HashMap;
+mod client_intention_packet;
+pub use client_intention_packet::ClientIntentionPacket;
+mod serverbound_status_request_packet;
+pub use serverbound_status_request_packet::ServerboundStatusRequestPacket;
use crate::friendly_byte_buf::FriendlyByteBuf;
@@ -13,9 +14,8 @@ pub enum ConnectionProtocol {
}
pub trait Packet {
- /// The id of the packet, this is always a byte in vanilla.
- /// This might be bigger than a u8 if using modpacks with lots of custom packets?
- const ID: u8;
-
+ /// Get the id of the packet, this is always a byte.
+ fn get_id(&self) -> u8;
+
fn write(&self, friendly_byte_buf: &mut FriendlyByteBuf) -> ();
}
diff --git a/minecraft-protocol/src/server_status_pinger.rs b/minecraft-protocol/src/server_status_pinger.rs
index 86d0cae9..e9393179 100644
--- a/minecraft-protocol/src/server_status_pinger.rs
+++ b/minecraft-protocol/src/server_status_pinger.rs
@@ -1,81 +1,22 @@
-use crate::{connection::Connection, resolver, ServerAddress};
-use tokio::{
- io::{AsyncReadExt, AsyncWriteExt, BufWriter},
- net::TcpStream,
-};
-
-struct ServerStatus {}
-
-async fn write_byte(buf: &mut Vec<u8>, n: u8) {
- buf.write_u8(n).await.unwrap();
- println!("write_byte: {}", n);
-}
-
-async fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
- buf.write_all(bytes).await.unwrap();
- println!("write_bytes: {:?}", buf);
-}
-
-async fn write_varint(buf: &mut Vec<u8>, mut n: u32) {
- loop {
- if (n & 0xFFFFFF80) == 0 {
- write_byte(buf, n as u8).await;
- return ();
- }
- write_byte(buf, (n & 0x7F | 0x80) as u8).await;
- n >>= 7;
- }
-}
-
-async fn write_utf(buf: &mut Vec<u8>, string: &[u8], len: usize) {
- if string.len() > len {
- panic!(
- "String too big (was {} bytes encoded, max {})",
- string.len(),
- len
- );
- }
- write_varint(buf, string.len() as u32).await;
- write_bytes(buf, string).await;
-}
-
-async fn write_short(buf: &mut Vec<u8>, n: u16) {
- buf.write_u16(n).await.unwrap();
- println!("write_short: {}", n);
-}
+use crate::{connection::Connection, resolver, ServerAddress, packets::{ClientIntentionPacket, ServerboundStatusRequestPacket, ConnectionProtocol}};
+use tokio::io::{AsyncReadExt, AsyncWriteExt};
pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
let resolved_address = resolver::resolve_address(&address).await?;
let mut conn = Connection::new(&resolved_address).await?;
- // protocol version is 757
-
- // client intention packet
- // friendlyByteBuf.writeVarInt(this.protocolVersion);
- // friendlyByteBuf.writeUtf(this.hostName);
- // friendlyByteBuf.writeShort(this.port);
- // friendlyByteBuf.writeVarInt(this.intention.getId());
-
println!("resolved_address {}", &resolved_address.ip);
println!("writing intention packet {}", address.host);
- let mut buf: Vec<u8> = vec![0x00]; // 0 is the packet id for handshake
- write_varint(&mut buf, 757).await;
- write_utf(&mut buf, address.host.as_bytes(), 32767).await;
- write_short(&mut buf, address.port).await;
- write_varint(&mut buf, 1).await;
+ conn.send_packet(&ClientIntentionPacket {
+ protocol_version: 757,
+ hostname: &address.host,
+ port: address.port,
+ intention: ConnectionProtocol::Status,
+ }).await;
+ conn.send_packet(&ServerboundStatusRequestPacket {}).await;
- let mut full_buffer = vec![];
- write_varint(&mut full_buffer, buf.len() as u32).await; // length of 1st packet id + data as VarInt
- full_buffer.append(&mut buf);
- full_buffer.extend_from_slice(&[
- 1, // length of 2nd packet id + data as VarInt
- 0x00, // 2nd packet id: 0 for request as VarInt
- ]);
-
- conn.stream.write_all(&full_buffer).await.unwrap();
- conn.stream.flush().await.unwrap();
// log what the server sends back
loop {
@@ -95,6 +36,4 @@ pub async fn ping_server(address: &ServerAddress) -> Result<(), String> {
}
}
}
-
- Ok(())
}