diff options
author | Plex <thinkplex@riseup.net> | 2022-06-15 17:22:59 +0200 |
---|---|---|
committer | Plex <thinkplex@riseup.net> | 2022-06-15 17:22:59 +0200 |
commit | 72627d2f6efe3f3297ce466a1fdd208015a19f88 (patch) | |
tree | d73c889a721dd31bc1a31f9532d542279026a665 | |
parent | 28b41ee492805971632e1d65ab9f855ce837767b (diff) |
-rw-r--r-- | .cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx | bin | 2354 -> 2312 bytes | |||
-rw-r--r-- | .cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx | bin | 746 -> 796 bytes | |||
-rw-r--r-- | .cache/clangd/index/mcping.c.7D35BB1188AA7031.idx | bin | 1204 -> 1340 bytes | |||
-rw-r--r-- | .cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx | bin | 2140 -> 2116 bytes | |||
-rw-r--r-- | .gitignore | 12 | ||||
-rw-r--r-- | Cargo.lock | 122 | ||||
-rw-r--r-- | Cargo.toml | 19 | ||||
-rw-r--r-- | compile_commands.json | 21 | ||||
-rw-r--r-- | include/mcnetwork.h | 9 | ||||
-rw-r--r-- | mcnetwork.c | 12 | ||||
-rw-r--r-- | mcping.c | 7 | ||||
-rw-r--r-- | src/bin/mcping.rs | 3 | ||||
-rw-r--r-- | src/bin/mcquery.rs | 314 |
13 files changed, 489 insertions, 30 deletions
diff --git a/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx b/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx Binary files differindex 4be19e7..2823793 100644 --- a/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx +++ b/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx diff --git a/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx b/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx Binary files differindex bfe1868..0e6d7ef 100644 --- a/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx +++ b/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx diff --git a/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx b/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx Binary files differindex 5e800aa..2bcee03 100644 --- a/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx +++ b/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx diff --git a/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx b/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx Binary files differindex 37d98da..5ca75a7 100644 --- a/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx +++ b/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx @@ -52,3 +52,15 @@ modules.order Module.symvers Mkfile.old dkms.conf + + +# Added by cargo + +/target + + +# Added by cargo +# +# already existing elements were commented out + +#/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8527c8d --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,122 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "bytes" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + +[[package]] +name = "libc" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c" + +[[package]] +name = "mc-comm" +version = "0.1.0" +dependencies = [ + "byteorder", + "bytes", + "getopts", + "json", + "rand", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" + +[[package]] +name = "rand" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", + "rand_hc", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_hc" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" +dependencies = [ + "rand_core", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + +[[package]] +name = "wasi" +version = "0.10.2+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..3f43147 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "mc-comm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "mcping" + +[[bin]] +name = "mcquery" + +[dependencies] +getopts = "0.2" +bytes = "1.1.0" +rand = "0.8.4" +byteorder = "1.4.3" +json = "0.12.4" diff --git a/compile_commands.json b/compile_commands.json index 17682cf..c93ab5e 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -7,21 +7,6 @@ "-I./include", "-c", "-o", - "mctypes.o", - "mctypes.c" - ], - "directory": "/home/kruezenberg/mc-comm", - "file": "/home/kruezenberg/mc-comm/mctypes.c", - "output": "/home/kruezenberg/mc-comm/mctypes.o" - }, - { - "arguments": [ - "/usr/lib/llvm/13/bin/clang", - "-Wall", - "-g", - "-I./include", - "-c", - "-o", "mcnetwork.o", "mcnetwork.c" ], @@ -83,7 +68,7 @@ "-internal-isystem", "/usr/local/include", "-internal-isystem", - "/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.0/../../../../x86_64-pc-linux-gnu/include", + "/usr/lib/gcc/x86_64-pc-linux-gnu/11.2.1/../../../../x86_64-pc-linux-gnu/include", "-internal-externc-isystem", "/include", "-internal-externc-isystem", @@ -98,11 +83,11 @@ "-x", "c", "-o", - "/tmp/mcping-08ccd4.o", + "/tmp/mcping-bc4e3a.o", "mcping.c" ], "directory": "/home/kruezenberg/mc-comm", "file": "/home/kruezenberg/mc-comm/mcping.c", - "output": "/tmp/mcping-08ccd4.o" + "output": "/tmp/mcping-bc4e3a.o" } ] diff --git a/include/mcnetwork.h b/include/mcnetwork.h index d3faaa1..f6306ff 100644 --- a/include/mcnetwork.h +++ b/include/mcnetwork.h @@ -1,8 +1,11 @@ #include <sys/socket.h> #include "mctypes.h" -void connect_mc_server_ping(int socket, char* address, unsigned short port); -void send_handshake(int socket, int protocol, char* address, unsigned short port, int next_state); -void send_packet(int socket, int packet_id, size_t raw_size, void* raw_data); +#define PING IPPROTO_TCP +#define QUERY IPPROTO_UDP + +void connect_mc_server(int socket, char* address, unsigned short port, int protocol); +void send_ping_handshake(int socket, int protocol, char* address, unsigned short port, int next_state); +void send_ping_packet(int socket, int packet_id, size_t raw_size, void* raw_data); packet recv_packet(int socket); varint recv_varint(int socket); diff --git a/mcnetwork.c b/mcnetwork.c index 00cdf6c..2d350c8 100644 --- a/mcnetwork.c +++ b/mcnetwork.c @@ -9,7 +9,7 @@ #include "mctypes.h" -void send_handshake(int socket, int protocol, char* address, +void send_ping_handshake(int socket, int protocol, char* address, unsigned short port, int next_state) { void* raw_handshake; @@ -17,16 +17,16 @@ void send_handshake(int socket, int protocol, char* address, handshake hs = { to_varint(protocol), { to_varint(strlen(address)), address }, port, to_varint(next_state) }; handshake_size = serialize_handshake(hs, &raw_handshake); - send_packet(socket, 0x0, handshake_size, raw_handshake); + send_ping_packet(socket, 0x0, handshake_size, raw_handshake); free_handshake(hs); } -void send_packet(int socket, int packet_id, size_t raw_size, void* raw_data) +void send_ping_packet(int socket, int packet_id, size_t raw_size, void* payload) { void* raw_packet; size_t p_size; packet p = { to_varint(raw_size + size_varint(to_varint(packet_id))), - to_varint(packet_id), raw_data }; + to_varint(packet_id), payload }; p_size = serialize_packet(p, &raw_packet); free_packet(p); @@ -34,7 +34,7 @@ void send_packet(int socket, int packet_id, size_t raw_size, void* raw_data) perror("packet failed"); } -void connect_mc_server_ping(int socket, char* address, unsigned short port) +void connect_mc_server(int socket, char* address, unsigned short port, int protocol) { struct addrinfo* mc_info = malloc(sizeof(struct addrinfo)); memset(mc_info, 0, sizeof(struct addrinfo)); @@ -42,7 +42,7 @@ void connect_mc_server_ping(int socket, char* address, unsigned short port) memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; + hints.ai_protocol = protocol; if (getaddrinfo(address, "80", &hints, &mc_info) != 0) exit(1); @@ -1,3 +1,4 @@ +#include <netinet/in.h> #include <string.h> #include <getopt.h> #include <stdlib.h> @@ -55,9 +56,9 @@ int main(int argc, char *argv[]) if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) perror("bad socket\n"); - connect_mc_server_ping(s, address, port); - send_handshake(s, protocol_ver, address, port, 1); - send_packet(s, 0x0, 0, NULL); // request packet (0x0 with no fields) + connect_mc_server(s, address, port, PING); + send_ping_handshake(s, protocol_ver, address, port, 1); + send_ping_packet(s, 0x0, 0, NULL); // request packet (0x0 with no fields) packet response = recv_packet(s); #ifdef _DEBUG diff --git a/src/bin/mcping.rs b/src/bin/mcping.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/bin/mcping.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/bin/mcquery.rs b/src/bin/mcquery.rs new file mode 100644 index 0000000..8dcd1bc --- /dev/null +++ b/src/bin/mcquery.rs @@ -0,0 +1,314 @@ +extern crate getopts; +use getopts::Options; +use std::env; +use rand::Rng; +use std::net::{UdpSocket,Ipv4Addr,ToSocketAddrs,SocketAddr}; + +pub mod querynet { + use std::net::{UdpSocket, SocketAddr}; + use std::str; + use bytes::{BytesMut, BufMut}; + use byteorder::{ByteOrder,LittleEndian}; + use std::collections::HashMap; + use json::object; + + pub struct BasicStat { + pub motd: String, + pub gametype: String, + pub map: String, + pub numplayers: u32, + pub maxplayers: u32, + pub hostport: u16, + pub hostip: String + } + + impl BasicStat { + pub fn ip(&self) { + println!("{}:{}", self.hostip, self.hostport); + } + + pub fn players(&self) { + println!("{}/{}", self.numplayers, self.maxplayers); + } + + pub fn info(&self) { + println!("{}\n{}, {}", self.motd, self.map, self.gametype) + } + + pub fn json(&self) -> String { + object!{ + motd: self.motd.clone(), + gametype: self.gametype.clone(), + map: self.map.clone(), + players: object!{ + max: self.maxplayers, + online: self.numplayers, + }, + hostport: self.hostport, + hostip: self.hostip.clone() + }.dump() + } + + } + + pub struct FullStat { + pub motd: String, + pub gametype: String, + pub game_id: String, + pub version: String, + pub plugins: String, // later? + pub map: String, + pub numplayers: u32, + pub maxplayers: u32, + pub hostport: u16, + pub hostip: String, + pub players: Vec<String>, + } + + impl FullStat { + + pub fn set_players(&mut self, players: Vec<String>) { + self.players = players; + } + + pub fn json(&self) -> String { + object!{ + motd: self.motd.clone(), + gametype: self.gametype.clone(), + gameid: self.game_id.clone(), + version: self.version.clone(), + plugins: self.plugins.clone(), + map: self.map.clone(), + players: object!{ + max: self.maxplayers, + online: self.numplayers, + list: self.players.clone() + }, + hostport: self.hostport, + hostip: self.hostip.clone() + }.dump() + } + } + + pub fn convert_kv(kv: HashMap<String, String>) -> FullStat { + FullStat { + motd: match kv.get(&String::from("hostname")) { Some(v) => v.clone(), _ => String::from("") }, + gametype: match kv.get(&String::from("gametype")) { Some(v) => v.clone(), _ => String::from("") }, + game_id: match kv.get(&String::from("game_id")) { Some(v) => v.clone(), _ => String::from("") }, + version: match kv.get(&String::from("version")) { Some(v) => v.clone(), _ => String::from("") }, + plugins: match kv.get(&String::from("plugins")) { Some(v) => v.clone(), _ => String::from("") }, + map: match kv.get(&String::from("map")) { Some(v) => v.clone(), _ => String::from("") }, + numplayers: match kv.get(&String::from("numplayers")) { Some(v) => v.clone().parse().expect("NaN"), _ => 0 }, + maxplayers: match kv.get(&String::from("maxplayers")) { Some(v) => v.clone().parse().expect("NaN"), _ => 0 }, + hostport: match kv.get(&String::from("hostport")) { Some(v) => v.clone().parse().expect("NaN"), _ => 0 }, + hostip: match kv.get(&String::from("hostip")) { Some(v) => v.clone(), _ => String::from("") }, + players: Vec::new() + } + } + + + pub fn slice_to_string(slice: &[u8]) -> String { + String::from_utf16(&slice.iter().map(|&slice| slice as u16).collect::<Vec<u16>>()[..]).expect("String is not UTF-16, for some reason.") + } + + pub fn send_packet(socket: &UdpSocket, addr: SocketAddr, ptype: u8, session_id: u32, payload: &[u8]) { + let mut packet = BytesMut::with_capacity(16384); + packet.put(&b"\xFE\xFD"[..]); + packet.put_u8(ptype); + packet.put_u32(session_id); + packet.put(payload); + socket.send_to(&packet, addr).expect("Couldn't send packet."); + } + + pub fn recv_packet(socket: &UdpSocket) -> BytesMut { + let mut raw_packet = [0; 16384]; + let (packet_length, _src_addr) = socket.recv_from(&mut raw_packet).expect("Drring, drring."); + let mut packet = BytesMut::with_capacity(16384); + packet.put_slice(&raw_packet[5..packet_length]); + return packet; + } + + pub fn send_handshake(socket: &UdpSocket, session_id: u32, addr: SocketAddr) { + send_packet(socket, addr, 9, session_id, &[0 as u8; 0]); + } + + pub fn recv_handshake(socket: &UdpSocket) -> u32 { + str::from_utf8(&recv_packet(socket)).expect("Non-UTF8 string.").trim_end_matches(char::from(0)).parse::<u32>().expect("Non-number string.") + } + + pub fn send_basicstat(socket: &UdpSocket, session_id: u32, addr: SocketAddr, challenge: u32) { + let mut challenge_token = BytesMut::with_capacity(32); + challenge_token.put_u32(challenge); + send_packet(socket, addr, 0, session_id, &challenge_token); + } + + pub fn recv_basicstat(socket: &UdpSocket) -> BasicStat { + let bs_buffer = &recv_packet(socket)[..]; + let bs_vector: Vec<&[u8]> = bs_buffer.split(|&ch| ch == 0).collect::<Vec<&[u8]>>(); + BasicStat { + motd: slice_to_string(bs_vector[0]), + gametype: slice_to_string(bs_vector[1]), + map: slice_to_string(bs_vector[2]), + numplayers: str::from_utf8(bs_vector[3]).expect("Players are not UTF-8.").parse().expect("Not a number."), + maxplayers: str::from_utf8(bs_vector[4]).expect("Players are not UTF-8.").parse().expect("Not a number."), + hostport: LittleEndian::read_u16(&bs_vector[5][..2]), + hostip: slice_to_string(&bs_vector[5][2..]), + } + } + + pub fn send_fullstat(socket: &UdpSocket, session_id: u32, addr: SocketAddr, challenge: u32) { + let mut challenge_token = BytesMut::with_capacity(64); + challenge_token.put_u32(challenge); + challenge_token.put_u32(0); + send_packet(socket, addr, 0, session_id, &challenge_token); + } + + pub fn recv_fullstat(socket: &UdpSocket) -> FullStat { + let fs_buffer = &recv_packet(socket)[11..]; + let mut fs_vector: Vec<&[u8]> = fs_buffer.split(|&ch| ch == 0).collect::<Vec<&[u8]>>(); + let mut fullset_kv: HashMap<String, String> = HashMap::new(); + let mut players: Vec<String> = Vec::new(); + while fs_vector[0] != [0;0] { + let key = fs_vector.remove(0); + let value = fs_vector.remove(0); + fullset_kv.insert(slice_to_string(key), slice_to_string(value)); + } + fs_vector.remove(0); + fs_vector.remove(0); // padding moment + fs_vector.remove(0); + while fs_vector[0] != [0;0] { + players.push(slice_to_string(fs_vector.remove(0))); + } + let mut fullstat = convert_kv(fullset_kv); + fullstat.set_players(players); + return fullstat; + } + +} + +fn usage(program: &str, opts: Options) { + let brief = format!("Usage: {} ADDRESS[:PORT]", program); + print!("{}", opts.usage(&brief)); +} + +fn main() { + let args: Vec<String> = env::args().collect(); + let program = args[0].clone(); + let mut opts = Options::new(); + opts.optflag("h", "help", "display this help and exit"); + opts.optflag("b", "basicstats", "sends a basic stat request"); + let flags = match opts.parse(&args[1..]) { + Ok(m) => { m } + Err(f) => { panic!("{}", f.to_string()) } + }; + if flags.opt_present("h") { + usage(&program, opts); + return; + } + let basic_stat = flags.opt_present("b"); + let server = if !flags.free.is_empty() { + if flags.free[0].contains(":") { + flags.free[0].clone() + } else { + flags.free[0].clone() + ":25565" + } + } else { + usage(&program, opts); + return; + }; + + let mut rng = rand::thread_rng(); + let session_id = rng.gen::<u32>() & 0x0F0F0F0F; + + let addrs: Vec<SocketAddr> = server.to_socket_addrs().expect("Unable to resolve domain.").collect(); + let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).expect("Couldn't bind to address."); + let addr = addrs[0]; + + querynet::send_handshake(&socket, session_id, addr); + let challenge_token = querynet::recv_handshake(&socket); + + if basic_stat { + querynet::send_basicstat(&socket, session_id, addr, challenge_token); + let basic_stats = querynet::recv_fullstat(&socket); + println!("{}", basic_stats.json()); + } else { + querynet::send_fullstat(&socket, session_id, addr, challenge_token); + let full_stats = querynet::recv_fullstat(&socket); + println!("{}", full_stats.json()); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + static REQUEST_HS: [u8; 7] = [0xFE, 0xFD, 0x09, 0x00, 0x00, 0x0A, 0xFE]; + static RESPONSE_HS: [u8; 13] = [0x09, 0x00, 0x00, 0x0A, 0xFE, 0x39, 0x35, 0x31, 0x33, 0x33, 0x30, 0x37, 0x00]; + + // #[test] + // fn test_encode() { + // assert_eq!(&querynet::encode_packet(9, 2814, &[0 as u8;0])[..], REQUEST_HS); + // } + + // #[test] + // fn test_decode() { + // let packet = &RESPONSE_HS[..]; + // assert_eq!(querynet::decode_packet(packet), b"\x39\x35\x31\x33\x33\x30\x37\x00"); + // } + + #[test] + fn test_send_hs() { + let addr = SocketAddr::from(([127, 0, 0, 1], 5005)); + let socket = UdpSocket::bind(addr).expect("Couldn't bind to address."); + querynet::send_handshake(&socket, 2814, addr); + let mut handshake: [u8; 7] = [0 as u8 ;7]; + socket.recv_from(&mut handshake).expect("Didn't receive data."); + assert_eq!(handshake, REQUEST_HS); + } + + #[test] + fn test_receive_hs() { + let addr = SocketAddr::from(([127, 0, 0, 1], 5006)); + let socket = UdpSocket::bind(addr).expect("Couldn't bind to address."); + socket.send_to(&RESPONSE_HS[..], addr).expect("Didn't send"); + assert_eq!(querynet::recv_handshake(&socket), 9513307); + } + + #[test] + fn test_hs() { + let addr = SocketAddr::from(([51, 75, 186, 103], 25625)); // tarkoza lmao + let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).expect("Couldn't bind to address."); + let mut rng = rand::thread_rng(); + let session_id = rng.gen::<u32>() & 0x0F0F0F0F; + println!("SESSION_ID: {} ", session_id); + querynet::send_handshake(&socket, session_id, addr); + let ch_tk = querynet::recv_handshake(&socket); + println!("CHALLENGE_TOKEN: {}", ch_tk); + } + + #[test] + fn test_basicstat() { + let addr = SocketAddr::from(([51, 75, 186, 103], 25625)); // tarkoza lmao + let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).expect("Couldn't bind to address."); + let mut rng = rand::thread_rng(); + let session_id = rng.gen::<u32>() & 0x0F0F0F0F; + querynet::send_handshake(&socket, session_id, addr); + let challenge_token = querynet::recv_handshake(&socket); + querynet::send_basicstat(&socket, session_id, addr, challenge_token); + let basic_stats = querynet::recv_basicstat(&socket); + assert_eq!(basic_stats.map, "Tkz"); + } + + #[test] + fn test_fullstat() { + let addr = SocketAddr::from(([51, 75, 186, 103], 25625)); // tarkoza lmao + let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0)).expect("Couldn't bind to address."); + let mut rng = rand::thread_rng(); + let session_id = rng.gen::<u32>() & 0x0F0F0F0F; + querynet::send_handshake(&socket, session_id, addr); + let challenge_token = querynet::recv_handshake(&socket); + querynet::send_fullstat(&socket, session_id, addr, challenge_token); + let full_stats = querynet::recv_fullstat(&socket); + assert_eq!(full_stats.map, "Tkz"); + } +} |