diff options
Diffstat (limited to 'app/src')
-rw-r--r-- | app/src/main/c/exec.c | 6 | ||||
-rw-r--r-- | app/src/main/java/org/pacien/tincapp/commands/Executor.kt | 17 | ||||
-rw-r--r-- | app/src/main/java/org/pacien/tincapp/commands/Tincd.kt | 3 | ||||
-rw-r--r-- | app/src/main/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 @@ | |||
1 | #include <jni.h> | 1 | #include <jni.h> |
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <sys/wait.h> | ||
4 | 5 | ||
5 | static inline const char **to_string_array(JNIEnv *env, jobjectArray ja) { | 6 | static inline const char **to_string_array(JNIEnv *env, jobjectArray ja) { |
6 | const int len = (*env)->GetArrayLength(env, ja); | 7 | const int len = (*env)->GetArrayLength(env, ja); |
@@ -32,3 +33,8 @@ Java_org_pacien_tincapp_commands_Executor_forkExec(JNIEnv *env, jclass class, jo | |||
32 | return pid; | 33 | return pid; |
33 | } | 34 | } |
34 | } | 35 | } |
36 | |||
37 | JNIEXPORT jint JNICALL | ||
38 | Java_org_pacien_tincapp_commands_Executor_wait(JNIEnv *env, jclass class, jint pid) { | ||
39 | return waitpid(pid, NULL, 0); | ||
40 | } | ||
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 | |||
13 | */ | 13 | */ |
14 | internal object Executor { | 14 | internal object Executor { |
15 | 15 | ||
16 | private const val FAILED = -1 | ||
17 | |||
16 | class CommandExecutionException(msg: String) : Exception(msg) | 18 | class CommandExecutionException(msg: String) : Exception(msg) |
17 | 19 | ||
18 | init { | 20 | init { |
@@ -20,14 +22,23 @@ internal object Executor { | |||
20 | } | 22 | } |
21 | 23 | ||
22 | /** | 24 | /** |
23 | * @return -1 on error, forked child PID otherwise | 25 | * @return FAILED (-1) on error, forked child PID otherwise |
24 | */ | 26 | */ |
25 | private external fun forkExec(argcv: Array<String>): Int | 27 | private external fun forkExec(argcv: Array<String>): Int |
26 | 28 | ||
29 | /** | ||
30 | * @return FAILED (-1) on error, 0 on no-op, the supplied PID otherwise | ||
31 | */ | ||
32 | private external fun wait(pid: Int): Int | ||
33 | |||
27 | private fun read(stream: InputStream) = BufferedReader(InputStreamReader(stream)).readLines() | 34 | private fun read(stream: InputStream) = BufferedReader(InputStreamReader(stream)).readLines() |
28 | 35 | ||
29 | fun forkExec(cmd: Command) { | 36 | fun forkExec(cmd: Command): CompletableFuture<Void> { |
30 | if (forkExec(cmd.asArray()) == -1) throw CommandExecutionException("Could not fork child process.") | 37 | val pid = forkExec(cmd.asArray()) |
38 | return when (pid) { | ||
39 | FAILED -> CompletableFuture.failedFuture(CommandExecutionException("Could not fork child process.")) | ||
40 | else -> CompletableFuture.runAsync { wait(pid) } | ||
41 | } | ||
31 | } | 42 | } |
32 | 43 | ||
33 | fun call(cmd: Command): CompletableFuture<List<String>> { | 44 | fun call(cmd: Command): CompletableFuture<List<String>> { |
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 | |||
7 | */ | 7 | */ |
8 | object Tincd { | 8 | object Tincd { |
9 | 9 | ||
10 | fun start(netName: String, deviceFd: Int, ed25519PrivateKeyFd: Int? = null, rsaPrivateKeyFd: Int? = null) { | 10 | fun start(netName: String, deviceFd: Int, ed25519PrivateKeyFd: Int? = null, rsaPrivateKeyFd: Int? = null) = |
11 | Executor.forkExec(Command(AppPaths.tincd().absolutePath) | 11 | Executor.forkExec(Command(AppPaths.tincd().absolutePath) |
12 | .withOption("no-detach") | 12 | .withOption("no-detach") |
13 | .withOption("config", AppPaths.confDir(netName).absolutePath) | 13 | .withOption("config", AppPaths.confDir(netName).absolutePath) |
@@ -17,6 +17,5 @@ object Tincd { | |||
17 | .withOption("option", "Device=" + deviceFd) | 17 | .withOption("option", "Device=" + deviceFd) |
18 | .apply { if (ed25519PrivateKeyFd != null) withOption("option", "Ed25519PrivateKeyFile=/proc/self/fd/$ed25519PrivateKeyFd") } | 18 | .apply { if (ed25519PrivateKeyFd != null) withOption("option", "Ed25519PrivateKeyFile=/proc/self/fd/$ed25519PrivateKeyFd") } |
19 | .apply { if (rsaPrivateKeyFd != null) withOption("option", "PrivateKeyFile=/proc/self/fd/$rsaPrivateKeyFd") }) | 19 | .apply { if (rsaPrivateKeyFd != null) withOption("option", "PrivateKeyFile=/proc/self/fd/$rsaPrivateKeyFd") }) |
20 | } | ||
21 | 20 | ||
22 | } | 21 | } |
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 | |||
6 | import android.net.VpnService | 6 | import android.net.VpnService |
7 | import android.os.ParcelFileDescriptor | 7 | import android.os.ParcelFileDescriptor |
8 | import android.util.Log | 8 | import android.util.Log |
9 | import java8.util.concurrent.CompletableFuture | ||
9 | import org.apache.commons.configuration2.ex.ConversionException | 10 | import org.apache.commons.configuration2.ex.ConversionException |
10 | import org.bouncycastle.openssl.PEMException | 11 | import org.bouncycastle.openssl.PEMException |
11 | import org.pacien.tincapp.BuildConfig | 12 | import org.pacien.tincapp.BuildConfig |
@@ -82,8 +83,8 @@ class TincVpnService : VpnService() { | |||
82 | return reportError(resources.getString(R.string.message_could_not_decrypt_private_keys_format, e.message)) | 83 | return reportError(resources.getString(R.string.message_could_not_decrypt_private_keys_format, e.message)) |
83 | } | 84 | } |
84 | 85 | ||
85 | Tincd.start(netName, deviceFd!!.fd, privateKeys.first?.fd, privateKeys.second?.fd) | 86 | val daemon = Tincd.start(netName, deviceFd!!.fd, privateKeys.first?.fd, privateKeys.second?.fd) |
86 | setState(true, netName, interfaceCfg, deviceFd) | 87 | setState(netName, interfaceCfg, deviceFd, daemon) |
87 | Log.i(TAG, "tinc daemon started.") | 88 | Log.i(TAG, "tinc daemon started.") |
88 | } | 89 | } |
89 | 90 | ||
@@ -111,16 +112,17 @@ class TincVpnService : VpnService() { | |||
111 | 112 | ||
112 | val TAG = this::class.java.canonicalName!! | 113 | val TAG = this::class.java.canonicalName!! |
113 | 114 | ||
114 | private var connected: Boolean = false | ||
115 | private var netName: String? = null | 115 | private var netName: String? = null |
116 | private var interfaceCfg: VpnInterfaceConfiguration? = null | 116 | private var interfaceCfg: VpnInterfaceConfiguration? = null |
117 | private var fd: ParcelFileDescriptor? = null | 117 | private var fd: ParcelFileDescriptor? = null |
118 | private var daemon: CompletableFuture<Void>? = null | ||
118 | 119 | ||
119 | private fun setState(connected: Boolean, netName: String?, interfaceCfg: VpnInterfaceConfiguration?, fd: ParcelFileDescriptor?) { | 120 | private fun setState(netName: String?, interfaceCfg: VpnInterfaceConfiguration?, |
120 | TincVpnService.connected = connected | 121 | fd: ParcelFileDescriptor?, daemon: CompletableFuture<Void>?) { |
121 | TincVpnService.netName = netName | 122 | TincVpnService.netName = netName |
122 | TincVpnService.interfaceCfg = interfaceCfg | 123 | TincVpnService.interfaceCfg = interfaceCfg |
123 | TincVpnService.fd = fd | 124 | TincVpnService.fd = fd |
125 | TincVpnService.daemon = daemon | ||
124 | } | 126 | } |
125 | 127 | ||
126 | fun startVpn(netName: String, passphrase: String? = null) { | 128 | fun startVpn(netName: String, passphrase: String? = null) { |
@@ -132,18 +134,19 @@ class TincVpnService : VpnService() { | |||
132 | try { | 134 | try { |
133 | Log.i(TAG, "Stopping any running tinc daemon.") | 135 | Log.i(TAG, "Stopping any running tinc daemon.") |
134 | if (netName != null) Tinc.stop(netName!!) | 136 | if (netName != null) Tinc.stop(netName!!) |
137 | daemon?.get() | ||
135 | fd?.close() | 138 | fd?.close() |
136 | Log.i(TAG, "All tinc daemons stopped.") | 139 | Log.i(TAG, "All tinc daemons stopped.") |
137 | } catch (e: IOException) { | 140 | } catch (e: IOException) { |
138 | Log.wtf(TAG, e) | 141 | Log.wtf(TAG, e) |
139 | } finally { | 142 | } finally { |
140 | setState(false, null, null, null) | 143 | setState(null, null, null, null) |
141 | } | 144 | } |
142 | } | 145 | } |
143 | 146 | ||
144 | fun getCurrentNetName() = netName | 147 | fun getCurrentNetName() = netName |
145 | fun getCurrentInterfaceCfg() = interfaceCfg | 148 | fun getCurrentInterfaceCfg() = interfaceCfg |
146 | fun isConnected() = connected | 149 | fun isConnected() = !(daemon?.isDone ?: true) |
147 | 150 | ||
148 | } | 151 | } |
149 | 152 | ||