diff options
| author | David Göransson <david.goransson@mullvad.net> | 2025-02-20 11:07:16 +0100 |
|---|---|---|
| committer | David Göransson <david.goransson@mullvad.net> | 2025-02-25 12:02:00 +0100 |
| commit | a473a917e1bfad3c7d9baa1a948eacb5096455aa (patch) | |
| tree | 81fd40d56c6c0278b004a54ca54626ddf22861cb /android/lib | |
| parent | 5bf54582abe5c1b8e0660c643feb01385d312f5c (diff) | |
| download | mullvadvpn-a473a917e1bfad3c7d9baa1a948eacb5096455aa.tar.xz mullvadvpn-a473a917e1bfad3c7d9baa1a948eacb5096455aa.zip | |
Fix incorrectly notifying offline
Incorrectly notifying that we are offline to the daemon would result in
us enter ErrorState, and thus restarting the tunnel in a blocking
state, opening a small window for leaks of traffic.
Diffstat (limited to 'android/lib')
| -rw-r--r-- | android/lib/talpid/src/main/kotlin/net/mullvad/talpid/ConnectivityListener.kt | 49 |
1 files changed, 30 insertions, 19 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 2e35e99f0f..9c82d62251 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 @@ -2,21 +2,23 @@ package net.mullvad.talpid import android.net.ConnectivityManager import android.net.LinkProperties -import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest import co.touchlab.kermit.Logger import java.net.InetAddress import kotlin.collections.ArrayList import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.merge 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 net.mullvad.talpid.model.NetworkState import net.mullvad.talpid.util.NetworkEvent import net.mullvad.talpid.util.RawNetworkState @@ -56,7 +58,12 @@ class ConnectivityListener(private val connectivityManager: ConnectivityManager) _isConnected = hasInternetCapability() .onEach { notifyConnectivityChange(it) } - .stateIn(scope, SharingStarted.Eagerly, false) + .stateIn( + scope, + SharingStarted.Eagerly, + true, // Assume we have internet until we know otherwise + ) + } /** * Invalidates the network state cache. E.g when the VPN is connected or disconnected, and we @@ -70,36 +77,40 @@ class ConnectivityListener(private val connectivityManager: ConnectivityManager) private fun LinkProperties.dnsServersWithoutFallback(): List<InetAddress> = dnsServers.filter { it.hostAddress != TalpidVpnService.FALLBACK_DUMMY_DNS_SERVER } - private fun hasInternetCapability(): Flow<Boolean> { - val request = - NetworkRequest.Builder() - .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .build() + private val nonVPNNetworksRequest = + NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN).build() + private fun hasInternetCapability(): Flow<Boolean> { + @Suppress("DEPRECATION") return connectivityManager - .networkEvents(request) - .scan(setOf<Network>()) { networks, event -> + .networkEvents(nonVPNNetworksRequest) + .scan( + connectivityManager.allNetworks.associateWith { + connectivityManager.getNetworkCapabilities(it) + } + ) { networks, event -> when (event) { - is NetworkEvent.Available -> { - Logger.d("Network available ${event.network}") - (networks + event.network).also { - Logger.d("Number of networks: ${it.size}") - } - } is NetworkEvent.Lost -> { Logger.d("Network lost ${event.network}") (networks - event.network).also { Logger.d("Number of networks: ${it.size}") } } + is NetworkEvent.CapabilitiesChanged -> { + Logger.d("Network capabilities changed ${event.network}") + (networks + (event.network to event.networkCapabilities)).also { + Logger.d("Number of networks: ${it.size}") + } + } else -> networks } } - .map { it.isNotEmpty() } - .distinctUntilChanged() + .map { it.any { it.value.hasInternetCapability() } } } + private fun NetworkCapabilities?.hasInternetCapability(): Boolean = + this?.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) == true + private fun RawNetworkState.toNetworkState(): NetworkState = NetworkState( network.networkHandle, |
