Always print result of manual scan
[dnsseed-rust] / src / reader.rs
1 use std::sync::atomic::Ordering;
2 use std::io::BufReader;
3 use std::net::SocketAddr;
4 use std::time::Instant;
5
6 use tokio::prelude::*;
7 use tokio::io::{stdin, lines};
8
9 use crate::printer::Printer;
10 use crate::datastore::{Store, AddressState, U64Setting, RegexSetting};
11
12 use crate::{START_SHUTDOWN, scan_node};
13
14 use regex::Regex;
15
16 pub fn read(store: &'static Store, printer: &'static Printer) {
17         tokio::spawn(lines(BufReader::new(stdin())).for_each(move |line| {
18                 macro_rules! err {
19                         () => { {
20                                 printer.add_line(format!("Unparsable input: \"{}\"", line), true);
21                                 return future::ok(());
22                         } }
23                 }
24                 let mut line_iter = line.split(' ');
25                 macro_rules! get_next_chunk {
26                         () => { {
27                                 match line_iter.next() {
28                                         Some(c) => c,
29                                         None => err!(),
30                                 }
31                         } }
32                 }
33                 macro_rules! try_parse_next_chunk {
34                         ($type: ty) => { {
35                                 match get_next_chunk!().parse::<$type>() {
36                                         Ok(res) => res,
37                                         Err(_) => err!(),
38                                 }
39                         } }
40                 }
41                 match get_next_chunk!() {
42                         "c" => store.set_u64(U64Setting::ConnsPerSec, try_parse_next_chunk!(u64)),
43                         "t" => store.set_u64(U64Setting::RunTimeout, try_parse_next_chunk!(u64)),
44                         "v" => store.set_u64(U64Setting::MinProtocolVersion, try_parse_next_chunk!(u64)),
45                         "w" => store.set_u64(U64Setting::WasGoodTimeout, try_parse_next_chunk!(u64)),
46                         "s" => {
47                                 if line.len() < 3 || !line.starts_with("s ") {
48                                         err!();
49                                 }
50                                 store.set_regex(RegexSetting::SubverRegex, match line[2..].parse::<Regex>() {
51                                         Ok(res) => res,
52                                         Err(_) => err!(),
53                                 });
54                         },
55                         "a" => scan_node(Instant::now(), try_parse_next_chunk!(SocketAddr), true),
56                         "r" => {
57                                 match AddressState::from_num(try_parse_next_chunk!(u8)) {
58                                         Some(state) => store.set_u64(U64Setting::RescanInterval(state), try_parse_next_chunk!(u64)),
59                                         None => err!(),
60                                 }
61                         },
62                         "q" => {
63                                 START_SHUTDOWN.store(true, Ordering::SeqCst);
64                                 return future::err(std::io::Error::new(std::io::ErrorKind::Other, ""));
65                         },
66                         _ => err!(),
67                 }
68                 future::ok(())
69         }).then(move |_| {
70                 printer.add_line("Shutting down...".to_string(), true);
71                 future::ok(())
72         }));
73 }