From 680fe07b6ea000ee29ac28e2f48665433e7011df Mon Sep 17 00:00:00 2001 From: pacien Date: Wed, 14 Feb 2018 01:25:48 +0100 Subject: Properly get daemon state --- app/src/main/c/exec.c | 6 ++++++ .../main/java/org/pacien/tincapp/commands/Executor.kt | 17 ++++++++++++++--- app/src/main/java/org/pacien/tincapp/commands/Tincd.kt | 3 +-- .../java/org/pacien/tincapp/service/TincVpnService.kt | 17 ++++++++++------- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/app/src/main/c/exec.c b/app/src/main/c/exec.c index a9871a5..d665341 100644 --- a/app/src/main/c/exec.c +++ b/app/src/main/c/exec.c @@ -1,6 +1,7 @@ #include #include #include +#include static inline const char **to_string_array(JNIEnv *env, jobjectArray ja) { const int len = (*env)->GetArrayLength(env, ja); @@ -32,3 +33,8 @@ Java_org_pacien_tincapp_commands_Executor_forkExec(JNIEnv *env, jclass class, jo return pid; } } + +JNIEXPORT jint JNICALL +Java_org_pacien_tincapp_commands_Executor_wait(JNIEnv *env, jclass class, jint pid) { + return waitpid(pid, NULL, 0); +} diff --git a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt index eace2e7..a3b5cea 100644 --- a/app/src/main/java/org/pacien/tincapp/commands/Executor.kt +++ b/app/src/main/java/org/pacien/tincapp/commands/Executor.kt @@ -13,6 +13,8 @@ import java.io.InputStreamReader */ internal object Executor { + private const val FAILED = -1 + class CommandExecutionException(msg: String) : Exception(msg) init { @@ -20,14 +22,23 @@ internal object Executor { } /** - * @return -1 on error, forked child PID otherwise + * @return FAILED (-1) on error, forked child PID otherwise */ private external fun forkExec(argcv: Array): Int + /** + * @return FAILED (-1) on error, 0 on no-op, the supplied PID otherwise + */ + private external fun wait(pid: Int): Int + private fun read(stream: InputStream) = BufferedReader(InputStreamReader(stream)).readLines() - fun forkExec(cmd: Command) { - if (forkExec(cmd.asArray()) == -1) throw CommandExecutionException("Could not fork child process.") + fun forkExec(cmd: Command): CompletableFuture { + val pid = forkExec(cmd.asArray()) + return when (pid) { + FAILED -> CompletableFuture.failedFuture(CommandExecutionException("Could not fork child process.")) + else -> CompletableFuture.runAsync { wait(pid) } + } } fun call(cmd: Command): CompletableFuture> { diff --git a/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt b/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt index d9c665d..44fcef5 100644 --- a/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt +++ b/app/src/main/java/org/pacien/tincapp/commands/Tincd.kt @@ -7,7 +7,7 @@ import org.pacien.tincapp.context.AppPaths */ object Tincd { - fun start(netName: String, deviceFd: Int, ed25519PrivateKeyFd: Int? = null, rsaPrivateKeyFd: Int? = null) { + fun start(netName: String, deviceFd: Int, ed25519PrivateKeyFd: Int? = null, rsaPrivateKeyFd: Int? = null) = Executor.forkExec(Command(AppPaths.tincd().absolutePath) .withOption("no-detach") .withOption("config", AppPaths.confDir(netName).absolutePath) @@ -17,6 +17,5 @@ object Tincd { .withOption("option", "Device=" + deviceFd) .apply { if (ed25519PrivateKeyFd != null) withOption("option", "Ed25519PrivateKeyFile=/proc/self/fd/$ed25519PrivateKeyFd") } .apply { if (rsaPrivateKeyFd != null) withOption("option", "PrivateKeyFile=/proc/self/fd/$rsaPrivateKeyFd") }) - } } diff --git a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt index 278d20a..ec0512a 100644 --- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt +++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt @@ -6,6 +6,7 @@ import android.net.Uri import android.net.VpnService import android.os.ParcelFileDescriptor import android.util.Log +import java8.util.concurrent.CompletableFuture import org.apache.commons.configuration2.ex.ConversionException import org.bouncycastle.openssl.PEMException import org.pacien.tincapp.BuildConfig @@ -82,8 +83,8 @@ class TincVpnService : VpnService() { return reportError(resources.getString(R.string.message_could_not_decrypt_private_keys_format, e.message)) } - Tincd.start(netName, deviceFd!!.fd, privateKeys.first?.fd, privateKeys.second?.fd) - setState(true, netName, interfaceCfg, deviceFd) + val daemon = Tincd.start(netName, deviceFd!!.fd, privateKeys.first?.fd, privateKeys.second?.fd) + setState(netName, interfaceCfg, deviceFd, daemon) Log.i(TAG, "tinc daemon started.") } @@ -111,16 +112,17 @@ class TincVpnService : VpnService() { val TAG = this::class.java.canonicalName!! - private var connected: Boolean = false private var netName: String? = null private var interfaceCfg: VpnInterfaceConfiguration? = null private var fd: ParcelFileDescriptor? = null + private var daemon: CompletableFuture? = null - private fun setState(connected: Boolean, netName: String?, interfaceCfg: VpnInterfaceConfiguration?, fd: ParcelFileDescriptor?) { - TincVpnService.connected = connected + private fun setState(netName: String?, interfaceCfg: VpnInterfaceConfiguration?, + fd: ParcelFileDescriptor?, daemon: CompletableFuture?) { TincVpnService.netName = netName TincVpnService.interfaceCfg = interfaceCfg TincVpnService.fd = fd + TincVpnService.daemon = daemon } fun startVpn(netName: String, passphrase: String? = null) { @@ -132,18 +134,19 @@ class TincVpnService : VpnService() { try { Log.i(TAG, "Stopping any running tinc daemon.") if (netName != null) Tinc.stop(netName!!) + daemon?.get() fd?.close() Log.i(TAG, "All tinc daemons stopped.") } catch (e: IOException) { Log.wtf(TAG, e) } finally { - setState(false, null, null, null) + setState(null, null, null, null) } } fun getCurrentNetName() = netName fun getCurrentInterfaceCfg() = interfaceCfg - fun isConnected() = connected + fun isConnected() = !(daemon?.isDone ?: true) } -- cgit v1.2.3