mirror of
https://github.com/tribufu/rust-gamedig
synced 2026-06-01 09:42:41 +00:00
Much more readable code!
This commit is contained in:
parent
c2742fbcf0
commit
3a83588802
2 changed files with 78 additions and 142 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
use std::net::UdpSocket;
|
use std::net::UdpSocket;
|
||||||
use crate::errors::GDError;
|
use crate::errors::GDError;
|
||||||
use crate::utils::{combine_two_u8, complete_address, concat_u8, find_first_string, get_u64_from_buf};
|
use crate::utils::{buffer, complete_address, concat_u8};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Server {
|
pub enum Server {
|
||||||
|
|
@ -108,127 +108,73 @@ impl ValveProtocol {
|
||||||
|
|
||||||
client.do_request(Request::A2sInfo(None), None);
|
client.do_request(Request::A2sInfo(None), None);
|
||||||
let mut buf = client.receive(DEFAULT_PACKET_SIZE);
|
let mut buf = client.receive(DEFAULT_PACKET_SIZE);
|
||||||
let mut pos = 5;
|
let mut pos = 4;
|
||||||
|
|
||||||
if buf[4] == 0x41 {
|
if buffer::get_u8(&buf, &mut pos)? == 0x41 {
|
||||||
client.do_request(Request::A2sInfo(Some([buf[pos], buf[pos + 1], buf[pos + 2], buf[pos + 3]])), None);
|
client.do_request(Request::A2sInfo(Some([buf[pos], buf[pos + 1], buf[pos + 2], buf[pos + 3]])), None);
|
||||||
buf = client.receive(DEFAULT_PACKET_SIZE);
|
buf = client.receive(DEFAULT_PACKET_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
let protocol = buf[5]; pos = pos + 1;
|
Ok(Response {
|
||||||
|
protocol: buffer::get_u8(&buf, &mut pos)?,
|
||||||
let name = find_first_string(&buf[pos..]); pos = pos + name.len() + 1;
|
name: buffer::get_string(&buf, &mut pos),
|
||||||
let map = find_first_string(&buf[pos..]); pos = pos + map.len() + 1;
|
map: buffer::get_string(&buf, &mut pos),
|
||||||
let folder = find_first_string(&buf[pos..]); pos = pos + folder.len() + 1;
|
folder: buffer::get_string(&buf, &mut pos),
|
||||||
let game = find_first_string(&buf[pos..]); pos = pos + game.len() + 1;
|
game: buffer::get_string(&buf, &mut pos),
|
||||||
|
id: buffer::get_u16(&buf, &mut pos),
|
||||||
let id = combine_two_u8(buf[pos + 1], buf[pos]); pos = pos + 2;
|
players: buffer::get_u8(&buf, &mut pos)?,
|
||||||
let players = buf[pos]; pos = pos + 1;
|
max_players: buffer::get_u8(&buf, &mut pos)?,
|
||||||
let max_players = buf[pos]; pos = pos + 1;
|
bots: buffer::get_u8(&buf, &mut pos)?,
|
||||||
let bots = buf[pos]; pos = pos + 1;
|
server_type: match buffer::get_u8(&buf, &mut pos)? as char {
|
||||||
|
'd' => Server::Dedicated,
|
||||||
let server_type = match buf[pos] as char {
|
'l' => Server::NonDedicated,
|
||||||
'd' => Server::Dedicated,
|
_ => Server::SourceTV
|
||||||
'l' => Server::NonDedicated,
|
},
|
||||||
_ => Server::SourceTV
|
environment_type: match buffer::get_u8(&buf, &mut pos)? as char {
|
||||||
}; pos = pos + 1;
|
'l' => Environment::Linux,
|
||||||
|
'w' => Environment::Windows,
|
||||||
let environment_type = match buf[pos] as char {
|
_ => Environment::Mac
|
||||||
'l' => Environment::Linux,
|
},
|
||||||
'w' => Environment::Windows,
|
has_password: buffer::get_u8(&buf, &mut pos)? == 1,
|
||||||
_ => Environment::Mac
|
vac_secured: buffer::get_u8(&buf, &mut pos)? == 1,
|
||||||
}; pos = pos + 1;
|
the_ship: match has_the_ship {
|
||||||
|
false => None,
|
||||||
let has_password = buf[pos] == 1; pos = pos + 1;
|
true => Some(TheShip {
|
||||||
let vac_secured = buf[pos] == 1; pos = pos + 1;
|
mode: buffer::get_u8(&buf, &mut pos)?,
|
||||||
|
witnesses: buffer::get_u8(&buf, &mut pos)?,
|
||||||
let the_ship = match has_the_ship {
|
duration: buffer::get_u8(&buf, &mut pos)?
|
||||||
false => None,
|
})
|
||||||
true => {
|
},
|
||||||
let ship = TheShip {
|
version: buffer::get_string(&buf, &mut pos),
|
||||||
mode: buf[pos],
|
extra_data: match buffer::get_u8(&buf, &mut pos) {
|
||||||
witnesses: buf[pos + 1],
|
Err(_) => None,
|
||||||
duration: buf[pos + 2]
|
Ok(value) => Some(ExtraData {
|
||||||
}; pos = pos + 3;
|
port: match (value & 0x80) > 0 {
|
||||||
Some(ship)
|
false => None,
|
||||||
}
|
true => Some(buffer::get_u16(&buf, &mut pos))
|
||||||
};
|
},
|
||||||
|
steam_id: match (value & 0x10) > 0 {
|
||||||
let version = find_first_string(&buf[pos..]); pos = pos + version.len() + 1;
|
false => None,
|
||||||
|
true => Some(buffer::get_u64(&buf, &mut pos))
|
||||||
pos = pos + 1; //look ahead
|
},
|
||||||
let extra_data = match buf.get(pos - 1) {
|
tv_port: match (value & 0x40) > 0 {
|
||||||
None => None,
|
false => None,
|
||||||
Some(value) => {
|
true => Some(buffer::get_u16(&buf, &mut pos))
|
||||||
let edf_port = match (value & 0x80) > 0 {
|
},
|
||||||
false => None,
|
tv_name: match (value & 0x40) > 0 {
|
||||||
true => {
|
false => None,
|
||||||
let p = combine_two_u8(buf[pos + 1], buf[pos]); pos = pos + 2;
|
true => Some(buffer::get_string(&buf, &mut pos))
|
||||||
Some(p)
|
},
|
||||||
|
keywords: match (value & 0x20) > 0 {
|
||||||
|
false => None,
|
||||||
|
true => Some(buffer::get_string(&buf, &mut pos))
|
||||||
|
},
|
||||||
|
game_id: match (value & 0x01) > 0 {
|
||||||
|
false => None,
|
||||||
|
true => Some(buffer::get_u64(&buf, &mut pos))
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let steam_id = match (value & 0x10) > 0 {
|
|
||||||
false => None,
|
|
||||||
true => {
|
|
||||||
let p = get_u64_from_buf(&buf[pos..]); pos = pos + 8;
|
|
||||||
Some(p)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (tv_port, tv_name) = match (value & 0x40) > 0 {
|
|
||||||
false => (None, None),
|
|
||||||
true => {
|
|
||||||
let tv_port = combine_two_u8(buf[pos + 1], buf[pos]); pos = pos + 2;
|
|
||||||
let tv_name = find_first_string(&buf[pos..]); pos = pos + tv_name.len() + 1;
|
|
||||||
(Some(tv_port), Some(tv_name))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let keywords = match (value & 0x20) > 0 {
|
|
||||||
false => None,
|
|
||||||
true => {
|
|
||||||
let keywords = find_first_string(&buf[pos..]); pos = pos + keywords.len() + 1;
|
|
||||||
Some(keywords)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let game_id = match (value & 0x01) > 0 {
|
|
||||||
false => None,
|
|
||||||
true => {
|
|
||||||
let game_id = get_u64_from_buf(&buf[pos..]); pos = pos + 8;
|
|
||||||
Some(game_id)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Some(ExtraData {
|
|
||||||
port: edf_port,
|
|
||||||
steam_id,
|
|
||||||
tv_port,
|
|
||||||
tv_name,
|
|
||||||
keywords,
|
|
||||||
game_id
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Response {
|
|
||||||
protocol,
|
|
||||||
name,
|
|
||||||
map,
|
|
||||||
folder,
|
|
||||||
game,
|
|
||||||
id,
|
|
||||||
players,
|
|
||||||
max_players,
|
|
||||||
bots,
|
|
||||||
server_type,
|
|
||||||
environment_type,
|
|
||||||
has_password,
|
|
||||||
vac_secured,
|
|
||||||
the_ship,
|
|
||||||
version,
|
|
||||||
extra_data
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/utils.rs
46
src/utils.rs
|
|
@ -1,18 +1,12 @@
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
use crate::GDError;
|
||||||
|
|
||||||
pub fn concat_u8(first: &[u8], second: &[u8]) -> Vec<u8> {
|
pub fn concat_u8(first: &[u8], second: &[u8]) -> Vec<u8> {
|
||||||
[first, second].concat()
|
[first, second].concat()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_first_null(arr: &[u8]) -> usize {
|
|
||||||
match arr.iter().position(|&x| x == 0) {
|
|
||||||
None => arr.len(),
|
|
||||||
Some(position) => position
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_first_string(arr: &[u8]) -> String {
|
pub fn find_first_string(arr: &[u8]) -> String {
|
||||||
arr.iter().take_while(|&&b| b != 0).map(|&e| e as char).collect::<String>()
|
std::str::from_utf8(&arr[..arr.iter().position(|&x| x == 0).unwrap()]).unwrap().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn complete_address(address: &str, port: u16) -> String {
|
pub fn complete_address(address: &str, port: u16) -> String {
|
||||||
|
|
@ -30,29 +24,31 @@ pub fn combine_eight_u8(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8, g: u8, h: u8)
|
||||||
pub mod buffer {
|
pub mod buffer {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub fn get_u8(buf: &[u8], pos: usize) -> (u8, usize) {
|
pub fn get_u8(buf: &[u8], pos: &mut usize) -> Result<u8, GDError> {
|
||||||
(buf[pos], pos + 1)
|
let value = buf[*pos];
|
||||||
|
*pos += 1;
|
||||||
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_u16(buf: &[u8], pos: usize) -> (u16, usize) {
|
pub fn get_u16(buf: &[u8], pos: &mut usize) -> u16 {
|
||||||
(combine_two_u8(buf[pos + 1], buf[pos]), pos + 2)
|
let value = combine_two_u8(buf[*pos + 1], buf[*pos]);
|
||||||
|
*pos += 2;
|
||||||
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_u64(buf: &[u8], pos: usize) -> (u64, usize) {
|
pub fn get_u64(buf: &[u8], pos: &mut usize) -> u64 {
|
||||||
(combine_eight_u8(buf[pos + 7], buf[pos + 6], buf[pos + 5], buf[pos + 4], buf[pos + 3], buf[pos + 2], buf[pos + 1], buf[pos]), pos + 8)
|
let value = combine_eight_u8(buf[*pos + 7], buf[*pos + 6], buf[*pos + 5], buf[*pos + 4], buf[*pos + 3], buf[*pos + 2], buf[*pos + 1], buf[*pos]);
|
||||||
|
*pos += 8;
|
||||||
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_string(buf: &[u8], pos: usize) -> (String, usize) {
|
pub fn get_string(buf: &[u8], pos: &mut usize) -> String {
|
||||||
let string = find_first_string(&buf[pos..]);
|
let value = find_first_string(&buf[*pos..]);
|
||||||
let string_size = string.len();
|
*pos += value.len() + 1;
|
||||||
(string, pos + string_size + 1)
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_u64_from_buf(buf: &[u8]) -> u64 {
|
|
||||||
combine_eight_u8(buf[7], buf[6], buf[5], buf[4], buf[3], buf[2], buf[1], buf[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod utils {
|
mod utils {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -68,12 +64,6 @@ mod utils {
|
||||||
assert_eq!(b[1], combined[3]);
|
assert_eq!(b[1], combined[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn find_null_in_array_test() {
|
|
||||||
let arr: [u8; 4] = [0x64, 0x32, 0x00, 0x20];
|
|
||||||
assert_eq!(2, find_first_null(&arr));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn complete_address_test() {
|
fn complete_address_test() {
|
||||||
let address = "192.168.0.1";
|
let address = "192.168.0.1";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue