diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-11-04 15:31:21 -0200 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-11-04 15:31:21 -0200 |
| commit | e190243460b1dead2ced88ce3b2ae1d6a5499603 (patch) | |
| tree | 02e400f26896879547455afcbc6f5e5fcb73f4c3 | |
| parent | ea6ca75a2c360048b807ce6108866a655371c2f3 (diff) | |
| parent | 8748940f30694c2d2fedb7c79adead5d76ff183a (diff) | |
| download | mullvadvpn-e190243460b1dead2ced88ce3b2ae1d6a5499603.tar.xz mullvadvpn-e190243460b1dead2ced88ce3b2ae1d6a5499603.zip | |
Merge branch 'recreate-tun-on-reconnect-loop'
| -rw-r--r-- | CHANGELOG.md | 3 | ||||
| -rw-r--r-- | mullvad-jni/src/vpn_service_tun_provider.rs | 84 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/tun_provider/mod.rs | 8 | ||||
| -rw-r--r-- | talpid-core/src/tunnel/tun_provider/stub.rs | 5 | ||||
| -rw-r--r-- | talpid-core/src/tunnel_state_machine/connecting_state.rs | 18 |
5 files changed, 79 insertions, 39 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 760e303df3..374a6659c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,9 @@ Line wrap the file at 100 chars. Th #### Windows - Use a larger icon in notifications on Windows 10. +#### Android +- Recreate tun device after a fixed number of connection attempts on the same tun device. + ### Fixed #### Windows - Detect removal of the OpenVPN TAP adapter on reconnection attempts. diff --git a/mullvad-jni/src/vpn_service_tun_provider.rs b/mullvad-jni/src/vpn_service_tun_provider.rs index 7da3ca3eef..68021ac8cd 100644 --- a/mullvad-jni/src/vpn_service_tun_provider.rs +++ b/mullvad-jni/src/vpn_service_tun_provider.rs @@ -92,42 +92,7 @@ impl VpnServiceTunProvider { fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> { if self.active_tun.is_none() || self.last_tun_config != config { - let env = self - .jvm - .attach_current_thread_as_daemon() - .map_err(Error::AttachJvmToThread)?; - let create_tun_method = env - .get_method_id( - &self.class, - "createTun", - "(Lnet/mullvad/mullvadvpn/model/TunConfig;)I", - ) - .map_err(|cause| Error::FindMethod("createTun", cause))?; - - let java_config = env.auto_local(config.clone().into_java(&env)); - let result = env - .call_method_unchecked( - self.object.as_obj(), - create_tun_method, - JavaType::Primitive(Primitive::Int), - &[JValue::Object(java_config.as_obj())], - ) - .map_err(|cause| Error::CallMethod("createTun", cause))?; - - match result { - JValue::Int(fd) => { - let tun = unsafe { File::from_raw_fd(fd) }; - - self.active_tun = Some(tun); - self.last_tun_config = config; - } - value => { - return Err(Error::InvalidMethodResult( - "createTun", - format!("{:?}", value), - )) - } - } + self.open_tun(config)?; } Ok(self @@ -136,6 +101,45 @@ impl VpnServiceTunProvider { .expect("Tunnel should be configured") .as_raw_fd()) } + + fn open_tun(&mut self, config: TunConfig) -> Result<(), Error> { + let env = self + .jvm + .attach_current_thread_as_daemon() + .map_err(Error::AttachJvmToThread)?; + let create_tun_method = env + .get_method_id( + &self.class, + "createTun", + "(Lnet/mullvad/mullvadvpn/model/TunConfig;)I", + ) + .map_err(|cause| Error::FindMethod("createTun", cause))?; + + let java_config = env.auto_local(config.clone().into_java(&env)); + let result = env + .call_method_unchecked( + self.object.as_obj(), + create_tun_method, + JavaType::Primitive(Primitive::Int), + &[JValue::Object(java_config.as_obj())], + ) + .map_err(|cause| Error::CallMethod("createTun", cause))?; + + match result { + JValue::Int(fd) => { + let tun = unsafe { File::from_raw_fd(fd) }; + + self.active_tun = Some(tun); + self.last_tun_config = config; + + Ok(()) + } + value => Err(Error::InvalidMethodResult( + "createTun", + format!("{:?}", value), + )), + } + } } impl TunProvider for VpnServiceTunProvider { @@ -153,10 +157,14 @@ impl TunProvider for VpnServiceTunProvider { })) } + fn create_tun(&mut self) -> Result<(), BoxedError> { + self.open_tun(self.last_tun_config.clone()) + .map_err(BoxedError::new) + } + fn create_tun_if_closed(&mut self) -> Result<(), BoxedError> { if self.active_tun.is_none() { - self.get_tun_fd(self.last_tun_config.clone()) - .map_err(BoxedError::new)?; + self.create_tun()?; } Ok(()) diff --git a/talpid-core/src/tunnel/tun_provider/mod.rs b/talpid-core/src/tunnel/tun_provider/mod.rs index 3cac459c51..16c9c3f17c 100644 --- a/talpid-core/src/tunnel/tun_provider/mod.rs +++ b/talpid-core/src/tunnel/tun_provider/mod.rs @@ -53,6 +53,14 @@ pub trait TunProvider: Send + 'static { fn get_tun(&mut self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError>; /// Open a tunnel device using the previous or the default configuration. + /// + /// Will open a new tunnel if there is already an active tunnel. The previous tunnel will be + /// closed. + #[cfg(target_os = "android")] + fn create_tun(&mut self) -> Result<(), BoxedError>; + + /// Open a tunnel device using the previous or the default configuration if there is no + /// currently active tunnel. #[cfg(target_os = "android")] fn create_tun_if_closed(&mut self) -> Result<(), BoxedError>; diff --git a/talpid-core/src/tunnel/tun_provider/stub.rs b/talpid-core/src/tunnel/tun_provider/stub.rs index be985c8045..3cd6dd0ee8 100644 --- a/talpid-core/src/tunnel/tun_provider/stub.rs +++ b/talpid-core/src/tunnel/tun_provider/stub.rs @@ -16,6 +16,11 @@ impl TunProvider for StubTunProvider { } #[cfg(target_os = "android")] + fn create_tun(&mut self) -> Result<(), BoxedError> { + unimplemented!(); + } + + #[cfg(target_os = "android")] fn create_tun_if_closed(&mut self) -> Result<(), BoxedError> { unimplemented!(); } diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs index da71d392f3..efc75f3cbb 100644 --- a/talpid-core/src/tunnel_state_machine/connecting_state.rs +++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs @@ -28,6 +28,7 @@ use talpid_types::{ }; +const MAX_ATTEMPTS_WITH_SAME_TUN: u32 = 5; const MIN_TUNNEL_ALIVE_TIME: Duration = Duration::from_millis(1000); /// The tunnel has been started, but it is not established/functional. @@ -350,11 +351,26 @@ impl TunnelState for ConnectingState { ); BlockedState::enter(shared_values, BlockReason::StartTunnelError) } else { + let tun_provider: &mut dyn TunProvider = + shared_values.tun_provider.borrow_mut(); + + #[cfg(target_os = "android")] + { + if retry_attempt > 0 && retry_attempt % MAX_ATTEMPTS_WITH_SAME_TUN == 0 { + if let Err(error) = tun_provider.create_tun() { + error!( + "{}", + error.display_chain_with_msg("Failed to recreate tun device") + ); + } + } + } + match Self::start_tunnel( tunnel_parameters, &shared_values.log_dir, &shared_values.resource_dir, - shared_values.tun_provider.borrow_mut(), + tun_provider, retry_attempt, ) { Ok(connecting_state) => { |
