diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-04-13 14:53:57 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2021-04-13 14:53:57 -0300 |
| commit | 4a3e5171461eb2c4079ec3ce7d75a875442b98b0 (patch) | |
| tree | 8b109f3b6db62b8c1451a3bfba927e7c1aac9826 /android/src | |
| parent | 57a5481e5d4a6f18ec8d357013d8af004282919c (diff) | |
| parent | 61f82b45342f640820200c26daee10f7e30246c0 (diff) | |
| download | mullvadvpn-4a3e5171461eb2c4079ec3ce7d75a875442b98b0.tar.xz mullvadvpn-4a3e5171461eb2c4079ec3ce7d75a875442b98b0.zip | |
Merge branch 'split-custom-dns'
Diffstat (limited to 'android/src')
10 files changed, 198 insertions, 119 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt index 1937ce424b..fc293e69a3 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ipc/Request.kt @@ -2,6 +2,7 @@ package net.mullvad.mullvadvpn.ipc import android.os.Message as RawMessage import android.os.Messenger +import java.net.InetAddress import kotlinx.parcelize.Parcelize import org.joda.time.DateTime @@ -10,6 +11,9 @@ sealed class Request : Message.RequestMessage() { protected override val messageKey = MESSAGE_KEY @Parcelize + data class AddCustomDnsServer(val address: InetAddress) : Request() + + @Parcelize object Connect : Request() @Parcelize @@ -49,6 +53,18 @@ sealed class Request : Message.RequestMessage() { data class RemoveAccountFromHistory(val account: String?) : Request() @Parcelize + data class RemoveCustomDnsServer(val address: InetAddress) : Request() + + @Parcelize + data class ReplaceCustomDnsServer( + val oldAddress: InetAddress, + val newAddress: InetAddress + ) : Request() + + @Parcelize + data class SetEnableCustomDns(val enable: Boolean) : Request() + + @Parcelize data class SetEnableSplitTunneling(val enable: Boolean) : Request() @Parcelize diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt deleted file mode 100644 index 447c215e1c..0000000000 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/CustomDns.kt +++ /dev/null @@ -1,95 +0,0 @@ -package net.mullvad.mullvadvpn.service - -import java.net.InetAddress -import java.util.ArrayList -import kotlin.properties.Delegates.observable -import net.mullvad.mullvadvpn.model.DnsOptions -import net.mullvad.mullvadvpn.service.endpoint.SettingsListener -import net.mullvad.talpid.util.EventNotifier - -class CustomDns(val daemon: MullvadDaemon, val settingsListener: SettingsListener) { - private var enabled by observable(false) { _, oldValue, newValue -> - if (oldValue != newValue) { - onEnabledChanged.notify(newValue) - } - } - - private var dnsServers by observable<ArrayList<InetAddress>>(ArrayList()) { _, _, servers -> - onDnsServersChanged.notify(servers.toList()) - } - - val onEnabledChanged = EventNotifier(false) - val onDnsServersChanged = EventNotifier<List<InetAddress>>(emptyList()) - - init { - settingsListener.dnsOptionsNotifier.subscribe(this) { maybeDnsOptions -> - maybeDnsOptions?.let { dnsOptions -> - enabled = dnsOptions.custom - dnsServers = dnsOptions.addresses - } - } - } - - fun onDestroy() { - settingsListener.dnsOptionsNotifier.unsubscribe(this) - } - - fun enable() { - synchronized(this) { - changeDnsOptions(true, dnsServers) - } - } - - fun disable() { - synchronized(this) { - changeDnsOptions(false, dnsServers) - } - } - - fun addDnsServer(server: InetAddress): Boolean { - synchronized(this) { - if (!dnsServers.contains(server)) { - dnsServers.add(server) - changeDnsOptions(enabled, dnsServers) - - return true - } - } - - return false - } - - fun replaceDnsServer(oldServer: InetAddress, newServer: InetAddress): Boolean { - synchronized(this) { - if (oldServer == newServer) { - return true - } else if (!dnsServers.contains(newServer)) { - val index = dnsServers.indexOf(oldServer) - - if (index >= 0) { - dnsServers.removeAt(index) - dnsServers.add(index, newServer) - changeDnsOptions(enabled, dnsServers) - - return true - } - } - } - - return false - } - - fun removeDnsServer(server: InetAddress) { - synchronized(this) { - if (dnsServers.remove(server)) { - changeDnsOptions(enabled, dnsServers) - } - } - } - - private fun changeDnsOptions(enable: Boolean, dnsServers: ArrayList<InetAddress>) { - val options = DnsOptions(enable, dnsServers) - - daemon.setDnsOptions(options) - } -} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt index 1d379c5775..2d057e2c97 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt @@ -57,8 +57,6 @@ class MullvadVpnService : TalpidVpnService() { private var instance by observable<ServiceInstance?>(null) { _, oldInstance, newInstance -> if (newInstance != oldInstance) { - oldInstance?.onDestroy() - accountExpiryNotification = newInstance?.let { instance -> AccountExpiryNotification(this, instance.daemon, endpoint.accountCache) } @@ -237,17 +235,10 @@ class MullvadVpnService : TalpidVpnService() { } private suspend fun setUpInstance(daemon: MullvadDaemon, settings: Settings) { - val customDns = CustomDns(daemon, endpoint.settingsListener) - handlePendingAction(settings) if (state == State.Running) { - instance = ServiceInstance( - endpoint.messenger, - daemon, - daemonInstance.intermittentDaemon, - customDns - ) + instance = ServiceInstance(endpoint.messenger, daemon) } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt index f4e898d143..383e735b24 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/ServiceInstance.kt @@ -1,15 +1,5 @@ package net.mullvad.mullvadvpn.service import android.os.Messenger -import net.mullvad.mullvadvpn.util.Intermittent -class ServiceInstance( - val messenger: Messenger, - val daemon: MullvadDaemon, - val intermittentDaemon: Intermittent<MullvadDaemon>, - val customDns: CustomDns, -) { - fun onDestroy() { - customDns.onDestroy() - } -} +class ServiceInstance(val messenger: Messenger, val daemon: MullvadDaemon) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/CustomDns.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/CustomDns.kt new file mode 100644 index 0000000000..7c22cef50c --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/CustomDns.kt @@ -0,0 +1,113 @@ +package net.mullvad.mullvadvpn.service.endpoint + +import java.net.InetAddress +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.channels.Channel +import kotlinx.coroutines.channels.ClosedReceiveChannelException +import kotlinx.coroutines.channels.actor +import kotlinx.coroutines.channels.sendBlocking +import net.mullvad.mullvadvpn.ipc.Request +import net.mullvad.mullvadvpn.model.DnsOptions + +class CustomDns(private val endpoint: ServiceEndpoint) { + private sealed class Command { + class AddDnsServer(val server: InetAddress) : Command() + class RemoveDnsServer(val server: InetAddress) : Command() + class ReplaceDnsServer(val oldServer: InetAddress, val newServer: InetAddress) : Command() + class SetEnabled(val enabled: Boolean) : Command() + } + + private val commandChannel = spawnActor() + private val dnsServers = ArrayList<InetAddress>() + + private val daemon + get() = endpoint.intermittentDaemon + + private var enabled = false + + init { + endpoint.settingsListener.dnsOptionsNotifier.subscribe(this) { maybeDnsOptions -> + maybeDnsOptions?.let { dnsOptions -> + enabled = dnsOptions.custom + dnsServers.clear() + dnsServers.addAll(dnsOptions.addresses) + } + } + + endpoint.dispatcher.apply { + registerHandler(Request.AddCustomDnsServer::class) { request -> + commandChannel.sendBlocking(Command.AddDnsServer(request.address)) + } + + registerHandler(Request.RemoveCustomDnsServer::class) { request -> + commandChannel.sendBlocking(Command.RemoveDnsServer(request.address)) + } + + registerHandler(Request.ReplaceCustomDnsServer::class) { request -> + commandChannel.sendBlocking( + Command.ReplaceDnsServer(request.oldAddress, request.newAddress) + ) + } + + registerHandler(Request.SetEnableCustomDns::class) { request -> + commandChannel.sendBlocking(Command.SetEnabled(request.enable)) + } + } + } + + fun onDestroy() { + endpoint.settingsListener.dnsOptionsNotifier.unsubscribe(this) + commandChannel.close() + } + + private fun spawnActor() = GlobalScope.actor<Command>(Dispatchers.Default, Channel.UNLIMITED) { + try { + while (true) { + val command = channel.receive() + + when (command) { + is Command.AddDnsServer -> doAddDnsServer(command.server) + is Command.RemoveDnsServer -> doRemoveDnsServer(command.server) + is Command.ReplaceDnsServer -> { + doReplaceDnsServer(command.oldServer, command.newServer) + } + is Command.SetEnabled -> changeDnsOptions(command.enabled) + } + } + } catch (exception: ClosedReceiveChannelException) { + // Closed sender, so stop the actor + } + } + + private suspend fun doAddDnsServer(server: InetAddress) { + if (!dnsServers.contains(server)) { + dnsServers.add(server) + changeDnsOptions(enabled) + } + } + + private suspend fun doReplaceDnsServer(oldServer: InetAddress, newServer: InetAddress) { + if (oldServer != newServer && !dnsServers.contains(newServer)) { + val index = dnsServers.indexOf(oldServer) + + if (index >= 0) { + dnsServers.removeAt(index) + dnsServers.add(index, newServer) + changeDnsOptions(enabled) + } + } + } + + private suspend fun doRemoveDnsServer(server: InetAddress) { + if (dnsServers.remove(server)) { + changeDnsOptions(enabled) + } + } + + private suspend fun changeDnsOptions(enable: Boolean) { + val options = DnsOptions(enable, dnsServers) + + daemon.await().setDnsOptions(options) + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt index 1d7ee77763..0f583d1fc9 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/ServiceEndpoint.kt @@ -40,6 +40,7 @@ class ServiceEndpoint( val settingsListener = SettingsListener(this) val accountCache = AccountCache(this) + val customDns = CustomDns(this) val keyStatusListener = KeyStatusListener(this) val locationInfoCache = LocationInfoCache(this) val splitTunneling = SplitTunneling(SplitTunnelingPersistence(context), this) @@ -56,6 +57,7 @@ class ServiceEndpoint( accountCache.onDestroy() connectionProxy.onDestroy() + customDns.onDestroy() keyStatusListener.onDestroy() locationInfoCache.onDestroy() settingsListener.onDestroy() diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt index 1927a0490f..fbb09689ca 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/ServiceDependentFragment.kt @@ -7,10 +7,10 @@ import android.view.ViewGroup import net.mullvad.mullvadvpn.R import net.mullvad.mullvadvpn.dataproxy.AppVersionInfoCache import net.mullvad.mullvadvpn.dataproxy.RelayListListener -import net.mullvad.mullvadvpn.service.CustomDns import net.mullvad.mullvadvpn.service.MullvadDaemon import net.mullvad.mullvadvpn.ui.serviceconnection.AccountCache import net.mullvad.mullvadvpn.ui.serviceconnection.ConnectionProxy +import net.mullvad.mullvadvpn.ui.serviceconnection.CustomDns import net.mullvad.mullvadvpn.ui.serviceconnection.KeyStatusListener import net.mullvad.mullvadvpn.ui.serviceconnection.LocationInfoCache import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnection diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt index c66fc04848..8b0ce3b48b 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/customdns/CustomDnsAdapter.kt @@ -8,7 +8,7 @@ import kotlin.properties.Delegates.observable import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import net.mullvad.mullvadvpn.R -import net.mullvad.mullvadvpn.service.CustomDns +import net.mullvad.mullvadvpn.ui.serviceconnection.CustomDns import net.mullvad.mullvadvpn.util.JobTracker import org.apache.commons.validator.routines.InetAddressValidator diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/CustomDns.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/CustomDns.kt new file mode 100644 index 0000000000..140d1135cd --- /dev/null +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/CustomDns.kt @@ -0,0 +1,61 @@ +package net.mullvad.mullvadvpn.ui.serviceconnection + +import android.os.Messenger +import java.net.InetAddress +import net.mullvad.mullvadvpn.ipc.Request +import net.mullvad.talpid.util.EventNotifier + +class CustomDns(val connection: Messenger, val settingsListener: SettingsListener) { + val onEnabledChanged = EventNotifier(false) + val onDnsServersChanged = EventNotifier<List<InetAddress>>(emptyList()) + + init { + settingsListener.dnsOptionsNotifier.subscribe(this) { maybeDnsOptions -> + maybeDnsOptions?.let { dnsOptions -> + synchronized(this) { + onEnabledChanged.notifyIfChanged(dnsOptions.custom) + onDnsServersChanged.notifyIfChanged(dnsOptions.addresses) + } + } + } + } + + fun enable() { + connection.send(Request.SetEnableCustomDns(true).message) + } + + fun disable() { + connection.send(Request.SetEnableCustomDns(false).message) + } + + fun addDnsServer(server: InetAddress): Boolean { + val alreadyHadServer = onDnsServersChanged.latestEvent.contains(server) + + connection.send(Request.AddCustomDnsServer(server).message) + + return alreadyHadServer + } + + fun replaceDnsServer(oldServer: InetAddress, newServer: InetAddress): Boolean { + synchronized(this) { + val dnsServers = onDnsServersChanged.latestEvent + val containsOldServer = dnsServers.contains(oldServer) + val replacementIsValid = oldServer == newServer || !dnsServers.contains(newServer) + + connection.send(Request.ReplaceCustomDnsServer(oldServer, newServer).message) + + return containsOldServer && replacementIsValid + } + } + + fun removeDnsServer(server: InetAddress) { + connection.send(Request.RemoveCustomDnsServer(server).message) + } + + fun onDestroy() { + onEnabledChanged.unsubscribeAll() + onDnsServersChanged.unsubscribeAll() + + settingsListener.dnsOptionsNotifier.unsubscribe(this) + } +} diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt index 6e2cee704f..e3b02a3bb8 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnection.kt @@ -30,7 +30,6 @@ class ServiceConnection(private val service: ServiceInstance, mainActivity: Main val daemon = service.daemon val accountCache = AccountCache(service.messenger, dispatcher) val connectionProxy = ConnectionProxy(service.messenger, dispatcher) - val customDns = service.customDns val keyStatusListener = KeyStatusListener(service.messenger, dispatcher) val locationInfoCache = LocationInfoCache(dispatcher) val settingsListener = SettingsListener(dispatcher) @@ -40,6 +39,7 @@ class ServiceConnection(private val service: ServiceInstance, mainActivity: Main val vpnPermission = VpnPermission(service.messenger) val appVersionInfoCache = AppVersionInfoCache(mainActivity, daemon, settingsListener) + val customDns = CustomDns(service.messenger, settingsListener) var relayListListener = RelayListListener(daemon, settingsListener) init { @@ -57,6 +57,7 @@ class ServiceConnection(private val service: ServiceInstance, mainActivity: Main settingsListener.onDestroy() appVersionInfoCache.onDestroy() + customDns.onDestroy() relayListListener.onDestroy() } |
