diff options
Diffstat (limited to 'app/src')
4 files changed, 91 insertions, 21 deletions
diff --git a/app/src/main/java/org/pacien/tincapp/context/App.kt b/app/src/main/java/org/pacien/tincapp/context/App.kt index d79ae3e..53049f3 100644 --- a/app/src/main/java/org/pacien/tincapp/context/App.kt +++ b/app/src/main/java/org/pacien/tincapp/context/App.kt | |||
@@ -9,15 +9,31 @@ import android.support.annotation.StringRes | |||
9 | import android.support.v7.app.AlertDialog | 9 | import android.support.v7.app.AlertDialog |
10 | import android.view.WindowManager | 10 | import android.view.WindowManager |
11 | import org.pacien.tincapp.R | 11 | import org.pacien.tincapp.R |
12 | import org.slf4j.Logger | ||
13 | import org.slf4j.LoggerFactory | ||
12 | 14 | ||
13 | /** | 15 | /** |
14 | * @author pacien | 16 | * @author pacien |
15 | */ | 17 | */ |
16 | class App : Application() { | 18 | class App : Application(), Thread.UncaughtExceptionHandler { |
19 | private var logger: Logger? = null | ||
20 | private var systemCrashHandler: Thread.UncaughtExceptionHandler? = null | ||
21 | |||
17 | override fun onCreate() { | 22 | override fun onCreate() { |
18 | super.onCreate() | 23 | super.onCreate() |
19 | appContext = applicationContext | 24 | appContext = applicationContext |
20 | handler = Handler() | 25 | handler = Handler() |
26 | |||
27 | AppLogger.configure() | ||
28 | logger = LoggerFactory.getLogger(this.javaClass) | ||
29 | |||
30 | systemCrashHandler = Thread.getDefaultUncaughtExceptionHandler() | ||
31 | Thread.setDefaultUncaughtExceptionHandler(this) | ||
32 | } | ||
33 | |||
34 | override fun uncaughtException(thread: Thread, throwable: Throwable) { | ||
35 | logger?.error("Fatal application error.", throwable) | ||
36 | systemCrashHandler?.uncaughtException(thread, throwable) | ||
21 | } | 37 | } |
22 | 38 | ||
23 | companion object { | 39 | companion object { |
diff --git a/app/src/main/java/org/pacien/tincapp/context/AppLogger.kt b/app/src/main/java/org/pacien/tincapp/context/AppLogger.kt new file mode 100644 index 0000000..e240e70 --- /dev/null +++ b/app/src/main/java/org/pacien/tincapp/context/AppLogger.kt | |||
@@ -0,0 +1,45 @@ | |||
1 | package org.pacien.tincapp.context | ||
2 | |||
3 | import ch.qos.logback.classic.Logger | ||
4 | import ch.qos.logback.classic.LoggerContext | ||
5 | import ch.qos.logback.classic.android.LogcatAppender | ||
6 | import ch.qos.logback.classic.encoder.PatternLayoutEncoder | ||
7 | import ch.qos.logback.classic.spi.ILoggingEvent | ||
8 | import ch.qos.logback.core.Context | ||
9 | import ch.qos.logback.core.FileAppender | ||
10 | import org.slf4j.LoggerFactory | ||
11 | |||
12 | /** | ||
13 | * @author pacien | ||
14 | */ | ||
15 | object AppLogger { | ||
16 | private const val LOGCAT_PATTERN = "[%thread] %msg%n%rEx" | ||
17 | private const val LOGFILE_PATTERN = "%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%rEx" | ||
18 | |||
19 | fun configure() { | ||
20 | (LoggerFactory.getILoggerFactory() as LoggerContext) | ||
21 | .apply { reset() } | ||
22 | .let { loggerContext -> | ||
23 | (LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME) as Logger) | ||
24 | .apply { | ||
25 | addAppender(LogcatAppender() | ||
26 | .apply { context = loggerContext } | ||
27 | .apply { encoder = patternEncoder(loggerContext, LOGCAT_PATTERN) } | ||
28 | .apply { start() }) | ||
29 | } | ||
30 | .apply { | ||
31 | addAppender(FileAppender<ILoggingEvent>() | ||
32 | .apply { context = loggerContext } | ||
33 | .apply { encoder = patternEncoder(loggerContext, LOGFILE_PATTERN) } | ||
34 | .apply { file = AppPaths.appLogFile().absolutePath } | ||
35 | .apply { start() }) | ||
36 | } | ||
37 | } | ||
38 | } | ||
39 | |||
40 | private fun patternEncoder(ctx: Context, pat: String) = | ||
41 | PatternLayoutEncoder() | ||
42 | .apply { context = ctx } | ||
43 | .apply { pattern = pat } | ||
44 | .apply { start() } | ||
45 | } | ||
diff --git a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt b/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt index 9315060..4b36dfe 100644 --- a/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt +++ b/app/src/main/java/org/pacien/tincapp/context/AppPaths.kt | |||
@@ -10,21 +10,22 @@ import java.io.FileNotFoundException | |||
10 | * @implNote Logs and PID files are stored in the cache directory for easy clean up. | 10 | * @implNote Logs and PID files are stored in the cache directory for easy clean up. |
11 | */ | 11 | */ |
12 | object AppPaths { | 12 | object AppPaths { |
13 | private val TINCD_BIN = "libtincd.so" | 13 | private const val TINCD_BIN = "libtincd.so" |
14 | private val TINC_BIN = "libtinc.so" | 14 | private const val TINC_BIN = "libtinc.so" |
15 | 15 | ||
16 | private val LOGFILE_FORMAT = "tinc.%s.log" | 16 | private const val APPLOG_FILE = "tincapp.log" |
17 | private val PIDFILE_FORMAT = "tinc.%s.pid" | 17 | private const val LOGFILE_FORMAT = "tinc.%s.log" |
18 | private const val PIDFILE_FORMAT = "tinc.%s.pid" | ||
18 | 19 | ||
19 | private val NET_CONF_FILE = "network.conf" | 20 | private const val NET_CONF_FILE = "network.conf" |
20 | private val NET_TINC_CONF_FILE = "tinc.conf" | 21 | private const val NET_TINC_CONF_FILE = "tinc.conf" |
21 | private val NET_HOSTS_DIR = "hosts" | 22 | private const val NET_HOSTS_DIR = "hosts" |
22 | private val NET_INVITATION_FILE = "invitation-data" | 23 | private const val NET_INVITATION_FILE = "invitation-data" |
23 | private val NET_DEFAULT_ED25519_PRIVATE_KEY_FILE = "ed25519_key.priv" | 24 | private const val NET_DEFAULT_ED25519_PRIVATE_KEY_FILE = "ed25519_key.priv" |
24 | private val NET_DEFAULT_RSA_PRIVATE_KEY_FILE = "rsa_key.priv" | 25 | private const val NET_DEFAULT_RSA_PRIVATE_KEY_FILE = "rsa_key.priv" |
25 | 26 | ||
26 | fun storageAvailable() = | 27 | fun storageAvailable() = |
27 | Environment.getExternalStorageState().let { it == Environment.MEDIA_MOUNTED && it != Environment.MEDIA_MOUNTED_READ_ONLY } | 28 | Environment.getExternalStorageState().let { it == Environment.MEDIA_MOUNTED && it != Environment.MEDIA_MOUNTED_READ_ONLY } |
28 | 29 | ||
29 | fun cacheDir() = App.getContext().externalCacheDir | 30 | fun cacheDir() = App.getContext().externalCacheDir |
30 | fun confDir() = App.getContext().getExternalFilesDir(null) | 31 | fun confDir() = App.getContext().getExternalFilesDir(null) |
@@ -37,6 +38,7 @@ object AppPaths { | |||
37 | fun invitationFile(netName: String) = File(confDir(netName), NET_INVITATION_FILE) | 38 | fun invitationFile(netName: String) = File(confDir(netName), NET_INVITATION_FILE) |
38 | fun logFile(netName: String) = File(cacheDir(), String.format(LOGFILE_FORMAT, netName)) | 39 | fun logFile(netName: String) = File(cacheDir(), String.format(LOGFILE_FORMAT, netName)) |
39 | fun pidFile(netName: String) = File(App.getContext().cacheDir, String.format(PIDFILE_FORMAT, netName)) | 40 | fun pidFile(netName: String) = File(App.getContext().cacheDir, String.format(PIDFILE_FORMAT, netName)) |
41 | fun appLogFile() = File(cacheDir(), APPLOG_FILE) | ||
40 | 42 | ||
41 | fun existing(f: File) = f.apply { if (!exists()) throw FileNotFoundException(f.absolutePath) } | 43 | fun existing(f: File) = f.apply { if (!exists()) throw FileNotFoundException(f.absolutePath) } |
42 | 44 | ||
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 0bf72a1..69811f4 100644 --- a/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt +++ b/app/src/main/java/org/pacien/tincapp/service/TincVpnService.kt | |||
@@ -5,7 +5,6 @@ import android.content.Intent | |||
5 | import android.net.VpnService | 5 | import android.net.VpnService |
6 | import android.os.ParcelFileDescriptor | 6 | import android.os.ParcelFileDescriptor |
7 | import android.support.v4.content.LocalBroadcastManager | 7 | import android.support.v4.content.LocalBroadcastManager |
8 | import android.util.Log | ||
9 | import java8.util.concurrent.CompletableFuture | 8 | import java8.util.concurrent.CompletableFuture |
10 | import org.apache.commons.configuration2.ex.ConversionException | 9 | import org.apache.commons.configuration2.ex.ConversionException |
11 | import org.bouncycastle.openssl.PEMException | 10 | import org.bouncycastle.openssl.PEMException |
@@ -22,19 +21,28 @@ import org.pacien.tincapp.extensions.Java.applyIgnoringException | |||
22 | import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg | 21 | import org.pacien.tincapp.extensions.VpnServiceBuilder.applyCfg |
23 | import org.pacien.tincapp.intent.Actions | 22 | import org.pacien.tincapp.intent.Actions |
24 | import org.pacien.tincapp.utils.TincKeyring | 23 | import org.pacien.tincapp.utils.TincKeyring |
24 | import org.slf4j.Logger | ||
25 | import org.slf4j.LoggerFactory | ||
25 | import java.io.FileNotFoundException | 26 | import java.io.FileNotFoundException |
26 | 27 | ||
27 | /** | 28 | /** |
28 | * @author pacien | 29 | * @author pacien |
29 | */ | 30 | */ |
30 | class TincVpnService : VpnService() { | 31 | class TincVpnService : VpnService() { |
32 | private var logger: Logger? = null | ||
33 | |||
34 | override fun onCreate() { | ||
35 | super.onCreate() | ||
36 | logger = LoggerFactory.getLogger(this.javaClass) | ||
37 | } | ||
38 | |||
31 | override fun onDestroy() { | 39 | override fun onDestroy() { |
32 | stopVpn() | 40 | stopVpn() |
33 | super.onDestroy() | 41 | super.onDestroy() |
34 | } | 42 | } |
35 | 43 | ||
36 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { | 44 | override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { |
37 | Log.i(TAG, intent.action) | 45 | logger?.info("Intent received: {}", intent.action) |
38 | 46 | ||
39 | when { | 47 | when { |
40 | intent.action == Actions.ACTION_CONNECT && intent.scheme == Actions.TINC_SCHEME -> | 48 | intent.action == Actions.ACTION_CONNECT && intent.scheme == Actions.TINC_SCHEME -> |
@@ -61,7 +69,7 @@ class TincVpnService : VpnService() { | |||
61 | if (!AppPaths.confDir(netName).exists()) | 69 | if (!AppPaths.confDir(netName).exists()) |
62 | return reportError(resources.getString(R.string.message_no_configuration_for_network_format, netName), docTopic = "configuration") | 70 | return reportError(resources.getString(R.string.message_no_configuration_for_network_format, netName), docTopic = "configuration") |
63 | 71 | ||
64 | Log.i(TAG, "Starting tinc daemon for network \"$netName\".") | 72 | logger?.info("Starting tinc daemon for network \"$netName\".") |
65 | if (isConnected()) stopVpn() | 73 | if (isConnected()) stopVpn() |
66 | 74 | ||
67 | val interfaceCfg = try { | 75 | val interfaceCfg = try { |
@@ -108,17 +116,17 @@ class TincVpnService : VpnService() { | |||
108 | if (exception != null) { | 116 | if (exception != null) { |
109 | reportError(resources.getString(R.string.message_daemon_exited, exception.cause!!.message!!), exception) | 117 | reportError(resources.getString(R.string.message_daemon_exited, exception.cause!!.message!!), exception) |
110 | } else { | 118 | } else { |
111 | Log.i(TAG, "tinc daemon started.") | 119 | logger?.info("tinc daemon started.") |
112 | broadcastEvent(Actions.EVENT_CONNECTED) |