Compare commits

..

No commits in common. "ec4d6035e8d8052fe64ac6f3f02de3202edb452b" and "53752c46c5efbe7dda76d11c30372c57baea1e9e" have entirely different histories.

4 changed files with 49 additions and 79 deletions

View file

@ -7,7 +7,7 @@ const RECURSION_DESIRED: u16 = 1 << 8;
const RECORD_TYPE_SRV: u16 = 33;
const RECORD_CLASS_IN: u16 = 1;
pub fn create_dns_query(qname: &str, qtype: u16, qclass: u16) -> Result<Vec<u8>> {
pub fn create_dns_query(qname: &String, qtype: u16, qclass: u16) -> Result<Vec<u8>> {
let qname = match qname.is_ascii() {
true => qname,
false => return Err(Error::new(ErrorKind::InvalidInput, "domain is not valid ASCII")),
@ -110,7 +110,7 @@ pub fn parse_srv_response(mut ptr: usize, recv: &[u8]) -> Option<DnsSrvResponse>
pub fn resolve_srv_port(domain: &str) -> Option<u16> {
let request = create_dns_query(
&format!("_minecraft._tcp.{}", domain),
&("_minecraft._tcp.".to_string() + domain),
RECORD_TYPE_SRV,
RECORD_CLASS_IN).unwrap();

View file

@ -41,7 +41,7 @@ impl StatusCode {
}
}
type HttpHandlerFunc = fn(&Request, Response, bool) -> Result<StatusCode>;
type HttpHandlerFunc = fn(&Request, Response) -> Result<StatusCode>;
pub struct Request<'a> {
stream: &'a TcpStream,
@ -213,21 +213,20 @@ impl<'a> Response<'a> {
}
}
pub struct HttpServer<'a> {
address: &'a str,
pub struct HttpServer {
address: String,
port: u16,
trusted_proxies: Arc<Vec<IpAddr>>,
max_connections: usize,
verbose: bool,
}
impl HttpServer <'_> {
pub fn new(address: &'_ str, max_connections: usize, trusted_proxies: Vec<IpAddr>, verbose: bool) -> HttpServer<'_> {
let mut _address = address;
impl HttpServer {
pub fn new(address: String, max_connections: usize, trusted_proxies: Vec<IpAddr>) -> HttpServer {
let mut _address = address.clone();
let mut _port: u16 = 8080;
match address.split_once(":") {
Some((ip, port)) => {
_address = ip;
_address = ip.to_string();
_port = port.parse::<u16>().expect(format!("Invalid port {}", port).as_str());
}
None => {}
@ -237,14 +236,12 @@ impl HttpServer <'_> {
port: _port,
trusted_proxies: Arc::new(trusted_proxies),
max_connections,
verbose,
}
}
pub fn start(&self, handler: HttpHandlerFunc) -> Result<()> {
let pool = ThreadPool::new(self.max_connections);
let listener = TcpListener::bind(format!("{}:{}", self.address, self.port)).expect("Failed to bind to port");
let verbose = self.verbose;
println!("Now listening on {}:{}", self.address, self.port);
@ -253,7 +250,7 @@ impl HttpServer <'_> {
Ok(stream) => {
let trusted_proxies = self.trusted_proxies.clone();
pool.execute(move || {
HttpServer::handle_client(&stream, handler, trusted_proxies, verbose);
HttpServer::handle_client(&stream, handler, trusted_proxies);
});
}
Err(e) => {
@ -265,7 +262,7 @@ impl HttpServer <'_> {
Ok(())
}
fn handle_client(stream: &TcpStream, handler: HttpHandlerFunc, trusted_proxies: Arc<Vec<IpAddr>>, verbose: bool) {
fn handle_client(stream: &TcpStream, handler: HttpHandlerFunc, trusted_proxies: Arc<Vec<IpAddr>>) {
let buf_reader = BufReader::new(stream);
let http_request: Vec<String> = buf_reader
.lines()
@ -283,7 +280,7 @@ impl HttpServer <'_> {
let response = Response::new(stream);
let start_date = Local::now();
match handler(&request, response, verbose) {
match handler(&request, response) {
Ok(status) => {
let end_date = Local::now();

View file

@ -53,7 +53,7 @@ fn parse_address(address: &str) -> Result<SocketAddr> {
}
}
fn handle_html_request(request: &Request, response: &mut Response, verbose: bool) -> Result<StatusCode> {
fn handle_html_request(request: &Request, response: &mut Response) -> Result<StatusCode> {
let content = include_str!("views/index.html");
response.set_header("Content-Type", "text/html".to_string());
response.status(StatusCode::OK);
@ -72,7 +72,7 @@ fn handle_html_request(request: &Request, response: &mut Response, verbose: bool
);
},
Ok(address) => {
match MinecraftStatus::fetch(&address, verbose) {
match MinecraftStatus::fetch(&address) {
Err(err) => {
println!(
"Failed to connect to {} ({}): {}",
@ -136,7 +136,7 @@ fn handle_html_request(request: &Request, response: &mut Response, verbose: bool
return response.send();
}
fn handle_json_request(request: &Request, response: &mut Response, verbose: bool) -> Result<StatusCode> {
fn handle_json_request(request: &Request, response: &mut Response) -> Result<StatusCode> {
response.set_header("Content-Type", "text/plain".to_string());
response.status(StatusCode::OK);
@ -149,7 +149,7 @@ fn handle_json_request(request: &Request, response: &mut Response, verbose: bool
response.body("Invalid server address.\n".to_string());
}
Ok(address) => {
match MinecraftStatus::fetch(&address, verbose) {
match MinecraftStatus::fetch(&address) {
Err(err) => {
println!(
"Failed to connect to {} ({}): {}",
@ -194,7 +194,9 @@ fn handle_json_request(request: &Request, response: &mut Response, verbose: bool
return response.send();
}
fn print_help() {
fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!(
r#"Crafty McStatusFace, v{} - made with <3 by ari melody
@ -204,29 +206,13 @@ $ mcstatusface serve [address[:port]]
Query a server:
$ mcstatusface <address[:port]>"#,
env!("CARGO_PKG_VERSION"));
}
fn main() -> Result<()> {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
print_help();
std::process::exit(0);
}
let verbose = args.contains(&String::from("-v"));
if args[1] != "serve" {
let address = parse_address(&args[1]).expect("Failed to parse address");
let status = MinecraftStatus::fetch(&address).unwrap();
if !args[1..].contains(&String::from("serve")) {
let address_arg = match args[1..].iter().find(|arg| !arg.starts_with("-")) {
Some(arg) => arg,
None => {
print_help();
std::process::exit(0);
}
};
let address = parse_address(&address_arg).expect("Failed to parse address");
match MinecraftStatus::fetch(&address, verbose) {
Ok(status) => {
println!("Version: {} ({})", status.version.name, status.version.protocol);
println!("Players: {}/{}", status.players.online, status.players.max);
println!(
@ -237,20 +223,10 @@ fn main() -> Result<()> {
println!("{}", status.parse_description());
return Ok(());
},
Err (e) => {
return Err(Error::new(
ErrorKind::Other,
format!("Failed to fetch status: {}", e)));
}
};
}
let mut address = "0.0.0.0:8080";
let address_args = args[1..].iter()
.filter(|arg| *arg != "-v" && *arg != "serve")
.collect::<Vec<_>>();
if !address_args.is_empty() { address = address_args[0] }
let mut address = "0.0.0.0:8080".to_string();
if args.len() > 2 { address = args[2].to_string() }
let trusted_proxies: Vec<IpAddr> =
match env::var("MCSTATUSFACE_TRUSTED_PROXIES") {
Err(_) => { vec![] }
@ -266,7 +242,7 @@ fn main() -> Result<()> {
}
};
HttpServer::new(address, 16, trusted_proxies, verbose).start(|request, mut response, verbose| {
HttpServer::new(address, 16, trusted_proxies).start(|request, mut response| {
response.status(StatusCode::OK);
response.set_header("Content-Type", "text/plain".to_string());
response.set_header("x-powered-by", "GIRL FUEL".to_string());
@ -288,11 +264,11 @@ fn main() -> Result<()> {
if request.headers().get("accept").is_some_and(
|accept| accept.contains("text/html")
) {
return handle_html_request(request, &mut response, verbose);
return handle_html_request(request, &mut response);
}
// JSON response
return handle_json_request(request, &mut response, verbose);
return handle_json_request(request, &mut response);
}
response.status(StatusCode::NotFound);

View file

@ -4,8 +4,6 @@ use std::time::Duration;
use crate::leb128::{read_leb128, write_leb128};
const TIMEOUT_SECS: u64 = 5;
#[derive(serde::Serialize, serde::Deserialize)]
pub struct MinecraftVersion {
pub name: String,
@ -58,21 +56,20 @@ pub struct MinecraftStatus {
}
impl MinecraftStatus {
pub fn fetch(address: &SocketAddr, verbose: bool) -> Result<MinecraftStatus> {
if verbose { println!("Connecting to {address}..."); }
pub fn fetch(address: &SocketAddr) -> Result<MinecraftStatus> {
//println!("Connecting to {address}...");
let mut stream = match TcpStream::connect_timeout(
address, Duration::from_secs(TIMEOUT_SECS)) {
Ok(stream) => stream,
Err(e) => {
return Err(e);
}
};
if verbose { println!("Connected!"); }
let stream = TcpStream::connect_timeout(address, Duration::new(5, 0));
if stream.is_err() { return Err(stream.unwrap_err()); }
if verbose { println!("Sending payload..."); }
//println!("Connected!");
let mut stream = stream.unwrap();
let mut send_buffer: Vec<u8> = Vec::new();
//println!("Sending payload...");
send_buffer.push(0x00); // packet ID
write_leb128(&mut send_buffer, 769); // "i am 1.21.4"
write_leb128(&mut send_buffer, // upcoming address length
@ -86,7 +83,7 @@ impl MinecraftStatus {
send_packet(&mut stream, &[0x00]).unwrap();
if verbose { println!("Awaiting response..."); }
//println!("Payload sent, receiving...\n");
let mut data: Vec<u8> = Vec::new();
let mut len: usize = 0;