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