Compare commits

..

4 Commits

Author SHA1 Message Date
Zane Schepke 89212fe191 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.
2023-07-07 23:11:15 -04:00
Zane Schepke a98a47f54d fix: prevent crash from bad file config upload and bug preventing vpn from starting via watcher service after reboot
Add catch for file configs that are malformed and display message to the user

Pass full tunnel config to watcher service after detecting reboot to allow watcher service to start tunnel properly.
2023-07-05 23:21:55 -04:00
Zane Schepke cb3a7d024b fix: discord link expired 2023-07-04 22:28:39 -04:00
Zane Schepke 259be21b04 docs: update README 2023-07-04 17:03:30 -04:00
8 changed files with 51 additions and 29 deletions
+1
View File
@@ -43,6 +43,7 @@ The inspiration for this app came from the inconvenience of constantly having to
* Add tunnels via .conf file
* Auto connect to VPN based on Wi-Fi SSID
* Split tunneling by application
* Configurable Trusted Network list
* Optional auto connect on mobile data
* Automatic service restart after reboot
+1 -1
View File
@@ -17,7 +17,7 @@ android {
val versionMajor = 2
val versionMinor = 0
val versionPatch = 0
val versionPatch = 3
val versionBuild = 0
defaultConfig {
@@ -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.TunnelConfig
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import javax.inject.Inject
@@ -25,7 +26,7 @@ class BootReceiver : BroadcastReceiver() {
@OptIn(DelicateCoroutinesApi::class)
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Intent.ACTION_BOOT_COMPLETED) {
GlobalScope.launch {
CoroutineScope(SupervisorJob()).launch {
try {
val settings = settingsRepo.getAll()
if (!settings.isNullOrEmpty()) {
@@ -36,7 +37,7 @@ class BootReceiver : BroadcastReceiver() {
Action.START, context,
WireGuardConnectivityWatcherService::class.java,
mapOf(context.resources.getString(R.string.tunnel_extras_key) to
defaultTunnel.id.toString())
defaultTunnel.toString())
)
}
}
@@ -6,8 +6,8 @@ import android.app.Service
import android.content.Context
import android.content.Context.ACTIVITY_SERVICE
import android.content.Intent
import android.content.SharedPreferences
import com.zaneschepke.wireguardautotunnel.R
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
object ServiceTracker {
@Suppress("DEPRECATION")
@@ -31,7 +31,11 @@ object ServiceTracker {
}
}
intent.component?.javaClass
application.startService(intent)
try {
application.startService(intent)
} catch (e : Exception) {
e.message?.let { Firebase.crashlytics.log(it) }
}
}
fun <T : Service> actionOnService(action: Action, context: Context, cls : Class<T>, extras : Map<String,String>? = null) {
@@ -43,6 +47,10 @@ object ServiceTracker {
}
}
intent.component?.javaClass
context.startService(intent)
try {
context.startService(intent)
} catch (e : Exception) {
e.message?.let { Firebase.crashlytics.log(it) }
}
}
}
@@ -19,9 +19,10 @@ import com.zaneschepke.wireguardautotunnel.service.notification.NotificationServ
import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.Settings
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -99,9 +100,7 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
//try to start task again if killed
override fun onTaskRemoved(rootIntent: Intent) {
Timber.d("Task Removed called")
val restartServiceIntent = Intent(applicationContext, this::class.java).also {
it.setPackage(packageName)
};
val restartServiceIntent = Intent(rootIntent)
val restartServicePendingIntent: PendingIntent = PendingIntent.getService(this, 1, restartServiceIntent,
PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE);
applicationContext.getSystemService(Context.ALARM_SERVICE);
@@ -126,16 +125,16 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
@OptIn(DelicateCoroutinesApi::class)
private fun startWatcherJob() {
watcherJob = GlobalScope.launch {
watcherJob = CoroutineScope(SupervisorJob()).launch {
val settings = settingsRepo.getAll();
if(!settings.isNullOrEmpty()) {
setting = settings[0]
}
GlobalScope.launch {
CoroutineScope(watcherJob).launch {
watchForWifiConnectivityChanges()
}
if(setting.isTunnelOnMobileDataEnabled) {
GlobalScope.launch {
CoroutineScope(watcherJob).launch {
watchForMobileDataConnectivityChanges()
}
}
@@ -194,11 +193,18 @@ class WireGuardConnectivityWatcherService : ForegroundService() {
is NetworkStatus.Unavailable -> {
isWifiConnected = false
Timber.d("Lost Wi-Fi connection")
if(setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.DOWN
&& isMobileDataConnected){
Timber.d("Wifi not available so starting vpn for mobile data")
startVPN()
if(!connecting || !disconnecting) {
if(setting.isTunnelOnMobileDataEnabled && vpnService.getState() == Tunnel.State.DOWN
&& isMobileDataConnected){
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()
}
}
}
}
}
@@ -8,10 +8,9 @@ import com.zaneschepke.wireguardautotunnel.service.tunnel.VpnService
import com.zaneschepke.wireguardautotunnel.service.tunnel.model.TunnelConfig
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@@ -29,12 +28,11 @@ class WireGuardTunnelService : ForegroundService() {
private lateinit var job : Job
@OptIn(DelicateCoroutinesApi::class)
override fun startService(extras : Bundle?) {
super.startService(extras)
val tunnelConfigString = extras?.getString(getString(R.string.tunnel_extras_key))
cancelJob()
job = GlobalScope.launch {
job = CoroutineScope(SupervisorJob()).launch {
if(tunnelConfigString != null) {
try {
val tunnelConfig = TunnelConfig.from(tunnelConfigString)
@@ -7,6 +7,7 @@ import android.net.Uri
import android.provider.OpenableColumns
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.wireguard.config.BadConfigException
import com.wireguard.config.Config
import com.zaneschepke.wireguardautotunnel.R
import com.zaneschepke.wireguardautotunnel.repository.Repository
@@ -122,12 +123,18 @@ class MainViewModel @Inject constructor(private val application : Application,
val stream = application.applicationContext.contentResolver.openInputStream(uri)
stream ?: return
val bufferReader = stream.bufferedReader(charset = Charsets.UTF_8)
val config = Config.parse(bufferReader)
val tunnelName = getNameFromFileName(fileName)
viewModelScope.launch {
tunnelRepo.save(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString()))
try {
val config = Config.parse(bufferReader)
val tunnelName = getNameFromFileName(fileName)
viewModelScope.launch {
tunnelRepo.save(TunnelConfig(name = tunnelName, wgQuick = config.toWgQuickString()))
}
stream.close()
} catch(_: BadConfigException) {
viewModelScope.launch {
showSnackBarMessage(application.applicationContext.getString(R.string.bad_config))
}
}
stream.close()
}
@SuppressLint("Range")
+2 -1
View File
@@ -12,7 +12,7 @@
<string name="turn_off_tunnel">Turn off tunnel before editing</string>
<string name="no_tunnels">No tunnels added yet!</string>
<string name="tunnel_exists">Tunnel name already exists</string>
<string name="discord_url">https://discord.gg/Ad5fuEts</string>
<string name="discord_url">https://discord.gg/rbRRNh6H7V</string>
<string name="watcher_notification_title">Watcher Service</string>
<string name="watcher_notification_text">Monitoring network state changes</string>
<string name="tunnel_start_title">VPN Connected</string>
@@ -57,4 +57,5 @@
<string name="no_thanks">No thanks</string>
<string name="turn_on">Turn on</string>
<string name="map">Map</string>
<string name="bad_config">Bad config. Please try again.</string>
</resources>