diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2024-06-13 16:31:40 +0200 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2024-06-14 13:27:05 +0200 |
| commit | e80e9ee68559fcd32747c28a829e70d2121e9344 (patch) | |
| tree | 0caefca40bdc425b44a5c1dc719b1f409933fb6f /android/lib | |
| parent | 6fb4623503fda3df77a9c7c3cc152a45506ba1a4 (diff) | |
| download | mullvadvpn-e80e9ee68559fcd32747c28a829e70d2121e9344.tar.xz mullvadvpn-e80e9ee68559fcd32747c28a829e70d2121e9344.zip | |
Add api acccess method functionality
Diffstat (limited to 'android/lib')
21 files changed, 391 insertions, 3 deletions
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt index f8073323c8..987b7e56ea 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt @@ -3,6 +3,8 @@ package net.mullvad.mullvadvpn.lib.daemon.grpc import android.net.LocalSocketAddress import android.util.Log import arrow.core.Either +import arrow.core.raise.either +import arrow.core.raise.ensure import arrow.optics.copy import arrow.optics.dsl.index import arrow.optics.typeclasses.Index @@ -42,7 +44,11 @@ import net.mullvad.mullvadvpn.lib.daemon.grpc.util.LogInterceptor import net.mullvad.mullvadvpn.lib.daemon.grpc.util.connectivityFlow import net.mullvad.mullvadvpn.lib.model.AccountData import net.mullvad.mullvadvpn.lib.model.AccountNumber +import net.mullvad.mullvadvpn.lib.model.AddApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.AddSplitTunnelingAppError +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethod +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodId +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodSetting import net.mullvad.mullvadvpn.lib.model.AppId import net.mullvad.mullvadvpn.lib.model.AppVersionInfo as ModelAppVersionInfo import net.mullvad.mullvadvpn.lib.model.ClearAllOverridesError @@ -67,6 +73,7 @@ import net.mullvad.mullvadvpn.lib.model.GetAccountHistoryError import net.mullvad.mullvadvpn.lib.model.GetDeviceListError import net.mullvad.mullvadvpn.lib.model.GetDeviceStateError import net.mullvad.mullvadvpn.lib.model.LoginAccountError +import net.mullvad.mullvadvpn.lib.model.NewAccessMethodSetting import net.mullvad.mullvadvpn.lib.model.ObfuscationSettings import net.mullvad.mullvadvpn.lib.model.Ownership as ModelOwnership import net.mullvad.mullvadvpn.lib.model.PlayPurchase @@ -84,9 +91,11 @@ import net.mullvad.mullvadvpn.lib.model.RelayItemId as ModelRelayItemId import net.mullvad.mullvadvpn.lib.model.RelayList as ModelRelayList import net.mullvad.mullvadvpn.lib.model.RelayList import net.mullvad.mullvadvpn.lib.model.RelaySettings +import net.mullvad.mullvadvpn.lib.model.RemoveApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.RemoveSplitTunnelingAppError import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation import net.mullvad.mullvadvpn.lib.model.SetAllowLanError +import net.mullvad.mullvadvpn.lib.model.SetApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.SetAutoConnectError import net.mullvad.mullvadvpn.lib.model.SetDnsOptionsError import net.mullvad.mullvadvpn.lib.model.SetObfuscationOptionsError @@ -96,8 +105,11 @@ import net.mullvad.mullvadvpn.lib.model.SetWireguardMtuError import net.mullvad.mullvadvpn.lib.model.SetWireguardQuantumResistantError import net.mullvad.mullvadvpn.lib.model.Settings as ModelSettings import net.mullvad.mullvadvpn.lib.model.SettingsPatchError +import net.mullvad.mullvadvpn.lib.model.TestApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.TunnelState as ModelTunnelState +import net.mullvad.mullvadvpn.lib.model.UnknownApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.UnknownCustomListError +import net.mullvad.mullvadvpn.lib.model.UpdateApiAccessMethodError import net.mullvad.mullvadvpn.lib.model.UpdateCustomListError import net.mullvad.mullvadvpn.lib.model.WebsiteAuthToken import net.mullvad.mullvadvpn.lib.model.WireguardConstraints as ModelWireguardConstraints @@ -161,6 +173,10 @@ class ManagementService( val wireguardEndpointData: Flow<ModelWireguardEndpointData> = relayList.mapNotNull { it.wireguardEndpointData } + private val _mutableCurrentAccessMethod = MutableStateFlow<ApiAccessMethodSetting?>(null) + val currentAccessMethod: Flow<ApiAccessMethodSetting> = + _mutableCurrentAccessMethod.filterNotNull() + fun start() { // Just to ensure that connection is set up since the connection won't be setup without a // call to the daemon @@ -196,9 +212,11 @@ class ManagementService( _mutableVersionInfo.update { event.versionInfo.toDomain() } ManagementInterface.DaemonEvent.EventCase.DEVICE -> _mutableDeviceState.update { event.device.newState.toDomain() } + ManagementInterface.DaemonEvent.EventCase.NEW_ACCESS_METHOD -> { + _mutableCurrentAccessMethod.update { event.newAccessMethod.toDomain() } + } ManagementInterface.DaemonEvent.EventCase.REMOVE_DEVICE -> {} ManagementInterface.DaemonEvent.EventCase.EVENT_NOT_SET -> {} - ManagementInterface.DaemonEvent.EventCase.NEW_ACCESS_METHOD -> {} } } } @@ -297,6 +315,7 @@ class ManagementService( async { _mutableSettings.update { getSettings() } }, async { _mutableVersionInfo.update { getVersionInfo() } }, async { _mutableRelayList.update { getRelayList() } }, + async { _mutableCurrentAccessMethod.update { getCurrentApiAccessMethod() } } ) } } @@ -572,6 +591,55 @@ class ManagementService( Either.catch { grpc.getWwwAuthToken(Empty.getDefaultInstance()) } .map { WebsiteAuthToken.fromString(it.value) } + suspend fun addApiAccessMethod( + newAccessMethodSetting: NewAccessMethodSetting + ): Either<AddApiAccessMethodError, ApiAccessMethodId> = + Either.catch { grpc.addApiAccessMethod(newAccessMethodSetting.fromDomain()) } + .mapLeft(AddApiAccessMethodError::Unknown) + .map { ApiAccessMethodId.fromString(it.value) } + + suspend fun removeApiAccessMethod( + apiAccessMethodId: ApiAccessMethodId + ): Either<RemoveApiAccessMethodError, Unit> = + Either.catch { grpc.removeApiAccessMethod(apiAccessMethodId.fromDomain()) } + .mapLeft(RemoveApiAccessMethodError::Unknown) + .mapEmpty() + + suspend fun setApiAccessMethod( + apiAccessMethodId: ApiAccessMethodId + ): Either<SetApiAccessMethodError, Unit> = + Either.catch { grpc.setApiAccessMethod(apiAccessMethodId.fromDomain()) } + .mapLeft(SetApiAccessMethodError::Unknown) + .mapEmpty() + + suspend fun updateApiAccessMethod( + apiAccessMethodSetting: ApiAccessMethodSetting + ): Either<UpdateApiAccessMethodError, Unit> = + Either.catch { grpc.updateApiAccessMethod(apiAccessMethodSetting.fromDomain()) } + .mapLeft(::UnknownApiAccessMethodError) + .mapEmpty() + + private suspend fun getCurrentApiAccessMethod(): ApiAccessMethodSetting = + grpc.getCurrentApiAccessMethod(Empty.getDefaultInstance()).toDomain() + + suspend fun testCustomApiAccessMethod( + customProxy: ApiAccessMethod.CustomProxy + ): Either<TestApiAccessMethodError, Unit> = + Either.catch { grpc.testCustomApiAccessMethod(customProxy.fromDomain()) } + .mapLeftStatus { TestApiAccessMethodError.Grpc } + .map { result -> + either { ensure(result.value) { TestApiAccessMethodError.CouldNotAccess } } + } + + suspend fun testApiAccessMethodById( + apiAccessMethodId: ApiAccessMethodId + ): Either<TestApiAccessMethodError, Unit> = + Either.catch { grpc.testApiAccessMethodById(apiAccessMethodId.fromDomain()) } + .mapLeftStatus { TestApiAccessMethodError.Grpc } + .map { result -> + either { ensure(result.value) { TestApiAccessMethodError.CouldNotAccess } } + } + private fun <A> Either<A, Empty>.mapEmpty() = map {} private inline fun <B, C> Either<Throwable, B>.mapLeftStatus( diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt index 4efd8c452e..014bafb85b 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/FromDomain.kt @@ -1,6 +1,9 @@ package net.mullvad.mullvadvpn.lib.daemon.grpc.mapper import mullvad_daemon.management_interface.ManagementInterface +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethod +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodId +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodSetting import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.CustomDnsOptions import net.mullvad.mullvadvpn.lib.model.CustomList @@ -9,6 +12,7 @@ import net.mullvad.mullvadvpn.lib.model.DefaultDnsOptions import net.mullvad.mullvadvpn.lib.model.DnsOptions import net.mullvad.mullvadvpn.lib.model.DnsState import net.mullvad.mullvadvpn.lib.model.GeoLocationId +import net.mullvad.mullvadvpn.lib.model.NewAccessMethodSetting import net.mullvad.mullvadvpn.lib.model.ObfuscationSettings import net.mullvad.mullvadvpn.lib.model.Ownership import net.mullvad.mullvadvpn.lib.model.PlayPurchase @@ -18,6 +22,8 @@ import net.mullvad.mullvadvpn.lib.model.Providers import net.mullvad.mullvadvpn.lib.model.RelayItemId import net.mullvad.mullvadvpn.lib.model.RelaySettings import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation +import net.mullvad.mullvadvpn.lib.model.SocksAuth +import net.mullvad.mullvadvpn.lib.model.TransportProtocol import net.mullvad.mullvadvpn.lib.model.Udp2TcpObfuscationSettings import net.mullvad.mullvadvpn.lib.model.WireguardConstraints @@ -160,3 +166,74 @@ internal fun PlayPurchase.fromDomain(): ManagementInterface.PlayPurchase = .setPurchaseToken(purchaseToken.fromDomain()) .setProductId(productId) .build() + +internal fun NewAccessMethodSetting.fromDomain(): ManagementInterface.NewAccessMethodSetting = + ManagementInterface.NewAccessMethodSetting.newBuilder() + .setName(name.value) + .setEnabled(enabled) + .setAccessMethod( + ManagementInterface.AccessMethod.newBuilder().setCustom(apiAccessMethod.fromDomain()) + ) + .build() + +internal fun ApiAccessMethod.fromDomain(): ManagementInterface.AccessMethod = + ManagementInterface.AccessMethod.newBuilder() + .let { + when (this) { + ApiAccessMethod.Direct -> + it.setDirect(ManagementInterface.AccessMethod.Direct.getDefaultInstance()) + ApiAccessMethod.Bridges -> + it.setBridges(ManagementInterface.AccessMethod.Bridges.getDefaultInstance()) + is ApiAccessMethod.CustomProxy -> it.setCustom(this.fromDomain()) + } + } + .build() + +internal fun ApiAccessMethod.CustomProxy.fromDomain(): ManagementInterface.CustomProxy = + ManagementInterface.CustomProxy.newBuilder() + .let { + when (this) { + is ApiAccessMethod.CustomProxy.Shadowsocks -> it.setShadowsocks(this.fromDomain()) + is ApiAccessMethod.CustomProxy.Socks5Remote -> it.setSocks5Remote(this.fromDomain()) + } + } + .build() + +internal fun ApiAccessMethod.CustomProxy.Socks5Remote.fromDomain(): + ManagementInterface.Socks5Remote = + ManagementInterface.Socks5Remote.newBuilder().setIp(ip).setPort(port.value).let { + auth?.let { auth -> it.setAuth(auth.fromDomain()) } + it.build() + } + +internal fun SocksAuth.fromDomain(): ManagementInterface.SocksAuth = + ManagementInterface.SocksAuth.newBuilder().setUsername(username).setPassword(password).build() + +internal fun ApiAccessMethod.CustomProxy.Shadowsocks.fromDomain(): ManagementInterface.Shadowsocks = + ManagementInterface.Shadowsocks.newBuilder() + .setIp(ip) + .setCipher(cipher.label) + .setPort(port.value) + .let { + if (password != null) { + it.setPassword(password) + } + it.build() + } + +internal fun TransportProtocol.fromDomain(): ManagementInterface.TransportProtocol = + when (this) { + TransportProtocol.Tcp -> ManagementInterface.TransportProtocol.TCP + TransportProtocol.Udp -> ManagementInterface.TransportProtocol.UDP + } + +internal fun ApiAccessMethodId.fromDomain(): ManagementInterface.UUID = + ManagementInterface.UUID.newBuilder().setValue(value.toString()).build() + +internal fun ApiAccessMethodSetting.fromDomain(): ManagementInterface.AccessMethodSetting = + ManagementInterface.AccessMethodSetting.newBuilder() + .setName(name.value) + .setId(id.fromDomain()) + .setEnabled(enabled) + .setAccessMethod(apiAccessMethod.fromDomain()) + .build() diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt index 59a94f62dc..13ebe74350 100644 --- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt +++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt @@ -13,8 +13,13 @@ import net.mullvad.mullvadvpn.lib.model.AccountData import net.mullvad.mullvadvpn.lib.model.AccountId import net.mullvad.mullvadvpn.lib.model.AccountNumber import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethod +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodId +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodName +import net.mullvad.mullvadvpn.lib.model.ApiAccessMethodSetting import net.mullvad.mullvadvpn.lib.model.AppId import net.mullvad.mullvadvpn.lib.model.AppVersionInfo +import net.mullvad.mullvadvpn.lib.model.Cipher import net.mullvad.mullvadvpn.lib.model.Constraint import net.mullvad.mullvadvpn.lib.model.CustomDnsOptions import net.mullvad.mullvadvpn.lib.model.CustomList @@ -53,6 +58,7 @@ import net.mullvad.mullvadvpn.lib.model.RelayOverride import net.mullvad.mullvadvpn.lib.model.RelaySettings import net.mullvad.mullvadvpn.lib.model.SelectedObfuscation import net.mullvad.mullvadvpn.lib.model.Settings +import net.mullvad.mullvadvpn.lib.model.SocksAuth import net.mullvad.mullvadvpn.lib.model.SplitTunnelSettings import net.mullvad.mullvadvpn.lib.model.TransportProtocol import net.mullvad.mullvadvpn.lib.model.TunnelEndpoint @@ -246,7 +252,8 @@ internal fun ManagementInterface.Settings.toDomain(): Settings = tunnelOptions = tunnelOptions.toDomain(), relayOverrides = relayOverridesList.map { it.toDomain() }, showBetaReleases = showBetaReleases, - splitTunnelSettings = splitTunnel.toDomain() + splitTunnelSettings = splitTunnel.toDomain(), + apiAccessMethodSettings = apiAccessMethods.toDomain() ) internal fun ManagementInterface.RelayOverride.toDomain(): RelayOverride = @@ -519,3 +526,53 @@ internal fun ManagementInterface.SplitTunnelSettings.toDomain(): SplitTunnelSett internal fun ManagementInterface.PlayPurchasePaymentToken.toDomain(): PlayPurchasePaymentToken = PlayPurchasePaymentToken(value = token) + +internal fun ManagementInterface.ApiAccessMethodSettings.toDomain(): List<ApiAccessMethodSetting> = + listOf(direct.toDomain(), mullvadBridges.toDomain()).plus(customList.map { it.toDomain() }) + +internal fun ManagementInterface.AccessMethodSetting.toDomain(): ApiAccessMethodSetting = + ApiAccessMethodSetting( + id = ApiAccessMethodId.fromString(id.value), + name = ApiAccessMethodName.fromString(name), + enabled = enabled, + apiAccessMethod = accessMethod.toDomain() + ) + +internal fun ManagementInterface.AccessMethod.toDomain(): ApiAccessMethod = + when { + hasDirect() -> ApiAccessMethod.Direct + hasBridges() -> ApiAccessMethod.Bridges + hasCustom() -> custom.toDomain() + else -> error("Type not found") + } + +internal fun ManagementInterface.CustomProxy.toDomain(): ApiAccessMethod.CustomProxy = + when { + hasShadowsocks() -> shadowsocks.toDomain() + hasSocks5Remote() -> socks5Remote.toDomain() + hasSocks5Local() -> error("Socks5 local not supported") + else -> error("Custom proxy not found") + } + +internal fun ManagementInterface.Shadowsocks.toDomain(): ApiAccessMethod.CustomProxy.Shadowsocks = + ApiAccessMethod.CustomProxy.Shadowsocks( + ip = ip, + port = Port(port), + password = password, + cipher = Cipher.fromString(cipher) + ) + +internal fun ManagementInterface.Socks5Remote.toDomain(): ApiAccessMethod.CustomProxy.Socks5Remote = + ApiAccessMethod.CustomProxy.Socks5Remote( + ip = ip, + port = Port(port), + auth = + if (hasAuth()) { + auth.toDomain() + } else { + null + } + ) + +internal fun ManagementInterface.SocksAuth.toDomain(): SocksAuth = + SocksAuth(username = username, password = password) diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/AddApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/AddApiAccessMethodError.kt new file mode 100644 index 0000000000..d0c741e53c --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/AddApiAccessMethodError.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface AddApiAccessMethodError { + data class Unknown(val t: Throwable) : AddApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethod.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethod.kt new file mode 100644 index 0000000000..d8762af391 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethod.kt @@ -0,0 +1,23 @@ +package net.mullvad.mullvadvpn.lib.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +sealed interface ApiAccessMethod : Parcelable { + @Parcelize data object Direct : ApiAccessMethod + + @Parcelize data object Bridges : ApiAccessMethod + + sealed interface CustomProxy : ApiAccessMethod { + @Parcelize + data class Socks5Remote(val ip: String, val port: Port, val auth: SocksAuth?) : CustomProxy + + @Parcelize + data class Shadowsocks( + val ip: String, + val port: Port, + val password: String?, + val cipher: Cipher + ) : CustomProxy + } +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodId.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodId.kt new file mode 100644 index 0000000000..a6dc0628df --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodId.kt @@ -0,0 +1,14 @@ +package net.mullvad.mullvadvpn.lib.model + +import android.os.Parcelable +import java.util.UUID +import kotlinx.parcelize.Parcelize + +@JvmInline +@Parcelize +value class ApiAccessMethodId private constructor(val value: UUID) : Parcelable { + + companion object { + fun fromString(id: String) = ApiAccessMethodId(value = UUID.fromString(id)) + } +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodName.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodName.kt new file mode 100644 index 0000000000..b1eada2982 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodName.kt @@ -0,0 +1,19 @@ +package net.mullvad.mullvadvpn.lib.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +@JvmInline +value class ApiAccessMethodName private constructor(val value: String) : Parcelable { + override fun toString() = value + + companion object { + const val MAX_LENGTH = 30 + + fun fromString(name: String): ApiAccessMethodName { + val trimmedName = name.trim().take(MAX_LENGTH) + return ApiAccessMethodName(trimmedName) + } + } +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodSetting.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodSetting.kt new file mode 100644 index 0000000000..07e1c185df --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/ApiAccessMethodSetting.kt @@ -0,0 +1,8 @@ +package net.mullvad.mullvadvpn.lib.model + +data class ApiAccessMethodSetting( + val id: ApiAccessMethodId, + val name: ApiAccessMethodName, + val enabled: Boolean, + val apiAccessMethod: ApiAccessMethod +) diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Cipher.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Cipher.kt new file mode 100644 index 0000000000..4571c824dd --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Cipher.kt @@ -0,0 +1,34 @@ +package net.mullvad.mullvadvpn.lib.model + +// All suppported shadowsocks ciphers +enum class Cipher(val label: String) { + AES_128_CFB("aes-128-cfb"), + AES_128_CFB1("aes-128-cfb1"), + AES_128_CFB8("aes-128-cfb8"), + AES_128_CFB128("aes-128-cfb128"), + AES_256_CFB("aes-256-cfb"), + AES_256_CFB1("aes-256-cfb1"), + AES_256_CFB8("aes-256-cfb8"), + AES_256_CFB128("aes-256-cfb128"), + RC4("rc4"), + RC4_MD5("rc4-md5"), + CHACHA20("chacha20"), + SALSA20("salsa20"), + CHACHA20_IETF("chacha20-ietf"), + AES_128_GCM("aes-128-gcm"), + AES_256_GCM("aes-256-gcm"), + CHACHA20_IETF_POLY1305("chacha20-ietf-poly1305"), + XCHACHA20_IETF_POLY1305("xchacha20-ietf-poly1305"), + AES_128_PMAC_SIV("aes-128-pmac-siv"), + AES_256_PMAC_SIV("aes-256-pmac-siv"); + + override fun toString(): String = label + + companion object { + fun fromString(input: String) = Cipher.entries.first { it.label == input } + + fun listAll() = Cipher.entries.sortedBy { it.label } + + fun first() = listAll().first() + } +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetApiAccessMethodError.kt new file mode 100644 index 0000000000..47f2ad29cc --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetApiAccessMethodError.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface GetApiAccessMethodError : UpdateApiAccessMethodError { + data object NotFound : GetApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetCurrentApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetCurrentApiAccessMethodError.kt new file mode 100644 index 0000000000..54c9791d0b --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/GetCurrentApiAccessMethodError.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface GetCurrentApiAccessMethodError { + data class Unknown(val t: Throwable) : GetCurrentApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/InvalidDataError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/InvalidDataError.kt new file mode 100644 index 0000000000..450d94e691 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/InvalidDataError.kt @@ -0,0 +1,27 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface InvalidDataError { + sealed interface NameError : InvalidDataError { + data object Required : NameError + } + + sealed interface ServerIpError : InvalidDataError { + data object Required : ServerIpError + + data object Invalid : ServerIpError + } + + sealed interface PortError : InvalidDataError { + data object Required : PortError + + data class Invalid(val portError: ParsePortError) : PortError + } + + sealed interface UserNameError : InvalidDataError { + data object Required : UserNameError + } + + sealed interface PasswordError : InvalidDataError { + data object Required : PasswordError + } +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/NewAccessMethodSetting.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/NewAccessMethodSetting.kt new file mode 100644 index 0000000000..990dc300bc --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/NewAccessMethodSetting.kt @@ -0,0 +1,11 @@ +package net.mullvad.mullvadvpn.lib.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class NewAccessMethodSetting( + val name: ApiAccessMethodName, + val enabled: Boolean, + val apiAccessMethod: ApiAccessMethod.CustomProxy +) : Parcelable diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Port.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Port.kt index 5ce44d0565..e6ca1e01b9 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Port.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Port.kt @@ -9,6 +9,9 @@ import kotlinx.parcelize.Parcelize @JvmInline @Parcelize value class Port(val value: Int) : Parcelable { + + override fun toString(): String = value.toString() + companion object { fun fromString(value: String): Either<ParsePortError, Port> = either { val number = value.toIntOrNull() ?: raise(ParsePortError.NotANumber(value)) diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RemoveApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RemoveApiAccessMethodError.kt new file mode 100644 index 0000000000..88516761c4 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/RemoveApiAccessMethodError.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface RemoveApiAccessMethodError { + data class Unknown(val t: Throwable) : RemoveApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetApiAccessMethodError.kt new file mode 100644 index 0000000000..1fa0544a82 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SetApiAccessMethodError.kt @@ -0,0 +1,5 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface SetApiAccessMethodError { + data class Unknown(val t: Throwable) : SetApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt index c5191531be..e801397b27 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/Settings.kt @@ -12,7 +12,8 @@ data class Settings( val tunnelOptions: TunnelOptions, val relayOverrides: List<RelayOverride>, val showBetaReleases: Boolean, - val splitTunnelSettings: SplitTunnelSettings + val splitTunnelSettings: SplitTunnelSettings, + val apiAccessMethodSettings: List<ApiAccessMethodSetting> ) { companion object } diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SocksAuth.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SocksAuth.kt new file mode 100644 index 0000000000..ff17641d63 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/SocksAuth.kt @@ -0,0 +1,6 @@ +package net.mullvad.mullvadvpn.lib.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize data class SocksAuth(val username: String, val password: String) : Parcelable diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TestApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TestApiAccessMethodError.kt new file mode 100644 index 0000000000..ce69919110 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/TestApiAccessMethodError.kt @@ -0,0 +1,9 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface TestApiAccessMethodError { + data object CouldNotAccess : TestApiAccessMethodError + + data object Grpc : TestApiAccessMethodError + + data class Unknown(val t: Throwable) : TestApiAccessMethodError +} diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UnknownApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UnknownApiAccessMethodError.kt new file mode 100644 index 0000000000..06cb81fc5e --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UnknownApiAccessMethodError.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.lib.model + +data class UnknownApiAccessMethodError(val throwable: Throwable) : UpdateApiAccessMethodError diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UpdateApiAccessMethodError.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UpdateApiAccessMethodError.kt new file mode 100644 index 0000000000..0597967375 --- /dev/null +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/UpdateApiAccessMethodError.kt @@ -0,0 +1,3 @@ +package net.mullvad.mullvadvpn.lib.model + +sealed interface UpdateApiAccessMethodError |
