diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-09 10:01:54 -0600 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-03-09 10:02:00 -0600 |
commit | d62526fde6566b6a51ccc2a3f2095ea6d6584fd6 (patch) | |
tree | 9fc4c71fb0e87066bfe54b957d6ba3d756f87bee /tunnel/src/main/java/com/wireguard | |
parent | 134f9c014e08e07eab65ff80b00f9ff5d1f36957 (diff) |
WgQuickBackend: by default use single-tunnel mode like GoBackend, but add option
Note that this currently doesn't play well with people activating
wg-quick tunnels from outside the app. Those tunnels won't be
deactivated. But presumably that's desired behavior anyway, considering
people are mucking around at the command line.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'tunnel/src/main/java/com/wireguard')
-rw-r--r-- | tunnel/src/main/java/com/wireguard/android/backend/WgQuickBackend.java | 38 |
1 files changed, 35 insertions, 3 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) { |