summaryrefslogtreecommitdiffhomepage
path: root/android/lib/talpid/src
diff options
context:
space:
mode:
authorDavid Göransson <david.goransson@mullvad.net>2025-02-20 11:09:42 +0100
committerDavid Göransson <david.goransson@mullvad.net>2025-02-25 12:02:00 +0100
commitb63bc866946795be36a617adf65c8c6db071b05d (patch)
treec93db6a693a01510653723812d0985c94f6cd910 /android/lib/talpid/src
parenta473a917e1bfad3c7d9baa1a948eacb5096455aa (diff)
downloadmullvadvpn-b63bc866946795be36a617adf65c8c6db071b05d.tar.xz
mullvadvpn-b63bc866946795be36a617adf65c8c6db071b05d.zip
Reduce open_tun calls (Establish)
Each call to Establish opens a window for leaks on android. By only invoking Establish if the VpnConfig if any of the input has changed and reusing it otherwise we avoid many of these leaks. This commit also waits for android to report back that the routes have been created to ping and verify connectivity to avoid pings going outside the tunnel.
Diffstat (limited to 'android/lib/talpid/src')
-rw-r--r--android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt17
-rw-r--r--android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt29
2 files changed, 18 insertions, 28 deletions
diff --git a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
index 9c82d62251..b702a39a6e 100644
--- a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
+++ b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt
@@ -10,6 +10,7 @@ import kotlin.collections.ArrayList
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
@@ -18,7 +19,7 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.scan
import kotlinx.coroutines.flow.stateIn
-import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.launch
import net.mullvad.talpid.model.NetworkState
import net.mullvad.talpid.util.NetworkEvent
import net.mullvad.talpid.util.RawNetworkState
@@ -31,29 +32,30 @@ class ConnectivityListener(private val connectivityManager: ConnectivityManager)
val isConnected
get() = _isConnected.value
- private lateinit var _currentNetworkState: StateFlow<NetworkState?>
+ private val _mutableNetworkState = MutableStateFlow<NetworkState?>(null)
private val resetNetworkState: Channel<Unit> = Channel()
// Used by JNI
val currentDefaultNetworkState: NetworkState?
- get() = _currentNetworkState.value
+ get() = _mutableNetworkState.value
// Used by JNI
val currentDnsServers: ArrayList<InetAddress>
- get() = _currentNetworkState.value?.dnsServers ?: ArrayList()
+ get() = _mutableNetworkState.value?.dnsServers ?: ArrayList()
fun register(scope: CoroutineScope) {
// Consider implementing retry logic for the flows below, because registering a listener on
// the default network may fail if the network on Android 11
// https://issuetracker.google.com/issues/175055271?pli=1
- _currentNetworkState =
+ scope.launch {
merge(
connectivityManager.defaultRawNetworkStateFlow(),
resetNetworkState.receiveAsFlow().map { null },
)
.map { it?.toNetworkState() }
.onEach { notifyDefaultNetworkChange(it) }
- .stateIn(scope, SharingStarted.Eagerly, null)
+ .collect(_mutableNetworkState)
+ }
_isConnected =
hasInternetCapability()
@@ -70,8 +72,7 @@ class ConnectivityListener(private val connectivityManager: ConnectivityManager)
* know the last known values not to be correct anymore.
*/
fun invalidateNetworkStateCache() {
- // TODO remove runBlocking
- runBlocking { resetNetworkState.send(Unit) }
+ _mutableNetworkState.value = null
}
private fun LinkProperties.dnsServersWithoutFallback(): List<InetAddress> =
diff --git a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
index a143df6132..1457ff35f4 100644
--- a/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
+++ b/android/lib/talpid/src/main/kotlin/net/mullvad/talpid/TalpidVpnService.kt
@@ -57,34 +57,22 @@ open class TalpidVpnService : LifecycleVpnService() {
// Used by JNI
fun openTun(config: TunConfig): CreateTunResult =
synchronized(this) {
- val tunStatus = activeTunStatus
-
- if (config == currentTunConfig && tunStatus != null && tunStatus.isOpen) {
- tunStatus
- } else {
- openTunImpl(config)
+ createTun(config).merge().also {
+ currentTunConfig = config
+ activeTunStatus = it
}
}
// Used by JNI
- fun openTunForced(config: TunConfig): CreateTunResult =
- synchronized(this) { openTunImpl(config) }
-
- // Used by JNI
- fun closeTun(): Unit = synchronized(this) { activeTunStatus = null }
+ fun closeTun(): Unit =
+ synchronized(this) {
+ connectivityListener.invalidateNetworkStateCache()
+ activeTunStatus = null
+ }
// Used by JNI
fun bypass(socket: Int): Boolean = protect(socket)
- private fun openTunImpl(config: TunConfig): CreateTunResult {
- val newTunStatus = createTun(config).merge()
-
- currentTunConfig = config
- activeTunStatus = newTunStatus
-
- return newTunStatus
- }
-
private fun createTun(
config: TunConfig
): Either<CreateTunResult.Error, CreateTunResult.Success> = either {
@@ -123,6 +111,7 @@ open class TalpidVpnService : LifecycleVpnService() {
builder.addDnsServer(FALLBACK_DUMMY_DNS_SERVER)
}
+ connectivityListener.invalidateNetworkStateCache()
val vpnInterfaceFd =
builder
.establishSafe()