diff --git a/CHANGELOG.md b/CHANGELOG.md index c2b0c83..097976a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,12 @@ Who knows what the future holds... # 0.0.4 - ??/??/???? Queries now support DNS resolve. -Changed Valve Protocol 3rd argument to Option, being None means everything should be gathered. -Better appid unknown cast error. +Changed Valve Protocol parameters to (ip, port, app, gather_settings), changes include: +- the app is now optional, being None means to anonymously query the server. +- gather_settings is now also an optional, being None means all query settings. + +Valve Protocol now supports querying anonymous apps (see previous lines). +Better bad game error. [Alien Swarm](https://store.steampowered.com/app/630/Alien_Swarm/) implementation (not tested). [Alien Swarm: Reactive Drop](https://store.steampowered.com/app/563560/Alien_Swarm_Reactive_Drop/) implementation. [Insurgency](https://store.steampowered.com/app/222880/Insurgency/) implementation. diff --git a/examples/master_querant.rs b/examples/master_querant.rs index 61012f2..7cc9c8f 100644 --- a/examples/master_querant.rs +++ b/examples/master_querant.rs @@ -1,6 +1,7 @@ use std::env; use gamedig::{aliens, asrd, csgo, css, dods, gm, hl2dm, ins, insmic, inss, l4d, l4d2, tf2, ts}; +use gamedig::valve::ValveProtocol; fn main() { let args: Vec = env::args().collect(); @@ -37,6 +38,7 @@ fn main() { "l4d" => println!("{:?}", l4d::query(ip, port)), "l4d2" => println!("{:?}", l4d2::query(ip, port)), "ts" => println!("{:?}", ts::query(ip, port)), + "_" => println!("{:?}", ValveProtocol::query(ip, 27015, None, None)), _ => panic!("Undefined game: {}", args[1]) }; } diff --git a/src/games/aliens.rs b/src/games/aliens.rs index 6daa58f..15a2127 100644 --- a/src/games/aliens.rs +++ b/src/games/aliens.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::ALIENS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::ALIENS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/asrd.rs b/src/games/asrd.rs index 6849381..cceb0cd 100644 --- a/src/games/asrd.rs +++ b/src/games/asrd.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::ASRD, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::ASRD), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/csgo.rs b/src/games/csgo.rs index 1de0abb..d0cdca9 100644 --- a/src/games/csgo.rs +++ b/src/games/csgo.rs @@ -69,10 +69,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::CSGO, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, Some(GatheringSettings { + }, Some(App::CSGO), Some(GatheringSettings { players: true, rules: false // cause csgo doesnt reply with rules anymore }))?; diff --git a/src/games/css.rs b/src/games/css.rs index 11d6341..bcc2ca0 100644 --- a/src/games/css.rs +++ b/src/games/css.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::CSS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::CSS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/dods.rs b/src/games/dods.rs index 9a2eff5..11ea284 100644 --- a/src/games/dods.rs +++ b/src/games/dods.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::DODS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::DODS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/gm.rs b/src/games/gm.rs index fcd5d08..f28e6c4 100644 --- a/src/games/gm.rs +++ b/src/games/gm.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::GM, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::GM), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/hl2dm.rs b/src/games/hl2dm.rs index 2f45195..3b4dd67 100644 --- a/src/games/hl2dm.rs +++ b/src/games/hl2dm.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::HL2DM, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::HL2DM), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/ins.rs b/src/games/ins.rs index 07f2f43..146f8d4 100644 --- a/src/games/ins.rs +++ b/src/games/ins.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::INS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::INS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/insmic.rs b/src/games/insmic.rs index 6e35caf..4166f74 100644 --- a/src/games/insmic.rs +++ b/src/games/insmic.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::INSMIC, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::INSMIC), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/inss.rs b/src/games/inss.rs index 3cd1325..bf4d168 100644 --- a/src/games/inss.rs +++ b/src/games/inss.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::INSS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27131, Some(port) => port - }, None)?; + }, Some(App::INSS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/l4d.rs b/src/games/l4d.rs index 38e652c..0c1ed00 100644 --- a/src/games/l4d.rs +++ b/src/games/l4d.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::L4D, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::L4D), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/l4d2.rs b/src/games/l4d2.rs index 20f046d..d549568 100644 --- a/src/games/l4d2.rs +++ b/src/games/l4d2.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::L4D2, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::L4D2), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/tf2.rs b/src/games/tf2.rs index 1af77c7..1bab6d0 100644 --- a/src/games/tf2.rs +++ b/src/games/tf2.rs @@ -71,10 +71,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::TF2, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::TF2), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/games/ts.rs b/src/games/ts.rs index 7ede50b..6a8b99d 100644 --- a/src/games/ts.rs +++ b/src/games/ts.rs @@ -83,10 +83,10 @@ impl Response { } pub fn query(address: &str, port: Option) -> GDResult { - let valve_response = ValveProtocol::query(App::TS, address, match port { + let valve_response = ValveProtocol::query(address, match port { None => 27015, Some(port) => port - }, None)?; + }, Some(App::TS), None)?; Ok(Response::new_from_valve_response(valve_response)) } diff --git a/src/protocols/valve.rs b/src/protocols/valve.rs index 30cfc72..b431ecf 100644 --- a/src/protocols/valve.rs +++ b/src/protocols/valve.rs @@ -238,7 +238,7 @@ struct SplitPacket { } impl SplitPacket { - fn new(_app: &App, buf: &[u8]) -> GDResult { + fn new(_appid: u32, buf: &[u8]) -> GDResult { let mut pos = 0; let header = buffer::get_u32_le(&buf, &mut pos)?; @@ -322,15 +322,15 @@ impl ValveProtocol { Ok(buf[..amt].to_vec()) } - fn receive(&self, app: &App, buffer_size: usize) -> GDResult { + fn receive(&self, appid: u32, buffer_size: usize) -> GDResult { let mut buf = self.receive_raw(buffer_size)?; if buf[0] == 0xFE { //the packet is split - let mut main_packet = SplitPacket::new(app, &buf)?; + let mut main_packet = SplitPacket::new(appid, &buf)?; for _ in 1..main_packet.total { buf = self.receive_raw(buffer_size)?; - let chunk_packet = SplitPacket::new(app, &buf)?; + let chunk_packet = SplitPacket::new(appid, &buf)?; main_packet.payload.extend(chunk_packet.payload); } @@ -342,11 +342,11 @@ impl ValveProtocol { } /// Ask for a specific request only. - pub fn get_request_data(&self, app: &App, kind: Request) -> GDResult> { + pub fn get_request_data(&self, appid: u32, kind: Request) -> GDResult> { let request_initial_packet = Packet::initial(kind.clone()).to_bytes(); self.send(&request_initial_packet)?; - let packet = self.receive(app, DEFAULT_PACKET_SIZE)?; + let packet = self.receive(appid, DEFAULT_PACKET_SIZE)?; if packet.kind != 0x41 { //'A' return Ok(packet.payload.clone()); @@ -356,12 +356,12 @@ impl ValveProtocol { let challenge_packet = Packet::challenge(kind.clone(), challenge).to_bytes(); self.send(&challenge_packet)?; - Ok(self.receive(app, DEFAULT_PACKET_SIZE)?.payload) + Ok(self.receive(appid, DEFAULT_PACKET_SIZE)?.payload) } /// Get the server information's. - pub fn get_server_info(&self, app: &App) -> GDResult { - let buf = self.get_request_data(app, Request::INFO)?; + pub fn get_server_info(&self, initial_appid: u32) -> GDResult { + let buf = self.get_request_data(initial_appid, Request::INFO)?; let mut pos = 0; let protocol = buffer::get_u8(&buf, &mut pos)?; @@ -387,7 +387,7 @@ impl ValveProtocol { }; let has_password = buffer::get_u8(&buf, &mut pos)? == 1; let vac_secured = buffer::get_u8(&buf, &mut pos)? == 1; - let the_ship = match *app == App::TS { + let the_ship = match appid == App::TS as u32 { false => None, true => Some(TheShip { mode: buffer::get_u8(&buf, &mut pos)?, @@ -452,8 +452,8 @@ impl ValveProtocol { } /// Get the server player's. - pub fn get_server_players(&self, app: &App) -> GDResult> { - let buf = self.get_request_data(app, Request::PLAYERS)?; + pub fn get_server_players(&self, appid: u32) -> GDResult> { + let buf = self.get_request_data(appid, Request::PLAYERS)?; let mut pos = 0; let count = buffer::get_u8(&buf, &mut pos)?; @@ -465,11 +465,11 @@ impl ValveProtocol { name: buffer::get_string(&buf, &mut pos)?, score: buffer::get_u32_le(&buf, &mut pos)?, duration: buffer::get_f32_le(&buf, &mut pos)?, - deaths: match *app == App::TS { + deaths: match appid == App::TS as u32 { false => None, true => Some(buffer::get_u32_le(&buf, &mut pos)?) }, - money: match *app == App::TS { + money: match appid == App::TS as u32 { false => None, true => Some(buffer::get_u32_le(&buf, &mut pos)?) } @@ -480,12 +480,12 @@ impl ValveProtocol { } /// Get the server rules's. - pub fn get_server_rules(&self, app: &App) -> GDResult>> { - if *app == App::CSGO { //cause csgo wont respond to this since feb 21 2014 update + pub fn get_server_rules(&self, appid: u32) -> GDResult>> { + if appid == App::CSGO as u32 { //cause csgo wont respond to this since feb 21 2014 update return Ok(None); } - let buf = self.get_request_data(app, Request::RULES)?; + let buf = self.get_request_data(appid, Request::RULES)?; let mut pos = 0; let count = buffer::get_u16_le(&buf, &mut pos)?; @@ -502,14 +502,22 @@ impl ValveProtocol { } /// Query any app. - pub fn query(app: App, address: &str, port: u16, gather_settings: Option) -> Result { + pub fn query(address: &str, port: u16, app: Option, gather_settings: Option) -> Result { let client = ValveProtocol::new(address, port)?; - let info = client.get_server_info(&app)?; + let mut query_app_id = match app { + None => 0, + Some(app) => app as u32 + }; - let query_app_id = app.clone() as u32; - if info.appid != query_app_id { - return Err(GDError::BadGame(format!("Expected {}, found {} instead!", query_app_id, info.appid))); + let info = client.get_server_info(query_app_id)?; + + if query_app_id != 0 { + if info.appid != query_app_id { + return Err(GDError::BadGame(format!("Expected {}, found {} instead!", query_app_id, info.appid))); + } + } else { + query_app_id = info.appid; } let (gather_players, gather_rules) = match gather_settings.is_some() { @@ -524,11 +532,11 @@ impl ValveProtocol { info, players: match gather_players { false => None, - true => Some(client.get_server_players(&app)?) + true => Some(client.get_server_players(query_app_id)?) }, rules: match gather_rules { false => None, - true => client.get_server_rules(&app)? + true => client.get_server_rules(query_app_id)? } }) }