-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};
#[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<SocketAddr> 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())),
}
}
}
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))
}
}
}
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)),
}
}
}
struct Nodes {
good_node_services: [HashSet<SockAddr>; 64],
nodes_to_state: HashMap<SockAddr, Node>,
- state_next_scan: Vec<Vec<SockAddr>>,
+ state_next_scan: [Vec<SockAddr>; AddressState::get_count() as usize],
}
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<SockAddr>>,
+ state_next_scan: &'a mut [Vec<SockAddr>; AddressState::get_count() as usize],
}
impl Nodes {
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,
}
}));
}
+ pub fn add_fresh_nodes_v2(&self, addresses: &Vec<AddrV2Message>) {
+ 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();
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 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());
}