[Protocol] Add quake protocols. (#35)

* [Protocol] Initial packet receive implementation

* [Protocol] Add key extraction

* [Protocol] Fix new Ipv4Addr query address and get string with unended

* [Protocol] Properly parse the received data

* [Protocol] Add parse players

* [Protocol] Add bots

* [Protocol] Extract into functions

* [Protocol] Remove quotes from player name

* [Protocol] Add two and three files

* [Protocol] Make quake queries very modular

* [Protocol] Remove the need of a client instance

* [Protocol] Revesed if statement

* [Protocol] Apply clippy fixes and replace String by &str in get send header

* [Protocol] Add one and three implementations

* [Protocol] Add quake2 and quake3 to master_querant

* [Protocol] Fix Q2 implementation

* [Protocol] Change from Ipv4Addr to IpAddr

* [Protocol] Fix Q3 response header

* [Protocol] Fix Q3 response

* [Crate] Add Q1, 2 and 3 to changelog and protocols

* [Protocol] Extract client into separate file and add some docs
This commit is contained in:
CosminPerRam 2023-05-30 15:33:41 +03:00 committed by GitHub
parent 3dbc6498ed
commit d302d1173f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 339 additions and 8 deletions

View file

@ -0,0 +1,55 @@
use std::net::IpAddr;
use std::slice::Iter;
use crate::{GDError, GDResult};
use crate::protocols::quake::one::QuakeOne;
use crate::protocols::quake::Response;
use crate::protocols::quake::client::{QuakeClient, client_query};
use crate::protocols::types::TimeoutSettings;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
/// Quake 2 player data.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Player {
pub frags: u8,
pub ping: u8,
pub name: String
}
pub(crate) struct QuakeTwo;
impl QuakeClient for QuakeTwo {
type Player = Player;
fn get_send_header<'a>() -> &'a str {
QuakeOne::get_send_header()
}
fn get_response_header<'a>() -> &'a [u8] {
&[0x70, 0x72, 0x69, 0x6E, 0x74, 0x0A]
}
fn parse_player_string(mut data: Iter<&str>) -> GDResult<Self::Player> {
Ok(Player {
frags: match data.next() {
None => Err(GDError::PacketBad)?,
Some(v) => v.parse().map_err(|_| GDError::PacketBad)?
},
ping: match data.next() {
None => Err(GDError::PacketBad)?,
Some(v) => v.parse().map_err(|_| GDError::PacketBad)?
},
name: match data.next() {
None => Err(GDError::PacketBad)?,
Some(v) => match v.starts_with('\"') && v.ends_with('\"') {
false => v,
true => &v[1..v.len() - 1]
}.to_string()
}
})
}
}
pub fn query(address: &IpAddr, port: u16, timeout_settings: Option<TimeoutSettings>) -> GDResult<Response<Player>> {
client_query::<QuakeTwo>(address, port, timeout_settings)
}