summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java38
-rw-r--r--ui/src/main/java/com/wireguard/android/Application.java20
-rw-r--r--ui/src/main/java/com/wireguard/android/activity/SettingsActivity.java3
-rw-r--r--ui/src/main/res/values/strings.xml3
-rw-r--r--ui/src/main/res/xml/preferences.xml6
5 files changed, 64 insertions, 6 deletions
diff --git a/tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java b/tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java
index 9695aab7..53fe3d42 100644
--- a/tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java
+++ b/tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java
@@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
import android.content.Context;
import android.util.Log;
+import android.util.Pair;
import com.wireguard.android.backend.BackendException.Reason;
import com.wireguard.android.backend.Tunnel.State;
@@ -23,6 +24,7 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -44,6 +46,7 @@ public final class WgQuickBackend implements Backend {
private final ToolsInstaller toolsInstaller;
private final File localTemporaryDir;
private final Map<Tunnel, Config> runningConfigs = new HashMap<>();
+ private boolean multipleTunnels;
public WgQuickBackend(final Context context, final RootShell rootShell, final ToolsInstaller toolsInstaller) {
localTemporaryDir = new File(context.getCacheDir(), "tmp");
@@ -51,6 +54,10 @@ public final class WgQuickBackend implements Backend {
this.toolsInstaller = toolsInstaller;
}
+ public void setMultipleTunnels(boolean on) {
+ multipleTunnels = on;
+ }
+
@Override
public Set<String> getRunningTunnelNames() {
final List<String> output = new ArrayList<>();
@@ -106,6 +113,7 @@ public final class WgQuickBackend implements Backend {
public State setState(final Tunnel tunnel, State state, @Nullable final Config config) throws Exception {
final State originalState = getState(tunnel);
final Config originalConfig = runningConfigs.get(tunnel);
+ final Map<Tunnel, Config> runningConfigsSnapshot = new HashMap<>(runningConfigs);
if (state == State.TOGGLE)
state = originalState == State.UP ? State.DOWN : State.UP;
@@ -114,13 +122,37 @@ public final class WgQuickBackend implements Backend {
return originalState;
if (state == State.UP) {
toolsInstaller.ensureToolsAvailable();
+ if (!multipleTunnels && originalState == State.DOWN) {
+ final List<Pair<Tunnel, Config>> rewind = new LinkedList<>();
+ try {
+ for (final Map.Entry<Tunnel, Config> entry : runningConfigsSnapshot.entrySet()) {
+ setStateInternal(entry.getKey(), entry.getValue(), State.DOWN);
+ rewind.add(Pair.create(entry.getKey(), entry.getValue()));
+ }
+ } catch (final Exception e) {
+ try {
+ for (final Pair<Tunnel, Config> entry : rewind) {
+ setStateInternal(entry.first, entry.second, State.UP);
+ }
+ } catch (final Exception ignored) { }
+ throw e;
+ }
+ }
if (originalState == State.UP)
setStateInternal(tunnel, originalConfig == null ? config : originalConfig, State.DOWN);
try {
setStateInternal(tunnel, config, State.UP);
- } catch(final Exception e) {
- if (originalState == State.UP && originalConfig != null)
- setStateInternal(tunnel, originalConfig, State.UP);
+ } catch (final Exception e) {
+ try {
+ if (originalState == State.UP && originalConfig != null) {
+ setStateInternal(tunnel, originalConfig, State.UP);
+ }
+ if (!multipleTunnels && originalState == State.DOWN) {
+ for (final Map.Entry<Tunnel, Config> entry : runningConfigsSnapshot.entrySet()) {
+ setStateInternal(entry.getKey(), entry.getValue(), State.UP);
+ }
+ }
+ } catch (final Exception ignored) { }
throw e;
}
} else if (state == State.DOWN) {
diff --git a/ui/src/main/java/com/wireguard/android/Application.java b/ui/src/main/java/com/wireguard/android/Application.java
index 2ebeb69d..655c6b21 100644
--- a/ui/src/main/java/com/wireguard/android/Application.java
+++ b/ui/src/main/java/com/wireguard/android/Application.java
@@ -35,7 +35,7 @@ import java.util.Locale;
import java9.util.concurrent.CompletableFuture;
-public class Application extends android.app.Application {
+public class Application extends android.app.Application implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = "WireGuard/" + Application.class.getSimpleName();
public static final String USER_AGENT;
@@ -86,7 +86,9 @@ public class Application extends android.app.Application {
try {
if (!didStartRootShell)
app.rootShell.start();
- backend = new WgQuickBackend(app.getApplicationContext(), app.rootShell, app.toolsInstaller);
+ WgQuickBackend wgQuickBackend = new WgQuickBackend(app.getApplicationContext(), app.rootShell, app.toolsInstaller);
+ wgQuickBackend.setMultipleTunnels(app.sharedPreferences.getBoolean("multiple_tunnels", false));
+ backend = wgQuickBackend;
} catch (final Exception ignored) {
}
}
@@ -167,5 +169,19 @@ public class Application extends android.app.Application {
tunnelManager.onCreate();
asyncWorker.supplyAsync(Application::getBackend).thenAccept(futureBackend::complete);
+
+ sharedPreferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onTerminate() {
+ sharedPreferences.unregisterOnSharedPreferenceChangeListener(this);
+ super.onTerminate();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(final SharedPreferences sharedPreferences, final String key) {
+ if ("multiple_tunnels".equals(key) && backend != null && backend instanceof WgQuickBackend)
+ ((WgQuickBackend)backend).setMultipleTunnels(sharedPreferences.getBoolean(key, false));
}
}
diff --git a/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.java b/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.java
index f545c371..b597a9b1 100644
--- a/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.java
+++ b/ui/src/main/java/com/wireguard/android/activity/SettingsActivity.java
@@ -99,7 +99,8 @@ public class SettingsActivity extends ThemeChangeAwareActivity {
final Preference wgQuickOnlyPrefs[] = {
getPreferenceManager().findPreference("tools_installer"),
- getPreferenceManager().findPreference("restore_on_boot")
+ getPreferenceManager().findPreference("restore_on_boot"),
+ getPreferenceManager().findPreference("multiple_tunnels")
};
for (final Preference pref : wgQuickOnlyPrefs)
pref.setVisible(false);
diff --git a/ui/src/main/res/values/strings.xml b/ui/src/main/res/values/strings.xml
index 45964eec..5df74017 100644
--- a/ui/src/main/res/values/strings.xml
+++ b/ui/src/main/res/values/strings.xml
@@ -104,6 +104,9 @@
<string name="module_installer_working">Downloading and installing…</string>
<string name="module_installer_error">Something went wrong. Please try again</string>
<string name="mtu">MTU</string>
+ <string name="multiple_tunnels_title">Allow multiple simultaneous tunnels</string>
+ <string name="multiple_tunnels_summary_on">Multiple tunnels may be turned on simultaneously</string>
+ <string name="multiple_tunnels_summary_off">Turning on one tunnel will turn off others</string>
<string name="name">Name</string>
<string name="no_config_error">Trying to bring up a tunnel with no config</string>
<string name="no_configs_error">No configurations found</string>
diff --git a/ui/src/main/res/xml/preferences.xml b/ui/src/main/res/xml/preferences.xml
index 9c09ae89..6899edce 100644
--- a/ui/src/main/res/xml/preferences.xml
+++ b/ui/src/main/res/xml/preferences.xml
@@ -8,6 +8,12 @@
android:title="@string/restore_on_boot_title" />
<com.wireguard.android.preference.ModuleDownloaderPreference android:key="module_downloader" />
<com.wireguard.android.preference.ToolsInstallerPreference android:key="tools_installer" />
+ <CheckBoxPreference
+ android:defaultValue="false"
+ android:key="multiple_tunnels"
+ android:summaryOff="@string/multiple_tunnels_summary_off"
+ android:summaryOn="@string/multiple_tunnels_summary_on"
+ android:title="@string/multiple_tunnels_title" />
<com.wireguard.android.preference.ZipExporterPreference />
<com.wireguard.android.preference.LogExporterPreference />
<CheckBoxPreference