X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=src%2Fdatastore.rs;h=1f2221029d6d2d76f79626f574c6fc64b066f86b;hb=5626798a0d61d3eab42edb0feacdda328620c580;hp=57689354ada941b44686cf8cf030205e4eeb1ff3;hpb=290b80cc5e710fff040962e5d17e5c8fef1ccb6d;p=dnsseed-rust diff --git a/src/datastore.rs b/src/datastore.rs index 5768935..1f22210 100644 --- a/src/datastore.rs +++ b/src/datastore.rs @@ -1,11 +1,11 @@ -use std::{cmp, mem}; +use std::cmp; use std::collections::{HashSet, HashMap, hash_map}; use std::sync::{Arc, RwLock}; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::time::{Duration, Instant}; use std::io::{BufRead, BufReader}; -use bitcoin::network::address::Address; +use bitcoin::network::address::{Address, AddrV2Message}; use rand::thread_rng; use rand::seq::{SliceRandom, IteratorRandom}; @@ -132,13 +132,17 @@ struct Node { #[derive(Clone, PartialEq, Eq, Hash)] enum SockAddr { V4(SocketAddrV4), - V6((Ipv6Addr, u16)), + V6(([u16; 8], u16)), +} +#[inline] +fn segs_to_ip6(segs: &[u16; 8]) -> Ipv6Addr { + Ipv6Addr::new(segs[0], segs[1], segs[2], segs[3], segs[4], segs[5], segs[6], segs[7]) } impl From for SockAddr { fn from(addr: SocketAddr) -> SockAddr { match addr { SocketAddr::V4(sa) => SockAddr::V4(sa), - SocketAddr::V6(sa) => SockAddr::V6((sa.ip().clone(), sa.port())), + SocketAddr::V6(sa) => SockAddr::V6((sa.ip().segments(), sa.port())), } } } @@ -146,7 +150,7 @@ impl Into for &SockAddr { fn into(self) -> SocketAddr { match self { &SockAddr::V4(sa) => SocketAddr::V4(sa), - &SockAddr::V6(sa) => SocketAddr::V6(SocketAddrV6::new(sa.0, sa.1, 0, 0)) + &SockAddr::V6(sa) => SocketAddr::V6(SocketAddrV6::new(segs_to_ip6(&sa.0), sa.1, 0, 0)) } } } @@ -166,7 +170,7 @@ impl SockAddr { pub fn ip(&self) -> IpAddr { match *self { SockAddr::V4(sa) => IpAddr::V4(sa.ip().clone()), - SockAddr::V6((ip, _)) => IpAddr::V6(ip), + SockAddr::V6((ip, _)) => IpAddr::V6(segs_to_ip6(&ip)), } } } @@ -174,12 +178,12 @@ impl SockAddr { struct Nodes { good_node_services: [HashSet; 64], nodes_to_state: HashMap, - state_next_scan: Vec>, + state_next_scan: [Vec; AddressState::get_count() as usize], } struct NodesMutRef<'a> { good_node_services: &'a mut [HashSet; 64], nodes_to_state: &'a mut HashMap, - state_next_scan: &'a mut Vec>, + state_next_scan: &'a mut [Vec; AddressState::get_count() as usize], } impl Nodes { @@ -262,10 +266,7 @@ impl Store { macro_rules! nodes_uninitd { () => { { - let mut state_vecs = Vec::with_capacity(AddressState::get_count() as usize); - for _ in 0..AddressState::get_count() { - state_vecs.push(Vec::new()); - } + let state_vecs = [Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()]; let good_node_services = [HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new(), HashSet::new()]; Nodes { good_node_services, @@ -383,6 +384,14 @@ impl Store { } })); } + pub fn add_fresh_nodes_v2(&self, addresses: &Vec) { + self.add_fresh_addrs(addresses.iter().filter_map(|addr| { + match addr.socket_addr() { + Ok(socketaddr) => Some(socketaddr), + Err(_) => None, // TODO: Handle onions + } + })); + } pub fn set_node_state(&self, sockaddr: SocketAddr, state: AddressState, services: u64) -> AddressState { let addr: SockAddr = sockaddr.into(); @@ -470,7 +479,7 @@ impl Store { 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 += ","; @@ -579,16 +588,16 @@ impl Store { } 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); } } } @@ -611,9 +620,7 @@ impl Store { 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 state_nodes.drain(..split_point as usize) { nodes.nodes_to_state.get_mut(&node).unwrap().queued = false; res.push((&node).into()); }