summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAurélien Chabot <aurelien@chabot.fr>2018-04-15 12:03:42 +1000
committerJason A. Donenfeld <Jason@zx2c4.com>2018-04-17 02:15:24 +0200
commit4c9143c83506a0cdbaf48f588222fa593b59e491 (patch)
tree584acd2ec5e134d7ce7340026683c10d988bbd4f
parent74eae55c878e031fa25971378abf0cadee7bbaaa (diff)
GoBackend: Handle vpn service expiration
After a timeout the android system is destroying the vpn service when it is not used. By using a completable future we can wait for the service to be relaunch on demand. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--app/src/main/java/com/wireguard/android/backend/GoBackend.java30
1 files changed, 22 insertions, 8 deletions
diff --git a/app/src/main/java/com/wireguard/android/backend/GoBackend.java b/app/src/main/java/com/wireguard/android/backend/GoBackend.java
index a8ee6e53..6467ba2c 100644
--- a/app/src/main/java/com/wireguard/android/backend/GoBackend.java
+++ b/app/src/main/java/com/wireguard/android/backend/GoBackend.java
@@ -22,6 +22,10 @@ import java.util.Collections;
import java.util.Formatter;
import java.util.Set;
import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import java9.util.concurrent.CompletableFuture;
public final class GoBackend implements Backend {
private static final String TAG = "WireGuard/" + GoBackend.class.getSimpleName();
@@ -37,20 +41,23 @@ public final class GoBackend implements Backend {
public GoBackend(Context context) {
this.context = context;
+ }
+
+ public void startVpnService() {
context.startService(new Intent(context, VpnService.class));
}
public static class VpnService extends android.net.VpnService {
@Override
public void onCreate() {
+ vpnService.complete(this);
super.onCreate();
- vpnService = this;
}
@Override
public void onDestroy() {
+ vpnService = vpnService.newIncompleteFuture();
super.onDestroy();
- vpnService = null;
}
public Builder getBuilder() {
@@ -58,7 +65,7 @@ public final class GoBackend implements Backend {
}
}
- private static VpnService vpnService = null;
+ private static CompletableFuture<VpnService> vpnService = new CompletableFuture<>();
private static native int wgGetSocketV4(int handle);
@@ -181,8 +188,15 @@ public final class GoBackend implements Backend {
if (VpnService.prepare(context) != null)
throw new Exception("VPN service not authorized by user");
- if (vpnService == null)
- throw new Exception("Android VPN service is not running");
+ VpnService service;
+ if (!vpnService.isDone())
+ startVpnService();
+
+ try {
+ service = vpnService.get(2, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new Exception("Unable to start Android VPN service");
+ }
if (currentTunnelHandle != -1) {
Log.w(TAG, "Tunnel already up");
@@ -215,7 +229,7 @@ public final class GoBackend implements Backend {
}
// Create the vpn tunnel with android API
- VpnService.Builder builder = vpnService.getBuilder();
+ VpnService.Builder builder = service.getBuilder();
builder.setSession(tunnel.getName());
for (final String addressString : config.getInterface().getAddress().split(" *, *")) {
@@ -248,8 +262,8 @@ public final class GoBackend implements Backend {
currentTunnel = tunnel;
- vpnService.protect(wgGetSocketV4(currentTunnelHandle));
- vpnService.protect(wgGetSocketV6(currentTunnelHandle));
+ service.protect(wgGetSocketV4(currentTunnelHandle));
+ service.protect(wgGetSocketV6(currentTunnelHandle));
} else {
Log.i(TAG, "Bringing tunnel down");