32 |
32 |
33 fn check(executable: &str, data_prefix: &str, buffer: &[u8]) -> Result<Vec<Vec<u8>>, CheckError> { |
33 fn check(executable: &str, data_prefix: &str, buffer: &[u8]) -> Result<Vec<Vec<u8>>, CheckError> { |
34 let mut replay = tempfile::NamedTempFile::new()?; |
34 let mut replay = tempfile::NamedTempFile::new()?; |
35 |
35 |
36 for line in buffer.split(|b| *b == '\n' as u8) { |
36 for line in buffer.split(|b| *b == '\n' as u8) { |
37 replay.write(&base64::decode(line)?); |
37 replay.write(&base64::decode(line)?)?; |
38 } |
38 } |
39 |
39 |
40 let temp_file_path = replay.path(); |
40 let temp_file_path = replay.path(); |
41 |
41 |
42 let mut home_dir = dirs::home_dir().unwrap(); |
42 let mut home_dir = dirs::home_dir().unwrap(); |
43 home_dir.push(".hedgewars"); |
43 home_dir.push(".hedgewars"); |
|
44 |
|
45 debug!("Checking replay in {}", temp_file_path.to_string_lossy()); |
44 |
46 |
45 let output = Command::new(executable) |
47 let output = Command::new(executable) |
46 .arg("--user-prefix") |
48 .arg("--user-prefix") |
47 .arg(&home_dir) |
49 .arg(&home_dir) |
48 .arg("--prefix") |
50 .arg("--prefix") |
52 .arg("--stats-only") |
54 .arg("--stats-only") |
53 .arg(temp_file_path) |
55 .arg(temp_file_path) |
54 .output()?; |
56 .output()?; |
55 |
57 |
56 let mut result = Vec::new(); |
58 let mut result = Vec::new(); |
57 for line in output.stdout.split(|b| *b == '\n' as u8) { |
59 |
58 result.push(line.to_vec()); |
60 let mut engine_lines = output |
59 } |
61 .stderr |
60 |
62 .split(|b| *b == '\n' as u8) |
61 Ok(result) |
63 .skip_while(|l| *l != b"WINNERS" && *l != b"DRAW"); |
|
64 |
|
65 loop { |
|
66 match engine_lines.next() { |
|
67 Some(b"DRAW") => result.push(b"DRAW".to_vec()), |
|
68 Some(b"WINNERS") => { |
|
69 result.push(b"WINNERS".to_vec()); |
|
70 let winners = engine_lines.next().unwrap(); |
|
71 let winners_num = u32::from_str(&String::from_utf8(winners.to_vec())?)?; |
|
72 result.push(winners.to_vec()); |
|
73 |
|
74 for _i in 0..winners_num { |
|
75 result.push(engine_lines.next().unwrap().to_vec()); |
|
76 } |
|
77 } |
|
78 Some(b"GHOST_POINTS") => { |
|
79 result.push(b"GHOST_POINTS".to_vec()); |
|
80 let points = engine_lines.next().unwrap(); |
|
81 let points_num = u32::from_str(&String::from_utf8(points.to_vec())?)? * 2; |
|
82 result.push(points.to_vec()); |
|
83 |
|
84 for _i in 0..points_num { |
|
85 result.push(engine_lines.next().unwrap().to_vec()); |
|
86 } |
|
87 } |
|
88 Some(b"ACHIEVEMENT") => { |
|
89 result.push(b"ACHIEVEMENT".to_vec()); |
|
90 for _i in 0..4 { |
|
91 result.push(engine_lines.next().unwrap().to_vec()); |
|
92 } |
|
93 } |
|
94 _ => break, |
|
95 } |
|
96 } |
|
97 |
|
98 if result.len() > 0 { |
|
99 Ok(result) |
|
100 } else { |
|
101 Err("no data from engine".into()) |
|
102 } |
62 } |
103 } |
63 |
104 |
64 fn connect_and_run( |
105 fn connect_and_run( |
65 username: &str, |
106 username: &str, |
66 password: &str, |
107 password: &str, |
91 } else if msg[..].starts_with(b"LOGONPASSED") { |
132 } else if msg[..].starts_with(b"LOGONPASSED") { |
92 info!("Logged in"); |
133 info!("Logged in"); |
93 stream.write(b"READY\n\n")?; |
134 stream.write(b"READY\n\n")?; |
94 } else if msg[..].starts_with(b"REPLAY") { |
135 } else if msg[..].starts_with(b"REPLAY") { |
95 info!("Got a replay"); |
136 info!("Got a replay"); |
96 let result = check(executable, data_prefix, &msg[7..])?; |
137 match check(executable, data_prefix, &msg[7..]) { |
97 |
138 Ok(result) => { |
98 debug!( |
139 info!("Checked"); |
99 "Check result: [{}]", |
140 debug!( |
100 String::from_utf8_lossy(&result.join(&(',' as u8))) |
141 "Check result: [{}]", |
101 ); |
142 String::from_utf8_lossy(&result.join(&(',' as u8))) |
102 |
143 ); |
103 stream.write(&result.join(&('\n' as u8)))?; |
144 |
104 stream.write(b"\n\n")?; |
145 stream.write(b"CHECKED\nOK\n")?; |
|
146 stream.write(&result.join(&('\n' as u8)))?; |
|
147 stream.write(b"\n\nREADY\n\n")?; |
|
148 } |
|
149 Err(e) => { |
|
150 info!("Check failed: {:?}", e); |
|
151 stream.write(b"CHECKED\nFAIL\nerror\n\nREADY\n\n")?; |
|
152 } |
|
153 } |
105 } else if msg[..].starts_with(b"BYE") { |
154 } else if msg[..].starts_with(b"BYE") { |
106 warn!("Received BYE: {}", String::from_utf8_lossy(&msg[..])); |
155 warn!("Received BYE: {}", String::from_utf8_lossy(&msg[..])); |
107 return Ok(()); |
156 return Ok(()); |
108 } else if msg[..].starts_with(b"ERROR") { |
157 } else if msg[..].starts_with(b"ERROR") { |
109 warn!("Received ERROR: {}", String::from_utf8_lossy(&msg[..])); |
158 warn!("Received ERROR: {}", String::from_utf8_lossy(&msg[..])); |