summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-12-03 09:32:25 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-12-03 09:32:25 -0300
commitda7b3f0ead28deee5991dff7d159c0b5cf5a5d40 (patch)
tree8dfb8d47a905ae2a9eb659f3b8747a35c96a161e
parentb0628860be5c03af241bbfc308887686ea561bed (diff)
parent7391871673e0640e04a4e2cb0e1d900042d16389 (diff)
downloadmullvadvpn-da7b3f0ead28deee5991dff7d159c0b5cf5a5d40.tar.xz
mullvadvpn-da7b3f0ead28deee5991dff7d159c0b5cf5a5d40.zip
Merge branch 'android-rust-context'
-rw-r--r--.travis.yml2
-rw-r--r--mullvad-daemon/src/lib.rs20
-rw-r--r--mullvad-jni/src/lib.rs35
-rw-r--r--talpid-core/src/tunnel/mod.rs6
-rw-r--r--talpid-core/src/tunnel/tun_provider/android.rs (renamed from mullvad-jni/src/vpn_service_tun_provider.rs)150
-rw-r--r--talpid-core/src/tunnel/tun_provider/mod.rs75
-rw-r--r--talpid-core/src/tunnel/tun_provider/stub.rs29
-rw-r--r--talpid-core/src/tunnel/tun_provider/unix.rs42
-rw-r--r--talpid-core/src/tunnel/tun_provider/windows.rs13
-rw-r--r--talpid-core/src/tunnel/wireguard/mod.rs11
-rw-r--r--talpid-core/src/tunnel/wireguard/wireguard_go.rs65
-rw-r--r--talpid-core/src/tunnel_state_machine/connecting_state.rs10
-rw-r--r--talpid-core/src/tunnel_state_machine/mod.rs17
-rw-r--r--talpid-types/src/android/mod.rs6
-rw-r--r--talpid-types/src/lib.rs2
15 files changed, 222 insertions, 261 deletions
diff --git a/.travis.yml b/.travis.yml
index ee29338415..676cf27d9a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -69,7 +69,7 @@ matrix:
- source env.sh aarch64-linux-android
- env
script:
- - cargo build --target aarch64-linux-android --verbose
+ - cargo build --target aarch64-linux-android --verbose --package mullvad-jni
- cd android
- ./gradlew --console plain assembleDebug
# Run ktlint with extra andorid rules
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index bae58b2f12..d63c28e6a6 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -59,9 +59,10 @@ use std::{
};
use talpid_core::{
mpsc::IntoSender,
- tunnel::tun_provider::{PlatformTunProvider, TunProvider},
tunnel_state_machine::{self, TunnelCommand, TunnelParametersGenerator},
};
+#[cfg(target_os = "android")]
+use talpid_types::android::AndroidContext;
use talpid_types::{
net::{openvpn, TransportProtocol, TunnelParameters},
tunnel::{BlockReason, ParameterGenerationError, TunnelStateTransition},
@@ -280,6 +281,8 @@ impl Daemon<ManagementInterfaceEventBroadcaster> {
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: PathBuf,
+ // TODO: Remove this once `ManagementInterface` is less coupled to the constructor.
+ #[cfg(target_os = "android")] android_context: AndroidContext,
) -> Result<Self> {
if rpc_uniqueness_check::is_another_instance_running() {
return Err(Error::DaemonIsAlreadyRunning);
@@ -291,10 +294,11 @@ impl Daemon<ManagementInterfaceEventBroadcaster> {
tx,
rx,
management_interface_broadcaster,
- PlatformTunProvider::default(),
log_dir,
resource_dir,
cache_dir,
+ #[cfg(target_os = "android")]
+ android_context,
)
}
@@ -336,12 +340,12 @@ impl<L> Daemon<L>
where
L: EventListener + Clone + Send + 'static,
{
- pub fn start_with_event_listener_and_tun_provider(
+ pub fn start_with_event_listener(
event_listener: L,
- tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: PathBuf,
+ #[cfg(target_os = "android")] android_context: AndroidContext,
) -> Result<Self> {
let (tx, rx) = mpsc::channel();
@@ -349,10 +353,11 @@ where
tx,
rx,
event_listener,
- tun_provider,
log_dir,
resource_dir,
cache_dir,
+ #[cfg(target_os = "android")]
+ android_context,
)
}
@@ -360,10 +365,10 @@ where
internal_event_tx: mpsc::Sender<InternalDaemonEvent>,
internal_event_rx: mpsc::Receiver<InternalDaemonEvent>,
event_listener: L,
- tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: PathBuf,
+ #[cfg(target_os = "android")] android_context: AndroidContext,
) -> Result<Self> {
let ca_path = resource_dir.join(mullvad_paths::resources::API_CA_FILENAME);
@@ -435,11 +440,12 @@ where
settings.get_allow_lan(),
settings.get_block_when_disconnected(),
tunnel_parameters_generator,
- tun_provider,
log_dir,
resource_dir,
cache_dir.clone(),
IntoSender::from(internal_event_tx.clone()),
+ #[cfg(target_os = "android")]
+ android_context,
)
.map_err(Error::TunnelError)?;
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index 0e00decd04..aeeb3ee742 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -5,11 +5,9 @@ mod daemon_interface;
mod from_java;
mod is_null;
mod jni_event_listener;
-mod vpn_service_tun_provider;
use crate::{
daemon_interface::DaemonInterface, from_java::FromJava, jni_event_listener::JniEventListener,
- vpn_service_tun_provider::VpnServiceTunProvider,
};
use jnix::{
jni::{
@@ -27,7 +25,7 @@ use std::{
sync::{mpsc, Once},
thread,
};
-use talpid_types::ErrorExt;
+use talpid_types::{android::AndroidContext, ErrorExt};
const LOG_FILENAME: &str = "daemon.log";
@@ -42,12 +40,15 @@ static LOAD_CLASSES: Once = Once::new();
#[derive(Debug, err_derive::Error)]
#[error(no_from)]
pub enum Error {
- #[error(display = "Failed to create VpnService tunnel provider")]
- CreateVpnServiceTunProvider(#[error(source)] vpn_service_tun_provider::Error),
+ #[error(display = "Failed to create global reference to Java object")]
+ CreateGlobalReference(#[error(cause)] jnix::jni::errors::Error),
#[error(display = "Failed to get cache directory path")]
GetCacheDir(#[error(source)] mullvad_paths::Error),
+ #[error(display = "Failed to get Java VM instance")]
+ GetJvmInstance(#[error(cause)] jnix::jni::errors::Error),
+
#[error(display = "Failed to get log directory path")]
GetLogDir(#[error(source)] mullvad_paths::Error),
@@ -130,26 +131,34 @@ fn initialize(
vpn_service: &JObject,
log_dir: PathBuf,
) -> Result<(), Error> {
- let tun_provider =
- VpnServiceTunProvider::new(env, vpn_service).map_err(Error::CreateVpnServiceTunProvider)?;
- let daemon_command_sender = spawn_daemon(env, this, tun_provider, log_dir)?;
+ let android_context = create_android_context(env, *vpn_service)?;
+ let daemon_command_sender = spawn_daemon(env, this, log_dir, android_context)?;
DAEMON_INTERFACE.set_command_sender(daemon_command_sender);
Ok(())
}
+fn create_android_context(env: &JnixEnv, vpn_service: JObject) -> Result<AndroidContext, Error> {
+ Ok(AndroidContext {
+ jvm: env.get_java_vm().map_err(Error::GetJvmInstance)?,
+ vpn_service: env
+ .new_global_ref(vpn_service)
+ .map_err(Error::CreateGlobalReference)?,
+ })
+}
+
fn spawn_daemon(
env: &JnixEnv,
this: &JObject,
- tun_provider: VpnServiceTunProvider,
log_dir: PathBuf,
+ android_context: AndroidContext,
) -> Result<DaemonCommandSender, Error> {
let listener = JniEventListener::spawn(env, this).map_err(Error::SpawnJniEventListener)?;
let (tx, rx) = mpsc::channel();
thread::spawn(
- move || match create_daemon(listener, tun_provider, log_dir) {
+ move || match create_daemon(listener, log_dir, android_context) {
Ok(daemon) => {
let _ = tx.send(Ok(daemon.command_sender()));
match daemon.run() {
@@ -168,18 +177,18 @@ fn spawn_daemon(
fn create_daemon(
listener: JniEventListener,
- tun_provider: VpnServiceTunProvider,
log_dir: PathBuf,
+ android_context: AndroidContext,
) -> Result<Daemon<JniEventListener>, Error> {
let resource_dir = mullvad_paths::get_resource_dir();
let cache_dir = mullvad_paths::cache_dir().map_err(Error::GetCacheDir)?;
- let daemon = Daemon::start_with_event_listener_and_tun_provider(
+ let daemon = Daemon::start_with_event_listener(
listener,
- tun_provider,
Some(log_dir),
resource_dir,
cache_dir,
+ android_context,
)
.map_err(Error::InitializeDaemon)?;
diff --git a/talpid-core/src/tunnel/mod.rs b/talpid-core/src/tunnel/mod.rs
index ddf19fcb66..6d167efed3 100644
--- a/talpid-core/src/tunnel/mod.rs
+++ b/talpid-core/src/tunnel/mod.rs
@@ -18,7 +18,7 @@ pub mod openvpn;
pub mod wireguard;
/// A module for low level platform specific tunnel device management.
-pub mod tun_provider;
+pub(crate) mod tun_provider;
const OPENVPN_LOG_FILENAME: &str = "openvpn.log";
const WIREGUARD_LOG_FILENAME: &str = "wireguard.log";
@@ -140,7 +140,7 @@ impl TunnelMonitor {
log_dir: &Option<PathBuf>,
resource_dir: &Path,
on_event: L,
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
) -> Result<Self>
where
L: Fn(TunnelEvent) + Send + Clone + Sync + 'static,
@@ -166,7 +166,7 @@ impl TunnelMonitor {
params: &wireguard_types::TunnelParameters,
log: Option<PathBuf>,
on_event: L,
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
) -> Result<Self>
where
L: Fn(TunnelEvent) + Send + Sync + Clone + 'static,
diff --git a/mullvad-jni/src/vpn_service_tun_provider.rs b/talpid-core/src/tunnel/tun_provider/android.rs
index 01f1905814..19d4325abf 100644
--- a/mullvad-jni/src/vpn_service_tun_provider.rs
+++ b/talpid-core/src/tunnel/tun_provider/android.rs
@@ -1,7 +1,8 @@
+use super::TunConfig;
use ipnetwork::IpNetwork;
use jnix::{
jni::{
- objects::{GlobalRef, JObject, JValue},
+ objects::{GlobalRef, JValue},
signature::{JavaType, Primitive},
JavaVM,
},
@@ -12,13 +13,11 @@ use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr},
os::unix::io::{AsRawFd, FromRawFd, RawFd},
};
-use talpid_core::tunnel::tun_provider::{Tun, TunConfig, TunProvider};
-use talpid_types::BoxedError;
+use talpid_types::android::AndroidContext;
/// Errors that occur while setting up VpnService tunnel.
#[derive(Debug, err_derive::Error)]
-#[error(display = "Failed to set up the VpnService")]
#[error(no_from)]
pub enum Error {
#[error(display = "Failed to attach Java VM to tunnel thread")]
@@ -33,15 +32,9 @@ pub enum Error {
#[error(display = "Failed to create Java VM handle clone")]
CloneJavaVm(#[error(source)] jnix::jni::errors::Error),
- #[error(display = "Failed to create global reference to TalpidVpnService instance")]
- CreateGlobalReference(#[error(source)] jnix::jni::errors::Error),
-
#[error(display = "Failed to find TalpidVpnService.{} method", _0)]
FindMethod(&'static str, #[error(source)] jnix::jni::errors::Error),
- #[error(display = "Failed to get Java VM instance")]
- GetJvmInstance(#[error(source)] jnix::jni::errors::Error),
-
#[error(
display = "Received an invalid result from TalpidVpnService.{}: {}",
_0,
@@ -51,7 +44,7 @@ pub enum Error {
}
/// Factory of tunnel devices on Android.
-pub struct VpnServiceTunProvider {
+pub struct AndroidTunProvider {
jvm: JavaVM,
class: GlobalRef,
object: GlobalRef,
@@ -59,15 +52,9 @@ pub struct VpnServiceTunProvider {
last_tun_config: TunConfig,
}
-impl VpnServiceTunProvider {
- /// Create a new VpnServiceTunProvider interfacing with Android's VpnService.
- pub fn new(env: &JnixEnv, mullvad_vpn_service: &JObject) -> Result<Self, Error> {
- let jvm = env.get_java_vm().map_err(Error::GetJvmInstance)?;
- let class = env.get_class("net/mullvad/talpid/TalpidVpnService");
- let object = env
- .new_global_ref(*mullvad_vpn_service)
- .map_err(Error::CreateGlobalReference)?;
-
+impl AndroidTunProvider {
+ /// Create a new AndroidTunProvider interfacing with Android's VpnService.
+ pub fn new(context: AndroidContext) -> Self {
// Initial configuration simply intercepts all packets. The only field that matters is
// `routes`, because it determines what must enter the tunnel. All other fields contain
// stub values.
@@ -83,15 +70,61 @@ impl VpnServiceTunProvider {
mtu: 1380,
};
- Ok(VpnServiceTunProvider {
- jvm,
- class,
- object,
+ let env = JnixEnv::from(
+ context
+ .jvm
+ .attach_current_thread_as_daemon()
+ .expect("Failed to attach thread to Java VM"),
+ );
+ let talpid_vpn_service_class = env.get_class("net/mullvad/talpid/TalpidVpnService");
+
+ AndroidTunProvider {
+ jvm: context.jvm,
+ class: talpid_vpn_service_class,
+ object: context.vpn_service,
active_tun: None,
last_tun_config: initial_tun_config,
+ }
+ }
+
+ /// 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 jvm = unsafe { JavaVM::from_raw(self.jvm.get_java_vm_pointer()) }
+ .map_err(Error::CloneJavaVm)?;
+
+ Ok(VpnServiceTun {
+ tunnel: tun_fd,
+ jvm,
+ class: self.class.clone(),
+ object: self.object.clone(),
})
}
+ /// 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.
+ pub fn create_tun(&mut self) -> Result<(), Error> {
+ self.open_tun(self.last_tun_config.clone())
+ }
+
+ /// 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()?;
+ }
+
+ Ok(())
+ }
+
+ /// Close currently active tunnel device.
+ pub fn close_tun(&mut self) {
+ self.active_tun = None;
+ }
+
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)?;
@@ -145,66 +178,30 @@ impl VpnServiceTunProvider {
}
}
-impl TunProvider for VpnServiceTunProvider {
- fn get_tun(&mut self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError> {
- let tun_fd = self.get_tun_fd(config).map_err(BoxedError::new)?;
-
- let jvm = unsafe { JavaVM::from_raw(self.jvm.get_java_vm_pointer()) }
- .map_err(|cause| BoxedError::new(Error::CloneJavaVm(cause)))?;
-
- Ok(Box::new(VpnServiceTun {
- tunnel: tun_fd,
- jvm,
- class: self.class.clone(),
- object: self.object.clone(),
- }))
- }
-
- 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.create_tun()?;
- }
-
- Ok(())
- }
-
- fn close_tun(&mut self) {
- self.active_tun = None;
- }
-}
-
-struct VpnServiceTun {
+/// Handle to a tunnel device on Android.
+pub struct VpnServiceTun {
tunnel: RawFd,
jvm: JavaVM,
class: GlobalRef,
object: GlobalRef,
}
-impl AsRawFd for VpnServiceTun {
- fn as_raw_fd(&self) -> RawFd {
- self.tunnel
- }
-}
-
-impl Tun for VpnServiceTun {
- fn interface_name(&self) -> &str {
+impl VpnServiceTun {
+ /// Retrieve the tunnel interface name.
+ pub fn interface_name(&self) -> &str {
"tun"
}
- fn bypass(&mut self, socket: RawFd) -> Result<(), BoxedError> {
+ /// Allow a socket to bypass the tunnel.
+ pub fn bypass(&mut self, socket: RawFd) -> Result<(), Error> {
let env = JnixEnv::from(
self.jvm
.attach_current_thread_as_daemon()
- .map_err(|cause| BoxedError::new(Error::AttachJvmToThread(cause)))?,
+ .map_err(|cause| Error::AttachJvmToThread(cause))?,
);
let create_tun_method = env
.get_method_id(&self.class, "bypass", "(I)Z")
- .map_err(|cause| BoxedError::new(Error::FindMethod("bypass", cause)))?;
+ .map_err(|cause| Error::FindMethod("bypass", cause))?;
let result = env
.call_method_unchecked(
@@ -213,15 +210,18 @@ impl Tun for VpnServiceTun {
JavaType::Primitive(Primitive::Boolean),
&[JValue::Int(socket)],
)
- .map_err(|cause| BoxedError::new(Error::CallMethod("bypass", cause)))?;
+ .map_err(|cause| Error::CallMethod("bypass", cause))?;
match result {
- JValue::Bool(0) => Err(BoxedError::new(Error::Bypass)),
+ JValue::Bool(0) => Err(Error::Bypass),
JValue::Bool(_) => Ok(()),
- value => Err(BoxedError::new(Error::InvalidMethodResult(
- "bypass",
- format!("{:?}", value),
- ))),
+ value => Err(Error::InvalidMethodResult("bypass", format!("{:?}", value))),
}
}
}
+
+impl AsRawFd for VpnServiceTun {
+ fn as_raw_fd(&self) -> RawFd {
+ self.tunnel
+ }
+}
diff --git a/talpid-core/src/tunnel/tun_provider/mod.rs b/talpid-core/src/tunnel/tun_provider/mod.rs
index f0bf8f69b6..b4751e019f 100644
--- a/talpid-core/src/tunnel/tun_provider/mod.rs
+++ b/talpid-core/src/tunnel/tun_provider/mod.rs
@@ -3,78 +3,33 @@ use ipnetwork::IpNetwork;
#[cfg(target_os = "android")]
use jnix::IntoJava;
use std::net::IpAddr;
-#[cfg(unix)]
-use std::os::unix::io::AsRawFd;
-#[cfg(target_os = "android")]
-use std::os::unix::io::RawFd;
-use talpid_types::BoxedError;
cfg_if! {
- if #[cfg(all(unix, not(target_os = "android")))] {
+ if #[cfg(target_os = "android")] {
+ #[path = "android.rs"]
+ mod imp;
+ use self::imp::{AndroidTunProvider, VpnServiceTun};
+ pub use self::imp::Error;
+
+ pub type Tun = VpnServiceTun;
+ pub type TunProvider = AndroidTunProvider;
+ } else if #[cfg(all(unix, not(target_os = "android")))] {
#[path = "unix.rs"]
mod imp;
- use self::imp::UnixTunProvider;
+ use self::imp::{UnixTun, UnixTunProvider};
+ pub use self::imp::Error;
- /// Default implementation of `TunProvider` for Unix based operating systems.
- ///
- /// Android has a different mechanism to obtain tunnel interfaces, so it is not supported
- /// here.
- pub type PlatformTunProvider = UnixTunProvider;
+ pub type Tun = UnixTun;
+ pub type TunProvider = UnixTunProvider;
} else {
mod stub;
use self::stub::StubTunProvider;
+ pub use self::stub::Error;
- /// Default stub implementation of `TunProvider` for Android and Windows.
- pub type PlatformTunProvider = StubTunProvider;
+ pub type TunProvider = StubTunProvider;
}
}
-/// Windows tunnel
-#[cfg(target_os = "windows")]
-pub mod windows;
-
-/// Generic tunnel device.
-///
-/// Must be associated with a platform specific file descriptor representing the device.
-#[cfg(unix)]
-pub trait Tun: AsRawFd + Send {
- /// Retrieve the tunnel interface name.
- fn interface_name(&self) -> &str;
-
- /// Allow a socket to bypass the tunnel.
- #[cfg(target_os = "android")]
- fn bypass(&mut self, socket: RawFd) -> Result<(), BoxedError>;
-}
-
-/// Stub tunnel device.
-#[cfg(windows)]
-pub trait Tun: Send {
- /// Retrieve the tunnel interface name.
- fn interface_name(&self) -> &str;
-}
-
-/// Factory of tunnel devices.
-pub trait TunProvider: Send + 'static {
- /// Retrieve a tunnel device with the provided configuration.
- 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>;
-
- /// Close currently active tunnel device.
- #[cfg(target_os = "android")]
- fn close_tun(&mut self);
-}
-
/// Configuration for creating a tunnel device.
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(target_os = "android", derive(IntoJava))]
diff --git a/talpid-core/src/tunnel/tun_provider/stub.rs b/talpid-core/src/tunnel/tun_provider/stub.rs
index 3cd6dd0ee8..ff659210cf 100644
--- a/talpid-core/src/tunnel/tun_provider/stub.rs
+++ b/talpid-core/src/tunnel/tun_provider/stub.rs
@@ -1,32 +1,17 @@
-use super::{Tun, TunConfig, TunProvider};
-use talpid_types::BoxedError;
+use super::TunConfig;
+
+/// Error stub.
+pub enum Error {}
/// Factory stub of tunnel devices.
pub struct StubTunProvider;
-impl Default for StubTunProvider {
- fn default() -> Self {
+impl StubTunProvider {
+ pub fn new() -> Self {
StubTunProvider
}
-}
-
-impl TunProvider for StubTunProvider {
- fn get_tun(&mut self, _: TunConfig) -> Result<Box<dyn Tun>, BoxedError> {
- unimplemented!();
- }
-
- #[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!();
- }
- #[cfg(target_os = "android")]
- fn close_tun(&mut self) {
+ pub fn get_tun(&mut self, _: TunConfig) -> Result<(), Error> {
unimplemented!();
}
}
diff --git a/talpid-core/src/tunnel/tun_provider/unix.rs b/talpid-core/src/tunnel/tun_provider/unix.rs
index 4e05505348..d8d3b7ce01 100644
--- a/talpid-core/src/tunnel/tun_provider/unix.rs
+++ b/talpid-core/src/tunnel/tun_provider/unix.rs
@@ -1,7 +1,6 @@
-use super::{Tun, TunConfig, TunProvider};
+use super::TunConfig;
use crate::network_interface::{self, NetworkInterface, TunnelDevice};
-use std::net::IpAddr;
-use talpid_types::BoxedError;
+use std::{net::IpAddr, ops::Deref};
/// Errors that can occur while setting up a tunnel device.
#[derive(Debug, err_derive::Error)]
@@ -23,33 +22,42 @@ pub enum Error {
/// Factory of tunnel devices on Unix systems.
pub struct UnixTunProvider;
-impl Default for UnixTunProvider {
- fn default() -> Self {
+impl UnixTunProvider {
+ pub fn new() -> Self {
UnixTunProvider
}
-}
-impl TunProvider for UnixTunProvider {
- fn get_tun(&mut self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError> {
- let mut tunnel_device = TunnelDevice::new()
- .map_err(|cause| BoxedError::new(Error::CreateTunnelDevice(cause)))?;
+ pub fn get_tun(&mut self, config: TunConfig) -> Result<UnixTun, Error> {
+ let mut tunnel_device = TunnelDevice::new().map_err(Error::CreateTunnelDevice)?;
for ip in config.addresses.iter() {
tunnel_device
.set_ip(*ip)
- .map_err(|cause| BoxedError::new(Error::SetIpAddr(*ip, cause)))?;
+ .map_err(|cause| Error::SetIpAddr(*ip, cause))?;
}
- tunnel_device
- .set_up(true)
- .map_err(|cause| BoxedError::new(Error::SetUp(cause)))?;
+ tunnel_device.set_up(true).map_err(Error::SetUp)?;
- Ok(Box::new(tunnel_device))
+ Ok(UnixTun(tunnel_device))
}
}
-impl Tun for TunnelDevice {
- fn interface_name(&self) -> &str {
+/// Generic tunnel device.
+///
+/// Contains the file descriptor representing the device.
+pub struct UnixTun(TunnelDevice);
+
+impl UnixTun {
+ /// Retrieve the tunnel interface name.
+ pub fn interface_name(&self) -> &str {
self.get_name()
}
}
+
+impl Deref for UnixTun {
+ type Target = TunnelDevice;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
diff --git a/talpid-core/src/tunnel/tun_provider/windows.rs b/talpid-core/src/tunnel/tun_provider/windows.rs
deleted file mode 100644
index 9a114bf4b7..0000000000
--- a/talpid-core/src/tunnel/tun_provider/windows.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-use super::Tun;
-
-/// Windows tunnel implementation
-pub struct WinTun {
- /// Name of tunnel interface
- pub interface_name: String,
-}
-
-impl Tun for WinTun {
- fn interface_name(&self) -> &str {
- &self.interface_name
- }
-}
diff --git a/talpid-core/src/tunnel/wireguard/mod.rs b/talpid-core/src/tunnel/wireguard/mod.rs
index d45a5676c3..a2c632d36f 100644
--- a/talpid-core/src/tunnel/wireguard/mod.rs
+++ b/talpid-core/src/tunnel/wireguard/mod.rs
@@ -1,10 +1,12 @@
#![allow(missing_docs)]
use self::config::Config;
+#[cfg(not(windows))]
+use super::tun_provider;
use super::{tun_provider::TunProvider, TunnelEvent, TunnelMetadata};
use crate::{ping_monitor, routing};
use std::{collections::HashMap, io, path::Path, sync::mpsc};
-use talpid_types::{BoxedError, ErrorExt};
+use talpid_types::ErrorExt;
pub mod config;
pub mod wireguard_go;
@@ -21,8 +23,9 @@ pub type Result<T> = std::result::Result<T, Error>;
#[error(no_from)]
pub enum Error {
/// Failed to setup a tunnel device.
+ #[cfg(not(windows))]
#[error(display = "Failed to create tunnel device")]
- SetupTunnelDeviceError(#[error(source)] BoxedError),
+ SetupTunnelDeviceError(#[error(source)] tun_provider::Error),
/// A recoverable error occurred while starting the wireguard tunnel
///
@@ -63,7 +66,7 @@ pub enum Error {
/// Failed to configure Wireguard sockets to bypass the tunnel.
#[cfg(target_os = "android")]
#[error(display = "Failed to configure Wireguard sockets to bypass the tunnel")]
- BypassError(#[error(source)] BoxedError),
+ BypassError(#[error(source)] tun_provider::Error),
/// Failed to duplicate tunnel file descriptor for wireguard-go
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
@@ -93,7 +96,7 @@ impl WireguardMonitor {
config: &Config,
log_path: Option<&Path>,
on_event: F,
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
) -> Result<WireguardMonitor> {
let tunnel = Box::new(WgGoTunnel::start_tunnel(
&config,
diff --git a/talpid-core/src/tunnel/wireguard/wireguard_go.rs b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
index 50df570d01..cff7f2f946 100644
--- a/talpid-core/src/tunnel/wireguard/wireguard_go.rs
+++ b/talpid-core/src/tunnel/wireguard/wireguard_go.rs
@@ -1,60 +1,60 @@
use super::{Config, Error, Result, Tunnel};
-use crate::tunnel::tun_provider::{Tun, TunProvider};
+use crate::tunnel::tun_provider::TunProvider;
use ipnetwork::IpNetwork;
use std::{ffi::CString, path::Path};
-#[cfg(not(target_os = "windows"))]
-use {
- crate::tunnel::tun_provider::TunConfig,
- std::{net::IpAddr, os::unix::io::RawFd, ptr},
-};
-
-
-#[cfg(target_os = "windows")]
-use crate::{
- tunnel::tun_provider::windows::WinTun,
- winnet::{self, add_device_ip_addresses},
-};
-
#[cfg(target_os = "android")]
-use talpid_types::BoxedError;
+use crate::tunnel::tun_provider;
#[cfg(not(target_os = "windows"))]
-const MAX_PREPARE_TUN_ATTEMPTS: usize = 4;
+use {
+ crate::tunnel::tun_provider::{Tun, TunConfig},
+ std::{
+ net::IpAddr,
+ os::unix::io::{AsRawFd, RawFd},
+ ptr,
+ },
+};
#[cfg(target_os = "windows")]
use {
+ crate::winnet::{self, add_device_ip_addresses},
chrono,
parking_lot::Mutex,
std::{collections::HashMap, fs, io::Write},
};
+#[cfg(target_os = "windows")]
+lazy_static::lazy_static! {
+ static ref LOG_MUTEX: Mutex<HashMap<u32, fs::File>> = Mutex::new(HashMap::new());
+}
+
+#[cfg(target_os = "windows")]
+static mut LOG_CONTEXT_NEXT_ORDINAL: u32 = 0;
+
+#[cfg(not(target_os = "windows"))]
+const MAX_PREPARE_TUN_ATTEMPTS: usize = 4;
+
+
pub struct WgGoTunnel {
interface_name: String,
handle: Option<i32>,
// holding on to the tunnel device and the log file ensures that the associated file handles
// live long enough and get closed when the tunnel is stopped
- _tunnel_device: Box<dyn Tun>,
+ #[cfg(not(target_os = "windows"))]
+ _tunnel_device: Tun,
// ordinal that maps to fs::File instance, used with logging callback
#[cfg(target_os = "windows")]
log_context_ordinal: u32,
}
-#[cfg(target_os = "windows")]
-lazy_static::lazy_static! {
- static ref LOG_MUTEX: Mutex<HashMap<u32, fs::File>> = Mutex::new(HashMap::new());
-}
-
-#[cfg(target_os = "windows")]
-static mut LOG_CONTEXT_NEXT_ORDINAL: u32 = 0;
-
impl WgGoTunnel {
#[cfg(not(target_os = "windows"))]
pub fn start_tunnel(
config: &Config,
log_path: Option<&Path>,
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
routes: impl Iterator<Item = IpNetwork>,
) -> Result<Self> {
#[cfg_attr(not(target_os = "android"), allow(unused_mut))]
@@ -105,7 +105,7 @@ impl WgGoTunnel {
pub fn start_tunnel(
config: &Config,
log_path: Option<&Path>,
- _tun_provider: &dyn TunProvider,
+ _tun_provider: &mut TunProvider,
_routes: impl Iterator<Item = IpNetwork>,
) -> Result<Self> {
let log_file = prepare_log_file(log_path)?;
@@ -147,9 +147,6 @@ impl WgGoTunnel {
Ok(WgGoTunnel {
interface_name: iface_name.clone(),
handle: Some(handle),
- _tunnel_device: Box::new(WinTun {
- interface_name: iface_name.clone(),
- }),
log_context_ordinal,
})
}
@@ -238,9 +235,9 @@ impl WgGoTunnel {
#[cfg(target_os = "android")]
fn bypass_tunnel_sockets(
- tunnel_device: &mut Box<dyn Tun>,
+ tunnel_device: &mut Tun,
handle: i32,
- ) -> std::result::Result<(), BoxedError> {
+ ) -> std::result::Result<(), tun_provider::Error> {
let socket_v4 = unsafe { wgGetSocketV4(handle) };
let socket_v6 = unsafe { wgGetSocketV6(handle) };
@@ -262,10 +259,10 @@ impl WgGoTunnel {
#[cfg(not(target_os = "windows"))]
fn get_tunnel(
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
config: &Config,
routes: impl Iterator<Item = IpNetwork>,
- ) -> Result<(Box<dyn Tun>, RawFd)> {
+ ) -> Result<(Tun, RawFd)> {
let mut last_error = None;
let tunnel_config = Self::create_tunnel_config(config, routes);
diff --git a/talpid-core/src/tunnel_state_machine/connecting_state.rs b/talpid-core/src/tunnel_state_machine/connecting_state.rs
index f87b96382f..67036ea98e 100644
--- a/talpid-core/src/tunnel_state_machine/connecting_state.rs
+++ b/talpid-core/src/tunnel_state_machine/connecting_state.rs
@@ -15,7 +15,6 @@ use futures::{
};
use log::{debug, error, info, trace, warn};
use std::{
- borrow::BorrowMut,
net::IpAddr,
path::{Path, PathBuf},
thread,
@@ -65,7 +64,7 @@ impl ConnectingState {
parameters: TunnelParameters,
log_dir: &Option<PathBuf>,
resource_dir: &Path,
- tun_provider: &mut dyn TunProvider,
+ tun_provider: &mut TunProvider,
retry_attempt: u32,
) -> crate::tunnel::Result<Self> {
let (event_tx, event_rx) = mpsc::unbounded();
@@ -351,13 +350,10 @@ 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() {
+ if let Err(error) = shared_values.tun_provider.create_tun() {
error!(
"{}",
error.display_chain_with_msg("Failed to recreate tun device")
@@ -370,7 +366,7 @@ impl TunnelState for ConnectingState {
tunnel_parameters,
&shared_values.log_dir,
&shared_values.resource_dir,
- tun_provider,
+ &mut shared_values.tun_provider,
retry_attempt,
) {
Ok(connecting_state) => {
diff --git a/talpid-core/src/tunnel_state_machine/mod.rs b/talpid-core/src/tunnel_state_machine/mod.rs
index 42c959c81e..d81a787f1a 100644
--- a/talpid-core/src/tunnel_state_machine/mod.rs
+++ b/talpid-core/src/tunnel_state_machine/mod.rs
@@ -28,6 +28,8 @@ use std::{
sync::{mpsc as sync_mpsc, Arc},
thread,
};
+#[cfg(target_os = "android")]
+use talpid_types::android::AndroidContext;
use talpid_types::{
net::TunnelParameters,
tunnel::{BlockReason, ParameterGenerationError, TunnelStateTransition},
@@ -64,11 +66,11 @@ pub fn spawn<P, T>(
allow_lan: bool,
block_when_disconnected: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
- tun_provider: impl TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: P,
state_change_listener: IntoSender<TunnelStateTransition, T>,
+ #[cfg(target_os = "android")] android_context: AndroidContext,
) -> Result<Arc<mpsc::UnboundedSender<TunnelCommand>>, Error>
where
P: AsRef<Path> + Send + 'static,
@@ -80,6 +82,11 @@ where
offline::spawn_monitor(Arc::downgrade(&command_tx)).map_err(Error::OfflineMonitorError)?;
let is_offline = offline_monitor.is_offline();
+ let tun_provider = TunProvider::new(
+ #[cfg(target_os = "android")]
+ android_context,
+ );
+
let (startup_result_tx, startup_result_rx) = sync_mpsc::channel();
thread::spawn(move || {
match create_event_loop(
@@ -126,7 +133,7 @@ fn create_event_loop<T>(
block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
- tun_provider: impl TunProvider,
+ tun_provider: TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: impl AsRef<Path>,
@@ -192,7 +199,7 @@ impl TunnelStateMachine {
block_when_disconnected: bool,
is_offline: bool,
tunnel_parameters_generator: impl TunnelParametersGenerator,
- tun_provider: impl TunProvider,
+ tun_provider: TunProvider,
log_dir: Option<PathBuf>,
resource_dir: PathBuf,
cache_dir: impl AsRef<Path>,
@@ -218,7 +225,7 @@ impl TunnelStateMachine {
block_when_disconnected,
is_offline,
tunnel_parameters_generator: Box::new(tunnel_parameters_generator),
- tun_provider: Box::new(tun_provider),
+ tun_provider,
log_dir,
resource_dir,
};
@@ -306,7 +313,7 @@ struct SharedTunnelStateValues {
/// The generator of new `TunnelParameter`s
tunnel_parameters_generator: Box<dyn TunnelParametersGenerator>,
/// The provider of tunnel devices.
- tun_provider: Box<dyn TunProvider>,
+ tun_provider: TunProvider,
/// Directory to store tunnel log file.
log_dir: Option<PathBuf>,
/// Resource directory path.
diff --git a/talpid-types/src/android/mod.rs b/talpid-types/src/android/mod.rs
new file mode 100644
index 0000000000..70c34fea95
--- /dev/null
+++ b/talpid-types/src/android/mod.rs
@@ -0,0 +1,6 @@
+use jnix::jni::{objects::GlobalRef, JavaVM};
+
+pub struct AndroidContext {
+ pub jvm: JavaVM,
+ pub vpn_service: GlobalRef,
+}
diff --git a/talpid-types/src/lib.rs b/talpid-types/src/lib.rs
index 569bc94fb9..00e87859a8 100644
--- a/talpid-types/src/lib.rs
+++ b/talpid-types/src/lib.rs
@@ -10,6 +10,8 @@
use std::{error::Error, fmt};
+#[cfg(target_os = "android")]
+pub mod android;
pub mod net;
pub mod tunnel;