Skip to content

Commit 5feceae

Browse files
Merge branch 'reconnect-on-split-tunnel-change'
2 parents a946419 + 5c9d6fc commit 5feceae

File tree

9 files changed

+85
-21
lines changed

9 files changed

+85
-21
lines changed

mullvad-management-interface/src/types/conversions/states.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,11 @@ impl From<mullvad_types::states::TunnelState> for proto::TunnelState {
107107
talpid_tunnel::ErrorStateCause::InvalidDnsServers(_) => {
108108
i32::from(Cause::SetDnsError)
109109
}
110-
#[cfg(any(target_os = "windows", target_os = "macos"))]
110+
#[cfg(any(
111+
target_os = "windows",
112+
target_os = "macos",
113+
target_os = "android"
114+
))]
111115
talpid_tunnel::ErrorStateCause::SplitTunnelError => {
112116
i32::from(Cause::SplitTunnelError)
113117
}

talpid-core/src/tunnel_state_machine/connected_state.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,31 @@ impl ConnectedState {
330330
shared_values.bypass_socket(fd, done_tx);
331331
SameState(self)
332332
}
333-
#[cfg(any(windows, target_os = "android"))]
333+
#[cfg(windows)]
334334
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
335335
shared_values.exclude_paths(paths, result_tx);
336336
SameState(self)
337337
}
338+
#[cfg(target_os = "android")]
339+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
340+
match shared_values.exclude_paths(paths) {
341+
Ok(changed) => {
342+
let _ = result_tx.send(Ok(()));
343+
if changed {
344+
self.disconnect(shared_values, AfterDisconnect::Reconnect(0))
345+
} else {
346+
SameState(self)
347+
}
348+
}
349+
Err(err) => {
350+
let _ = result_tx.send(Err(err));
351+
self.disconnect(
352+
shared_values,
353+
AfterDisconnect::Block(ErrorStateCause::SplitTunnelError),
354+
)
355+
}
356+
}
357+
}
338358
#[cfg(target_os = "macos")]
339359
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
340360
match shared_values.set_exclude_paths(paths) {

talpid-core/src/tunnel_state_machine/connecting_state.rs

+17-1
Original file line numberDiff line numberDiff line change
@@ -470,11 +470,27 @@ impl ConnectingState {
470470
shared_values.bypass_socket(fd, done_tx);
471471
SameState(self)
472472
}
473-
#[cfg(any(windows, target_os = "android"))]
473+
#[cfg(windows)]
474474
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
475475
shared_values.exclude_paths(paths, result_tx);
476476
SameState(self)
477477
}
478+
#[cfg(target_os = "android")]
479+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
480+
match shared_values.exclude_paths(paths) {
481+
Ok(_changed) => {
482+
let _ = result_tx.send(Ok(()));
483+
SameState(self)
484+
}
485+
Err(error) => {
486+
let _ = result_tx.send(Err(error));
487+
self.disconnect(
488+
shared_values,
489+
AfterDisconnect::Block(ErrorStateCause::SplitTunnelError),
490+
)
491+
}
492+
}
493+
}
478494
#[cfg(target_os = "macos")]
479495
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
480496
match shared_values.set_exclude_paths(paths) {

talpid-core/src/tunnel_state_machine/disconnected_state.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,16 @@ impl TunnelState for DisconnectedState {
211211
shared_values.bypass_socket(fd, done_tx);
212212
SameState(self)
213213
}
214-
#[cfg(any(windows, target_os = "android"))]
214+
#[cfg(windows)]
215215
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
216216
shared_values.exclude_paths(paths, result_tx);
217217
SameState(self)
218218
}
219+
#[cfg(target_os = "android")]
220+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
221+
let _ = result_tx.send(shared_values.exclude_paths(paths).map(|_| ()));
222+
SameState(self)
223+
}
219224
#[cfg(target_os = "macos")]
220225
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
221226
let _ = result_tx.send(shared_values.set_exclude_paths(paths).map(|_| ()));

talpid-core/src/tunnel_state_machine/disconnecting_state.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,16 @@ impl DisconnectingState {
7676
shared_values.bypass_socket(fd, done_tx);
7777
AfterDisconnect::Nothing
7878
}
79-
#[cfg(any(windows, target_os = "android"))]
79+
#[cfg(windows)]
8080
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
8181
shared_values.exclude_paths(paths, result_tx);
8282
AfterDisconnect::Nothing
8383
}
84+
#[cfg(target_os = "android")]
85+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
86+
let _ = result_tx.send(shared_values.exclude_paths(paths).map(|_| ()));
87+
AfterDisconnect::Nothing
88+
}
8489
#[cfg(target_os = "macos")]
8590
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
8691
let _ = result_tx.send(shared_values.set_exclude_paths(paths).map(|_| ()));
@@ -127,11 +132,16 @@ impl DisconnectingState {
127132
shared_values.bypass_socket(fd, done_tx);
128133
AfterDisconnect::Block(reason)
129134
}
130-
#[cfg(any(windows, target_os = "android"))]
135+
#[cfg(windows)]
131136
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
132137
shared_values.exclude_paths(paths, result_tx);
133138
AfterDisconnect::Block(reason)
134139
}
140+
#[cfg(target_os = "android")]
141+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
142+
let _ = result_tx.send(shared_values.exclude_paths(paths).map(|_| ()));
143+
AfterDisconnect::Block(reason)
144+
}
135145
#[cfg(target_os = "macos")]
136146
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
137147
let _ = result_tx.send(shared_values.set_exclude_paths(paths).map(|_| ()));
@@ -179,11 +189,16 @@ impl DisconnectingState {
179189
shared_values.bypass_socket(fd, done_tx);
180190
AfterDisconnect::Reconnect(retry_attempt)
181191
}
182-
#[cfg(any(windows, target_os = "android"))]
192+
#[cfg(windows)]
183193
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
184194
shared_values.exclude_paths(paths, result_tx);
185195
AfterDisconnect::Reconnect(retry_attempt)
186196
}
197+
#[cfg(target_os = "android")]
198+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
199+
let _ = result_tx.send(shared_values.exclude_paths(paths).map(|_| ()));
200+
AfterDisconnect::Reconnect(retry_attempt)
201+
}
187202
#[cfg(target_os = "macos")]
188203
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
189204
let _ = result_tx.send(shared_values.set_exclude_paths(paths).map(|_| ()));

talpid-core/src/tunnel_state_machine/error_state.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,12 @@ impl TunnelState for ErrorState {
211211
shared_values.bypass_socket(fd, done_tx);
212212
SameState(self)
213213
}
214-
#[cfg(any(windows, target_os = "android"))]
214+
#[cfg(target_os = "android")]
215+
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
216+
let _ = result_tx.send(shared_values.exclude_paths(paths).map(|_| ()));
217+
SameState(self)
218+
}
219+
#[cfg(windows)]
215220
Some(TunnelCommand::SetExcludedApps(result_tx, paths)) => {
216221
shared_values.exclude_paths(paths, result_tx);
217222
SameState(self)

talpid-core/src/tunnel_state_machine/mod.rs

+9-10
Original file line numberDiff line numberDiff line change
@@ -651,14 +651,10 @@ impl SharedTunnelStateValues {
651651
}
652652

653653
/// Update the set of excluded paths (split tunnel apps) for the tunnel provider.
654+
/// Returns `Ok(true)` if the tunnel state machine should issue a tunnel reconnect.
654655
#[cfg(target_os = "android")]
655-
pub fn exclude_paths(
656-
&mut self,
657-
apps: Vec<String>,
658-
tx: oneshot::Sender<Result<(), split_tunnel::Error>>,
659-
) {
660-
let exclude_apps_result = self
661-
.tun_provider
656+
pub fn exclude_paths(&mut self, apps: Vec<String>) -> Result<bool, split_tunnel::Error> {
657+
self.tun_provider
662658
.lock()
663659
.unwrap()
664660
.set_exclude_apps(apps)
@@ -670,9 +666,12 @@ impl SharedTunnelStateValues {
670666
"Failed to restart tunnel after updating excluded apps",
671667
)
672668
);
673-
});
674-
675-
let _ = tx.send(exclude_apps_result);
669+
})?;
670+
// NOTE: For now, we tell the TSM to always reconnect when this function has been
671+
// successfully called. We still return a boolean value in case we would like to introduce
672+
// some condition in the future, thus forcing the TSM to be ready to handle both cases
673+
// already.
674+
Ok(true)
676675
}
677676
}
678677

talpid-tunnel/src/tun_provider/android/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ impl AndroidTunProvider {
299299
}
300300

301301
fn prepare_tun_config_for_excluded_apps(&self, config: &mut TunConfig) {
302-
config.excluded_packages = self.excluded_apps.clone();
302+
config.excluded_packages.clone_from(&self.excluded_apps);
303303
}
304304

305305
/// Allow a socket to bypass the tunnel.

talpid-types/src/tunnel.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub enum ErrorStateCause {
9696
#[cfg(target_os = "android")]
9797
VpnPermissionDenied,
9898
/// Error reported by split tunnel module.
99-
#[cfg(any(target_os = "windows", target_os = "macos"))]
99+
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "android"))]
100100
SplitTunnelError,
101101
/// Missing permissions required by macOS split tunneling.
102102
#[cfg(target_os = "macos")]
@@ -202,7 +202,7 @@ impl fmt::Display for ErrorStateCause {
202202
IsOffline => "This device is offline, no tunnels can be established",
203203
#[cfg(target_os = "android")]
204204
VpnPermissionDenied => "The Android VPN permission was denied when creating the tunnel",
205-
#[cfg(any(target_os = "windows", target_os = "macos"))]
205+
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "android"))]
206206
SplitTunnelError => "The split tunneling module reported an error",
207207
#[cfg(target_os = "macos")]
208208
NeedFullDiskPermissions => "Need full disk access to enable split tunneling",

0 commit comments

Comments
 (0)