rust/hedgewars-checker/src/main.rs
changeset 16009 39ae4ed7de6e
parent 16008 1635ce22b214
equal deleted inserted replaced
16008:1635ce22b214 16009:39ae4ed7de6e
     1 use anyhow::{bail, Result};
     1 use anyhow::{anyhow, bail, Result};
     2 use argparse::{ArgumentParser, Store};
     2 use argparse::{ArgumentParser, Store};
     3 use base64::{engine::general_purpose, Engine};
     3 use base64::{engine::general_purpose, Engine};
     4 use hedgewars_network_protocol::{
     4 use hedgewars_network_protocol::{
     5     messages::HwProtocolMessage as ClientMessage, messages::HwServerMessage::*, parser,
     5     messages::HwProtocolMessage as ClientMessage, messages::HwServerMessage::*, parser,
     6 };
     6 };
     7 use ini::Ini;
     7 use ini::Ini;
     8 use log::{debug, info, warn};
     8 use log::{debug, info, warn};
     9 use netbuf::Buf;
     9 use netbuf::Buf;
    10 use std::{io::Write, str::FromStr};
    10 use std::{io::Write, str::FromStr};
       
    11 use tokio::time::MissedTickBehavior;
    11 use tokio::{io, io::AsyncWriteExt, net::TcpStream, process::Command, sync::mpsc};
    12 use tokio::{io, io::AsyncWriteExt, net::TcpStream, process::Command, sync::mpsc};
    12 
    13 
    13 async fn check(executable: &str, data_prefix: &str, buffer: &[String]) -> Result<Vec<String>> {
    14 async fn check(executable: &str, data_prefix: &str, buffer: &[String]) -> Result<Vec<String>> {
    14     let mut replay = tempfile::NamedTempFile::new()?;
    15     let mut replay = tempfile::NamedTempFile::new()?;
    15 
    16 
    17         replay.write_all(&general_purpose::STANDARD.decode(line)?)?;
    18         replay.write_all(&general_purpose::STANDARD.decode(line)?)?;
    18     }
    19     }
    19 
    20 
    20     let temp_file_path = replay.path();
    21     let temp_file_path = replay.path();
    21 
    22 
    22     let mut home_dir = dirs::home_dir().unwrap();
    23     let mut home_dir = dirs::home_dir().ok_or(anyhow!("Home path not detected"))?;
    23     home_dir.push(".hedgewars");
    24     home_dir.push(".hedgewars");
    24 
    25 
    25     debug!("Checking replay in {}", temp_file_path.to_string_lossy());
    26     debug!("Checking replay in {}", temp_file_path.to_string_lossy());
    26 
    27 
    27     let output = Command::new(executable)
    28     let output = Command::new(executable)
   117 
   118 
   118     let mut stream = TcpStream::connect("hedgewars.org:46631").await?;
   119     let mut stream = TcpStream::connect("hedgewars.org:46631").await?;
   119 
   120 
   120     let mut buf = Buf::new();
   121     let mut buf = Buf::new();
   121 
   122 
       
   123     let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(30));
       
   124     interval.set_missed_tick_behavior(MissedTickBehavior::Delay);
       
   125 
   122     loop {
   126     loop {
   123         let r = tokio::select! {
   127         let r = tokio::select! {
       
   128             _ = interval.tick() => {
       
   129                 // Send Ping
       
   130                 stream.write_all(ClientMessage::Ping.to_raw_protocol().as_bytes()).await?;
       
   131                 None
       
   132             },
   124             _ = stream.readable() => None,
   133             _ = stream.readable() => None,
   125             r = results_receiver.recv() => r
   134             r = results_receiver.recv() => r
   126         };
   135         };
   127 
   136 
   128         //println!("Loop: {:?}", &r);
   137         //println!("Loop: {:?}", &r);
   198                 Ping => {
   207                 Ping => {
   199                     stream
   208                     stream
   200                         .write_all(ClientMessage::Pong.to_raw_protocol().as_bytes())
   209                         .write_all(ClientMessage::Pong.to_raw_protocol().as_bytes())
   201                         .await?;
   210                         .await?;
   202                 }
   211                 }
       
   212                 Pong => {
       
   213                     // do nothing
       
   214                 }
   203                 LogonPassed => {
   215                 LogonPassed => {
   204                     stream
   216                     stream
   205                         .write_all(ClientMessage::CheckerReady.to_raw_protocol().as_bytes())
   217                         .write_all(ClientMessage::CheckerReady.to_raw_protocol().as_bytes())
   206                         .await?;
   218                         .await?;
   207                 }
   219                 }
   244 }
   256 }
   245 
   257 
   246 async fn get_protocol_number(executable: &str) -> Result<u16> {
   258 async fn get_protocol_number(executable: &str) -> Result<u16> {
   247     let output = Command::new(executable).arg("--protocol").output().await?;
   259     let output = Command::new(executable).arg("--protocol").output().await?;
   248 
   260 
   249     Ok(u16::from_str(String::from_utf8(output.stdout).unwrap().trim()).unwrap_or(55))
   261     Ok(u16::from_str(String::from_utf8(output.stdout)?.trim()).unwrap_or(55))
   250 }
   262 }
   251 
   263 
   252 #[tokio::main]
   264 #[tokio::main]
   253 async fn main() -> Result<()> {
   265 async fn main() -> Result<()> {
   254     stderrlog::new()
   266     stderrlog::new()
   255         .verbosity(3)
   267         .verbosity(3)
   256         .timestamp(stderrlog::Timestamp::Second)
   268         .timestamp(stderrlog::Timestamp::Second)
   257         .module(module_path!())
   269         .module(module_path!())
   258         .init()
   270         .init()?;
   259         .unwrap();
   271 
   260 
   272     let mut frontend_settings = dirs::home_dir().ok_or(anyhow!("Home path not detected"))?;
   261     let mut frontend_settings = dirs::home_dir().unwrap();
       
   262     frontend_settings.push(".hedgewars/settings.ini");
   273     frontend_settings.push(".hedgewars/settings.ini");
   263 
   274 
   264     let i = Ini::load_from_file(frontend_settings.to_str().unwrap()).unwrap();
   275     let i = Ini::load_from_file(frontend_settings.to_str().unwrap()).unwrap();
   265     let username = i.get_from(Some("net"), "nick").unwrap();
   276     let username = i
   266     let password = i.get_from(Some("net"), "passwordhash").unwrap();
   277         .get_from(Some("net"), "nick")
       
   278         .ok_or(anyhow!("Nickname not found in frontend config"))?;
       
   279     let password = i
       
   280         .get_from(Some("net"), "passwordhash")
       
   281         .ok_or(anyhow!("Password not found in frontend config"))?;
   267 
   282 
   268     let mut exe = "/usr/local/bin/hwengine".to_string();
   283     let mut exe = "/usr/local/bin/hwengine".to_string();
   269     let mut prefix = "/usr/local/share/hedgewars/Data".to_string();
   284     let mut prefix = "/usr/local/share/hedgewars/Data".to_string();
   270     {
   285     {
   271         let mut ap = ArgumentParser::new();
   286         let mut ap = ArgumentParser::new();
   278     }
   293     }
   279 
   294 
   280     info!("Executable: {}", exe);
   295     info!("Executable: {}", exe);
   281     info!("Data dir: {}", prefix);
   296     info!("Data dir: {}", prefix);
   282 
   297 
   283     let protocol_number = get_protocol_number(exe.as_str()).await.unwrap_or_default();
   298     let protocol_number = get_protocol_number(exe.as_str()).await?;
   284 
   299 
   285     info!("Using protocol number {}", protocol_number);
   300     info!("Using protocol number {}", protocol_number);
   286 
   301 
   287     let (replay_sender, replay_receiver) = mpsc::channel(1);
   302     let (replay_sender, replay_receiver) = mpsc::channel(1);
   288     let (results_sender, results_receiver) = mpsc::channel(1);
   303     let (results_sender, results_receiver) = mpsc::channel(1);