forked from lx/netapp
Handle the possibility of several alternative IP addresses for peers
This commit is contained in:
parent
faecefc7a8
commit
677c471548
3 changed files with 70 additions and 11 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -433,7 +433,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "netapp"
|
name = "netapp"
|
||||||
version = "0.4.1"
|
version = "0.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "netapp"
|
name = "netapp"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
authors = ["Alex Auvolat <alex@adnab.me>"]
|
authors = ["Alex Auvolat <alex@adnab.me>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
license-file = "LICENSE"
|
license-file = "LICENSE"
|
||||||
|
|
|
@ -52,7 +52,13 @@ impl Message for PeerListMessage {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PeerInfoInternal {
|
struct PeerInfoInternal {
|
||||||
|
// addr is the currently connected address,
|
||||||
|
// or the last address we were connected to,
|
||||||
|
// or an arbitrary address some other peer gave us
|
||||||
addr: SocketAddr,
|
addr: SocketAddr,
|
||||||
|
// all_addrs contains all of the addresses everyone gave us
|
||||||
|
all_addrs: Vec<SocketAddr>,
|
||||||
|
|
||||||
state: PeerConnState,
|
state: PeerConnState,
|
||||||
last_seen: Option<Instant>,
|
last_seen: Option<Instant>,
|
||||||
ping: VecDeque<Duration>,
|
ping: VecDeque<Duration>,
|
||||||
|
@ -180,6 +186,7 @@ impl FullMeshPeeringStrategy {
|
||||||
id,
|
id,
|
||||||
PeerInfoInternal {
|
PeerInfoInternal {
|
||||||
addr,
|
addr,
|
||||||
|
all_addrs: vec![addr],
|
||||||
state: PeerConnState::Waiting(0, Instant::now()),
|
state: PeerConnState::Waiting(0, Instant::now()),
|
||||||
last_seen: None,
|
last_seen: None,
|
||||||
ping: VecDeque::new(),
|
ping: VecDeque::new(),
|
||||||
|
@ -194,6 +201,7 @@ impl FullMeshPeeringStrategy {
|
||||||
netapp.id,
|
netapp.id,
|
||||||
PeerInfoInternal {
|
PeerInfoInternal {
|
||||||
addr,
|
addr,
|
||||||
|
all_addrs: vec![addr],
|
||||||
state: PeerConnState::Ourself,
|
state: PeerConnState::Ourself,
|
||||||
last_seen: None,
|
last_seen: None,
|
||||||
ping: VecDeque::new(),
|
ping: VecDeque::new(),
|
||||||
|
@ -281,11 +289,22 @@ impl FullMeshPeeringStrategy {
|
||||||
info!(
|
info!(
|
||||||
"Retrying connection to {} at {} ({})",
|
"Retrying connection to {} at {} ({})",
|
||||||
hex::encode(&id[..8]),
|
hex::encode(&id[..8]),
|
||||||
h.addr,
|
h.all_addrs
|
||||||
|
.iter()
|
||||||
|
.map(|x| format!("{}", x))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(", "),
|
||||||
i + 1
|
i + 1
|
||||||
);
|
);
|
||||||
h.state = PeerConnState::Trying(i);
|
h.state = PeerConnState::Trying(i);
|
||||||
tokio::spawn(self.clone().try_connect(id, h.addr));
|
|
||||||
|
let alternate_addrs = h
|
||||||
|
.all_addrs
|
||||||
|
.iter()
|
||||||
|
.filter(|x| **x != h.addr)
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
tokio::spawn(self.clone().try_connect(id, h.addr, alternate_addrs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,7 +441,12 @@ impl FullMeshPeeringStrategy {
|
||||||
|
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
for (id, addr) in list.iter() {
|
for (id, addr) in list.iter() {
|
||||||
if !known_hosts.list.contains_key(id) {
|
if let Some(kh) = known_hosts.list.get_mut(id) {
|
||||||
|
if !kh.all_addrs.contains(addr) {
|
||||||
|
kh.all_addrs.push(*addr);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
known_hosts.list.insert(*id, self.new_peer(id, *addr));
|
known_hosts.list.insert(*id, self.new_peer(id, *addr));
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
@ -434,10 +458,42 @@ impl FullMeshPeeringStrategy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_connect(self: Arc<Self>, id: NodeID, addr: SocketAddr) {
|
async fn try_connect(
|
||||||
let conn_result = self.netapp.clone().try_connect(addr, id).await;
|
self: Arc<Self>,
|
||||||
if let Err(e) = conn_result {
|
id: NodeID,
|
||||||
warn!("Error connecting to {}: {}", hex::encode(&id[..8]), e);
|
default_addr: SocketAddr,
|
||||||
|
alternate_addrs: Vec<SocketAddr>,
|
||||||
|
) {
|
||||||
|
let conn_addr = {
|
||||||
|
let mut ret = None;
|
||||||
|
for addr in [default_addr].iter().chain(alternate_addrs.iter()) {
|
||||||
|
debug!("Trying address {} for peer {}", addr, hex::encode(&id[..8]));
|
||||||
|
match self.netapp.clone().try_connect(*addr, id).await {
|
||||||
|
Ok(()) => {
|
||||||
|
ret = Some(*addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
debug!(
|
||||||
|
"Error connecting to {} at {}: {}",
|
||||||
|
hex::encode(&id[..8]),
|
||||||
|
addr,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ok_addr) = conn_addr {
|
||||||
|
self.on_connected(id, ok_addr, false);
|
||||||
|
} else {
|
||||||
|
warn!(
|
||||||
|
"Could not connect to peer {} ({} addresses tried)",
|
||||||
|
hex::encode(&id[..8]),
|
||||||
|
1 + alternate_addrs.len()
|
||||||
|
);
|
||||||
let mut known_hosts = self.known_hosts.write().unwrap();
|
let mut known_hosts = self.known_hosts.write().unwrap();
|
||||||
if let Some(host) = known_hosts.list.get_mut(&id) {
|
if let Some(host) = known_hosts.list.get_mut(&id) {
|
||||||
host.state = match host.state {
|
host.state = match host.state {
|
||||||
|
@ -452,8 +508,6 @@ impl FullMeshPeeringStrategy {
|
||||||
};
|
};
|
||||||
self.update_public_peer_list(&known_hosts);
|
self.update_public_peer_list(&known_hosts);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
self.on_connected(id, addr, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,12 +529,16 @@ impl FullMeshPeeringStrategy {
|
||||||
if let Some(host) = known_hosts.list.get_mut(&id) {
|
if let Some(host) = known_hosts.list.get_mut(&id) {
|
||||||
host.state = PeerConnState::Connected;
|
host.state = PeerConnState::Connected;
|
||||||
host.addr = addr;
|
host.addr = addr;
|
||||||
|
if !host.all_addrs.contains(&addr) {
|
||||||
|
host.all_addrs.push(addr);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
known_hosts.list.insert(
|
known_hosts.list.insert(
|
||||||
id,
|
id,
|
||||||
PeerInfoInternal {
|
PeerInfoInternal {
|
||||||
state: PeerConnState::Connected,
|
state: PeerConnState::Connected,
|
||||||
addr,
|
addr,
|
||||||
|
all_addrs: vec![addr],
|
||||||
last_seen: None,
|
last_seen: None,
|
||||||
ping: VecDeque::new(),
|
ping: VecDeque::new(),
|
||||||
failed_pings: 0,
|
failed_pings: 0,
|
||||||
|
@ -512,6 +570,7 @@ impl FullMeshPeeringStrategy {
|
||||||
};
|
};
|
||||||
PeerInfoInternal {
|
PeerInfoInternal {
|
||||||
addr,
|
addr,
|
||||||
|
all_addrs: vec![addr],
|
||||||
state,
|
state,
|
||||||
last_seen: None,
|
last_seen: None,
|
||||||
ping: VecDeque::new(),
|
ping: VecDeque::new(),
|
||||||
|
|
Loading…
Reference in a new issue