summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-23 16:20:44 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-05-23 16:20:44 -0300
commit40de1e01c0ebe0d6bf1183e9a8ecc956d15a0bb5 (patch)
tree83354b998e1303baf62024c2f46044415a5fa200
parentfb9711759ddad7a5b984dda8e65df4effe312500 (diff)
parent074a68305b2a2f67ff6c0d3156f3490ef0aa006c (diff)
downloadmullvadvpn-40de1e01c0ebe0d6bf1183e9a8ecc956d15a0bb5.tar.xz
mullvadvpn-40de1e01c0ebe0d6bf1183e9a8ecc956d15a0bb5.zip
Merge branch 'listen-for-tunnel-states-on-android'
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt20
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt58
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt19
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt19
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt7
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt19
-rw-r--r--android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelStateTransition.kt9
-rw-r--r--mullvad-jni/src/into_java.rs23
-rw-r--r--mullvad-jni/src/jni_event_listener.rs123
-rw-r--r--mullvad-jni/src/lib.rs53
11 files changed, 265 insertions, 92 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt
index 4a577cd337..faf4a61521 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectActionButton.kt
@@ -3,15 +3,19 @@ package net.mullvad.mullvadvpn
import android.view.View
import android.widget.Button
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
+
class ConnectActionButton(val parentView: View) {
private val button: Button = parentView.findViewById(R.id.action_button)
- var state = ConnectionState.Disconnected
+ var state: TunnelStateTransition = TunnelStateTransition.Disconnected()
set(value) {
when (value) {
- ConnectionState.Disconnected -> disconnected()
- ConnectionState.Connecting -> connecting()
- ConnectionState.Connected -> connected()
+ is TunnelStateTransition.Disconnected -> disconnected()
+ is TunnelStateTransition.Disconnecting -> disconnected()
+ is TunnelStateTransition.Connecting -> connecting()
+ is TunnelStateTransition.Connected -> connected()
+ is TunnelStateTransition.Blocked -> connected()
}
field = value
@@ -27,9 +31,11 @@ class ConnectActionButton(val parentView: View) {
private fun action() {
when (state) {
- ConnectionState.Disconnected -> onConnect?.invoke()
- ConnectionState.Connecting -> onCancel?.invoke()
- ConnectionState.Connected -> onDisconnect?.invoke()
+ is TunnelStateTransition.Disconnected -> onConnect?.invoke()
+ is TunnelStateTransition.Disconnecting -> onConnect?.invoke()
+ is TunnelStateTransition.Connecting -> onCancel?.invoke()
+ is TunnelStateTransition.Connected -> onDisconnect?.invoke()
+ is TunnelStateTransition.Blocked -> onDisconnect?.invoke()
}
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
index 8d7abfd24e..11bfabe912 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectFragment.kt
@@ -4,6 +4,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.Job
import android.content.Context
import android.os.Bundle
@@ -14,24 +15,18 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
+
class ConnectFragment : Fragment() {
private lateinit var actionButton: ConnectActionButton
private lateinit var headerBar: HeaderBar
private lateinit var notificationBanner: NotificationBanner
private lateinit var status: ConnectionStatus
- private lateinit var connectHandler: Handler
private lateinit var daemon: Deferred<MullvadDaemon>
- private var state = ConnectionState.Disconnected
- set(value) {
- actionButton.state = value
- headerBar.state = value
- notificationBanner.state = value
- status.state = value
-
- field = value
- }
+ private var attachListenerJob: Job? = null
+ private var updateViewJob: Job? = null
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -39,12 +34,6 @@ class ConnectFragment : Fragment() {
daemon = (context as MainActivity).asyncDaemon
}
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- connectHandler = Handler()
- }
-
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -67,31 +56,40 @@ class ConnectFragment : Fragment() {
onDisconnect = { disconnect() }
}
+ attachListenerJob = attachListener()
+
return view
}
- private fun connect() {
- state = ConnectionState.Connecting
- GlobalScope.launch(Dispatchers.Default) {
- daemon.await().connect()
- }
+ override fun onDestroyView() {
+ attachListenerJob?.cancel()
+ detachListener()
+ updateViewJob?.cancel()
+ super.onDestroyView()
+ }
- connectHandler.postDelayed(Runnable { connected() }, 1000)
+ private fun attachListener() = GlobalScope.launch(Dispatchers.Default) {
+ daemon.await().onTunnelStateChange = { state -> updateViewJob = updateView(state) }
}
- private fun disconnect() {
- state = ConnectionState.Disconnected
+ private fun detachListener() = GlobalScope.launch(Dispatchers.Default) {
+ daemon.await().onTunnelStateChange = null
+ }
- GlobalScope.launch(Dispatchers.Default) {
- daemon.await().disconnect()
- }
+ private fun connect() = GlobalScope.launch(Dispatchers.Default) {
+ daemon.await().connect()
+ }
- connectHandler.removeCallbacksAndMessages(null)
+ private fun disconnect() = GlobalScope.launch(Dispatchers.Default) {
+ daemon.await().disconnect()
}
- private fun connected() {
- state = ConnectionState.Connected
+ private fun updateView(state: TunnelStateTransition) = GlobalScope.launch(Dispatchers.Main) {
+ actionButton.state = state
+ headerBar.setState(state)
+ notificationBanner.setState(state)
+ status.setState(state)
}
private fun openSwitchLocationScreen() {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt
deleted file mode 100644
index 4764ce05fe..0000000000
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionState.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.mullvad.mullvadvpn
-
-enum class ConnectionState {
- Disconnected,
- Connecting,
- Connected,
-}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt
index 7f608c5431..652eae4da5 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ConnectionStatus.kt
@@ -4,6 +4,8 @@ import android.content.Context
import android.view.View
import android.widget.TextView
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
+
class ConnectionStatus(val parentView: View, val context: Context) {
private val spinner: View = parentView.findViewById(R.id.connecting_spinner)
private val text: TextView = parentView.findViewById(R.id.connection_status)
@@ -12,16 +14,15 @@ class ConnectionStatus(val parentView: View, val context: Context) {
private val connectingTextColor = context.getColor(R.color.white)
private val connectedTextColor = context.getColor(R.color.green)
- var state = ConnectionState.Disconnected
- set(value) {
- when (value) {
- ConnectionState.Disconnected -> disconnected()
- ConnectionState.Connecting -> connecting()
- ConnectionState.Connected -> connected()
- }
-
- field = value
+ fun setState(state: TunnelStateTransition) {
+ when (state) {
+ is TunnelStateTransition.Disconnecting -> disconnected()
+ is TunnelStateTransition.Disconnected -> disconnected()
+ is TunnelStateTransition.Connecting -> connecting()
+ is TunnelStateTransition.Connected -> connected()
+ is TunnelStateTransition.Blocked -> connected()
}
+ }
private fun disconnected() {
spinner.visibility = View.GONE
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt
index 4c46174f51..6988dae839 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/HeaderBar.kt
@@ -3,22 +3,23 @@ package net.mullvad.mullvadvpn
import android.content.Context
import android.view.View
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
+
class HeaderBar(val parentView: View, val context: Context) {
private val headerBar: View = parentView.findViewById(R.id.header_bar)
private val securedColor = context.getColor(R.color.green)
private val unsecuredColor = context.getColor(R.color.red)
- var state = ConnectionState.Disconnected
- set(value) {
- when (value) {
- ConnectionState.Disconnected -> unsecured()
- ConnectionState.Connecting -> secured()
- ConnectionState.Connected -> secured()
- }
-
- field = value
+ fun setState(state: TunnelStateTransition) {
+ when (state) {
+ is TunnelStateTransition.Disconnected -> unsecured()
+ is TunnelStateTransition.Connecting -> secured()
+ is TunnelStateTransition.Connected -> secured()
+ is TunnelStateTransition.Disconnecting -> secured()
+ is TunnelStateTransition.Blocked -> secured()
}
+ }
private fun unsecured() {
headerBar.setBackgroundColor(unsecuredColor)
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
index e95a761ba5..80ac09eef2 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/MullvadDaemon.kt
@@ -4,6 +4,7 @@ import net.mullvad.mullvadvpn.model.AccountData
import net.mullvad.mullvadvpn.model.RelayList
import net.mullvad.mullvadvpn.model.RelaySettingsUpdate
import net.mullvad.mullvadvpn.model.Settings
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
class MullvadDaemon {
init {
@@ -11,6 +12,8 @@ class MullvadDaemon {
initialize()
}
+ var onTunnelStateChange: ((TunnelStateTransition) -> Unit)? = null
+
external fun connect()
external fun disconnect()
external fun getAccountData(accountToken: String): AccountData?
@@ -20,4 +23,8 @@ class MullvadDaemon {
external fun updateRelaySettings(update: RelaySettingsUpdate)
private external fun initialize()
+
+ private fun notifyTunnelStateEvent(event: TunnelStateTransition) {
+ onTunnelStateChange?.invoke(event)
+ }
}
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt
index 531e43f96f..7789d57435 100644
--- a/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/NotificationBanner.kt
@@ -2,20 +2,21 @@ package net.mullvad.mullvadvpn
import android.view.View
+import net.mullvad.mullvadvpn.model.TunnelStateTransition
+
class NotificationBanner(val parentView: View) {
private val banner: View = parentView.findViewById(R.id.notification_banner)
private var visible = false
- var state = ConnectionState.Disconnected
- set(value) {
- when (value) {
- ConnectionState.Disconnected -> hide()
- ConnectionState.Connecting -> show()
- ConnectionState.Connected -> hide()
- }
-
- field = value
+ fun setState(state: TunnelStateTransition) {
+ when (state) {
+ is TunnelStateTransition.Disconnecting -> hide()
+ is TunnelStateTransition.Disconnected -> hide()
+ is TunnelStateTransition.Connecting -> show()
+ is TunnelStateTransition.Connected -> hide()
+ is TunnelStateTransition.Blocked -> show()
}
+ }
private fun show() {
if (!visible) {
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelStateTransition.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelStateTransition.kt
new file mode 100644
index 0000000000..ec65037e42
--- /dev/null
+++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/model/TunnelStateTransition.kt
@@ -0,0 +1,9 @@
+package net.mullvad.mullvadvpn.model
+
+sealed class TunnelStateTransition() {
+ class Disconnected() : TunnelStateTransition()
+ class Connecting() : TunnelStateTransition()
+ class Connected() : TunnelStateTransition()
+ class Disconnecting() : TunnelStateTransition()
+ class Blocked() : TunnelStateTransition()
+}
diff --git a/mullvad-jni/src/into_java.rs b/mullvad-jni/src/into_java.rs
index 1c6733252b..743328dbff 100644
--- a/mullvad-jni/src/into_java.rs
+++ b/mullvad-jni/src/into_java.rs
@@ -12,6 +12,7 @@ use mullvad_types::{
CustomTunnelEndpoint,
};
use std::fmt::Debug;
+use talpid_types::tunnel::TunnelStateTransition;
pub trait IntoJava<'env> {
type JavaType;
@@ -294,3 +295,25 @@ impl<'env> IntoJava<'env> for Settings {
.expect("Failed to create Settings Java object")
}
}
+
+impl<'env> IntoJava<'env> for TunnelStateTransition {
+ type JavaType = JObject<'env>;
+
+ fn into_java(self, env: &JNIEnv<'env>) -> Self::JavaType {
+ let variant = match self {
+ TunnelStateTransition::Disconnected => "Disconnected",
+ TunnelStateTransition::Connecting(_) => "Connecting",
+ TunnelStateTransition::Connected(_) => "Connected",
+ TunnelStateTransition::Disconnecting(_) => "Disconnecting",
+ TunnelStateTransition::Blocked(_) => "Blocked",
+ };
+
+ let class = get_class(&format!(
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition${}",
+ variant
+ ));
+
+ env.new_object(&class, "()V", &[])
+ .expect("Failed to create TunnelStateTransition sub-class variant Java object")
+ }
+}
diff --git a/mullvad-jni/src/jni_event_listener.rs b/mullvad-jni/src/jni_event_listener.rs
new file mode 100644
index 0000000000..7beb7ae844
--- /dev/null
+++ b/mullvad-jni/src/jni_event_listener.rs
@@ -0,0 +1,123 @@
+use crate::{get_class, into_java::IntoJava};
+use jni::{
+ objects::{JMethodID, JObject, JValue},
+ signature::{JavaType, Primitive},
+ AttachGuard, JNIEnv,
+};
+use mullvad_daemon::EventListener;
+use mullvad_types::{relay_list::RelayList, settings::Settings};
+use std::{sync::mpsc, thread};
+use talpid_types::{tunnel::TunnelStateTransition, ErrorExt};
+
+#[derive(Debug, err_derive::Error)]
+pub enum Error {
+ #[error(display = "Failed to create global reference to MullvadDaemon Java object")]
+ CreateGlobalReference(#[error(cause)] jni::errors::Error),
+
+ #[error(display = "Failed to find {} method", _0)]
+ FindMethod(&'static str, #[error(cause)] jni::errors::Error),
+
+ #[error(display = "Failed to retrieve Java VM instance")]
+ GetJvmInstance(#[error(cause)] jni::errors::Error),
+}
+
+#[derive(Clone, Debug)]
+pub struct JniEventListener(mpsc::Sender<TunnelStateTransition>);
+
+impl JniEventListener {
+ pub fn spawn(env: &JNIEnv, mullvad_daemon: &JObject) -> Result<Self, Error> {
+ JniEventHandler::spawn(env, mullvad_daemon)
+ }
+}
+
+impl EventListener for JniEventListener {
+ fn notify_new_state(&self, state: TunnelStateTransition) {
+ let _ = self.0.send(state);
+ }
+
+ fn notify_settings(&self, _: Settings) {}
+ fn notify_relay_list(&self, _: RelayList) {}
+}
+
+struct JniEventHandler<'env> {
+ env: AttachGuard<'env>,
+ mullvad_ipc_client: JObject<'env>,
+ notify_tunnel_event: JMethodID<'env>,
+ events: mpsc::Receiver<TunnelStateTransition>,
+}
+
+impl JniEventHandler<'_> {
+ pub fn spawn(
+ old_env: &JNIEnv,
+ old_mullvad_ipc_client: &JObject,
+ ) -> Result<JniEventListener, Error> {
+ let (tx, rx) = mpsc::channel();
+ let jvm = old_env.get_java_vm().map_err(Error::GetJvmInstance)?;
+ let mullvad_ipc_client = old_env
+ .new_global_ref(*old_mullvad_ipc_client)
+ .map_err(Error::CreateGlobalReference)?;
+
+ thread::spawn(move || match jvm.attach_current_thread() {
+ Ok(env) => match JniEventHandler::new(env, mullvad_ipc_client.as_obj(), rx) {
+ Ok(mut listener) => listener.run(),
+ Err(error) => log::error!("{}", error.display_chain()),
+ },
+ Err(error) => {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg(
+ "Failed to attach tunnel event listener thread to Java VM"
+ )
+ );
+ }
+ });
+
+ Ok(JniEventListener(tx))
+ }
+}
+
+impl<'env> JniEventHandler<'env> {
+ fn new(
+ env: AttachGuard<'env>,
+ mullvad_ipc_client: JObject<'env>,
+ events: mpsc::Receiver<TunnelStateTransition>,
+ ) -> Result<Self, Error> {
+ let class = get_class("net/mullvad/mullvadvpn/MullvadDaemon");
+ let notify_tunnel_event = env
+ .get_method_id(
+ &class,
+ "notifyTunnelStateEvent",
+ "(Lnet/mullvad/mullvadvpn/model/TunnelStateTransition;)V",
+ )
+ .map_err(|error| Error::FindMethod("notifyTunnelStateEvent", error))?;
+
+ Ok(JniEventHandler {
+ env,
+ mullvad_ipc_client,
+ notify_tunnel_event,
+ events,
+ })
+ }
+
+ fn run(&mut self) {
+ while let Ok(event) = self.events.recv() {
+ self.handle_tunnel_event(event);
+ }
+ }
+
+ fn handle_tunnel_event(&self, event: TunnelStateTransition) {
+ let result = self.env.call_method_unchecked(
+ self.mullvad_ipc_client,
+ self.notify_tunnel_event,
+ JavaType::Primitive(Primitive::Void),
+ &[JValue::Object(event.into_java(&self.env))],
+ );
+
+ if let Err(error) = result {
+ log::error!(
+ "{}",
+ error.display_chain_with_msg("Failed to call MullvadDaemon.notifyTunnelStateEvent")
+ );
+ }
+ }
+}
diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs
index d5708c9a0a..83e60e0486 100644
--- a/mullvad-jni/src/lib.rs
+++ b/mullvad-jni/src/lib.rs
@@ -4,18 +4,21 @@ mod daemon_interface;
mod from_java;
mod into_java;
mod is_null;
+mod jni_event_listener;
-use crate::{daemon_interface::DaemonInterface, from_java::FromJava, into_java::IntoJava};
+use crate::{
+ daemon_interface::DaemonInterface, from_java::FromJava, into_java::IntoJava,
+ jni_event_listener::JniEventListener,
+};
use jni::{
objects::{GlobalRef, JObject, JString},
JNIEnv,
};
use lazy_static::lazy_static;
-use mullvad_daemon::{logging, version, Daemon, DaemonCommandSender, EventListener};
-use mullvad_types::{relay_list::RelayList, settings::Settings};
+use mullvad_daemon::{logging, version, Daemon, DaemonCommandSender};
use parking_lot::{Mutex, RwLock};
use std::{collections::HashMap, path::PathBuf, sync::mpsc, thread};
-use talpid_types::{tunnel::TunnelStateTransition, ErrorExt};
+use talpid_types::ErrorExt;
const LOG_FILENAME: &str = "daemon.log";
@@ -36,6 +39,12 @@ const CLASSES_TO_LOAD: &[&str] = &[
"net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint",
"net/mullvad/mullvadvpn/model/RelaySettingsUpdate$RelayConstraintsUpdate",
"net/mullvad/mullvadvpn/model/Settings",
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition$Blocked",
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition$Connected",
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition$Connecting",
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition$Disconnected",
+ "net/mullvad/mullvadvpn/model/TunnelStateTransition$Disconnecting",
+ "net/mullvad/mullvadvpn/MullvadDaemon",
];
lazy_static! {
@@ -51,19 +60,22 @@ pub enum Error {
#[error(display = "Failed to initialize the mullvad daemon")]
InitializeDaemon(#[error(cause)] mullvad_daemon::Error),
+
+ #[error(display = "Failed to spawn the JNI event listener")]
+ SpawnJniEventListener(#[error(cause)] jni_event_listener::Error),
}
#[no_mangle]
#[allow(non_snake_case)]
pub extern "system" fn Java_net_mullvad_mullvadvpn_MullvadDaemon_initialize(
env: JNIEnv,
- _: JObject,
+ this: JObject,
) {
let log_dir = start_logging();
load_classes(&env);
- if let Err(error) = initialize(log_dir) {
+ if let Err(error) = initialize(&env, &this, log_dir) {
log::error!("{}", error.display_chain());
}
}
@@ -97,8 +109,8 @@ fn load_class_reference(env: &JNIEnv, name: &str) -> GlobalRef {
.expect("Failed to convert local reference to Java class into a global reference")
}
-fn initialize(log_dir: PathBuf) -> Result<(), Error> {
- let daemon_command_sender = spawn_daemon(log_dir)?;
+fn initialize(env: &JNIEnv, this: &JObject, log_dir: PathBuf) -> Result<(), Error> {
+ let daemon_command_sender = spawn_daemon(env, this, log_dir)?;
DAEMON_INTERFACE
.lock()
@@ -107,10 +119,15 @@ fn initialize(log_dir: PathBuf) -> Result<(), Error> {
Ok(())
}
-fn spawn_daemon(log_dir: PathBuf) -> Result<DaemonCommandSender, Error> {
+fn spawn_daemon(
+ env: &JNIEnv,
+ this: &JObject,
+ log_dir: PathBuf,
+) -> Result<DaemonCommandSender, Error> {
+ let listener = JniEventListener::spawn(env, this).map_err(Error::SpawnJniEventListener)?;
let (tx, rx) = mpsc::channel();
- thread::spawn(move || match create_daemon(log_dir) {
+ thread::spawn(move || match create_daemon(listener, log_dir) {
Ok(daemon) => {
let _ = tx.send(Ok(daemon.command_sender()));
match daemon.run() {
@@ -126,12 +143,15 @@ fn spawn_daemon(log_dir: PathBuf) -> Result<DaemonCommandSender, Error> {
rx.recv().unwrap()
}
-fn create_daemon(log_dir: PathBuf) -> Result<Daemon<DummyListener>, Error> {
+fn create_daemon(
+ listener: JniEventListener,
+ log_dir: PathBuf,
+) -> 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(
- DummyListener,
+ listener,
Some(log_dir),
resource_dir,
cache_dir,
@@ -142,15 +162,6 @@ fn create_daemon(log_dir: PathBuf) -> Result<Daemon<DummyListener>, Error> {
Ok(daemon)
}
-#[derive(Clone, Copy, Debug)]
-struct DummyListener;
-
-impl EventListener for DummyListener {
- fn notify_new_state(&self, _: TunnelStateTransition) {}
- fn notify_settings(&self, _: Settings) {}
- fn notify_relay_list(&self, _: RelayList) {}
-}
-
fn get_class(name: &str) -> GlobalRef {
match CLASSES.read().get(name) {
Some(class) => class.clone(),