use crate::bgp_client::BGPClient;
pub const SECS_PER_SCAN_RESULTS: u64 = 15;
+const MAX_CONNS_PER_SEC_PER_STATUS: u64 = 30;
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub enum AddressState {
last_good: Instant, // Ignored unless state is Good or WasGood
last_services: u64,
state: AddressState,
+ queued: bool,
}
/// Essentially SocketAddr but without a traffic class or scope
struct Nodes {
good_node_services: [HashSet<SockAddr>; 64],
nodes_to_state: HashMap<SockAddr, Node>,
- state_next_scan: Vec<Vec<(Instant, SockAddr)>>,
+ state_next_scan: Vec<Vec<SockAddr>>,
}
struct NodesMutRef<'a> {
good_node_services: &'a mut [HashSet<SockAddr>; 64],
nodes_to_state: &'a mut HashMap<SockAddr, Node>,
- state_next_scan: &'a mut Vec<Vec<(Instant, SockAddr)>>,
+ state_next_scan: &'a mut Vec<Vec<SockAddr>>,
}
impl Nodes {
}
let nodes_future = File::open(store.clone() + "/nodes").and_then(|f| {
- let start_time = Instant::now() - Duration::from_secs(60 * 60 * 24);
let mut res = nodes_uninitd!();
let l = BufReader::new(f).lines();
for line_res in l {
last_services,
last_update: Instant::now(),
last_good: Instant::now(),
+ queued: true,
};
if node.state == AddressState::Good {
for i in 0..64 {
}
}
}
- res.state_next_scan[node.state.to_num() as usize].push((start_time, sockaddr.into()));
+ res.state_next_scan[node.state.to_num() as usize].push(sockaddr.into());
res.nodes_to_state.insert(sockaddr.into(), node);
}
future::ok(res)
last_services: 0,
last_update: cur_time,
last_good: cur_time,
+ queued: true,
});
- nodes.state_next_scan[AddressState::Untested.to_num() as usize].push((cur_time, addr.into()));
+ nodes.state_next_scan[AddressState::Untested.to_num() as usize].push(addr.into());
res += 1;
},
hash_map::Entry::Occupied(_) => {},
last_services: 0,
last_update: now,
last_good: now,
+ queued: false,
});
let ret = state_ref.state;
if (state_ref.state == AddressState::Good || state_ref.state == AddressState::WasGood)
}
}
state_ref.last_services = 0;
- nodes.state_next_scan[AddressState::WasGood.to_num() as usize].push((now, addr));
+ if !state_ref.queued {
+ nodes.state_next_scan[AddressState::WasGood.to_num() as usize].push(addr);
+ state_ref.queued = true;
+ }
} else {
state_ref.state = state;
if state == AddressState::Good {
state_ref.last_services = services;
state_ref.last_good = now;
}
- nodes.state_next_scan[state.to_num() as usize].push((now, addr));
+ if !state_ref.queued {
+ nodes.state_next_scan[state.to_num() as usize].push(addr);
+ state_ref.queued = true;
+ }
}
state_ref.last_update = now;
ret
let mut nodes_buff = String::new();
{
let nodes = self.nodes.read().unwrap();
- nodes_buff.reserve(nodes.nodes_to_state.len() * 20);
+ nodes_buff.reserve(nodes.nodes_to_state.len() * 32);
for (ref sockaddr, ref node) in nodes.nodes_to_state.iter() {
nodes_buff += &sockaddr.to_string();
nodes_buff += ",";
let mut dns_buff = String::new();
{
let mut rng = thread_rng();
- for i in &[1u64, 4, 5, 8, 9, 12, 13, 1024, 1025, 1028, 1029, 1032, 1033, 1036, 1037] {
+ for i in &[ 0b00000000001u64,
+ 0b00000000100,
+ 0b00000000101,
+ 0b00000001000,
+ 0b00000001001,
+ 0b00000001100,
+ 0b00000001101,
+ 0b00001001001,
+ 0b10000000000,
+ 0b10000000001,
+ 0b10000000100,
+ 0b10000000101,
+ 0b10000001000,
+ 0b10000001001,
+ 0b10000001100,
+ 0b10000001101,
+ 0b10001001000] {
+ // ^ NODE_NETWORK_LIIMTED
+ //COMPACT_FILTERS ^ ^ NODE_BLOOM
+ // NODE_WITNESS ^ ^ NODE_NETWORK
+ // We support all combos of NETWORK, NETWORK_LIMITED, BLOOM, and WITNESS
+ // We support COMPACT_FILTERS with WITNESS and NETWORK or NETWORK_LIIMTED.
let mut tor_set: Vec<Ipv6Addr> = Vec::new();
let mut v6_set: Vec<Ipv6Addr> = Vec::new();
let mut v4_set: Vec<Ipv4Addr> = Vec::new();
}
let mut asn_set = HashSet::with_capacity(cmp::max(v4_set.len(), v6_set.len()));
asn_set.insert(0);
- for a in v4_set.iter().filter(|a| asn_set.insert(bgp_client.get_asn(IpAddr::V4(**a)))).choose_multiple(&mut rng, 21) {
- dns_buff += &format!("x{:x}.dnsseed\tIN\tA\t{}\n", i, a);
+ for (a, asn) in v4_set.iter().map(|a| (a, bgp_client.get_asn(IpAddr::V4(*a)))).filter(|a| asn_set.insert(a.1)).choose_multiple(&mut rng, 21) {
+ dns_buff += &format!("x{:x}.dnsseed\tIN\tA\t{} ; AS{}\n", i, a, asn);
}
asn_set.clear();
asn_set.insert(0);
- for a in v6_set.iter().filter(|a| asn_set.insert(bgp_client.get_asn(IpAddr::V6(**a)))).choose_multiple(&mut rng, 10) {
- dns_buff += &format!("x{:x}.dnsseed\tIN\tAAAA\t{}\n", i, a);
+ for (a, asn) in v6_set.iter().map(|a| (a, bgp_client.get_asn(IpAddr::V6(*a)))).filter(|a| asn_set.insert(a.1)).choose_multiple(&mut rng, 10) {
+ dns_buff += &format!("x{:x}.dnsseed\tIN\tAAAA\t{} ; AS{}\n", i, a, asn);
}
for a in tor_set.iter().choose_multiple(&mut rng, 2) {
- dns_buff += &format!("x{:x}.dnsseed\tIN\tAAAA\t{}\n", i, a);
+ dns_buff += &format!("x{:x}.dnsseed\tIN\tAAAA\t{} ; Tor Onionv2\n", i, a);
}
}
}
pub fn get_next_scan_nodes(&self) -> Vec<SocketAddr> {
let mut res = Vec::with_capacity(128);
- let cur_time = Instant::now();
{
- let mut nodes = self.nodes.write().unwrap();
+ let mut nodes_lock = self.nodes.write().unwrap();
+ let nodes = nodes_lock.borrow_mut();
for (idx, state_nodes) in nodes.state_next_scan.iter_mut().enumerate() {
let rescan_interval = cmp::max(self.get_u64(U64Setting::RescanInterval(AddressState::from_num(idx as u8).unwrap())), 1);
- let cmp_time = cur_time - Duration::from_secs(rescan_interval);
- let split_point = cmp::min(SECS_PER_SCAN_RESULTS * state_nodes.len() as u64 / rescan_interval,
- state_nodes.binary_search_by(|a| a.0.cmp(&cmp_time)).unwrap_or_else(|idx| idx) as u64);
+ let split_point = cmp::min(cmp::min(SECS_PER_SCAN_RESULTS * state_nodes.len() as u64 / rescan_interval,
+ SECS_PER_SCAN_RESULTS * MAX_CONNS_PER_SEC_PER_STATUS),
+ state_nodes.len() as u64);
let mut new_nodes = state_nodes.split_off(split_point as usize);
mem::swap(&mut new_nodes, state_nodes);
- for (_, node) in new_nodes.drain(..) {
+ for node in new_nodes.drain(..) {
+ nodes.nodes_to_state.get_mut(&node).unwrap().queued = false;
res.push((&node).into());
}
}