# HG changeset patch # User unc0rr # Date 1540332503 -7200 # Node ID e98e2fc556a7f61c8b8b68c659948084e1b3655b # Parent d12ca66054aacffffa16174c9a8abfbcdd6fec52 Create replay file, run engine, result from it and send it to the server. Not implemented: filtering of engine output. diff -r d12ca66054aa -r e98e2fc556a7 rust/hedgewars-checker/Cargo.toml --- a/rust/hedgewars-checker/Cargo.toml Tue Oct 23 22:53:28 2018 +0200 +++ b/rust/hedgewars-checker/Cargo.toml Wed Oct 24 00:08:23 2018 +0200 @@ -1,7 +1,7 @@ [package] name = "hedgewars-checker" version = "0.1.0" -authors = ["Andrei Korotaev "] +authors = ["Andrey Korotaev "] [dependencies] rust-ini = "0.13" @@ -10,3 +10,5 @@ log = "0.4" stderrlog = "0.4" netbuf = "0.4" +tempfile = "3.0" +base64 = "0.9.3" diff -r d12ca66054aa -r e98e2fc556a7 rust/hedgewars-checker/src/main.rs --- a/rust/hedgewars-checker/src/main.rs Tue Oct 23 22:53:28 2018 +0200 +++ b/rust/hedgewars-checker/src/main.rs Wed Oct 24 00:08:23 2018 +0200 @@ -1,19 +1,23 @@ #[macro_use] extern crate log; extern crate argparse; +extern crate base64; extern crate dirs; extern crate ini; extern crate netbuf; extern crate stderrlog; +extern crate tempfile; use argparse::{ArgumentParser, Store}; use ini::Ini; use netbuf::Buf; -use std::io::{Result, Write}; +use std::io::Write; use std::net::TcpStream; use std::process::Command; use std::str::FromStr; +type CheckError = Box; + fn extract_packet(buf: &mut Buf) -> Option { let packet_end = (&buf[..]).windows(2).position(|window| window == b"\n\n")?; @@ -26,13 +30,44 @@ Some(tail) } +fn check(executable: &str, data_prefix: &str, buffer: &[u8]) -> Result>, CheckError> { + let mut replay = tempfile::NamedTempFile::new()?; + + for line in buffer.split(|b| *b == '\n' as u8) { + replay.write(&base64::decode(line)?); + } + + let temp_file_path = replay.path(); + + let mut home_dir = dirs::home_dir().unwrap(); + home_dir.push(".hedgewars"); + + let output = Command::new(executable) + .arg("--user-prefix") + .arg(&home_dir) + .arg("--prefix") + .arg(data_prefix) + .arg("--nomusic") + .arg("--nosound") + .arg("--stats-only") + .arg(temp_file_path) + .output()?; + + let mut result = Vec::new(); + for line in output.stdout.split(|b| *b == '\n' as u8) { + result.push(line.to_vec()); + } + + Ok(result) +} + fn connect_and_run( username: &str, password: &str, protocol_number: u32, executable: &str, data_prefix: &str, -) -> Result<()> { +) -> Result<(), CheckError> { info!("Connecting..."); let mut stream = TcpStream::connect("hedgewars.org:46631")?; @@ -56,9 +91,23 @@ } else if msg[..].starts_with(b"LOGONPASSED") { info!("Logged in"); stream.write(b"READY\n\n")?; + } else if msg[..].starts_with(b"REPLAY") { + info!("Got a replay"); + let result = check(executable, data_prefix, &msg[7..])?; + + debug!( + "Check result: [{}]", + String::from_utf8_lossy(&result.join(&(',' as u8))) + ); + + stream.write(&result.join(&('\n' as u8)))?; + stream.write(b"\n\n")?; } else if msg[..].starts_with(b"BYE") { warn!("Received BYE: {}", String::from_utf8_lossy(&msg[..])); return Ok(()); + } else if msg[..].starts_with(b"ERROR") { + warn!("Received ERROR: {}", String::from_utf8_lossy(&msg[..])); + return Ok(()); } else { warn!( "Unknown protocol command: {}", @@ -69,7 +118,7 @@ } } -fn get_protocol_number(executable: &str) -> Result { +fn get_protocol_number(executable: &str) -> std::io::Result { let output = Command::new(executable).arg("--protocol").output()?; Ok(u32::from_str(&String::from_utf8(output.stdout).unwrap().as_str()).unwrap_or(55))