Skip to content

Commit 69cf072

Browse files
Merge branch 'detect-available-ip-versions-when-wireguard-ip-version-is-des-552'
2 parents 32e4537 + a6a26bf commit 69cf072

File tree

15 files changed

+282
-169
lines changed

15 files changed

+282
-169
lines changed

mullvad-daemon/src/api.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use mullvad_types::access_method::{
2121
};
2222
use std::{net::SocketAddr, path::PathBuf};
2323
use talpid_core::mpsc::Sender;
24-
use talpid_types::net::{AllowedClients, AllowedEndpoint, Endpoint, TransportProtocol};
24+
use talpid_types::net::{
25+
AllowedClients, AllowedEndpoint, Connectivity, Endpoint, TransportProtocol,
26+
};
2527

2628
pub enum Message {
2729
Get(ResponseTx<ResolvedConnectionMode>),
@@ -527,18 +529,26 @@ pub fn allowed_clients(connection_mode: &ApiConnectionMode) -> AllowedClients {
527529
}
528530
}
529531

532+
/// Forwards the received values from `offline_state_rx` to the [`ApiAvailabilityHandle`].
530533
pub(crate) fn forward_offline_state(
531534
api_availability: ApiAvailabilityHandle,
532-
mut offline_state_rx: mpsc::UnboundedReceiver<bool>,
535+
mut offline_state_rx: mpsc::UnboundedReceiver<Connectivity>,
533536
) {
534537
tokio::spawn(async move {
535-
let initial_state = offline_state_rx
538+
let is_offline = offline_state_rx
536539
.next()
537540
.await
538-
.expect("missing initial offline state");
539-
api_availability.set_offline(initial_state);
540-
while let Some(is_offline) = offline_state_rx.next().await {
541-
api_availability.set_offline(is_offline);
541+
.expect("missing initial offline state")
542+
.is_offline();
543+
log::info!(
544+
"Initial offline state - {state}",
545+
state = if is_offline { "offline" } else { "online" },
546+
);
547+
api_availability.set_offline(is_offline);
548+
549+
while let Some(state) = offline_state_rx.next().await {
550+
log::info!("Detecting changes to offline state - {state:?}");
551+
api_availability.set_offline(state.is_offline());
542552
}
543553
});
544554
}

mullvad-types/src/access_method.rs

+2-12
Original file line numberDiff line numberDiff line change
@@ -77,20 +77,11 @@ impl Settings {
7777
/// Check that `self` contains atleast one enabled access methods. If not,
7878
/// the `Direct` access method is re-enabled.
7979
fn ensure_consistent_state(&mut self) {
80-
if self.collect_enabled().is_empty() {
80+
if self.iter().all(|access_method| access_method.disabled()) {
8181
self.direct.enable();
8282
}
8383
}
8484

85-
// TODO(markus): This can surely be removed.
86-
/// Retrieve all [`AccessMethodSetting`]s which are enabled.
87-
pub fn collect_enabled(&self) -> Vec<AccessMethodSetting> {
88-
self.iter()
89-
.filter(|access_method| access_method.enabled)
90-
.cloned()
91-
.collect()
92-
}
93-
9485
/// Iterate over references of built-in & custom access methods.
9586
pub fn iter(&self) -> impl Iterator<Item = &AccessMethodSetting> {
9687
use std::iter::once;
@@ -128,8 +119,7 @@ impl Settings {
128119
&self.mullvad_bridges
129120
}
130121

131-
// TODO(markus): This can probably be made private
132-
pub fn create_direct() -> AccessMethodSetting {
122+
fn create_direct() -> AccessMethodSetting {
133123
let method = BuiltInAccessMethod::Direct;
134124
AccessMethodSetting::new(method.canonical_name(), true, AccessMethod::from(method))
135125
}

talpid-core/src/offline/android.rs

+24-23
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ use jnix::{
44
self,
55
objects::{GlobalRef, JObject, JValue},
66
signature::{JavaType, Primitive},
7-
sys::{jboolean, jlong, JNI_FALSE},
7+
sys::{jboolean, jlong, JNI_TRUE},
88
JNIEnv, JavaVM,
99
},
1010
JnixEnv,
1111
};
1212
use std::sync::{Arc, Weak};
13-
use talpid_types::{android::AndroidContext, ErrorExt};
13+
use talpid_types::{android::AndroidContext, net::Connectivity, ErrorExt};
1414

1515
#[derive(err_derive::Error, Debug)]
1616
#[error(no_from)]
@@ -43,13 +43,13 @@ pub struct MonitorHandle {
4343
jvm: Arc<JavaVM>,
4444
class: GlobalRef,
4545
object: GlobalRef,
46-
_sender: Arc<UnboundedSender<bool>>,
46+
_sender: Arc<UnboundedSender<Connectivity>>,
4747
}
4848

4949
impl MonitorHandle {
5050
pub fn new(
5151
android_context: AndroidContext,
52-
sender: Arc<UnboundedSender<bool>>,
52+
sender: Arc<UnboundedSender<Connectivity>>,
5353
) -> Result<Self, Error> {
5454
let env = JnixEnv::from(
5555
android_context
@@ -101,30 +101,29 @@ impl MonitorHandle {
101101
}
102102

103103
#[allow(clippy::unused_async)]
104-
pub async fn host_is_offline(&self) -> bool {
105-
match self.get_is_connected() {
106-
Ok(is_connected) => !is_connected,
107-
Err(error) => {
104+
pub async fn connectivity(&self) -> Connectivity {
105+
self.get_is_connected()
106+
.map(|connected| Connectivity::Status { connected })
107+
.unwrap_or_else(|error| {
108108
log::error!(
109109
"{}",
110110
error.display_chain_with_msg("Failed to check connectivity status")
111111
);
112-
false
113-
}
114-
}
112+
Connectivity::PresumeOnline
113+
})
115114
}
116115

117116
fn get_is_connected(&self) -> Result<bool, Error> {
118-
let result = self.call_method(
117+
let is_connected = self.call_method(
119118
"isConnected",
120119
"()Z",
121120
&[],
122121
JavaType::Primitive(Primitive::Boolean),
123122
)?;
124123

125-
match result {
126-
JValue::Bool(JNI_FALSE) => Ok(false),
127-
JValue::Bool(_) => Ok(true),
124+
match is_connected {
125+
JValue::Bool(JNI_TRUE) => Ok(true),
126+
JValue::Bool(_) => Ok(false),
128127
value => Err(Error::InvalidMethodResult(
129128
"ConnectivityListener",
130129
"isConnected",
@@ -133,7 +132,7 @@ impl MonitorHandle {
133132
}
134133
}
135134

136-
fn set_sender(&self, sender: Weak<UnboundedSender<bool>>) -> Result<(), Error> {
135+
fn set_sender(&self, sender: Weak<UnboundedSender<Connectivity>>) -> Result<(), Error> {
137136
let sender_ptr = Box::new(sender);
138137
let sender_address = Box::into_raw(sender_ptr) as jlong;
139138

@@ -182,14 +181,16 @@ impl MonitorHandle {
182181
pub extern "system" fn Java_net_mullvad_talpid_ConnectivityListener_notifyConnectivityChange(
183182
_: JNIEnv<'_>,
184183
_: JObject<'_>,
185-
is_connected: jboolean,
184+
connected: jboolean,
186185
sender_address: jlong,
187186
) {
187+
let connected = JNI_TRUE == connected;
188188
let sender_ref = Box::leak(unsafe { get_sender_from_address(sender_address) });
189-
let is_offline = is_connected == JNI_FALSE;
190-
191189
if let Some(sender) = sender_ref.upgrade() {
192-
if sender.unbounded_send(is_offline).is_err() {
190+
if sender
191+
.unbounded_send(Connectivity::Status { connected })
192+
.is_err()
193+
{
193194
log::warn!("Failed to send offline change event");
194195
}
195196
}
@@ -206,13 +207,13 @@ pub extern "system" fn Java_net_mullvad_talpid_ConnectivityListener_destroySende
206207
let _ = unsafe { get_sender_from_address(sender_address) };
207208
}
208209

209-
unsafe fn get_sender_from_address(address: jlong) -> Box<Weak<UnboundedSender<bool>>> {
210-
Box::from_raw(address as *mut Weak<UnboundedSender<bool>>)
210+
unsafe fn get_sender_from_address(address: jlong) -> Box<Weak<UnboundedSender<Connectivity>>> {
211+
Box::from_raw(address as *mut Weak<UnboundedSender<Connectivity>>)
211212
}
212213

213214
#[allow(clippy::unused_async)]
214215
pub async fn spawn_monitor(
215-
sender: UnboundedSender<bool>,
216+
sender: UnboundedSender<Connectivity>,
216217
android_context: AndroidContext,
217218
) -> Result<MonitorHandle, Error> {
218219
let sender = Arc::new(sender);

talpid-core/src/offline/linux.rs

+27-21
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::{
44
sync::Arc,
55
};
66
use talpid_routing::{self, RouteManagerHandle};
7-
use talpid_types::ErrorExt;
7+
use talpid_types::{net::Connectivity, ErrorExt};
88

99
pub type Result<T> = std::result::Result<T, Error>;
1010

@@ -18,30 +18,31 @@ pub enum Error {
1818
pub struct MonitorHandle {
1919
route_manager: RouteManagerHandle,
2020
fwmark: Option<u32>,
21-
_notify_tx: Arc<UnboundedSender<bool>>,
21+
_notify_tx: Arc<UnboundedSender<Connectivity>>,
2222
}
2323

24+
/// A non-local IPv4 address.
2425
const PUBLIC_INTERNET_ADDRESS_V4: IpAddr = IpAddr::V4(Ipv4Addr::new(193, 138, 218, 78));
26+
/// A non-local IPv6 address.
2527
const PUBLIC_INTERNET_ADDRESS_V6: IpAddr =
2628
IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6));
2729

2830
impl MonitorHandle {
29-
pub async fn host_is_offline(&self) -> bool {
30-
match public_ip_unreachable(&self.route_manager, self.fwmark).await {
31-
Ok(is_offline) => is_offline,
32-
Err(err) => {
31+
pub async fn connectivity(&self) -> Connectivity {
32+
public_ip_unreachable(&self.route_manager, self.fwmark)
33+
.await
34+
.unwrap_or_else(|err| {
3335
log::error!(
3436
"Failed to verify offline state: {}. Presuming connectivity",
3537
err
3638
);
37-
false
38-
}
39-
}
39+
Connectivity::PresumeOnline
40+
})
4041
}
4142
}
4243

4344
pub async fn spawn_monitor(
44-
notify_tx: UnboundedSender<bool>,
45+
notify_tx: UnboundedSender<Connectivity>,
4546
route_manager: RouteManagerHandle,
4647
fwmark: Option<u32>,
4748
) -> Result<MonitorHandle> {
@@ -71,7 +72,7 @@ pub async fn spawn_monitor(
7172
"{}",
7273
err.display_chain_with_msg("Failed to infer offline state")
7374
);
74-
false
75+
Connectivity::PresumeOnline
7576
});
7677
if new_offline_state != is_offline {
7778
is_offline = new_offline_state;
@@ -86,15 +87,20 @@ pub async fn spawn_monitor(
8687
Ok(monitor_handle)
8788
}
8889

89-
async fn public_ip_unreachable(handle: &RouteManagerHandle, fwmark: Option<u32>) -> Result<bool> {
90-
Ok(handle
91-
.get_destination_route(PUBLIC_INTERNET_ADDRESS_V4, fwmark)
92-
.await
93-
.map_err(Error::RouteManagerError)?
94-
.is_none()
95-
&& handle
96-
.get_destination_route(PUBLIC_INTERNET_ADDRESS_V6, fwmark)
90+
async fn public_ip_unreachable(
91+
handle: &RouteManagerHandle,
92+
fwmark: Option<u32>,
93+
) -> Result<Connectivity> {
94+
let route_exists = |destination| async move {
95+
handle
96+
.get_destination_route(destination, fwmark)
9797
.await
98-
.unwrap_or(None)
99-
.is_none())
98+
.map_err(Error::RouteManagerError)
99+
.map(|route| route.is_some())
100+
};
101+
let connectivity = Connectivity::Status {
102+
ipv4: route_exists(PUBLIC_INTERNET_ADDRESS_V4).await?,
103+
ipv6: route_exists(PUBLIC_INTERNET_ADDRESS_V6).await?,
104+
};
105+
Ok(connectivity)
100106
}

0 commit comments

Comments
 (0)