diff options
| author | David Göransson <david.goransson90@gmail.com> | 2023-12-14 16:23:09 +0100 |
|---|---|---|
| committer | Albin <albin@mullvad.net> | 2023-12-14 16:54:21 +0100 |
| commit | f33b1f76eac937b579ef589cc047da8f3421f630 (patch) | |
| tree | 89e54908a6c5f7162813213bec00bfa425e521a0 /android/app/src/main | |
| parent | 0d4451264d129bc6bcc8ae30bf12dc807f8ab3bc (diff) | |
| download | mullvadvpn-f33b1f76eac937b579ef589cc047da8f3421f630.tar.xz mullvadvpn-f33b1f76eac937b579ef589cc047da8f3421f630.zip | |
Add OutOfTimeUseCase
Diffstat (limited to 'android/app/src/main')
| -rw-r--r-- | android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCase.kt | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCase.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCase.kt new file mode 100644 index 0000000000..ba7ce83172 --- /dev/null +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/OutOfTimeUseCase.kt @@ -0,0 +1,77 @@ +package net.mullvad.mullvadvpn.usecase + +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onStart +import net.mullvad.mullvadvpn.lib.ipc.Event +import net.mullvad.mullvadvpn.lib.ipc.MessageHandler +import net.mullvad.mullvadvpn.lib.ipc.events +import net.mullvad.mullvadvpn.model.AccountExpiry +import net.mullvad.mullvadvpn.model.TunnelState +import net.mullvad.mullvadvpn.repository.AccountRepository +import net.mullvad.talpid.tunnel.ErrorStateCause +import org.joda.time.DateTime + +const val accountRefreshIntervalMillis = 60L * 1000L // 1 minute +const val bufferTimeMillis = 60L * 1000L // 1 minute + +class OutOfTimeUseCase( + private val repository: AccountRepository, + private val messageHandler: MessageHandler +) { + + fun isOutOfTime(): Flow<Boolean?> = + combine(pastAccountExpiry(), isTunnelBlockedBecauseOutOfTime()) { + accountExpiryHasPast, + tunnelOutOfTime -> + reduce(accountExpiryHasPast, tunnelOutOfTime) + } + .distinctUntilChanged() + + private fun reduce(vararg outOfTimeProperty: Boolean?): Boolean? = + when { + // If any advertises as out of time + outOfTimeProperty.any { it == true } -> true + // If all advertise as not out of time + outOfTimeProperty.all { it == false } -> false + // If some are unknown + else -> null + } + + private fun isTunnelBlockedBecauseOutOfTime() = + messageHandler + .events<Event.TunnelStateChange>() + .map { it.tunnelState.isTunnelErrorStateDueToExpiredAccount() } + .onStart { emit(false) } + + private fun TunnelState.isTunnelErrorStateDueToExpiredAccount(): Boolean { + return ((this as? TunnelState.Error)?.errorState?.cause as? ErrorStateCause.AuthFailed) + ?.isCausedByExpiredAccount() + ?: false + } + + private fun pastAccountExpiry(): Flow<Boolean?> = + combine( + repository.accountExpiryState.map { + if (it is AccountExpiry.Available) { + it.date() + } else { + null + } + }, + timeFlow() + ) { expiryDate, time -> + expiryDate?.isBefore(time.plus(bufferTimeMillis)) + } + + private fun timeFlow() = flow { + while (true) { + emit(DateTime.now()) + delay(accountRefreshIntervalMillis) + } + } +} |
