Compare commits

..

4 Commits

Author SHA1 Message Date
Zane Schepke 0008573b4d Revert "chore: bump version w/notes"
This reverts commit 47b2deaf3d.
2024-12-09 22:43:16 -05:00
Zane Schepke 47b2deaf3d chore: bump version w/notes 2024-12-09 22:42:46 -05:00
Zane Schepke 99f6b438ab add tunnel notification 2024-12-09 22:33:47 -05:00
Zane Schepke f047a1e1b8 feat: improved notifications
- improved tile state sync
2024-12-08 22:30:01 -05:00
9 changed files with 101 additions and 85 deletions
@@ -8,7 +8,6 @@ import com.zaneschepke.wireguardautotunnel.data.repository.AppStateRepository
import com.zaneschepke.wireguardautotunnel.data.repository.SettingsRepository
import com.zaneschepke.wireguardautotunnel.module.ApplicationScope
import com.zaneschepke.wireguardautotunnel.module.IoDispatcher
import com.zaneschepke.wireguardautotunnel.module.MainDispatcher
import com.zaneschepke.wireguardautotunnel.service.tunnel.BackendState
import com.zaneschepke.wireguardautotunnel.service.tunnel.TunnelService
import com.zaneschepke.wireguardautotunnel.util.LocaleUtil
@@ -18,7 +17,6 @@ import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import javax.inject.Inject
@@ -45,10 +43,6 @@ class WireGuardAutoTunnel : Application() {
@IoDispatcher
lateinit var ioDispatcher: CoroutineDispatcher
@Inject
@MainDispatcher
lateinit var mainDispatcher: CoroutineDispatcher
override fun onCreate() {
super.onCreate()
instance = this
@@ -65,19 +59,22 @@ class WireGuardAutoTunnel : Application() {
} else {
Timber.plant(ReleaseTree())
}
applicationScope.launch {
withContext(mainDispatcher) {
if (appStateRepository.isLocalLogsEnabled() && !isRunningOnTv()) logReader.initialize()
}
if (!settingsRepository.getSettings().isKernelEnabled) {
tunnelService.setBackendState(BackendState.SERVICE_ACTIVE, emptyList())
}
appStateRepository.getLocale()?.let {
LocaleUtil.changeLocale(it)
}
}
if (!isRunningOnTv()) {
applicationScope.launch(ioDispatcher) {
if (appStateRepository.isLocalLogsEnabled()) {
Timber.d("Starting logger")
logReader.start()
}
}
}
}
override fun onTerminate() {
@@ -2,9 +2,9 @@ package com.zaneschepke.wireguardautotunnel.module
import android.content.Context
import com.zaneschepke.logcatter.LogReader
import com.zaneschepke.logcatter.LogcatCollector
import com.zaneschepke.wireguardautotunnel.service.notification.NotificationService
import com.zaneschepke.wireguardautotunnel.service.notification.WireGuardNotification
import com.zaneschepke.logcatter.LogcatReader
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@@ -27,7 +27,7 @@ class AppModule {
@Singleton
@Provides
fun provideLogCollect(@ApplicationContext context: Context): LogReader {
return LogcatReader.init(storageDir = context.filesDir.absolutePath)
return LogcatCollector.init(context = context)
}
@Singleton
@@ -141,6 +141,7 @@ constructor(
}
private suspend fun onLoggerStop() {
logReader.stop()
logReader.deleteAndClearLogs()
}
+2 -2
View File
@@ -1,7 +1,7 @@
object Constants {
const val VERSION_NAME = "3.6.3"
const val VERSION_NAME = "3.6.1"
const val JVM_TARGET = "17"
const val VERSION_CODE = 36300
const val VERSION_CODE = 36100
const val TARGET_SDK = 35
const val MIN_SDK = 26
const val APP_ID = "com.zaneschepke.wireguardautotunnel"
@@ -1,5 +0,0 @@
What's new:
- Added VPN kill switch w/LAN bypass
- Improved auto tunnel speed and reliability
- Improved tile sync
- Various bug fixes and improvements
-1
View File
@@ -49,7 +49,6 @@ dependencies {
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
implementation(libs.androidx.lifecycle.process)
// logging
implementation(libs.timber)
}
@@ -4,7 +4,8 @@ import com.zaneschepke.logcatter.model.LogMessage
import kotlinx.coroutines.flow.Flow
interface LogReader {
fun initialize(onLogMessage: ((message: LogMessage) -> Unit)? = null)
suspend fun start(onLogMessage: ((message: LogMessage) -> Unit)? = null)
fun stop()
fun zipLogFiles(path: String)
suspend fun deleteAndClearLogs()
val bufferedLogs: Flow<LogMessage>
@@ -1,30 +1,26 @@
package com.zaneschepke.logcatter
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import android.content.Context
import com.zaneschepke.logcatter.model.LogMessage
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber
import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStreamReader
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
object LogcatReader {
object LogcatCollector {
private const val MAX_FILE_SIZE = 2097152L // 2MB
private const val MAX_FOLDER_SIZE = 10485760L // 10MB
@@ -44,7 +40,7 @@ object LogcatReader {
var logcatPath = ""
}
fun init(maxFileSize: Long = MAX_FILE_SIZE, maxFolderSize: Long = MAX_FOLDER_SIZE, storageDir: String): LogReader {
fun init(maxFileSize: Long = MAX_FILE_SIZE, maxFolderSize: Long = MAX_FOLDER_SIZE, context: Context): LogReader {
if (maxFileSize > maxFolderSize) {
throw IllegalStateException("maxFileSize must be less than maxFolderSize")
}
@@ -52,11 +48,13 @@ object LogcatReader {
LogcatHelperInit.maxFileSize = maxFileSize
LogcatHelperInit.maxFolderSize = maxFolderSize
LogcatHelperInit.pID = android.os.Process.myPid()
LogcatHelperInit.publicAppDirectory = storageDir
LogcatHelperInit.logcatPath = LogcatHelperInit.publicAppDirectory + File.separator + "logs"
val logDirectory = File(LogcatHelperInit.logcatPath)
if (!logDirectory.exists()) {
logDirectory.mkdir()
context.getExternalFilesDir(null)?.let {
LogcatHelperInit.publicAppDirectory = it.absolutePath
LogcatHelperInit.logcatPath = LogcatHelperInit.publicAppDirectory + File.separator + "logs"
val logDirectory = File(LogcatHelperInit.logcatPath)
if (!logDirectory.exists()) {
logDirectory.mkdir()
}
}
return Logcat
}
@@ -64,12 +62,7 @@ object LogcatReader {
internal object Logcat : LogReader {
private lateinit var logcatReader: LogcatReader
override fun initialize(onLogMessage: ((message: LogMessage) -> Unit)?) {
logcatReader = LogcatReader(LogcatHelperInit.pID.toString(), LogcatHelperInit.logcatPath, onLogMessage)
ProcessLifecycleOwner.get().lifecycle.addObserver(logcatReader)
}
private var logcatReader: LogcatReader? = null
private fun obfuscator(log: String): String {
return findKeyRegex.replace(log, "<crypto-key>").let { first ->
@@ -79,10 +72,22 @@ object LogcatReader {
}.let { last -> findIpv4AddressRegex.replace(last, "<ipv4-address>") }
}
override suspend fun start(onLogMessage: ((message: LogMessage) -> Unit)?) {
logcatReader ?: run {
logcatReader = LogcatReader(LogcatHelperInit.pID.toString(), LogcatHelperInit.logcatPath, onLogMessage)
}
logcatReader?.run()
}
override fun stop() {
logcatReader?.stop()
logcatReader = null
}
override fun zipLogFiles(path: String) {
logcatReader.cancel()
logcatReader?.pause()
zipAll(path)
logcatReader.onCreate(ProcessLifecycleOwner.get())
logcatReader?.resume()
}
private fun zipAll(zipFilePath: String) {
@@ -105,10 +110,10 @@ object LogcatReader {
@OptIn(ExperimentalCoroutinesApi::class)
override suspend fun deleteAndClearLogs() {
withContext(ioDispatcher) {
logcatReader.cancel()
logcatReader?.pause()
_bufferedLogs.resetReplayCache()
logcatReader.deleteAllFiles()
logcatReader.onCreate(ProcessLifecycleOwner.get())
logcatReader?.deleteAllFiles()
logcatReader?.resume()
}
}
@@ -129,25 +134,57 @@ object LogcatReader {
pID: String,
private val logcatPath: String,
private val callback: ((input: LogMessage) -> Unit)?,
) : DefaultLifecycleObserver {
) {
private var logcatProc: Process? = null
private var reader: BufferedReader? = null
private val command = "logcat -v epoch | grep \"($pID)\""
private val clearLogCommand = "logcat -c"
private var logJob: Job? = null
@get:Synchronized @set:Synchronized
private var paused = false
@get:Synchronized @set:Synchronized
private var stopped = false
private var command = ""
private var clearLogCommand = ""
private var outputStream: FileOutputStream? = null
override fun onCreate(owner: LifecycleOwner) {
super.onCreate(owner)
logJob = owner.lifecycleScope.launch(ioDispatcher) {
init {
try {
outputStream = FileOutputStream(createLogFile(logcatPath))
} catch (e: FileNotFoundException) {
Timber.e(e)
}
command = "logcat -v epoch | grep \"($pID)\""
clearLogCommand = "logcat -c"
}
fun pause() {
paused = true
}
fun stop() {
stopped = true
}
fun resume() {
paused = false
}
fun clear() {
Runtime.getRuntime().exec(clearLogCommand)
}
suspend fun run() {
withContext(ioDispatcher) {
paused = false
stopped = false
if (outputStream == null) return@withContext
try {
if (outputStream == null) outputStream = createNewLogFileStream()
clear()
logcatProc = Runtime.getRuntime().exec(command)
reader = BufferedReader(InputStreamReader(logcatProc!!.inputStream), 1024)
var line: String? = null
while (true) {
var line: String?
while (!stopped) {
if (paused) continue
line = reader?.readLine()
if (line.isNullOrEmpty()) continue
outputStream?.let {
@@ -159,8 +196,8 @@ object LogcatReader {
deleteOldestFile()
}
line.let { text ->
val sanitized = obfuscator(text)
it.write((sanitized + System.lineSeparator()).toByteArray())
val obfuscated = obfuscator(text)
it.write((obfuscated + System.lineSeparator()).toByteArray())
try {
val logMessage = LogMessage.from(text)
_bufferedLogs.tryEmit(logMessage)
@@ -177,34 +214,19 @@ object LogcatReader {
} catch (e: IOException) {
Timber.e(e)
} finally {
reset()
logcatProc?.destroy()
logcatProc = null
try {
reader?.close()
outputStream?.close()
reader = null
outputStream = null
} catch (e: IOException) {
Timber.e(e)
}
}
}
logJob?.invokeOnCompletion {
reset()
}
}
override fun onDestroy(owner: LifecycleOwner) {
super.onDestroy(owner)
logJob?.cancel()
}
fun cancel() {
logJob?.cancel()
}
private fun reset() {
logcatProc?.destroy()
logcatProc = null
reader?.close()
outputStream?.close()
reader = null
outputStream = null
}
fun clear() {
Runtime.getRuntime().exec(clearLogCommand)
}
private fun getFolderSize(path: String): Long {
@@ -244,6 +266,7 @@ object LogcatReader {
directory.listFiles()?.toMutableList()?.run {
this.forEach { it.delete() }
}
outputStream = createNewLogFileStream()
}
}
}
+1 -1
View File
@@ -1 +1 @@
13
12