Make TunnelManager the point of asynchronicity
Signed-off-by: Samuel Holland <samuel@sholland.org>
This commit is contained in:
@@ -4,8 +4,6 @@ import com.wireguard.config.Config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import java9.util.concurrent.CompletionStage;
|
||||
|
||||
/**
|
||||
* Interface for persistent storage providers for WireGuard configurations.
|
||||
*/
|
||||
@@ -17,39 +15,32 @@ public interface ConfigStore {
|
||||
*
|
||||
* @param name The name of the tunnel to create.
|
||||
* @param config Configuration for the new tunnel.
|
||||
* @return A future completed when the tunnel and its configuration have been saved to
|
||||
* persistent storage. This future encapsulates the configuration that was actually saved to
|
||||
* persistent storage. This future will always be completed on the main thread.
|
||||
* @return The configuration that was actually saved to persistent storage.
|
||||
*/
|
||||
CompletionStage<Config> create(final String name, final Config config);
|
||||
Config create(final String name, final Config config) throws Exception;
|
||||
|
||||
/**
|
||||
* Delete a persistent tunnel.
|
||||
*
|
||||
* @param name The name of the tunnel to delete.
|
||||
* @return A future completed when the tunnel and its configuration have been deleted. This
|
||||
* future will always be completed on the main thread.
|
||||
*/
|
||||
CompletionStage<Void> delete(final String name);
|
||||
void delete(final String name) throws Exception;
|
||||
|
||||
/**
|
||||
* Enumerate the names of tunnels present in persistent storage.
|
||||
*
|
||||
* @return A future completed when the set of present tunnel names is available. This future
|
||||
* will always be completed on the main thread.
|
||||
* @return The set of present tunnel names.
|
||||
*/
|
||||
CompletionStage<Set<String>> enumerate();
|
||||
Set<String> enumerate() throws Exception;
|
||||
|
||||
/**
|
||||
* Load the configuration for the tunnel given by {@code name}.
|
||||
*
|
||||
* @param name The identifier for the configuration in persistent storage (i.e. the name of the
|
||||
* tunnel).
|
||||
* @return A future completed when an in-memory representation of the configuration is
|
||||
* available. This future encapsulates the configuration loaded from persistent storage. This
|
||||
* future will always be completed on the main thread.
|
||||
* @return An in-memory representation of the configuration loaded from persistent storage.
|
||||
*/
|
||||
CompletionStage<Config> load(final String name);
|
||||
Config load(final String name) throws Exception;
|
||||
|
||||
/**
|
||||
* Save the configuration for an existing tunnel given by {@code name}.
|
||||
@@ -57,9 +48,7 @@ public interface ConfigStore {
|
||||
* @param name The identifier for the configuration in persistent storage (i.e. the name of
|
||||
* the tunnel).
|
||||
* @param config An updated configuration object for the tunnel.
|
||||
* @return A future completed when the configuration has been saved to persistent storage. This
|
||||
* future encapsulates the configuration that was actually saved to persistent storage. This
|
||||
* future will always be completed on the main thread.
|
||||
* @return The configuration that was actually saved to persistent storage.
|
||||
*/
|
||||
CompletionStage<Config> save(final String name, final Config config);
|
||||
Config save(final String name, final Config config) throws Exception;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.wireguard.android.Application.ApplicationContext;
|
||||
import com.wireguard.android.util.AsyncWorker;
|
||||
import com.wireguard.config.Config;
|
||||
|
||||
import java.io.File;
|
||||
@@ -14,56 +13,48 @@ import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
|
||||
import java9.util.concurrent.CompletionStage;
|
||||
import java9.util.stream.Collectors;
|
||||
import java9.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Created by samuel on 12/28/17.
|
||||
* Configuration store that uses a {@code wg-quick}-style file for each configured tunnel.
|
||||
*/
|
||||
|
||||
public final class FileConfigStore implements ConfigStore {
|
||||
private static final String TAG = FileConfigStore.class.getSimpleName();
|
||||
|
||||
private final AsyncWorker asyncWorker;
|
||||
private final Context context;
|
||||
|
||||
public FileConfigStore(final AsyncWorker asyncWorker,
|
||||
@ApplicationContext final Context context) {
|
||||
this.asyncWorker = asyncWorker;
|
||||
public FileConfigStore(@ApplicationContext final Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Config> create(final String name, final Config config) {
|
||||
return asyncWorker.supplyAsync(() -> {
|
||||
final File file = fileFor(name);
|
||||
if (!file.createNewFile()) {
|
||||
final String message = "Configuration file " + file.getName() + " already exists";
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
try (FileOutputStream stream = new FileOutputStream(file, false)) {
|
||||
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
||||
return config;
|
||||
}
|
||||
});
|
||||
public Config create(final String name, final Config config) throws IOException {
|
||||
final File file = fileFor(name);
|
||||
if (!file.createNewFile()) {
|
||||
final String message = "Configuration file " + file.getName() + " already exists";
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
try (FileOutputStream stream = new FileOutputStream(file, false)) {
|
||||
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Void> delete(final String name) {
|
||||
return asyncWorker.runAsync(() -> {
|
||||
final File file = fileFor(name);
|
||||
if (!file.delete())
|
||||
throw new IOException("Cannot delete configuration file " + file.getName());
|
||||
});
|
||||
public void delete(final String name) throws IOException {
|
||||
final File file = fileFor(name);
|
||||
if (!file.delete())
|
||||
throw new IOException("Cannot delete configuration file " + file.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Set<String>> enumerate() {
|
||||
return asyncWorker.supplyAsync(() -> Stream.of(context.fileList())
|
||||
public Set<String> enumerate() {
|
||||
return Stream.of(context.fileList())
|
||||
.filter(name -> name.endsWith(".conf"))
|
||||
.map(name -> name.substring(0, name.length() - ".conf".length()))
|
||||
.collect(Collectors.toUnmodifiableSet()));
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
}
|
||||
|
||||
private File fileFor(final String name) {
|
||||
@@ -71,28 +62,23 @@ public final class FileConfigStore implements ConfigStore {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Config> load(final String name) {
|
||||
return asyncWorker.supplyAsync(() -> {
|
||||
try (FileInputStream stream = new FileInputStream(fileFor(name))) {
|
||||
return Config.from(stream);
|
||||
}
|
||||
});
|
||||
public Config load(final String name) throws IOException {
|
||||
try (FileInputStream stream = new FileInputStream(fileFor(name))) {
|
||||
return Config.from(stream);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletionStage<Config> save(final String name, final Config config) {
|
||||
public Config save(final String name, final Config config) throws IOException {
|
||||
Log.d(TAG, "Requested save config for tunnel " + name);
|
||||
return asyncWorker.supplyAsync(() -> {
|
||||
final File file = fileFor(name);
|
||||
if (!file.isFile()) {
|
||||
final String message = "Configuration file " + file.getName() + " not found";
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
try (FileOutputStream stream = new FileOutputStream(file, false)) {
|
||||
Log.d(TAG, "Writing out config for tunnel " + name);
|
||||
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
||||
return config;
|
||||
}
|
||||
});
|
||||
final File file = fileFor(name);
|
||||
if (!file.isFile()) {
|
||||
final String message = "Configuration file " + file.getName() + " not found";
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
try (FileOutputStream stream = new FileOutputStream(file, false)) {
|
||||
stream.write(config.toString().getBytes(StandardCharsets.UTF_8));
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user