aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fw.rs1
-rw-r--r--src/stun_actor.rs36
2 files changed, 28 insertions, 9 deletions
diff --git a/src/fw.rs b/src/fw.rs
index a320fa2..a3e6dec 100644
--- a/src/fw.rs
+++ b/src/fw.rs
@@ -1,5 +1,4 @@
use std::collections::HashSet;
-use std::sync::Arc;
use anyhow::{Context, Result};
use iptables;
diff --git a/src/stun_actor.rs b/src/stun_actor.rs
index 3182662..4cca4f1 100644
--- a/src/stun_actor.rs
+++ b/src/stun_actor.rs
@@ -8,6 +8,11 @@ use serde::{Deserialize, Serialize};
use crate::config::{RuntimeConfigConsul, RuntimeConfigStun};
use crate::consul;
+/// If autodiscovery returns None but an address was obtained less than
+/// this number of seconds ago (here 15 minutes), we keep that address
+/// in the Consul db instead of insterting a None.
+const PERSIST_SOME_RESULT_DURATION_SECS: u64 = 900;
+
pub struct StunActor {
consul: consul::Consul,
refresh_time: Duration,
@@ -78,7 +83,7 @@ impl StunActor {
}
impl StunAutodiscovery {
- async fn do_iteration(&self, consul: &consul::Consul) -> Result<()> {
+ async fn do_iteration(&mut self, consul: &consul::Consul) -> Result<()> {
let binding_ip = match self.is_ipv4 {
true => IpAddr::V4(Ipv4Addr::UNSPECIFIED), // 0.0.0.0
false => IpAddr::V6(Ipv6Addr::UNSPECIFIED), // [::]
@@ -96,16 +101,31 @@ impl StunAutodiscovery {
None => None,
};
+ let now = timestamp();
+
+ if discovered_addr.is_none() {
+ if let Some(last_result) = &self.last_result {
+ if last_result.address.is_some()
+ && now - last_result.timestamp <= PERSIST_SOME_RESULT_DURATION_SECS
+ {
+ // Keep non-None result that was obtained before by not
+ // writing/taking into account None result.
+ return Ok(());
+ }
+ }
+ }
+
+ let current_result = AutodiscoverResult {
+ timestamp: now,
+ address: discovered_addr,
+ };
+
consul
- .kv_put(
- &self.consul_key,
- serde_json::to_vec(&AutodiscoverResult {
- timestamp: timestamp(),
- address: discovered_addr,
- })?,
- )
+ .kv_put(&self.consul_key, serde_json::to_vec(&current_result)?)
.await?;
+ self.last_result = Some(current_result);
+
Ok(())
}
}