diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-06-14 13:48:25 +0000 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-06-18 10:40:26 +0000 |
| commit | 2dc2f762228ed61cd27971fefe74c3540778f1a1 (patch) | |
| tree | 38eb2dbb36c32c6e72526116c3e45c41d9009c26 | |
| parent | a60873ee8564157fc0e0a1c40df205c6c4104436 (diff) | |
| download | mullvadvpn-2dc2f762228ed61cd27971fefe74c3540778f1a1.tar.xz mullvadvpn-2dc2f762228ed61cd27971fefe74c3540778f1a1.zip | |
Create `LocationInfoCache` helper class
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt new file mode 100644 index 0000000000..ba3f9cefd4 --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/dataproxy/LocationInfoCache.kt @@ -0,0 +1,67 @@ +package net.mullvad.mullvadvpn.dataproxy + +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.Job + +import net.mullvad.mullvadvpn.model.GeoIpLocation +import net.mullvad.mullvadvpn.model.TunnelStateTransition +import net.mullvad.mullvadvpn.MullvadDaemon + +class LocationInfoCache(val daemon: Deferred<MullvadDaemon>) { + private var lastKnownRealLocation: GeoIpLocation? = null + private var activeFetch: Job? = null + + var onNewLocation: ((String, String, String) -> Unit)? = null + + var location: GeoIpLocation? = null + set(value) { + field = value + notifyNewLocation(value) + } + + fun setState(state: TunnelStateTransition) { + activeFetch?.cancel() + activeFetch = null + + when (state) { + is TunnelStateTransition.Disconnected -> activeFetch = fetchRealLocation() + is TunnelStateTransition.Connecting -> activeFetch = fetchRelayLocation() + is TunnelStateTransition.Connected -> activeFetch = fetchRelayLocation() + is TunnelStateTransition.Disconnecting -> location = lastKnownRealLocation + is TunnelStateTransition.Blocked -> location = null + } + } + + fun notifyNewLocation(location: GeoIpLocation?) { + val country = location?.country ?: "" + val city = location?.city ?: "" + val hostname = location?.hostname ?: "" + + onNewLocation?.invoke(country, city, hostname) + } + + private fun fetchRealLocation() = GlobalScope.launch(Dispatchers.Main) { + var realLocation: GeoIpLocation? = null + var remainingAttempts = 10 + + while (realLocation == null && remainingAttempts > 0) { + realLocation = fetchLocation().await() + remainingAttempts -= 1 + } + + lastKnownRealLocation = realLocation + location = realLocation + } + + private fun fetchRelayLocation() = GlobalScope.launch(Dispatchers.Main) { + location = fetchLocation().await() + } + + private fun fetchLocation() = GlobalScope.async(Dispatchers.Default) { + daemon.await().getCurrentLocation() + } +} |
