diff options
| author | Emīls Piņķis <emils@mullvad.net> | 2020-06-25 15:51:27 +0100 |
|---|---|---|
| committer | Emīls <emils@mullvad.net> | 2020-06-30 15:17:11 +0100 |
| commit | 81574c56671083aae30fa25eb08b1d65d9d95b2b (patch) | |
| tree | dbbe453d481f85853899ca1657dd5fda677f2270 | |
| parent | 34122a18051480dab1e4c0a61c6ea572fd35c34f (diff) | |
| download | mullvadvpn-81574c56671083aae30fa25eb08b1d65d9d95b2b.tar.xz mullvadvpn-81574c56671083aae30fa25eb08b1d65d9d95b2b.zip | |
Try and make the pinger more resilient on MacOS
| -rw-r--r-- | talpid-core/src/ping_monitor/unix.rs | 15 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/wireguard/connectivity_check.rs | 41 |
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 { |
