Commit 7d52441c authored by Daniel Wolf's avatar Daniel Wolf
Browse files

Show a notification when the VPN seems to have disconnected

parent ae14ccff
......@@ -95,6 +95,7 @@ class DnsVpnService : VpnService(), Runnable, CoroutineScope {
private var localResolver:LocalResolver? = null
private var runInNonVpnMode:Boolean = getPreferences().runWithoutVpn
private var connectionWatchDog:ConnectionWatchdog? = null
private var vpnWatchdog:VpnWatchDog? = null
private var watchdogDisabledForSession = false
private val coroutineSupervisor = SupervisorJob()
@Suppress("EXPERIMENTAL_API_USAGE")
......@@ -912,6 +913,7 @@ class DnsVpnService : VpnService(), Runnable, CoroutineScope {
vpnProxy?.stop()
dnsServerProxy?.stop()
connectionWatchDog?.stop()
vpnWatchdog?.stop()
if(ipTablesRedirector == null || ipTablesRedirector?.endForward() == IpTablesPacketRedirector.IpTablesMode.SUCCEEDED) {
getPreferences().lastIptablesRedirectAddress = null
getPreferences().lastIptablesRedirectAddressIPv6 = null
......@@ -973,16 +975,20 @@ class DnsVpnService : VpnService(), Runnable, CoroutineScope {
BackgroundVpnConfigureActivity.prepareVpn(this, userServerConfig)
}, 250)
} else if(getPreferences().showNotificationOnRevoked){
NotificationCompat.Builder(this, Notifications.getHighPriorityChannelId(this)).apply {
setSmallIcon(R.drawable.ic_cloud_warn)
setContentTitle(getString(R.string.notification_service_revoked_title))
setContentText(getString(R.string.notification_service_revoked_message))
setContentIntent(PendingIntent.getActivity(this@DnsVpnService, RequestCodes.RESTART_AFTER_REVOKE, Intent(this@DnsVpnService, BackgroundVpnConfigureActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT))
setAutoCancel(true)
priority = NotificationCompat.PRIORITY_HIGH
}.build().also {
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(Notifications.ID_SERVICE_REVOKED, it)
}
showVpnRevokedNotification()
}
}
private fun showVpnRevokedNotification() {
NotificationCompat.Builder(this, Notifications.getHighPriorityChannelId(this)).apply {
setSmallIcon(R.drawable.ic_cloud_warn)
setContentTitle(getString(R.string.notification_service_revoked_title))
setContentText(getString(R.string.notification_service_revoked_message))
setContentIntent(PendingIntent.getActivity(this@DnsVpnService, RequestCodes.RESTART_AFTER_REVOKE, Intent(this@DnsVpnService, BackgroundVpnConfigureActivity::class.java), PendingIntent.FLAG_CANCEL_CURRENT))
setAutoCancel(true)
priority = NotificationCompat.PRIORITY_HIGH
}.build().also {
(getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).notify(Notifications.ID_SERVICE_REVOKED, it)
}
}
......@@ -1383,7 +1389,6 @@ class DnsVpnService : VpnService(), Runnable, CoroutineScope {
val usedAddress = if(bindAddress == defaultBindAddress) "localhost" else bindAddress.hostAddress
showDnsServerModeNotification(usedAddress, actualPort, preferredPort, iptablesMode)
currentTrafficStats = vpnProxy?.trafficStats
createConnectionWatchdog()
log("Non-VPN proxy started.")
}
} else {
......@@ -1427,6 +1432,9 @@ class DnsVpnService : VpnService(), Runnable, CoroutineScope {
hideBadConnectionNotification()
}, logger = this@DnsVpnService.logger, advancedLogging = getPreferences().advancedLogging)
}
vpnWatchdog = VpnWatchDog({
showVpnRevokedNotification()
}, this)
}
private fun createQueryLogger(): QueryListener? {
......
package com.frostnerd.smokescreen.service
import android.content.Context
import android.net.ConnectivityManager
import com.frostnerd.smokescreen.Logger
import com.frostnerd.smokescreen.isVpnNetwork
import com.frostnerd.smokescreen.logger
import kotlinx.coroutines.*
/*
* Copyright (C) 2020 Daniel Wolf (Ch4t4r)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* You can contact the developer at daniel.wolf@frostnerd.com.
*/
class VpnWatchDog(private val onVpnDisconnected:() -> Unit,
private val context: Context) {
private val supervisor = SupervisorJob()
private val scope = CoroutineScope(supervisor + Dispatchers.IO)
private var running = true
private var vpnRunning:Boolean = true
private val logger:Logger? = context.logger
private val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
init {
scope.launch {
checkConnection()
}
}
private fun log(text:String) {
logger?.log(text, "ConnectionWatchdog")
}
private suspend fun checkConnection() {
delay(3000)
log("Beginning VPN-check")
val networks = connectivityManager.allNetworks.toList().filterNotNull()
val isStillRunning = networks.any { connectivityManager.isVpnNetwork(it) } || networks.isEmpty()
if(!isStillRunning && vpnRunning) {
callCallback()
}
vpnRunning = isStillRunning
if(running) {
log("Connection check done.")
scope.launch {
checkConnection()
}
}
}
private fun callCallback() {
if(!running) return
log("Calling callback.")
onVpnDisconnected()
}
fun stop() {
supervisor.cancel()
running = false
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment