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>
This commit is contained in:
parent
134f9c014e
commit
d62526fde6
@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.wireguard.android.backend.BackendException.Reason;
|
import com.wireguard.android.backend.BackendException.Reason;
|
||||||
import com.wireguard.android.backend.Tunnel.State;
|
import com.wireguard.android.backend.Tunnel.State;
|
||||||
@ -23,6 +24,7 @@ import java.nio.charset.StandardCharsets;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -44,6 +46,7 @@ public final class WgQuickBackend implements Backend {
|
|||||||
private final ToolsInstaller toolsInstaller;
|
private final ToolsInstaller toolsInstaller;
|
||||||
private final File localTemporaryDir;
|
private final File localTemporaryDir;
|
||||||
private final Map<Tunnel, Config> runningConfigs = new HashMap<>();
|
private final Map<Tunnel, Config> runningConfigs = new HashMap<>();
|
||||||
|
private boolean multipleTunnels;
|
||||||
|
|
||||||
public WgQuickBackend(final Context context, final RootShell rootShell, final ToolsInstaller toolsInstaller) {
|
public WgQuickBackend(final Context context, final RootShell rootShell, final ToolsInstaller toolsInstaller) {
|
||||||
localTemporaryDir = new File(context.getCacheDir(), "tmp");
|
localTemporaryDir = new File(context.getCacheDir(), "tmp");
|
||||||
@ -51,6 +54,10 @@ public final class WgQuickBackend implements Backend {
|
|||||||
this.toolsInstaller = toolsInstaller;
|
this.toolsInstaller = toolsInstaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMultipleTunnels(boolean on) {
|
||||||
|
multipleTunnels = on;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getRunningTunnelNames() {
|
public Set<String> getRunningTunnelNames() {
|
||||||
final List<String> output = new ArrayList<>();
|
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 {
|
public State setState(final Tunnel tunnel, State state, @Nullable final Config config) throws Exception {
|
||||||
final State originalState = getState(tunnel);
|
final State originalState = getState(tunnel);
|
||||||
final Config originalConfig = runningConfigs.get(tunnel);
|
final Config originalConfig = runningConfigs.get(tunnel);
|
||||||
|
final Map<Tunnel, Config> runningConfigsSnapshot = new HashMap<>(runningConfigs);
|
||||||
|
|
||||||
if (state == State.TOGGLE)
|
if (state == State.TOGGLE)
|
||||||
state = originalState == State.UP ? State.DOWN : State.UP;
|
state = originalState == State.UP ? State.DOWN : State.UP;
|
||||||
@ -114,13 +122,37 @@ public final class WgQuickBackend implements Backend {
|
|||||||
return originalState;
|
return originalState;
|
||||||
if (state == State.UP) {
|
if (state == State.UP) {
|
||||||
toolsInstaller.ensureToolsAvailable();
|
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)
|
if (originalState == State.UP)
|
||||||
setStateInternal(tunnel, originalConfig == null ? config : originalConfig, State.DOWN);
|
setStateInternal(tunnel, originalConfig == null ? config : originalConfig, State.DOWN);
|
||||||
try {
|
try {
|
||||||
setStateInternal(tunnel, config, State.UP);
|
setStateInternal(tunnel, config, State.UP);
|
||||||
} catch(final Exception e) {
|
} catch (final Exception e) {
|
||||||
if (originalState == State.UP && originalConfig != null)
|
try {
|
||||||
|
if (originalState == State.UP && originalConfig != null) {
|
||||||
setStateInternal(tunnel, originalConfig, State.UP);
|
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;
|
throw e;
|
||||||
}
|
}
|
||||||
} else if (state == State.DOWN) {
|
} else if (state == State.DOWN) {
|
||||||
|
@ -35,7 +35,7 @@ import java.util.Locale;
|
|||||||
|
|
||||||
import java9.util.concurrent.CompletableFuture;
|
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();
|
private static final String TAG = "WireGuard/" + Application.class.getSimpleName();
|
||||||
public static final String USER_AGENT;
|
public static final String USER_AGENT;
|
||||||
|
|
||||||
@ -86,7 +86,9 @@ public class Application extends android.app.Application {
|
|||||||
try {
|
try {
|
||||||
if (!didStartRootShell)
|
if (!didStartRootShell)
|
||||||
app.rootShell.start();
|
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) {
|
} catch (final Exception ignored) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,5 +169,19 @@ public class Application extends android.app.Application {
|
|||||||
tunnelManager.onCreate();
|
tunnelManager.onCreate();
|
||||||
|
|
||||||
asyncWorker.supplyAsync(Application::getBackend).thenAccept(futureBackend::complete);
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,8 @@ public class SettingsActivity extends ThemeChangeAwareActivity {
|
|||||||
|
|
||||||
final Preference wgQuickOnlyPrefs[] = {
|
final Preference wgQuickOnlyPrefs[] = {
|
||||||
getPreferenceManager().findPreference("tools_installer"),
|
getPreferenceManager().findPreference("tools_installer"),
|
||||||
getPreferenceManager().findPreference("restore_on_boot")
|
getPreferenceManager().findPreference("restore_on_boot"),
|
||||||
|
getPreferenceManager().findPreference("multiple_tunnels")
|
||||||
};
|
};
|
||||||
for (final Preference pref : wgQuickOnlyPrefs)
|
for (final Preference pref : wgQuickOnlyPrefs)
|
||||||
pref.setVisible(false);
|
pref.setVisible(false);
|
||||||
|
@ -104,6 +104,9 @@
|
|||||||
<string name="module_installer_working">Downloading and installing…</string>
|
<string name="module_installer_working">Downloading and installing…</string>
|
||||||
<string name="module_installer_error">Something went wrong. Please try again</string>
|
<string name="module_installer_error">Something went wrong. Please try again</string>
|
||||||
<string name="mtu">MTU</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="name">Name</string>
|
||||||
<string name="no_config_error">Trying to bring up a tunnel with no config</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>
|
<string name="no_configs_error">No configurations found</string>
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
android:title="@string/restore_on_boot_title" />
|
android:title="@string/restore_on_boot_title" />
|
||||||
<com.wireguard.android.preference.ModuleDownloaderPreference android:key="module_downloader" />
|
<com.wireguard.android.preference.ModuleDownloaderPreference android:key="module_downloader" />
|
||||||
<com.wireguard.android.preference.ToolsInstallerPreference android:key="tools_installer" />
|
<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.ZipExporterPreference />
|
||||||
<com.wireguard.android.preference.LogExporterPreference />
|
<com.wireguard.android.preference.LogExporterPreference />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
|
Loading…
Reference in New Issue
Block a user