Fix subver regex parsing with spaces
[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)),
56                         "r" => {
57                                 match try_parse_next_chunk!(u8) {
58                                         0 => store.set_u64(U64Setting::RescanInterval(AddressState::Untested), try_parse_next_chunk!(u64)),
59                                         1 => store.set_u64(U64Setting::RescanInterval(AddressState::LowBlockCount), try_parse_next_chunk!(u64)),
60                                         2 => store.set_u64(U64Setting::RescanInterval(AddressState::HighBlockCount), try_parse_next_chunk!(u64)),
61                                         3 => store.set_u64(U64Setting::RescanInterval(AddressState::LowVersion), try_parse_next_chunk!(u64)),
62                                         4 => store.set_u64(U64Setting::RescanInterval(AddressState::BadVersion), try_parse_next_chunk!(u64)),
63                                         5 => store.set_u64(U64Setting::RescanInterval(AddressState::NotFullNode), try_parse_next_chunk!(u64)),
64                                         6 => store.set_u64(U64Setting::RescanInterval(AddressState::ProtocolViolation), try_parse_next_chunk!(u64)),
65                                         7 => store.set_u64(U64Setting::RescanInterval(AddressState::Timeout), try_parse_next_chunk!(u64)),
66                                         8 => store.set_u64(U64Setting::RescanInterval(AddressState::TimeoutDuringRequest), try_parse_next_chunk!(u64)),
67                                         9 => store.set_u64(U64Setting::RescanInterval(AddressState::Good), try_parse_next_chunk!(u64)),
68                                         10 => store.set_u64(U64Setting::RescanInterval(AddressState::WasGood), try_parse_next_chunk!(u64)),
69                                         _ => err!(),
70                                 }
71                         },
72                         "q" => {
73                                 START_SHUTDOWN.store(true, Ordering::SeqCst);
74                                 return future::err(std::io::Error::new(std::io::ErrorKind::Other, ""));
75                         },
76                         _ => err!(),
77                 }
78                 future::ok(())
79         }).then(move |_| {
80                 printer.add_line("Shutting down...".to_string(), true);
81                 future::ok(())
82         }));
83 }