rust/hedgewars-checker/src/main.rs
author unc0rr
Tue, 23 Oct 2018 22:53:28 +0200
changeset 13952 d12ca66054aa
child 13953 e98e2fc556a7
permissions -rw-r--r--
Start checker implementation in rust
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
13952
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     1
#[macro_use]
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     2
extern crate log;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     3
extern crate argparse;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     4
extern crate dirs;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     5
extern crate ini;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     6
extern crate netbuf;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     7
extern crate stderrlog;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     8
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
     9
use argparse::{ArgumentParser, Store};
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    10
use ini::Ini;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    11
use netbuf::Buf;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    12
use std::io::{Result, Write};
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    13
use std::net::TcpStream;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    14
use std::process::Command;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    15
use std::str::FromStr;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    16
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    17
fn extract_packet(buf: &mut Buf) -> Option<netbuf::Buf> {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    18
    let packet_end = (&buf[..]).windows(2).position(|window| window == b"\n\n")?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    19
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    20
    let mut tail = buf.split_off(packet_end);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    21
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    22
    std::mem::swap(&mut tail, buf);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    23
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    24
    buf.consume(2);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    25
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    26
    Some(tail)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    27
}
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    28
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    29
fn connect_and_run(
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    30
    username: &str,
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    31
    password: &str,
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    32
    protocol_number: u32,
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    33
    executable: &str,
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    34
    data_prefix: &str,
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    35
) -> Result<()> {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    36
    info!("Connecting...");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    37
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    38
    let mut stream = TcpStream::connect("hedgewars.org:46631")?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    39
    stream.set_nonblocking(false)?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    40
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    41
    let mut buf = Buf::new();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    42
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    43
    loop {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    44
        buf.read_from(&mut stream)?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    45
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    46
        while let Some(msg) = extract_packet(&mut buf) {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    47
            if msg[..].starts_with(b"CONNECTED") {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    48
                info!("Connected");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    49
                let p = format!(
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    50
                    "CHECKER\n{}\n{}\n{}\n\n",
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    51
                    protocol_number, username, password
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    52
                );
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    53
                stream.write(p.as_bytes())?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    54
            } else if msg[..].starts_with(b"PING") {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    55
                stream.write(b"PONG\n\n")?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    56
            } else if msg[..].starts_with(b"LOGONPASSED") {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    57
                info!("Logged in");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    58
                stream.write(b"READY\n\n")?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    59
            } else if msg[..].starts_with(b"BYE") {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    60
                warn!("Received BYE: {}", String::from_utf8_lossy(&msg[..]));
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    61
                return Ok(());
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    62
            } else {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    63
                warn!(
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    64
                    "Unknown protocol command: {}",
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    65
                    String::from_utf8_lossy(&msg[..])
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    66
                )
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    67
            }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    68
        }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    69
    }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    70
}
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    71
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    72
fn get_protocol_number(executable: &str) -> Result<u32> {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    73
    let output = Command::new(executable).arg("--protocol").output()?;
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    74
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    75
    Ok(u32::from_str(&String::from_utf8(output.stdout).unwrap().as_str()).unwrap_or(55))
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    76
}
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    77
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    78
fn main() {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    79
    stderrlog::new()
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    80
        .verbosity(3)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    81
        .timestamp(stderrlog::Timestamp::Second)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    82
        .module(module_path!())
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    83
        .init()
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    84
        .unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    85
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    86
    let mut frontend_settings = dirs::home_dir().unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    87
    frontend_settings.push(".hedgewars/settings.ini");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    88
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    89
    let i = Ini::load_from_file(frontend_settings.to_str().unwrap()).unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    90
    let username = i.get_from(Some("net"), "nick").unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    91
    let password = i.get_from(Some("net"), "passwordhash").unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    92
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    93
    let mut exe = "/usr/local/bin/hwengine".to_string();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    94
    let mut prefix = "/usr/local/share/hedgewars/Data".to_string();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    95
    {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    96
        let mut ap = ArgumentParser::new();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    97
        ap.set_description("Game replay checker for hedgewars.");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    98
        ap.refer(&mut exe)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
    99
            .add_option(&["--exe"], Store, "Path to hwengine executable");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   100
        ap.refer(&mut prefix)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   101
            .add_option(&["--prefix"], Store, "Path main Data dir");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   102
        ap.parse_args_or_exit();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   103
    }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   104
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   105
    info!("Executable: {}", exe);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   106
    info!("Data dir: {}", prefix);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   107
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   108
    let protocol_number = get_protocol_number(&exe.as_str()).unwrap_or_default();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   109
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   110
    info!("Using protocol number {}", protocol_number);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   111
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   112
    connect_and_run(&username, &password, protocol_number, &exe, &prefix);
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   113
}
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   114
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   115
#[cfg(test)]
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   116
#[test]
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   117
fn test() {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   118
    let mut buf = Buf::new();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   119
    buf.extend(b"Hell");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   120
    if let Some(_) = extract_packet(&mut buf) {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   121
        assert!(false)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   122
    }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   123
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   124
    buf.extend(b"o\n\nWorld");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   125
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   126
    let packet2 = extract_packet(&mut buf).unwrap();
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   127
    assert_eq!(&buf[..], b"World");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   128
    assert_eq!(&packet2[..], b"Hello");
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   129
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   130
    if let Some(_) = extract_packet(&mut buf) {
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   131
        assert!(false)
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   132
    }
d12ca66054aa Start checker implementation in rust
unc0rr
parents:
diff changeset
   133
}