add timeout to mcstat

This commit is contained in:
LordMZTE 2020-09-25 16:20:39 +02:00
parent 68096eb2d2
commit e3387624e8
2 changed files with 63 additions and 23 deletions

View file

@ -17,6 +17,12 @@ args:
help: "the protocol version to use" help: "the protocol version to use"
default_value: "751" default_value: "751"
takes_value: true takes_value: true
- timeout:
long: "timeout"
short: t
help: "the time before the server ping times out in milliseconds"
takes_value: true
default_value: "500"
# IMAGE ARGS # IMAGE ARGS
# TODO due to a bug in clap, the image argument is always required because size has a default value # TODO due to a bug in clap, the image argument is always required because size has a default value

View file

@ -2,52 +2,81 @@
extern crate clap; extern crate clap;
#[macro_use] #[macro_use]
extern crate mcstat; extern crate mcstat;
#[macro_use]
extern crate anyhow;
use std::io::{Cursor, Write}; use std::io::{Cursor, Write};
use time::Duration;
use tokio::time;
use mcstat::{AsciiConfig, remove_formatting};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use asciify::AsciiBuilder; use asciify::AsciiBuilder;
use async_minecraft_ping::ConnectionConfig; use async_minecraft_ping::{ConnectionConfig, StatusResponse};
use clap::App; use clap::App;
use image::ImageFormat; use image::ImageFormat;
use itertools::Itertools; use itertools::Itertools;
use mcstat::{remove_formatting, AsciiConfig};
use termcolor::{Buffer, BufferWriter, ColorChoice, WriteColor}; use termcolor::{Buffer, BufferWriter, ColorChoice, WriteColor};
const ARGUMENT_FAIL_MESSAGE: &str = "failed to get value from args";
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
let yaml = load_yaml!("args.yml"); let yaml = load_yaml!("args.yml");
let matches = App::from_yaml(yaml).get_matches(); let matches = App::from_yaml(yaml).get_matches();
//region Network //region Network
let config = ConnectionConfig::build(matches.value_of("ip").unwrap().to_owned()) let config = ConnectionConfig::build(
.with_port( matches
matches .value_of("ip")
.value_of("port") .context(ARGUMENT_FAIL_MESSAGE)?
.unwrap() .to_owned(),
.parse() )
.ok() .with_port(
.and_then(|p| if p > 0 && p < u16::MAX { Some(p) } else { None }) matches
.context("invalid port")?, .value_of("port")
) .context(ARGUMENT_FAIL_MESSAGE)?
.with_protocol_version( .parse()
matches .context("invalid port")
.value_of("protocol-version") .and_then(|p| {
.unwrap() if p > 0 && p < u16::MAX {
.parse() Ok(p)
.context("invalid protocol version")?, } else {
); Err(anyhow!(ARGUMENT_FAIL_MESSAGE))
let mut connection = config.connect().await?; }
let response = connection.status().await?; })
.context("invalid port")?,
)
.with_protocol_version(
matches
.value_of("protocol-version")
.context(ARGUMENT_FAIL_MESSAGE)?
.parse()
.context("invalid protocol version")?,
);
//create timeout for server connection
let mut timeout = time::delay_for(Duration::from_millis(
matches
.value_of("timeout")
.context(ARGUMENT_FAIL_MESSAGE)?
.parse()
.context("timeout is invalid value")?,
));
let response = tokio::select! {
_ = &mut timeout => Err(anyhow!("Connection to server timed out")),
r = ping_server(config) => r,
}?;
//endregion //endregion
//region Image //region Image
let image_size: u32 = matches let image_size: u32 = matches
.value_of("size") .value_of("size")
.unwrap() .context("failed to get value from args")?
.parse() .parse()
.with_context(|| "image size must be number")?; .context("image size must be number")?;
let mut image = None; let mut image = None;
if let (Some(favicon), true) = (response.favicon, matches.is_present("image")) { if let (Some(favicon), true) = (response.favicon, matches.is_present("image")) {
//The image parsing and asciifying is done while the table is printing //The image parsing and asciifying is done while the table is printing
image = Some(tokio::spawn(get_image( image = Some(tokio::spawn(get_image(
@ -112,3 +141,8 @@ async fn get_image(favicon: String, config: AsciiConfig) -> Result<Vec<u8>> {
buf.reset()?; buf.reset()?;
Ok(buf.as_slice().to_vec()) Ok(buf.as_slice().to_vec())
} }
async fn ping_server(server: ConnectionConfig) -> Result<StatusResponse> {
let mut con = server.connect().await?;
con.status().await
}