From 16df1c7adba25970d2b4e4db8c9ce53579349624 Mon Sep 17 00:00:00 2001 From: Jonathan Nobels Date: Wed, 4 Jun 2025 11:37:24 -0400 Subject: [PATCH] android: use updated exit node detection logic in exit node categorizer updates tailscale/corp#29045 The exit node sorting logic wasn't using node.isMullvadNode and still had a variant of the original issue (listing mullvad nodes as self-nodes). This also switches the logic to ignore the name fields entirely and queue only off the Location field matching Windows and Apple. Signed-off-by: Jonathan Nobels --- .../src/main/java/com/tailscale/ipn/ui/model/TailCfg.kt | 8 ++------ .../tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/android/src/main/java/com/tailscale/ipn/ui/model/TailCfg.kt b/android/src/main/java/com/tailscale/ipn/ui/model/TailCfg.kt index 2e9be75..7392aa6 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/model/TailCfg.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/model/TailCfg.kt @@ -107,13 +107,9 @@ class Tailcfg { val isExitNode: Boolean = (AllowedIPs?.contains("0.0.0.0/0") ?: false) && (AllowedIPs?.contains("::/0") ?: false) - // mullvad nodes are exit nodes with a mullvad.ts.net domain *or* Location Info. - // These checks are intentionally redundant to avoid false negatives. + // mullvad nodes are exit nodes with non-nil Location info. val isMullvadNode: Boolean - get() = - Name.endsWith(".mullvad.ts.net") || - ComputedName?.endsWith(".mullvad.ts.net") == true || - Hostinfo.Location != null + get() = Hostinfo.Location != null val displayName: String get() = ComputedName ?: Name diff --git a/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt b/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt index 360d30d..857eca9 100644 --- a/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt +++ b/android/src/main/java/com/tailscale/ipn/ui/viewModel/ExitNodePickerViewModel.kt @@ -12,12 +12,12 @@ import com.tailscale.ipn.ui.model.StableNodeID import com.tailscale.ipn.ui.notifier.Notifier import com.tailscale.ipn.ui.util.LoadingIndicator import com.tailscale.ipn.ui.util.set -import java.util.TreeMap import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +import java.util.TreeMap data class ExitNodePickerNav( val onNavigateBackHome: () -> Unit, @@ -75,7 +75,7 @@ class ExitNodePickerViewModel(private val nav: ExitNodePickerNav) : IpnViewModel label = it.displayName, online = MutableStateFlow(it.Online ?: false), selected = it.StableID == exitNodeId, - mullvad = it.Name.endsWith(".mullvad.ts.net."), + mullvad = it.isMullvadNode, priority = it.Hostinfo.Location?.Priority ?: 0, countryCode = it.Hostinfo.Location?.CountryCode ?: "", country = it.Hostinfo.Location?.Country ?: "",