[Crate] Refactor: Buffer (#62)

* merge: local -> fresh pr

* fix: utf16 bugs + clean up

* docs: buffer

* [feat/buffer] Replaced errors, partial valve protocol ported

* fix: change buffer name + add endian switch

* chore: update module

* refactor: valve_master

* refactor: mc bedrock

* refactor: mc java

* refactor: mc types

* refactor: mc legacy 1.8

* refactor: mc legacy 1.4

* refactor: valve

* refactor: valve types

* refactor: quake

* refactor: mc legacy 1.6

* refactor: gamespy 1

* fix: make switch endian move cursor

* fix: reset cursor on switch

* chore: add switch endian tests

* chore: remove todo comment

* chore: clean up buffer generic types

* refactor: prop len when switching in mc bedrock

* fix: tests and current pos fn

* refactor: ffow

* refactor: jc2mp

* refactor: gs 3

* refactor: gs 2

* fix: mc bedrock prop on move + move data

* fix: mc java lifetime error

* fix: mc legacy 1.6 using pub not pub crate

* fix: quake client lifetime

* fix: quake 2 clippy warning

* fix: valve lifetime issue

* fix: buffer test

* chore: format to keep ci happy

* fix: buffer move_cursor

* fix: quake client

* feat: GameSpy 1 small optimization

* fix: incomplete gamespy 3 fix

* fix: gamespy 3 fix

* fix: minecraft java

* fix: minecraft bedrock

* feat: update the CHANGELOG to mention the buffer rewrite and thank @cainthebest for it

* fix: minecraft legacy 1.6

---------

Co-authored-by: CosminPerRam <cosmin.p@live.com>
This commit is contained in:
Cain 2023-07-18 09:46:53 +01:00 committed by GitHub
parent a8342296d6
commit 66cc39eb26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 859 additions and 568 deletions

View file

@ -1,4 +1,6 @@
use crate::bufferer::{Bufferer, Endianess};
use byteorder::LittleEndian;
use crate::buffer::{Buffer, Utf8Decoder};
use crate::protocols::quake::types::Response;
use crate::protocols::types::TimeoutSettings;
use crate::socket::{Socket, UdpSocket};
@ -15,10 +17,7 @@ pub(crate) trait QuakeClient {
fn parse_player_string(data: Iter<&str>) -> GDResult<Self::Player>;
}
fn get_data<Client: QuakeClient>(
address: &SocketAddr,
timeout_settings: Option<TimeoutSettings>,
) -> GDResult<Bufferer> {
fn get_data<Client: QuakeClient>(address: &SocketAddr, timeout_settings: Option<TimeoutSettings>) -> GDResult<Vec<u8>> {
let mut socket = UdpSocket::new(address)?;
socket.apply_timeout(timeout_settings)?;
@ -32,24 +31,24 @@ fn get_data<Client: QuakeClient>(
)?;
let data = socket.receive(None)?;
let mut bufferer = Bufferer::new_with_data(Endianess::Little, &data);
let mut bufferer = Buffer::<LittleEndian>::new(&data);
if bufferer.get_u32()? != 4294967295 {
if bufferer.read::<u32>()? != 4294967295 {
return Err(GDError::PacketBad);
}
let response_header = Client::get_response_header().as_bytes();
if !bufferer.remaining_data().starts_with(response_header) {
if !bufferer.remaining_bytes().starts_with(response_header) {
Err(GDError::PacketBad)?
}
bufferer.move_position_ahead(response_header.len());
bufferer.move_cursor(response_header.len() as isize)?;
Ok(bufferer)
Ok(bufferer.remaining_bytes().to_vec()) //TODO: Maybe fix?
}
fn get_server_values(bufferer: &mut Bufferer) -> GDResult<HashMap<String, String>> {
let data = bufferer.get_string_utf8_newline()?;
fn get_server_values(bufferer: &mut Buffer<LittleEndian>) -> GDResult<HashMap<String, String>> {
let data = bufferer.read_string::<Utf8Decoder>(Some([0x0A]))?;
let mut data_split = data.split('\\').collect::<Vec<&str>>();
if let Some(first) = data_split.first() {
if first == &"" {
@ -74,11 +73,14 @@ fn get_server_values(bufferer: &mut Bufferer) -> GDResult<HashMap<String, String
Ok(vars)
}
fn get_players<Client: QuakeClient>(bufferer: &mut Bufferer) -> GDResult<Vec<Client::Player>> {
fn get_players<Client: QuakeClient>(bufferer: &mut Buffer<LittleEndian>) -> GDResult<Vec<Client::Player>> {
let mut players: Vec<Client::Player> = Vec::new();
while !bufferer.is_remaining_empty() && bufferer.remaining_data() != [0x00] {
let data = bufferer.get_string_utf8_newline()?;
// this needs to be looked at again as theres no way to check if the buffer has
// a remaining null byte the original code was:
// while !bufferer.is_remaining_empty() && bufferer.remaining_data() != [0x00]
while !bufferer.remaining_length() == 0 {
let data = bufferer.read_string::<Utf8Decoder>(Some([0x0A]))?;
let data_split = data.split(' ').collect::<Vec<&str>>();
let data_iter = data_split.iter();
@ -92,7 +94,8 @@ pub(crate) fn client_query<Client: QuakeClient>(
address: &SocketAddr,
timeout_settings: Option<TimeoutSettings>,
) -> GDResult<Response<Client::Player>> {
let mut bufferer = get_data::<Client>(address, timeout_settings)?;
let data = get_data::<Client>(address, timeout_settings)?;
let mut bufferer = Buffer::<LittleEndian>::new(&data);
let mut server_vars = get_server_values(&mut bufferer)?;
let players = get_players::<Client>(&mut bufferer)?;

View file

@ -56,10 +56,7 @@ impl QuakeClient for QuakeTwo {
None => Err(GDError::PacketBad)?,
Some(v) => remove_wrapping_quotes(v).to_string(),
},
address: match data.next() {
None => None,
Some(v) => Some(remove_wrapping_quotes(v).to_string()),
},
address: data.next().map(|v| remove_wrapping_quotes(v).to_string()),
})
}
}