Total runtime timeout, fix saves
[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" => store.set_regex(RegexSetting::SubverRegex, try_parse_next_chunk!(Regex)),
47                         "a" => scan_node(Instant::now(), try_parse_next_chunk!(SocketAddr)),
48                         "r" => {
49                                 match try_parse_next_chunk!(u8) {
50                                         0 => store.set_u64(U64Setting::RescanInterval(AddressState::Untested), try_parse_next_chunk!(u64)),
51                                         1 => store.set_u64(U64Setting::RescanInterval(AddressState::LowBlockCount), try_parse_next_chunk!(u64)),
52                                         2 => store.set_u64(U64Setting::RescanInterval(AddressState::HighBlockCount), try_parse_next_chunk!(u64)),
53                                         3 => store.set_u64(U64Setting::RescanInterval(AddressState::LowVersion), try_parse_next_chunk!(u64)),
54                                         4 => store.set_u64(U64Setting::RescanInterval(AddressState::BadVersion), try_parse_next_chunk!(u64)),
55                                         5 => store.set_u64(U64Setting::RescanInterval(AddressState::NotFullNode), try_parse_next_chunk!(u64)),
56                                         6 => store.set_u64(U64Setting::RescanInterval(AddressState::ProtocolViolation), try_parse_next_chunk!(u64)),
57                                         7 => store.set_u64(U64Setting::RescanInterval(AddressState::Timeout), try_parse_next_chunk!(u64)),
58                                         8 => store.set_u64(U64Setting::RescanInterval(AddressState::TimeoutDuringRequest), try_parse_next_chunk!(u64)),
59                                         9 => store.set_u64(U64Setting::RescanInterval(AddressState::Good), try_parse_next_chunk!(u64)),
60                                         10 => store.set_u64(U64Setting::RescanInterval(AddressState::WasGood), try_parse_next_chunk!(u64)),
61                                         _ => err!(),
62                                 }
63                         },
64                         "q" => {
65                                 START_SHUTDOWN.store(true, Ordering::SeqCst);
66                                 return future::err(std::io::Error::new(std::io::ErrorKind::Other, ""));
67                         },
68                         _ => err!(),
69                 }
70                 future::ok(())
71         }).then(move |_| {
72                 printer.add_line("Shutting down...".to_string(), true);
73                 future::ok(())
74         }));
75 }