summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEmīls Piņķis <emils@mullvad.net>2020-06-25 15:51:27 +0100
committerEmīls <emils@mullvad.net>2020-06-30 15:17:11 +0100
commit81574c56671083aae30fa25eb08b1d65d9d95b2b (patch)
treedbbe453d481f85853899ca1657dd5fda677f2270
parent34122a18051480dab1e4c0a61c6ea572fd35c34f (diff)
downloadmullvadvpn-81574c56671083aae30fa25eb08b1d65d9d95b2b.tar.xz
mullvadvpn-81574c56671083aae30fa25eb08b1d65d9d95b2b.zip
Try and make the pinger more resilient on MacOS
-rw-r--r--talpid-core/src/ping_monitor/unix.rs15
-rw-r--r--talpid-core/src/tunnel/wireguard/connectivity_check.rs41
2 files changed, 53 insertions, 3 deletions
diff --git a/talpid-core/src/ping_monitor/unix.rs b/talpid-core/src/ping_monitor/unix.rs
index c1afa60fae..7e0953289f 100644
--- a/talpid-core/src/ping_monitor/unix.rs
+++ b/talpid-core/src/ping_monitor/unix.rs
@@ -35,6 +35,21 @@ impl Pinger {
Ok(())
}
+ pub fn reset(&mut self) {
+ let processes = std::mem::replace(&mut self.processes, vec![]);
+ for proc in processes {
+ if proc
+ .try_wait()
+ .map(|maybe_stopped| maybe_stopped.is_none())
+ .unwrap_or(false)
+ {
+ if let Err(err) = proc.kill() {
+ log::error!("Failed to kill ping process - {}", err);
+ }
+ }
+ }
+ }
+
fn try_deplete_process_list(&mut self) {
self.processes.retain(|child| {
match child.try_wait() {
diff --git a/talpid-core/src/tunnel/wireguard/connectivity_check.rs b/talpid-core/src/tunnel/wireguard/connectivity_check.rs
index 63f296d2e3..7426e674d7 100644
--- a/talpid-core/src/tunnel/wireguard/connectivity_check.rs
+++ b/talpid-core/src/tunnel/wireguard/connectivity_check.rs
@@ -124,7 +124,24 @@ impl ConnectivityMonitor {
}
fn wait_loop(&mut self, iter_delay: Duration) -> Result<(), Error> {
- while self.check_connectivity()? && !self.should_shut_down(iter_delay) {}
+ let mut last_iteration = Instant::now();
+ while !self.should_shut_down(iter_delay) {
+ let mut current_iteration = Instant::now();
+ let time_slept = current_iteration - last_iteration;
+ if time_slept < (iter_delay * 2) {
+ self.check_connectivity()?;
+ let end = Instant::now();
+ if end - current_iteration > Duration::from_secs(1) {
+ current_iteration = end;
+ }
+ } else {
+ // Loop was suspended for too long, so it's safer to assume that the host still has
+ // connectivity.
+ self.reset_pinger();
+ self.conn_state.reset_after_suspension(current_iteration);
+ }
+ last_iteration = current_iteration;
+ }
Ok(())
}
@@ -137,8 +154,7 @@ impl ConnectivityMonitor {
let new_stats = new_stats?;
if self.conn_state.update(now, new_stats) {
- self.initial_ping_timestamp = None;
- self.num_pings_sent = 0;
+ self.reset_pinger();
return Ok(true);
}
@@ -185,6 +201,14 @@ impl ConnectivityMonitor {
.map(|initial_ping_timestamp| initial_ping_timestamp.elapsed() > PING_TIMEOUT)
.unwrap_or(false)
}
+
+ /// Reset timeouts - assume that the last time bytes were received is now.
+ fn reset_pinger(&mut self) {
+ self.initial_ping_timestamp = None;
+ self.num_pings_sent = 0;
+ #[cfg(unix)]
+ self.pinger.reset();
+ }
}
enum ConnState {
@@ -261,6 +285,17 @@ impl ConnState {
}
}
}
+
+ pub fn reset_after_suspension(&mut self, now: Instant) {
+ if let ConnState::Connected {
+ ref mut rx_timestamp,
+ ..
+ } = self
+ {
+ *rx_timestamp = now;
+ }
+ }
+
// check if last time data was received is too long ago
pub fn rx_timed_out(&self) -> bool {
match self {