persist gossip state to disk
This commit is contained in:
parent
43eced6e9a
commit
c96aec520d
1 changed files with 37 additions and 2 deletions
39
src/main.rs
39
src/main.rs
|
@ -21,6 +21,8 @@ const TIMEOUT: Duration = Duration::from_secs(300);
|
||||||
/// Interval at which to gossip last_seen info
|
/// Interval at which to gossip last_seen info
|
||||||
const GOSSIP_INTERVAL: Duration = Duration::from_secs(300);
|
const GOSSIP_INTERVAL: Duration = Duration::from_secs(300);
|
||||||
|
|
||||||
|
const PERSIST_INTERVAL: Duration = Duration::from_secs(600);
|
||||||
|
|
||||||
const LAN_BROADCAST_INTERVAL: Duration = Duration::from_secs(60);
|
const LAN_BROADCAST_INTERVAL: Duration = Duration::from_secs(60);
|
||||||
|
|
||||||
const IGD_INTERVAL: Duration = Duration::from_secs(60);
|
const IGD_INTERVAL: Duration = Duration::from_secs(60);
|
||||||
|
@ -37,6 +39,8 @@ struct Config {
|
||||||
/// The secret to use to authenticate nodes between them
|
/// The secret to use to authenticate nodes between them
|
||||||
gossip_secret: Option<String>,
|
gossip_secret: Option<String>,
|
||||||
gossip_secret_file: Option<String>,
|
gossip_secret_file: Option<String>,
|
||||||
|
/// The file where to persist known peer addresses
|
||||||
|
persist_file: Option<String>,
|
||||||
|
|
||||||
/// Enable LAN discovery
|
/// Enable LAN discovery
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -187,6 +191,14 @@ impl Daemon {
|
||||||
let (our_pubkey, listen_port, _peers) = wg_dump(&config)?;
|
let (our_pubkey, listen_port, _peers) = wg_dump(&config)?;
|
||||||
let socket = UdpSocket::bind(SocketAddr::new("0.0.0.0".parse()?, config.gossip_port))?;
|
let socket = UdpSocket::bind(SocketAddr::new("0.0.0.0".parse()?, config.gossip_port))?;
|
||||||
socket.set_broadcast(true)?;
|
socket.set_broadcast(true)?;
|
||||||
|
|
||||||
|
let gossip = config
|
||||||
|
.persist_file
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|x| std::fs::read(x).ok())
|
||||||
|
.and_then(|x| bincode::deserialize(&x).ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
Ok(Daemon {
|
Ok(Daemon {
|
||||||
config,
|
config,
|
||||||
gossip_key,
|
gossip_key,
|
||||||
|
@ -195,7 +207,7 @@ impl Daemon {
|
||||||
socket,
|
socket,
|
||||||
state: Mutex::new(State {
|
state: Mutex::new(State {
|
||||||
peers: HashMap::new(),
|
peers: HashMap::new(),
|
||||||
gossip: HashMap::new(),
|
gossip,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -216,6 +228,7 @@ impl Daemon {
|
||||||
thread::scope(|s| {
|
thread::scope(|s| {
|
||||||
s.spawn(|| self.wg_loop());
|
s.spawn(|| self.wg_loop());
|
||||||
s.spawn(|| self.recv_loop());
|
s.spawn(|| self.recv_loop());
|
||||||
|
s.spawn(|| self.persist_loop());
|
||||||
s.spawn(|| self.lan_broadcast_loop());
|
s.spawn(|| self.lan_broadcast_loop());
|
||||||
s.spawn(|| self.igd_loop());
|
s.spawn(|| self.igd_loop());
|
||||||
});
|
});
|
||||||
|
@ -335,6 +348,23 @@ impl Daemon {
|
||||||
Ok((src, gossip))
|
Ok((src, gossip))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn persist_loop(&self) {
|
||||||
|
if let Some(file) = &self.config.persist_file {
|
||||||
|
loop {
|
||||||
|
if let Err(e) = self.persist_state(file) {
|
||||||
|
error!("Could not write persistent state to disk: {}", e);
|
||||||
|
}
|
||||||
|
std::thread::sleep(PERSIST_INTERVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn persist_state(&self, file: &str) -> Result<()> {
|
||||||
|
let data = bincode::serialize(&self.state.lock().unwrap().gossip)?;
|
||||||
|
std::fs::write(file, &data)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn lan_broadcast_loop(&self) {
|
fn lan_broadcast_loop(&self) {
|
||||||
if self.config.lan_discovery {
|
if self.config.lan_discovery {
|
||||||
loop {
|
loop {
|
||||||
|
@ -603,7 +633,12 @@ impl State {
|
||||||
if !endpoints.is_empty() {
|
if !endpoints.is_empty() {
|
||||||
let endpoint = endpoints[i % endpoints.len()].0;
|
let endpoint = endpoints[i % endpoints.len()].0;
|
||||||
|
|
||||||
if self.peers.get(&peer_cfg.pubkey).map(|x| x.endpoint == Some(endpoint)).unwrap_or(false) {
|
if self
|
||||||
|
.peers
|
||||||
|
.get(&peer_cfg.pubkey)
|
||||||
|
.map(|x| x.endpoint == Some(endpoint))
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
// Skip if we are already using that endpoint
|
// Skip if we are already using that endpoint
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue