1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

writing packets is now friendlier

This commit is contained in:
mat 2021-12-15 19:23:27 -06:00
parent ff8e3f2d9e
commit 4794b4f1a0
4 changed files with 64 additions and 48 deletions

View file

@ -10,18 +10,31 @@ use tokio::io::{AsyncRead, AsyncReadExt};
const MAX_STRING_LENGTH: u16 = 32767;
// const MAX_COMPONENT_STRING_LENGTH: u32 = 262144;
pub fn write_byte(buf: &mut Vec<u8>, n: u8) {
WriteBytesExt::write_u8(buf, n).unwrap();
#[async_trait]
pub trait Writable {
fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error>;
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
fn write_varint(&mut self, value: i32) -> Result<(), std::io::Error>;
fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error>;
fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error>;
fn write_short(&mut self, n: u16) -> Result<(), std::io::Error>;
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
}
pub fn write_bytes(buf: &mut Vec<u8>, bytes: &[u8]) {
buf.extend_from_slice(bytes);
}
#[async_trait]
impl Writable for Vec<u8> {
fn write_byte(&mut self, n: u8) -> Result<(), std::io::Error> {
WriteBytesExt::write_u8(self, n)
}
pub fn write_varint(buf: &mut Vec<u8>, mut value: i32) {
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
Ok(self.extend_from_slice(bytes))
}
fn write_varint(&mut self, mut value: i32) -> Result<(), std::io::Error> {
let mut buffer = [0];
if value == 0 {
buf.write_all(&buffer).unwrap();
self.write_all(&buffer).unwrap();
}
while value != 0 {
buffer[0] = (value & 0b0111_1111) as u8;
@ -29,11 +42,12 @@ pub fn write_varint(buf: &mut Vec<u8>, mut value: i32) {
if value != 0 {
buffer[0] |= 0b1000_0000;
}
buf.write_all(&buffer).unwrap();
self.write_all(&buffer)?;
}
Ok(())
}
}
pub fn write_utf_with_len(buf: &mut Vec<u8>, string: &str, len: usize) {
fn write_utf_with_len(&mut self, string: &str, len: usize) -> Result<(), std::io::Error> {
if string.len() > len {
panic!(
"String too big (was {} bytes encoded, max {})",
@ -41,20 +55,22 @@ pub fn write_utf_with_len(buf: &mut Vec<u8>, string: &str, len: usize) {
len
);
}
write_varint(buf, string.len() as i32);
write_bytes(buf, string.as_bytes());
}
pub fn write_utf(buf: &mut Vec<u8>, string: &str) {
write_utf_with_len(buf, string, MAX_STRING_LENGTH.into());
}
self.write_varint(string.len() as i32);
self.write_bytes(string.as_bytes())
}
pub fn write_short(buf: &mut Vec<u8>, n: u16) {
WriteBytesExt::write_u16::<BigEndian>(buf, n).unwrap();
}
fn write_utf(&mut self, string: &str) -> Result<(), std::io::Error> {
self.write_utf_with_len(string, MAX_STRING_LENGTH.into())
}
pub fn write_byte_array(buf: &mut Vec<u8>, bytes: &[u8]) {
write_varint(buf, bytes.len() as i32);
write_bytes(buf, bytes);
fn write_short(&mut self, n: u16) -> Result<(), std::io::Error> {
WriteBytesExt::write_u16::<BigEndian>(self, n)
}
fn write_byte_array(&mut self, bytes: &[u8]) -> Result<(), std::io::Error> {
self.write_varint(bytes.len() as i32);
self.write_bytes(bytes)
}
}
#[async_trait]
@ -159,11 +175,11 @@ mod tests {
#[test]
fn test_write_varint() {
let mut buf = Vec::new();
write_varint(&mut buf, 123456);
buf.write_varint(123456);
assert_eq!(buf, vec![192, 196, 7]);
let mut buf = Vec::new();
write_varint(&mut buf, 0);
buf.write_varint(0);
assert_eq!(buf, vec![0]);
}

View file

@ -2,7 +2,7 @@ use std::hash::Hash;
use tokio::io::BufReader;
use crate::{mc_buf, packets::ConnectionProtocol};
use crate::{mc_buf::Writable, packets::ConnectionProtocol};
use super::HandshakePacket;
@ -21,10 +21,10 @@ impl ClientIntentionPacket {
}
pub fn write(&self, buf: &mut Vec<u8>) {
mc_buf::write_varint(buf, self.protocol_version as i32);
mc_buf::write_utf(buf, &self.hostname);
mc_buf::write_short(buf, self.port);
mc_buf::write_varint(buf, self.intention.clone() as i32);
buf.write_varint(self.protocol_version as i32).unwrap();
buf.write_utf(&self.hostname).unwrap();
buf.write_short(self.port).unwrap();
buf.write_varint(self.intention.clone() as i32).unwrap();
}
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(

View file

@ -1,7 +1,7 @@
use std::hash::Hash;
use tokio::io::BufReader;
use crate::mc_buf;
use crate::mc_buf::Writable;
use super::LoginPacket;
@ -16,7 +16,7 @@ impl ServerboundHelloPacket {
}
pub fn write(&self, buf: &mut Vec<u8>) {
mc_buf::write_utf(buf, &self.username);
buf.write_utf(&self.username).unwrap();
}
pub async fn read<T: tokio::io::AsyncRead + std::marker::Unpin + std::marker::Send>(

View file

@ -1,6 +1,6 @@
use tokio::{io::AsyncWriteExt, net::TcpStream};
use crate::{mc_buf, packets::ProtocolPacket};
use crate::{mc_buf::Writable, packets::ProtocolPacket};
pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
// TODO: implement compression
@ -10,7 +10,7 @@ pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
// write the packet id
let mut id_and_data_buf = vec![];
mc_buf::write_varint(&mut id_and_data_buf, packet.id() as i32);
id_and_data_buf.write_varint(packet.id() as i32);
packet.write(&mut id_and_data_buf);
// write the packet data
@ -18,7 +18,7 @@ pub async fn write_packet(packet: impl ProtocolPacket, stream: &mut TcpStream) {
// 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.write_varint(id_and_data_buf.len() as i32);
complete_buf.append(&mut id_and_data_buf);
// finally, write and flush to the stream