From 5447ec73f786d9879ec9396c605bae87cd8a9323 Mon Sep 17 00:00:00 2001 From: Zane Schepke Date: Tue, 16 Apr 2024 00:14:06 -0400 Subject: [PATCH] fix: stop tunnel regression Fixes regression where tunnel is stuck in on state after x amount of toggles. Closes #163 Adds obfuscation of potentially sensitive data from logs. Closes #160 Adds hiding of FAB on scroll to allow users to toggle tunnels when they have many tunnel configs. Closes #161 --- .github/workflows/pre-release.yml | 7 +++-- .github/workflows/release.yml | 7 +++-- .../receiver/NotificationActionReceiver.kt | 2 +- .../service/foreground/Action.kt | 3 +- .../service/foreground/ForegroundService.kt | 17 ++--------- .../service/foreground/ServiceManager.kt | 15 ++++++++-- .../WireGuardConnectivityWatcherService.kt | 28 +++++++++---------- .../foreground/WireGuardTunnelService.kt | 15 +++++----- .../service/shortcut/ShortcutsActivity.kt | 2 +- .../service/tile/TunnelControlTile.kt | 2 +- .../service/tunnel/WireGuardTunnel.kt | 9 ++++-- .../wireguardautotunnel/ui/AppViewModel.kt | 4 +-- .../ui/screens/main/MainScreen.kt | 27 ++++++++++++++++-- .../wireguardautotunnel/util/Constants.kt | 2 ++ buildSrc/src/main/kotlin/Constants.kt | 4 +-- .../android/en-US/changelogs/34200.txt | 4 +++ gradle/libs.versions.toml | 2 +- .../com/zaneschepke/logcatter/Logcatter.kt | 19 +++++++++++-- 18 files changed, 108 insertions(+), 61 deletions(-) create mode 100644 fastlane/metadata/android/en-US/changelogs/34200.txt diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index 16090e8..1462010 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -97,7 +97,7 @@ jobs: - name: Get checksum id: checksum - run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*")" | awk '{$1=$1};1' >> $GITHUB_OUTPUT + run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")" >> $GITHUB_OUTPUT - name: Append checksum id: append_checksum @@ -105,8 +105,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - body: > -
SHA256 fingerprint:
```${{ steps.checksum.outputs.checksum }}``` + body: | + SHA256 fingerprint: + ```${{ steps.checksum.outputs.checksum }}``` tag_name: ${{ github.ref_name }} name: ${{ github.ref_name }} draft: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 245cbec..c3ac882 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -103,7 +103,7 @@ jobs: - name: Get checksum id: checksum - run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*")" | awk '{$1=$1};1' >> $GITHUB_OUTPUT + run: echo "checksum=$(apksigner verify -print-certs ${{ steps.apk-path.outputs.path }} | grep -Po "(?<=SHA-256 digest:) .*" | tr -d "[:blank:]")" >> $GITHUB_OUTPUT - name: Append checksum id: append_checksum @@ -111,8 +111,9 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: - body: > -
SHA256 fingerprint:
```${{ steps.checksum.outputs.checksum }}``` + body: | + SHA256 fingerprint: + ```${{ steps.checksum.outputs.checksum }}``` tag_name: ${{ github.ref_name }} name: ${{ github.ref_name }} draft: false diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt index bcfb90f..812da89 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/receiver/NotificationActionReceiver.kt @@ -24,7 +24,7 @@ class NotificationActionReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent?) = goAsync { try { //TODO fix for manual start changes when enabled - serviceManager.stopVpnService(context) + serviceManager.stopVpnServiceForeground(context) delay(Constants.TOGGLE_TUNNEL_DELAY) serviceManager.startVpnServiceForeground(context) } catch (e: Exception) { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt index e68a61c..dc563ea 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/Action.kt @@ -3,5 +3,6 @@ package com.zaneschepke.wireguardautotunnel.service.foreground enum class Action { START, START_FOREGROUND, - STOP + STOP, + STOP_FOREGROUND } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt index 4cdc5a8..f58e4bb 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ForegroundService.kt @@ -24,7 +24,7 @@ open class ForegroundService : LifecycleService() { when (action) { Action.START.name, Action.START_FOREGROUND.name -> startService(intent.extras) - + Action.STOP.name, Action.STOP_FOREGROUND.name -> stopService() Constants.ALWAYS_ON_VPN_ACTION -> { Timber.i("Always-on VPN starting service") startService(intent.extras) @@ -37,16 +37,9 @@ open class ForegroundService : LifecycleService() { "with a null intent. It has been probably restarted by the system.", ) } - // by returning this we make sure the service is restarted if the system kills the service return START_STICKY } - override fun onDestroy() { - super.onDestroy() - Timber.d("The service has been destroyed") - stopService() - } - protected open fun startService(extras: Bundle?) { if (isServiceStarted) return Timber.d("Starting ${this.javaClass.simpleName}") @@ -55,12 +48,8 @@ open class ForegroundService : LifecycleService() { protected open fun stopService() { Timber.d("Stopping ${this.javaClass.simpleName}") - try { - stopForeground(STOP_FOREGROUND_REMOVE) - stopSelf() - } catch (e: Exception) { - Timber.e(e) - } + stopForeground(STOP_FOREGROUND_REMOVE) + stopSelf() isServiceStarted = false } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt index 0d240fe..ec7129d 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/ServiceManager.kt @@ -23,9 +23,8 @@ class ServiceManager(private val appDataRepository: AppDataRepository) { intent.component?.javaClass try { when (action) { - Action.START_FOREGROUND -> context.startForegroundService(intent) - Action.START -> context.startService(intent) - Action.STOP -> context.stopService(intent) + Action.START_FOREGROUND, Action.STOP_FOREGROUND -> context.startForegroundService(intent) + Action.START, Action.STOP -> context.startService(intent) } } catch (e: Exception) { Timber.e(e.message) @@ -46,6 +45,16 @@ class ServiceManager(private val appDataRepository: AppDataRepository) { ) } + suspend fun stopVpnServiceForeground(context: Context, isManualStop: Boolean = false) { + if (isManualStop) onManualStop() + Timber.i("Stopping vpn service") + actionOnService( + Action.STOP_FOREGROUND, + context, + WireGuardTunnelService::class.java, + ) + } + suspend fun stopVpnService(context: Context, isManualStop: Boolean = false) { if (isManualStop) onManualStop() Timber.i("Stopping vpn service") diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt index ddcee0b..be31496 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardConnectivityWatcherService.kt @@ -18,6 +18,7 @@ import com.zaneschepke.wireguardautotunnel.service.notification.NotificationServ import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService import com.zaneschepke.wireguardautotunnel.util.Constants import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay @@ -56,7 +57,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() { private val networkEventsFlow = MutableStateFlow(WatcherState()) - private lateinit var watcherJob: Job + private var watcherJob: Job? = null private var wakeLock: PowerManager.WakeLock? = null private val tag = this.javaClass.name @@ -74,11 +75,6 @@ class WireGuardConnectivityWatcherService : ForegroundService() { } } - override fun onDestroy() { - super.onDestroy() - stopService() - } - override fun startService(extras: Bundle?) { super.startService(extras) try { @@ -139,8 +135,10 @@ class WireGuardConnectivityWatcherService : ForegroundService() { } private fun cancelWatcherJob() { - if (this::watcherJob.isInitialized) { - watcherJob.cancel() + try { + watcherJob?.cancel() + } catch (e : CancellationException) { + Timber.i("Watcher job cancelled") } } @@ -236,7 +234,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() { } if (results.contains(false)) { Timber.i("Restarting VPN for ping failure") - serviceManager.stopVpnService(this) + serviceManager.stopVpnServiceForeground(this) delay(Constants.VPN_RESTART_DELAY) serviceManager.startVpnServiceForeground(this) delay(Constants.PING_COOLDOWN) @@ -324,7 +322,9 @@ class WireGuardConnectivityWatcherService : ForegroundService() { ) val ssid = wifiService.getNetworkName(it.networkCapabilities) ssid?.let { - Timber.i("Detected SSID: $ssid") + if(it.contains(Constants.UNREADABLE_SSID)) { + Timber.w("SSID unreadable: missing permissions") + } else Timber.i("Detected valid SSID") appDataRepository.appState.setCurrentSsid(ssid) networkEventsFlow.value = networkEventsFlow.value.copy( @@ -381,7 +381,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() { watcherState.isTunnelOffOnMobileDataConditionMet() -> { Timber.i("$autoTunnel - tunnel off on mobile data met, turning vpn off") - serviceManager.stopVpnService(this) + serviceManager.stopVpnServiceForeground(this) } watcherState.isTunnelNotWifiNamePreferredMet(watcherState.currentNetworkSSID) -> { @@ -407,17 +407,17 @@ class WireGuardConnectivityWatcherService : ForegroundService() { watcherState.isTrustedWifiConditionMet() -> { Timber.i("$autoTunnel - tunnel off on trusted wifi condition met, turning vpn off") - serviceManager.stopVpnService(this) + serviceManager.stopVpnServiceForeground(this) } watcherState.isTunnelOffOnWifiConditionMet() -> { Timber.i("$autoTunnel - tunnel off on wifi condition met, turning vpn off") - serviceManager.stopVpnService(this) + serviceManager.stopVpnServiceForeground(this) } watcherState.isTunnelOffOnNoConnectivityMet() -> { Timber.i("$autoTunnel - tunnel off on no connectivity met, turning vpn off") - serviceManager.stopVpnService(this) + serviceManager.stopVpnServiceForeground(this) } else -> { diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt index 5f9dc63..b6c2052 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/foreground/WireGuardTunnelService.kt @@ -16,10 +16,12 @@ import com.zaneschepke.wireguardautotunnel.util.Constants import com.zaneschepke.wireguardautotunnel.util.handshakeStatus import com.zaneschepke.wireguardautotunnel.util.mapPeerStats import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint @@ -35,7 +37,7 @@ class WireGuardTunnelService : ForegroundService() { @Inject lateinit var notificationService: NotificationService - private lateinit var job: Job + private var job: Job? = null private var didShowConnected = false @@ -49,11 +51,6 @@ class WireGuardTunnelService : ForegroundService() { } } - override fun onDestroy() { - super.onDestroy() - - } - override fun startService(extras: Bundle?) { super.startService(extras) cancelJob() @@ -182,8 +179,10 @@ class WireGuardTunnelService : ForegroundService() { } private fun cancelJob() { - if (this::job.isInitialized) { - job.cancel() + try { + job?.cancel() + } catch (e : CancellationException) { + Timber.i("Tunnel job cancelled") } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt index ffa3525..afcd91c 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/shortcut/ShortcutsActivity.kt @@ -40,7 +40,7 @@ class ShortcutsActivity : ComponentActivity() { this@ShortcutsActivity, tunnelConfig?.id, isManualStart = true, ) - Action.STOP.name -> serviceManager.stopVpnService( + Action.STOP.name -> serviceManager.stopVpnServiceForeground( this@ShortcutsActivity, isManualStop = true, ) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt index c62e423..eb221b6 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tile/TunnelControlTile.kt @@ -80,7 +80,7 @@ class TunnelControlTile : TileService() { scope.launch { try { if (vpnService.getState() == Tunnel.State.UP) { - serviceManager.stopVpnService( + serviceManager.stopVpnServiceForeground( this@TunnelControlTile, isManualStop = true, ) diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt index 9eb841c..4f6b6e4 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/service/tunnel/WireGuardTunnel.kt @@ -10,6 +10,7 @@ import com.zaneschepke.wireguardautotunnel.data.repository.AppDataRepository import com.zaneschepke.wireguardautotunnel.module.Kernel import com.zaneschepke.wireguardautotunnel.module.Userspace import com.zaneschepke.wireguardautotunnel.util.Constants +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -33,7 +34,7 @@ constructor( private val scope = CoroutineScope(Dispatchers.IO) - private lateinit var statsJob: Job + private var statsJob: Job? = null private var backend: Backend = userspaceBackend @@ -134,8 +135,10 @@ constructor( } } if (state == State.DOWN) { - if (this::statsJob.isInitialized) { - statsJob.cancel() + try { + statsJob?.cancel() + } catch (e : CancellationException) { + Timber.i("Stats job cancelled") } } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/AppViewModel.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/AppViewModel.kt index 667df97..8555d8d 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/AppViewModel.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/AppViewModel.kt @@ -118,12 +118,12 @@ constructor( fun readLogCatOutput() = viewModelScope.launch(viewModelScope.coroutineContext + Dispatchers.IO) { launch { - Logcatter.logs { + Logcatter.logs(callback = { logs.add(it) if (logs.size > Constants.LOG_BUFFER_SIZE) { logs.removeRange(0, (logs.size - Constants.LOG_BUFFER_SIZE).toInt()) } - } + }) } } diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt index a2282fb..05202b1 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/ui/screens/main/MainScreen.kt @@ -71,8 +71,12 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.onFocusChanged +import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.hapticfeedback.HapticFeedbackType +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalHapticFeedback @@ -124,6 +128,25 @@ fun MainScreen( val sheetState = rememberModalBottomSheetState() var showBottomSheet by remember { mutableStateOf(false) } + // Nested scroll for control FAB + val nestedScrollConnection = remember { + object : NestedScrollConnection { + override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { + // Hide FAB + if (available.y < -1) { + isVisible.value = false + } + // Show FAB + if (available.y > 1) { + isVisible.value = true + } + + return Offset.Zero + } + } + } + + var showDeleteTunnelAlertDialog by remember { mutableStateOf(false) } var selectedTunnel by remember { mutableStateOf(null) } val uiState by viewModel.uiState.collectAsStateWithLifecycle() @@ -377,8 +400,8 @@ fun MainScreen( verticalArrangement = Arrangement.Top, modifier = Modifier - .fillMaxWidth() - .overscroll(ScrollableDefaults.overscrollEffect()), + .fillMaxSize() + .overscroll(ScrollableDefaults.overscrollEffect()).nestedScroll(nestedScrollConnection), state = rememberLazyListState(0, uiState.tunnels.count()), userScrollEnabled = true, reverseLayout = false, diff --git a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/Constants.kt b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/Constants.kt index ea1d356..2e55229 100644 --- a/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/Constants.kt +++ b/app/src/main/java/com/zaneschepke/wireguardautotunnel/util/Constants.kt @@ -35,4 +35,6 @@ object Constants { const val TUNNEL_EXTRA_KEY = "tunnelId" + const val UNREADABLE_SSID = "" + } diff --git a/buildSrc/src/main/kotlin/Constants.kt b/buildSrc/src/main/kotlin/Constants.kt index 6d3d4f4..c8a68a7 100644 --- a/buildSrc/src/main/kotlin/Constants.kt +++ b/buildSrc/src/main/kotlin/Constants.kt @@ -1,7 +1,7 @@ object Constants { - const val VERSION_NAME = "3.4.1" + const val VERSION_NAME = "3.4.2" const val JVM_TARGET = "17" - const val VERSION_CODE = 34100 + const val VERSION_CODE = 34200 const val TARGET_SDK = 34 const val MIN_SDK = 26 const val APP_ID = "com.zaneschepke.wireguardautotunnel" diff --git a/fastlane/metadata/android/en-US/changelogs/34200.txt b/fastlane/metadata/android/en-US/changelogs/34200.txt new file mode 100644 index 0000000..f678937 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/34200.txt @@ -0,0 +1,4 @@ +What's new: +- Fix stop tunnel regression +- Add logs obfuscation +- Add hide FAB on scroll diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3aee43f..092ac5d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -20,7 +20,7 @@ pinLockCompose = "1.0.3" roomVersion = "2.6.1" timber = "5.0.1" tunnel = "1.0.20230706" -androidGradlePlugin = "8.4.0-rc01" +androidGradlePlugin = "8.4.0-rc02" kotlin = "1.9.23" ksp = "1.9.23-1.0.19" composeBom = "2024.03.00" diff --git a/logcatter/src/main/java/com/zaneschepke/logcatter/Logcatter.kt b/logcatter/src/main/java/com/zaneschepke/logcatter/Logcatter.kt index 4611d62..f1fd5ee 100644 --- a/logcatter/src/main/java/com/zaneschepke/logcatter/Logcatter.kt +++ b/logcatter/src/main/java/com/zaneschepke/logcatter/Logcatter.kt @@ -3,14 +3,29 @@ package com.zaneschepke.logcatter import com.zaneschepke.logcatter.model.LogMessage object Logcatter { - fun logs(callback: (input: LogMessage) -> Unit) { + + private val findKeyRegex = """[A-Za-z0-9+/]{42}[AEIMQUYcgkosw480]=""".toRegex() + private val findIpv6AddressRegex = """(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))""".toRegex() + private val findIpv4AddressRegex = """((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}""".toRegex() + private val findTunnelNameRegex = """(?<=tunnel ).*?(?= UP| DOWN)""".toRegex() + + + fun logs(callback: (input: LogMessage) -> Unit, obfuscator: (log : String) -> String = { log -> this.obfuscator(log)}){ clear() Runtime.getRuntime().exec("logcat -v epoch") .inputStream .bufferedReader() .useLines { lines -> - lines.forEach { callback(LogMessage.from(it)) } + lines.forEach { callback(LogMessage.from(obfuscator(it))) } + } + } + + private fun obfuscator(log : String) : String { + return findKeyRegex.replace(log, "").let { first -> + findIpv6AddressRegex.replace(first, "").let { second -> + findTunnelNameRegex.replace(second, "") } + }.let{ last -> findIpv4AddressRegex.replace(last,"") } } fun clear() {