aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idxbin2354 -> 2312 bytes
-rw-r--r--.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idxbin746 -> 796 bytes
-rw-r--r--.cache/clangd/index/mcping.c.7D35BB1188AA7031.idxbin1204 -> 1340 bytes
-rw-r--r--.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idxbin2140 -> 2116 bytes
-rw-r--r--.gitignore12
-rw-r--r--Cargo.lock122
-rw-r--r--Cargo.toml19
-rw-r--r--compile_commands.json21
-rw-r--r--include/mcnetwork.h9
-rw-r--r--mcnetwork.c12
-rw-r--r--mcping.c7
-rw-r--r--src/bin/mcping.rs3
-rw-r--r--src/bin/mcquery.rs314
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
index 4be19e7..2823793 100644
--- a/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx
+++ b/.cache/clangd/index/mcnetwork.c.B508600D61ADFA6B.idx
Binary files differ
diff --git a/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx b/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx
index bfe1868..0e6d7ef 100644
--- a/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx
+++ b/.cache/clangd/index/mcnetwork.h.887D4E662A2D9D8B.idx
Binary files differ
diff --git a/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx b/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx
index 5e800aa..2bcee03 100644
--- a/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx
+++ b/.cache/clangd/index/mcping.c.7D35BB1188AA7031.idx
Binary files differ
diff --git a/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx b/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx
index 37d98da..5ca75a7 100644
--- a/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx
+++ b/.cache/clangd/index/mctypes.h.7136FA4A3E0277AB.idx
Binary files differ
diff --git a/.gitignore b/.gitignore
index 1a7b40e..cfcd9cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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);
diff --git a/mcping.c b/mcping.c
index 037dcc5..cc43e73 100644
--- a/mcping.c
+++ b/mcping.c
@@ -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");
+ }
+}