fix: fix bug causing inconsistent behavior after making trusted ssid changes, fix bug causing vpn not to disconnect on mobile data

This fixes a bug causing inconsistent connects and disconnects to vpn on wifi capability changes by properly associated a child job to a parent job using a SupervisorJob instead of a GlobalScope job.

This fixes a bug causing VPN to stay connected on mobile data even when the setting is disabled by adding an additional check for this situation to disable the tunnel.
This commit is contained in:
Zane Schepke 2023-07-07 23:11:15 -04:00
parent a98a47f54d
commit 89212fe191
4 changed files with 23 additions and 20 deletions

View File

@ -17,7 +17,7 @@ android {
val versionMajor = 2 val versionMajor = 2
val versionMinor = 0 val versionMinor = 0
val versionPatch = 2 val versionPatch = 3
val versionBuild = 0 val versionBuild = 0
defaultConfig { defaultConfig {

View File

@ -10,8 +10,9 @@ import com.zaneschepke.wireguardautotunnel.service.foreground.WireGuardConnectiv
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -25,7 +26,7 @@ class BootReceiver : BroadcastReceiver() {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) { if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
GlobalScope.launch { CoroutineScope(SupervisorJob()).launch {
try { try {
val settings = settingsRepo.getAll() val settings = settingsRepo.getAll()
if (!settings.isNullOrEmpty()) { if (!settings.isNullOrEmpty()) {

View File

@ -19,9 +19,10 @@ import com.zaneschepke.wireguardautotunnel.service.notification.NotificationServ
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -99,9 +100,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
//try to start task again if killed //try to start task again if killed
override fun onTaskRemoved(rootIntent: Intent) { override fun onTaskRemoved(rootIntent: Intent) {
Timber.d("Task Removed called") Timber.d("Task Removed called")
val restartServiceIntent = Intent(applicationContext, this::class.java).also { val restartServiceIntent = Intent(rootIntent)
it.setPackage(packageName)
};
val restartServicePendingIntent: PendingIntent = PendingIntent.getService(this, 1, restartServiceIntent, val restartServicePendingIntent: PendingIntent = PendingIntent.getService(this, 1, restartServiceIntent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE); PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE);
applicationContext.getSystemService(Context.ALARM_SERVICE); applicationContext.getSystemService(Context.ALARM_SERVICE);
@ -126,16 +125,16 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
@OptIn(DelicateCoroutinesApi::class) @OptIn(DelicateCoroutinesApi::class)
private fun startWatcherJob() { private fun startWatcherJob() {
watcherJob = GlobalScope.launch { watcherJob = CoroutineScope(SupervisorJob()).launch {
val settings = settingsRepo.getAll(); val settings = settingsRepo.getAll();
if(!settings.isNullOrEmpty()) { if(!settings.isNullOrEmpty()) {
setting = settings[0] setting = settings[0]
} }
GlobalScope.launch { CoroutineScope(watcherJob).launch {
watchForWifiConnectivityChanges() watchForWifiConnectivityChanges()
} }
if(setting.isTunnelOnMobileDataEnabled) { if(setting.isTunnelOnMobileDataEnabled) {
GlobalScope.launch { CoroutineScope(watcherJob).launch {
watchForMobileDataConnectivityChanges() watchForMobileDataConnectivityChanges()
} }
} }
@ -161,7 +160,6 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
if(!isWifiConnected && vpnService.getState() == Tunnel.State.UP) stopVPN() if(!isWifiConnected && vpnService.getState() == Tunnel.State.UP) stopVPN()
Timber.d("Lost mobile data connection") Timber.d("Lost mobile data connection")
} }
else -> {}
} }
} }
} }
@ -195,13 +193,19 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
is NetworkStatus.Unavailable -> { is NetworkStatus.Unavailable -> {
isWifiConnected = false isWifiConnected = false
Timber.d("Lost Wi-Fi connection") Timber.d("Lost Wi-Fi connection")
if(setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.DOWN if(!connecting || !disconnecting) {
&& isMobileDataConnected){ if(setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.DOWN
Timber.d("Wifi not available so starting vpn for mobile data") && isMobileDataConnected){
startVPN() Timber.d("Wifi not available so starting vpn for mobile data")
startVPN()
}
if(!setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.UP) {
Timber.d("Lost WiFi connection, disabling vpn")
stopVPN()
}
} }
} }
else -> {}
} }
} }
} }

View File

@ -8,10 +8,9 @@ import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -29,12 +28,11 @@ class WireGuardTunnelService : ForegroundService() {
private lateinit var job : Job private lateinit var job : Job
@OptIn(DelicateCoroutinesApi::class)
override fun startService(extras : Bundle?) { override fun startService(extras : Bundle?) {
super.startService(extras) super.startService(extras)
val tunnelConfigString = extras?.getString(getString(R.string.tunnel_extras_key)) val tunnelConfigString = extras?.getString(getString(R.string.tunnel_extras_key))
cancelJob() cancelJob()
job = GlobalScope.launch { job = CoroutineScope(SupervisorJob()).launch {
if(tunnelConfigString != null) { if(tunnelConfigString != null) {
try { try {
val tunnelConfig = TunnelConfig.from(tunnelConfigString) val tunnelConfig = TunnelConfig.from(tunnelConfigString)