summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-07-16 02:56:14 +0000
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2020-07-20 13:10:19 +0000
commit1774c36b7d53d88050dd068cbf3fcf733d78e2d2 (patch)
tree5bafc4263a9218576af8b2d7861a15466979a83e /talpid-core/src
parent9c1d25cbcba7310bc2bdb5c527a74ee01c812d42 (diff)
downloadmullvadvpn-1774c36b7d53d88050dd068cbf3fcf733d78e2d2.tar.xz
mullvadvpn-1774c36b7d53d88050dd068cbf3fcf733d78e2d2.zip
Handle tun device reuse in the Java side
Diffstat (limited to 'talpid-core/src')
-rw-r--r--talpid-core/src/tunnel/tun_provider/android/mod.rs159
1 files changed, 102 insertions, 57 deletions
diff --git a/talpid-core/src/tunnel/tun_provider/android/mod.rs b/talpid-core/src/tunnel/tun_provider/android/mod.rs
index 3cf6f16cd5..e4e8f4fbac 100644
--- a/talpid-core/src/tunnel/tun_provider/android/mod.rs
+++ b/talpid-core/src/tunnel/tun_provider/android/mod.rs
@@ -12,12 +12,11 @@ use jnix::{
IntoJava, JnixEnv,
};
use std::{
- fs::File,
net::{IpAddr, Ipv4Addr, Ipv6Addr},
- os::unix::io::{AsRawFd, FromRawFd, RawFd},
+ os::unix::io::{AsRawFd, RawFd},
sync::Arc,
};
-use talpid_types::android::AndroidContext;
+use talpid_types::{android::AndroidContext, ErrorExt};
/// Errors that occur while setting up VpnService tunnel.
@@ -58,7 +57,6 @@ pub struct AndroidTunProvider {
jvm: Arc<JavaVM>,
class: GlobalRef,
object: GlobalRef,
- active_tun: Option<File>,
last_tun_config: TunConfig,
allow_lan: bool,
}
@@ -78,7 +76,6 @@ impl AndroidTunProvider {
jvm: context.jvm,
class: talpid_vpn_service_class,
object: context.vpn_service,
- active_tun: None,
last_tun_config: TunConfig::default(),
allow_lan,
}
@@ -87,10 +84,7 @@ impl AndroidTunProvider {
pub fn set_allow_lan(&mut self, allow_lan: bool) -> Result<(), Error> {
if self.allow_lan != allow_lan {
self.allow_lan = allow_lan;
-
- if self.active_tun.is_some() {
- self.create_tun()?;
- }
+ self.recreate_tun_if_open()?;
}
Ok(())
@@ -98,7 +92,9 @@ impl AndroidTunProvider {
/// Retrieve a tunnel device with the provided configuration.
pub fn get_tun(&mut self, config: TunConfig) -> Result<VpnServiceTun, Error> {
- let tun_fd = self.get_tun_fd(config)?;
+ let tun_fd = self.get_tun_fd(config.clone())?;
+
+ self.last_tun_config = config;
let jvm = unsafe { JavaVM::from_raw(self.jvm.get_java_vm_pointer()) }
.map_err(Error::CloneJavaVm)?;
@@ -116,34 +112,98 @@ impl AndroidTunProvider {
/// Will open a new tunnel if there is already an active tunnel. The previous tunnel will be
/// closed.
pub fn create_tun(&mut self) -> Result<(), Error> {
- self.open_tun(self.last_tun_config.clone())
+ let result = self.call_method(
+ "createTun",
+ "()V",
+ JavaType::Primitive(Primitive::Void),
+ &[],
+ )?;
+
+ match result {
+ JValue::Void => Ok(()),
+ value => Err(Error::InvalidMethodResult(
+ "createTun",
+ format!("{:?}", value),
+ )),
+ }
}
/// Open a tunnel device using the previous or the default configuration if there is no
/// currently active tunnel.
pub fn create_tun_if_closed(&mut self) -> Result<(), Error> {
- if self.active_tun.is_none() {
- self.create_tun()?;
- }
+ let result = self.call_method(
+ "createTunIfClosed",
+ "()V",
+ JavaType::Primitive(Primitive::Void),
+ &[],
+ )?;
- Ok(())
+ match result {
+ JValue::Void => Ok(()),
+ value => Err(Error::InvalidMethodResult(
+ "createTunIfClosed",
+ format!("{:?}", value),
+ )),
+ }
}
/// Close currently active tunnel device.
pub fn close_tun(&mut self) {
- self.active_tun = None;
+ let result = self.call_method("closeTun", "()V", JavaType::Primitive(Primitive::Void), &[]);
+
+ let error = match result {
+ Ok(JValue::Void) => None,
+ Ok(value) => Some(Error::InvalidMethodResult(
+ "closeTun",
+ format!("{:?}", value),
+ )),
+ Err(error) => Some(error),
+ };
+
+ if let Some(error) = error {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to close the tunnel")
+ );
+ }
}
fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> {
- if self.active_tun.is_none() || self.last_tun_config != config {
- self.open_tun(config)?;
+ let env = self.env()?;
+ let actual_config = self.prepare_tun_config(config);
+ let java_config = actual_config.into_java(&env);
+
+ let result = self.call_method(
+ "getTun",
+ "(Lnet/mullvad/talpid/tun_provider/TunConfig;)I",
+ JavaType::Primitive(Primitive::Int),
+ &[JValue::Object(java_config.as_obj())],
+ )?;
+
+ match result {
+ JValue::Int(0) => Err(Error::TunnelDeviceError),
+ JValue::Int(-1) => Err(Error::PermissionDenied),
+ JValue::Int(fd) => Ok(fd),
+ value => Err(Error::InvalidMethodResult("getTun", format!("{:?}", value))),
}
+ }
+
+ fn recreate_tun_if_open(&mut self) -> Result<(), Error> {
+ let env = self.env()?;
+ let actual_config = self.prepare_tun_config(self.last_tun_config.clone());
+ let java_config = actual_config.into_java(&env);
+
+ let result = self.call_method(
+ "recreateTunIfOpen",
+ "(Lnet/mullvad/talpid/tun_provider/TunConfig;)V",
+ JavaType::Primitive(Primitive::Void),
+ &[JValue::Object(java_config.as_obj())],
+ )?;
- Ok(self
- .active_tun
- .as_ref()
- .expect("Tunnel should be configured")
- .as_raw_fd())
+ match result {
+ JValue::Void => Ok(()),
+ value => Err(Error::InvalidMethodResult("getTun", format!("{:?}", value))),
+ }
}
fn prepare_tun_config(&self, config: TunConfig) -> TunConfig {
@@ -189,48 +249,33 @@ impl AndroidTunProvider {
}
}
- fn open_tun(&mut self, config: TunConfig) -> Result<(), Error> {
- let actual_config = self.prepare_tun_config(config.clone());
-
+ fn call_method(
+ &self,
+ name: &'static str,
+ signature: &str,
+ return_type: JavaType,
+ parameters: &[JValue<'_>],
+ ) -> Result<JValue<'_>, Error> {
let env = JnixEnv::from(
self.jvm
.attach_current_thread_as_daemon()
.map_err(Error::AttachJvmToThread)?,
);
- let create_tun_method = env
- .get_method_id(
- &self.class,
- "createTun",
- "(Lnet/mullvad/talpid/tun_provider/TunConfig;)I",
- )
- .map_err(|cause| Error::FindMethod("createTun", cause))?;
+ let method_id = env
+ .get_method_id(&self.class, name, signature)
+ .map_err(|cause| Error::FindMethod(name, cause))?;
- let java_config = actual_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(0) => Err(Error::TunnelDeviceError),
- JValue::Int(-1) => Err(Error::PermissionDenied),
- JValue::Int(fd) => {
- let tun = unsafe { File::from_raw_fd(fd) };
+ env.call_method_unchecked(self.object.as_obj(), method_id, return_type, parameters)
+ .map_err(|cause| Error::CallMethod(name, cause))
+ }
- self.active_tun = Some(tun);
- self.last_tun_config = config;
+ fn env(&self) -> Result<JnixEnv<'_>, Error> {
+ let jni_env = self
+ .jvm
+ .attach_current_thread_as_daemon()
+ .map_err(Error::AttachJvmToThread)?;
- Ok(())
- }
- value => Err(Error::InvalidMethodResult(
- "createTun",
- format!("{:?}", value),
- )),
- }
+ Ok(JnixEnv::from(jni_env))
}
}