diff options
44 files changed, 560 insertions, 1061 deletions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/RelayListListener.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/RelayListListener.kt index d0f54a0cf6..5c6e765b4e 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/RelayListListener.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/RelayListListener.kt @@ -28,28 +28,13 @@ class RelayListListener( var selectedRelayItem: RelayItem? = null private set - var selectedRelayLocation: GeographicLocationConstraint? - get() { - val settings = relaySettings as? RelaySettings.Normal - val location = settings?.relayConstraints?.location as? Constraint.Only - - return location?.value?.toGeographicLocationConstraint() - } - set(value) { - connection.send(Request.SetRelayLocation(value).message) - } - - var selectedWireguardConstraints: WireguardConstraints? - get() { - val settings = relaySettings as? RelaySettings.Normal + fun updateSelectedRelayLocation(value: GeographicLocationConstraint) { + connection.send(Request.SetRelayLocation(value).message) + } - return settings?.relayConstraints?.wireguardConstraints?.port?.let { port -> - WireguardConstraints(port) - } - } - set(value) { - connection.send(Request.SetWireguardConstraints(value).message) - } + fun updateSelectedWireguardConstraints(value: WireguardConstraints) { + connection.send(Request.SetWireguardConstraints(value).message) + } var onRelayCountriesChange: ((List<RelayCountry>, RelayItem?) -> Unit)? = null set(value) { diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt index 2507e9fb19..0d8f753d8f 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt @@ -71,8 +71,10 @@ class SelectLocationViewModel(private val serviceConnectionManager: ServiceConne @Suppress("konsist.ensure public properties use permitted names") val enterTransitionEndAction = _enterTransitionEndAction.asSharedFlow() - fun selectRelay(relayItem: RelayItem?) { - serviceConnectionManager.relayListListener()?.selectedRelayLocation = relayItem?.location + fun selectRelay(relayItem: RelayItem) { + serviceConnectionManager + .relayListListener() + ?.updateSelectedRelayLocation(relayItem.location) serviceConnectionManager.connectionProxy()?.connect() viewModelScope.launch { _closeAction.emit(Unit) } } diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt index 0827c81e99..94abf1da90 100644 --- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt +++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt @@ -352,8 +352,9 @@ class VpnSettingsViewModel( fun onWireguardPortSelected(port: Constraint<Port>) { viewModelScope.launch(dispatcher) { - serviceConnectionManager.relayListListener()?.selectedWireguardConstraints = - WireguardConstraints(port = port) + serviceConnectionManager + .relayListListener() + ?.updateSelectedWireguardConstraints(WireguardConstraints(port = port)) } hideDialog() } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt index 59cd9f48b5..3cadfe575f 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt @@ -132,7 +132,7 @@ class SelectLocationViewModelTest { assertEquals(Unit, awaitItem()) verify { connectionProxyMock.connect() - mockRelayListListener.selectedRelayLocation = mockLocation + mockRelayListListener.updateSelectedRelayLocation(mockLocation) } } } diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt index 66d301d903..13561737c8 100644 --- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt +++ b/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt @@ -159,7 +159,9 @@ class VpnSettingsViewModelTest { // Arrange val wireguardPort: Constraint<Port> = Constraint.Only(Port(99)) val wireguardConstraints = WireguardConstraints(port = wireguardPort) - every { mockRelayListListener.selectedWireguardConstraints = any() } returns Unit + every { + mockRelayListListener.updateSelectedWireguardConstraints(wireguardConstraints) + } returns Unit // Act mockConnectionState.value = @@ -168,7 +170,7 @@ class VpnSettingsViewModelTest { // Assert verify(exactly = 1) { - mockRelayListListener.selectedWireguardConstraints = wireguardConstraints + mockRelayListListener.updateSelectedWireguardConstraints(wireguardConstraints) } } diff --git a/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/Request.kt b/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/Request.kt index 2a8636fa95..cbd1f28b27 100644 --- a/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/Request.kt +++ b/android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/Request.kt @@ -74,7 +74,7 @@ sealed class Request : Message.RequestMessage() { @Parcelize data class SetEnableSplitTunneling(val enable: Boolean) : Request() @Parcelize - data class SetRelayLocation(val relayLocation: GeographicLocationConstraint?) : Request() + data class SetRelayLocation(val relayLocation: GeographicLocationConstraint) : Request() @Parcelize data class SetWireGuardMtu(val mtu: Int?) : Request() @@ -89,7 +89,7 @@ sealed class Request : Message.RequestMessage() { @Parcelize data class SetObfuscationSettings(val settings: ObfuscationSettings?) : Request() @Parcelize - data class SetWireguardConstraints(val wireguardConstraints: WireguardConstraints?) : Request() + data class SetWireguardConstraints(val wireguardConstraints: WireguardConstraints) : Request() @Parcelize data class SetWireGuardQuantumResistant(val quantumResistant: QuantumResistantState) : diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraintsUpdate.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraintsUpdate.kt deleted file mode 100644 index 8a382a87d9..0000000000 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraintsUpdate.kt +++ /dev/null @@ -1,8 +0,0 @@ -package net.mullvad.mullvadvpn.model - -data class RelayConstraintsUpdate( - val location: Constraint<LocationConstraint>?, - val providers: Constraint<Providers>?, - val ownership: Constraint<Ownership>?, - val wireguardConstraints: WireguardConstraints? -) diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt index 7832a00e77..381305f2c3 100644 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt +++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt @@ -4,7 +4,7 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize sealed class RelaySettings : Parcelable { - @Parcelize object CustomTunnelEndpoint : RelaySettings() + @Parcelize data object CustomTunnelEndpoint : RelaySettings() - @Parcelize class Normal(val relayConstraints: RelayConstraints) : RelaySettings() + @Parcelize data class Normal(val relayConstraints: RelayConstraints) : RelaySettings() } diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettingsUpdate.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettingsUpdate.kt deleted file mode 100644 index f8d27f115e..0000000000 --- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettingsUpdate.kt +++ /dev/null @@ -1,7 +0,0 @@ -package net.mullvad.mullvadvpn.model - -sealed class RelaySettingsUpdate { - object CustomTunnelEndpoint : RelaySettingsUpdate() - - data class Normal(val constraints: RelayConstraintsUpdate) : RelaySettingsUpdate() -} diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt index ceb95a48b7..fd734bbeac 100644 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt @@ -19,7 +19,7 @@ import net.mullvad.mullvadvpn.model.PlayPurchaseInitResult import net.mullvad.mullvadvpn.model.PlayPurchaseVerifyResult import net.mullvad.mullvadvpn.model.QuantumResistantState import net.mullvad.mullvadvpn.model.RelayList -import net.mullvad.mullvadvpn.model.RelaySettingsUpdate +import net.mullvad.mullvadvpn.model.RelaySettings import net.mullvad.mullvadvpn.model.RemoveDeviceEvent import net.mullvad.mullvadvpn.model.RemoveDeviceResult import net.mullvad.mullvadvpn.model.Settings @@ -182,8 +182,8 @@ class MullvadDaemon( return verifyPlayPurchase(daemonInterfaceAddress, playPurchase) } - fun updateRelaySettings(update: RelaySettingsUpdate) { - updateRelaySettings(daemonInterfaceAddress, update) + fun setRelaySettings(update: RelaySettings) { + setRelaySettings(daemonInterfaceAddress, update) } fun setObfuscationSettings(settings: ObfuscationSettings?) { @@ -289,10 +289,7 @@ class MullvadDaemon( playPurchase: PlayPurchase, ): PlayPurchaseVerifyResult - private external fun updateRelaySettings( - daemonInterfaceAddress: Long, - update: RelaySettingsUpdate - ) + private external fun setRelaySettings(daemonInterfaceAddress: Long, update: RelaySettings) private external fun setObfuscationSettings( daemonInterfaceAddress: Long, diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/RelayListListener.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/RelayListListener.kt index 6974d804a1..7a0b3fbe97 100644 --- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/RelayListListener.kt +++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/RelayListListener.kt @@ -12,9 +12,9 @@ import net.mullvad.mullvadvpn.lib.ipc.Request import net.mullvad.mullvadvpn.model.Constraint import net.mullvad.mullvadvpn.model.GeographicLocationConstraint import net.mullvad.mullvadvpn.model.LocationConstraint -import net.mullvad.mullvadvpn.model.RelayConstraintsUpdate +import net.mullvad.mullvadvpn.model.RelayConstraints import net.mullvad.mullvadvpn.model.RelayList -import net.mullvad.mullvadvpn.model.RelaySettingsUpdate +import net.mullvad.mullvadvpn.model.RelaySettings import net.mullvad.mullvadvpn.model.WireguardConstraints import net.mullvad.mullvadvpn.service.MullvadDaemon @@ -87,16 +87,18 @@ class RelayListListener(endpoint: ServiceEndpoint) { } private suspend fun updateRelayConstraints() { + val currentRelayConstraints = getCurrentRelayConstraints() val location: Constraint<LocationConstraint> = selectedRelayLocation?.let { location -> Constraint.Only(LocationConstraint.Location(location)) } - ?: Constraint.Any() - val wireguardConstraints: WireguardConstraints? = selectedWireguardConstraints + ?: currentRelayConstraints.location + val wireguardConstraints: WireguardConstraints = + selectedWireguardConstraints ?: currentRelayConstraints.wireguardConstraints val update = - RelaySettingsUpdate.Normal( - RelayConstraintsUpdate( + RelaySettings.Normal( + RelayConstraints( location = location, wireguardConstraints = wireguardConstraints, ownership = Constraint.Any(), @@ -104,9 +106,21 @@ class RelayListListener(endpoint: ServiceEndpoint) { ) ) - daemon.await().updateRelaySettings(update) + daemon.await().setRelaySettings(update) } + private suspend fun getCurrentRelayConstraints(): RelayConstraints = + when (val relaySettings = daemon.await().getSettings()?.relaySettings) { + is RelaySettings.Normal -> relaySettings.relayConstraints + else -> + RelayConstraints( + location = Constraint.Any(), + providers = Constraint.Any(), + ownership = Constraint.Any(), + wireguardConstraints = WireguardConstraints(Constraint.Any()) + ) + } + companion object { private enum class Command { SetRelayLocation, diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 288bbfd7fc..65ad96519c 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -41,6 +41,7 @@ import { IRelayListCountry, IRelayListHostname, IRelayListWithEndpointData, + IRelaySettingsNormal, ISettings, ITunnelOptions, ITunnelStateRelayInfo, @@ -58,12 +59,12 @@ import { RelayLocationGeographical, RelayProtocol, RelaySettings, - RelaySettingsUpdate, TunnelParameterError, TunnelProtocol, TunnelState, TunnelType, VoucherResponse, + wrapConstraint, } from '../shared/daemon-rpc-types'; import log from '../shared/logging'; import { ManagementServiceClient } from './management_interface/management_interface_grpc_pb'; @@ -297,52 +298,14 @@ export class DaemonRpc { } // TODO: Custom tunnel configurations are not supported by the GUI. - public async updateRelaySettings(relaySettings: RelaySettingsUpdate): Promise<void> { + public async setRelaySettings(relaySettings: RelaySettings): Promise<void> { if ('normal' in relaySettings) { - const settingsUpdate = relaySettings.normal; - const grpcRelaySettings = new grpcTypes.RelaySettingsUpdate(); + const normalSettings = relaySettings.normal; + const grpcRelaySettings = new grpcTypes.RelaySettings(); + grpcRelaySettings.setNormal(convertToRelayConstraints(normalSettings)); - const normalUpdate = new grpcTypes.NormalRelaySettingsUpdate(); - - if (settingsUpdate.tunnelProtocol) { - const tunnelTypeUpdate = new grpcTypes.TunnelTypeUpdate(); - if (settingsUpdate.tunnelProtocol !== 'any') { - tunnelTypeUpdate.setTunnelType(convertToTunnelType(settingsUpdate.tunnelProtocol.only)); - } - normalUpdate.setTunnelType(tunnelTypeUpdate); - } - - if (settingsUpdate.location) { - normalUpdate.setLocation(convertToLocation(liftConstraint(settingsUpdate.location))); - } - - if (settingsUpdate.wireguardConstraints) { - normalUpdate.setWireguardConstraints( - convertToWireguardConstraints(settingsUpdate.wireguardConstraints), - ); - } - - if (settingsUpdate.openvpnConstraints) { - normalUpdate.setOpenvpnConstraints( - convertToOpenVpnConstraints(settingsUpdate.openvpnConstraints), - ); - } - - if (settingsUpdate.providers) { - const providerUpdate = new grpcTypes.ProviderUpdate(); - providerUpdate.setProvidersList(settingsUpdate.providers); - normalUpdate.setProviders(providerUpdate); - } - - if (settingsUpdate.ownership !== undefined) { - const ownershipUpdate = new grpcTypes.OwnershipUpdate(); - ownershipUpdate.setOwnership(convertToOwnership(settingsUpdate.ownership)); - normalUpdate.setOwnership(ownershipUpdate); - } - - grpcRelaySettings.setNormal(normalUpdate); - await this.call<grpcTypes.RelaySettingsUpdate, Empty>( - this.client.updateRelaySettings, + await this.call<grpcTypes.RelaySettings, Empty>( + this.client.setRelaySettings, grpcRelaySettings, ); } @@ -1148,7 +1111,7 @@ function convertFromRelaySettings( case grpcTypes.RelaySettings.EndpointCase.NORMAL: { const normal = relaySettings.getNormal()!; const locationConstraint = convertFromLocationConstraint(normal.getLocation()); - const location = locationConstraint ? { only: locationConstraint } : 'any'; + const location = wrapConstraint(locationConstraint); // `getTunnelType()` is not falsy if type is 'any' const tunnelProtocol = convertFromTunnelTypeConstraint( normal.hasTunnelType() ? normal.getTunnelType() : undefined, @@ -1184,7 +1147,7 @@ function convertFromBridgeSettings(bridgeSettings: grpcTypes.BridgeSettings): Br const locationConstraint = convertFromLocationConstraint( bridgeSettings.getNormal()?.getLocation(), ); - const location = locationConstraint ? { only: locationConstraint } : 'any'; + const location = wrapConstraint(locationConstraint); const providers = normalSettings.providersList; const ownership = convertFromOwnership(normalSettings.ownership); return { @@ -1475,7 +1438,7 @@ function convertFromWireguardConstraints( const entryLocation = constraints.getEntryLocation(); if (entryLocation) { const location = convertFromLocationConstraint(entryLocation); - result.entryLocation = location ? { only: location } : 'any'; + result.entryLocation = wrapConstraint(location); } return result; @@ -1505,6 +1468,27 @@ function convertFromConstraint<T>(value: T | undefined): Constraint<T> { } } +function convertToRelayConstraints( + constraints: IRelaySettingsNormal<IOpenVpnConstraints, IWireguardConstraints>, +): grpcTypes.NormalRelaySettings { + const relayConstraints = new grpcTypes.NormalRelaySettings(); + + if (constraints.tunnelProtocol !== 'any') { + relayConstraints.setTunnelType(convertToTunnelType(constraints.tunnelProtocol.only)); + } + relayConstraints.setLocation(convertToLocation(liftConstraint(constraints.location))); + relayConstraints.setWireguardConstraints( + convertToWireguardConstraints(constraints.wireguardConstraints), + ); + relayConstraints.setOpenvpnConstraints( + convertToOpenVpnConstraints(constraints.openvpnConstraints), + ); + relayConstraints.setProvidersList(constraints.providers); + relayConstraints.setOwnership(convertToOwnership(constraints.ownership)); + + return relayConstraints; +} + function convertToNormalBridgeSettings( constraints: IBridgeConstraints, ): grpcTypes.BridgeSettings.BridgeConstraints { diff --git a/gui/src/main/settings.ts b/gui/src/main/settings.ts index 3016e75289..fc2450581f 100644 --- a/gui/src/main/settings.ts +++ b/gui/src/main/settings.ts @@ -56,8 +56,8 @@ export default class Settings implements Readonly<ISettings> { IpcMainEventChannel.settings.handleSetWireguardQuantumResistant((quantumResistant?: boolean) => this.daemonRpc.setWireguardQuantumResistant(quantumResistant), ); - IpcMainEventChannel.settings.handleUpdateRelaySettings((update) => - this.daemonRpc.updateRelaySettings(update), + IpcMainEventChannel.settings.handleSetRelaySettings((relaySettings) => + this.daemonRpc.setRelaySettings(relaySettings), ); IpcMainEventChannel.settings.handleUpdateBridgeSettings((bridgeSettings) => { return this.daemonRpc.setBridgeSettings(bridgeSettings); diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index bab17524d6..584e80ed4f 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -23,7 +23,6 @@ import { liftConstraint, ObfuscationSettings, RelaySettings, - RelaySettingsUpdate, TunnelState, } from '../shared/daemon-rpc-types'; import { messages, relayLocations } from '../shared/gettext'; @@ -304,8 +303,8 @@ export default class AppRenderer { public connectTunnel = () => IpcRendererEventChannel.tunnel.connect(); public disconnectTunnel = () => IpcRendererEventChannel.tunnel.disconnect(); public reconnectTunnel = () => IpcRendererEventChannel.tunnel.reconnect(); - public updateRelaySettings = (relaySettings: RelaySettingsUpdate) => - IpcRendererEventChannel.settings.updateRelaySettings(relaySettings); + public setRelaySettings = (relaySettings: RelaySettings) => + IpcRendererEventChannel.settings.setRelaySettings(relaySettings); public updateBridgeSettings = (bridgeSettings: BridgeSettings) => IpcRendererEventChannel.settings.updateBridgeSettings(bridgeSettings); public setDnsOptions = (dnsOptions: IDnsOptions) => @@ -575,7 +574,7 @@ export default class AppRenderer { this.reduxActions.userInterface.updateLocale(locale); } - private setRelaySettings(relaySettings: RelaySettings) { + private setReduxRelaySettings(relaySettings: RelaySettings) { const actions = this.reduxActions; if ('normal' in relaySettings) { @@ -790,7 +789,7 @@ export default class AppRenderer { reduxSettings.updateObfuscationSettings(newSettings.obfuscationSettings); reduxSettings.updateCustomLists(newSettings.customLists); - this.setRelaySettings(newSettings.relaySettings); + this.setReduxRelaySettings(newSettings.relaySettings); this.setBridgeSettings(newSettings.bridgeSettings); } diff --git a/gui/src/renderer/components/Filter.tsx b/gui/src/renderer/components/Filter.tsx index 2cbc9ab239..d989cbca95 100644 --- a/gui/src/renderer/components/Filter.tsx +++ b/gui/src/renderer/components/Filter.tsx @@ -4,7 +4,7 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; import { Ownership } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; -import { useAppContext } from '../context'; +import { useRelaySettingsUpdater } from '../lib/constraint-updater'; import { EndpointType, filterLocations, @@ -38,7 +38,7 @@ const StyledNavigationScrollbars = styled(NavigationScrollbars)({ export default function Filter() { const history = useHistory(); - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); const initialProviders = useSelector(providersSelector); const [providers, setProviders] = useState<Record<string, boolean>>(initialProviders); @@ -69,9 +69,13 @@ export default function Filter() { // Applies the changes by sending them to the daemon. const onApply = useCallback(async () => { - await updateRelaySettings({ normal: { providers: formattedProviderList, ownership } }); + await relaySettingsUpdater((settings) => { + settings.providers = formattedProviderList; + settings.ownership = ownership; + return settings; + }); history.pop(); - }, [formattedProviderList, ownership, history, updateRelaySettings]); + }, [formattedProviderList, ownership, history, relaySettingsUpdater]); return ( <BackAction action={history.pop}> diff --git a/gui/src/renderer/components/OpenVpnSettings.tsx b/gui/src/renderer/components/OpenVpnSettings.tsx index dc14cd979f..f3224dc370 100644 --- a/gui/src/renderer/components/OpenVpnSettings.tsx +++ b/gui/src/renderer/components/OpenVpnSettings.tsx @@ -3,12 +3,17 @@ import { sprintf } from 'sprintf-js'; import styled from 'styled-components'; import { strings } from '../../config.json'; -import { BridgeState, RelayProtocol, TunnelProtocol } from '../../shared/daemon-rpc-types'; +import { + BridgeState, + RelayProtocol, + TunnelProtocol, + wrapConstraint, +} from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import log from '../../shared/logging'; -import RelaySettingsBuilder from '../../shared/relay-settings-builder'; import { removeNonNumericCharacters } from '../../shared/string-helpers'; import { useAppContext } from '../context'; +import { useRelaySettingsUpdater } from '../lib/constraint-updater'; import { useHistory } from '../lib/history'; import { formatHtml } from '../lib/html-formatter'; import { useBoolean } from '../lib/utilityHooks'; @@ -120,6 +125,7 @@ export default function OpenVpnSettings() { } function TransportProtocolSelector() { + const relaySettingsUpdater = useRelaySettingsUpdater(); const relaySettings = useSelector((state) => state.settings.relaySettings); const bridgeState = useSelector((state) => state.settings.bridgeState); @@ -128,7 +134,15 @@ function TransportProtocolSelector() { return protocol === 'any' ? null : protocol; }, [relaySettings]); - const protocolAndPortUpdater = useProtocolAndPortUpdater(); + const onSelect = useCallback( + async (protocol: RelayProtocol | null) => { + await relaySettingsUpdater((settings) => { + settings.openvpnConstraints.protocol = wrapConstraint(protocol); + return settings; + }); + }, + [relaySettingsUpdater], + ); const items: SelectorItem<RelayProtocol>[] = useMemo( () => [ @@ -152,7 +166,7 @@ function TransportProtocolSelector() { title={messages.pgettext('openvpn-settings-view', 'Transport protocol')} items={items} value={protocol} - onSelect={protocolAndPortUpdater} + onSelect={onSelect} automaticValue={null} /> {bridgeState === 'on' && ( @@ -176,41 +190,8 @@ function TransportProtocolSelector() { ); } -function useProtocolAndPortUpdater() { - const { updateRelaySettings } = useAppContext(); - - const updater = useCallback( - async (protocol: RelayProtocol | null, port?: number | null) => { - const relayUpdate = RelaySettingsBuilder.normal() - .tunnel.openvpn((openvpn) => { - if (protocol) { - openvpn.protocol.exact(protocol); - } else { - openvpn.protocol.any(); - } - - if (port) { - openvpn.port.exact(port); - } else { - openvpn.port.any(); - } - }) - .build(); - - try { - await updateRelaySettings(relayUpdate); - } catch (e) { - const error = e as Error; - log.error('Failed to update relay settings', error.message); - } - }, - [updateRelaySettings], - ); - - return updater; -} - function PortSelector() { + const relaySettingsUpdater = useRelaySettingsUpdater(); const relaySettings = useSelector((state) => state.settings.relaySettings); const protocol = useMemo(() => { @@ -223,13 +204,14 @@ function PortSelector() { return port === 'any' ? null : port; }, [relaySettings]); - const protocolAndPortUpdater = useProtocolAndPortUpdater(); - const onSelect = useCallback( async (port: number | null) => { - await protocolAndPortUpdater(protocol, port); + await relaySettingsUpdater((settings) => { + settings.openvpnConstraints.port = wrapConstraint(port); + return settings; + }); }, - [protocolAndPortUpdater, protocol], + [relaySettingsUpdater], ); const portItems = { diff --git a/gui/src/renderer/components/VpnSettings.tsx b/gui/src/renderer/components/VpnSettings.tsx index c884db3e5e..0aa90af8c3 100644 --- a/gui/src/renderer/components/VpnSettings.tsx +++ b/gui/src/renderer/components/VpnSettings.tsx @@ -3,11 +3,11 @@ import { sprintf } from 'sprintf-js'; import styled from 'styled-components'; import { colors, strings } from '../../config.json'; -import { IDnsOptions, TunnelProtocol } from '../../shared/daemon-rpc-types'; +import { IDnsOptions, TunnelProtocol, wrapConstraint } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import log from '../../shared/logging'; -import RelaySettingsBuilder from '../../shared/relay-settings-builder'; import { useAppContext } from '../context'; +import { useRelaySettingsUpdater } from '../lib/constraint-updater'; import { useHistory } from '../lib/history'; import { formatHtml } from '../lib/html-formatter'; import { RoutePath } from '../lib/routes'; @@ -663,25 +663,22 @@ function TunnelProtocolSetting() { const tunnelProtocol = useSelector((state) => mapRelaySettingsToProtocol(state.settings.relaySettings), ); - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); - const setTunnelProtocol = useCallback(async (tunnelProtocol: TunnelProtocol | null) => { - const relayUpdate = RelaySettingsBuilder.normal() - .tunnel.tunnelProtocol((config) => { - if (tunnelProtocol !== null) { - config.tunnelProtocol.exact(tunnelProtocol); - } else { - config.tunnelProtocol.any(); - } - }) - .build(); - try { - await updateRelaySettings(relayUpdate); - } catch (e) { - const error = e as Error; - log.error('Failed to update tunnel protocol constraints', error.message); - } - }, []); + const setTunnelProtocol = useCallback( + async (tunnelProtocol: TunnelProtocol | null) => { + try { + await relaySettingsUpdater((settings) => ({ + ...settings, + tunnelProtocol: wrapConstraint(tunnelProtocol), + })); + } catch (e) { + const error = e as Error; + log.error('Failed to update tunnel protocol constraints', error.message); + } + }, + [relaySettingsUpdater], + ); const tunnelProtocolItems: Array<SelectorItem<TunnelProtocol>> = useMemo( () => [ diff --git a/gui/src/renderer/components/WireguardSettings.tsx b/gui/src/renderer/components/WireguardSettings.tsx index e0e73f230e..7cd93b98bd 100644 --- a/gui/src/renderer/components/WireguardSettings.tsx +++ b/gui/src/renderer/components/WireguardSettings.tsx @@ -8,12 +8,13 @@ import { liftConstraint, LiftedConstraint, ObfuscationType, + wrapConstraint, } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import log from '../../shared/logging'; import { removeNonNumericCharacters } from '../../shared/string-helpers'; import { useAppContext } from '../context'; -import { createWireguardRelayUpdater } from '../lib/constraint-updater'; +import { useRelaySettingsUpdater } from '../lib/constraint-updater'; import { useHistory } from '../lib/history'; import { useBoolean } from '../lib/utilityHooks'; import { useSelector } from '../redux/store'; @@ -132,7 +133,7 @@ export default function WireguardSettings() { function PortSelector() { const relaySettings = useSelector((state) => state.settings.relaySettings); - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); const allowedPortRanges = useSelector((state) => state.settings.wireguardEndpointData.portRanges); const wireguardPortItems = useMemo<Array<SelectorItem<number>>>( @@ -147,23 +148,17 @@ function PortSelector() { const setWireguardPort = useCallback( async (port: number | null) => { - const relayUpdate = createWireguardRelayUpdater(relaySettings) - .tunnel.wireguard((wireguard) => { - if (port !== null) { - wireguard.port.exact(port); - } else { - wireguard.port.any(); - } - }) - .build(); try { - await updateRelaySettings(relayUpdate); + await relaySettingsUpdater((settings) => { + settings.wireguardConstraints.port = wrapConstraint(port); + return settings; + }); } catch (e) { const error = e as Error; log.error('Failed to update relay settings', error.message); } }, - [relaySettings], + [relaySettingsUpdater], ); const parseValue = useCallback((port: string) => parseInt(port), []); @@ -288,7 +283,7 @@ function Udp2tcpPortSetting() { ...obfuscationSettings, udp2tcpSettings: { ...obfuscationSettings.udp2tcpSettings, - port: port === 'any' ? 'any' : { only: port }, + port: wrapConstraint(port), }, }); }, @@ -324,7 +319,7 @@ function Udp2tcpPortSetting() { function MultihopSetting() { const relaySettings = useSelector((state) => state.settings.relaySettings); - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); const multihop = 'normal' in relaySettings ? relaySettings.normal.wireguard.useMultihop : false; @@ -332,17 +327,17 @@ function MultihopSetting() { const setMultihopImpl = useCallback( async (enabled: boolean) => { - const relayUpdate = createWireguardRelayUpdater(relaySettings) - .tunnel.wireguard((wireguard) => wireguard.useMultihop(enabled)) - .build(); try { - await updateRelaySettings(relayUpdate); + await relaySettingsUpdater((settings) => { + settings.wireguardConstraints.useMultihop = enabled; + return settings; + }); } catch (e) { const error = e as Error; log.error('Failed to update WireGuard multihop settings', error.message); } }, - [relaySettings, updateRelaySettings], + [relaySettingsUpdater], ); const setMultihop = useCallback( @@ -416,7 +411,7 @@ function MultihopSetting() { } function IpVersionSetting() { - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); const relaySettings = useSelector((state) => state.settings.relaySettings); const ipVersion = useMemo(() => { const ipVersion = 'normal' in relaySettings ? relaySettings.normal.wireguard.ipVersion : 'any'; @@ -439,23 +434,17 @@ function IpVersionSetting() { const setIpVersion = useCallback( async (ipVersion: IpVersion | null) => { - const relayUpdate = createWireguardRelayUpdater(relaySettings) - .tunnel.wireguard((wireguard) => { - if (ipVersion !== null) { - wireguard.ipVersion.exact(ipVersion); - } else { - wireguard.ipVersion.any(); - } - }) - .build(); try { - await updateRelaySettings(relayUpdate); + await relaySettingsUpdater((settings) => { + settings.wireguardConstraints.ipVersion = wrapConstraint(ipVersion); + return settings; + }); } catch (e) { const error = e as Error; log.error('Failed to update relay settings', error.message); } }, - [relaySettings, updateRelaySettings], + [relaySettingsUpdater], ); return ( diff --git a/gui/src/renderer/components/select-location/SelectLocation.tsx b/gui/src/renderer/components/select-location/SelectLocation.tsx index c812d84835..e09823586f 100644 --- a/gui/src/renderer/components/select-location/SelectLocation.tsx +++ b/gui/src/renderer/components/select-location/SelectLocation.tsx @@ -4,7 +4,7 @@ import { sprintf } from 'sprintf-js'; import { colors } from '../../../config.json'; import { Ownership } from '../../../shared/daemon-rpc-types'; import { messages } from '../../../shared/gettext'; -import { useAppContext } from '../../context'; +import { useRelaySettingsUpdater } from '../../lib/constraint-updater'; import { filterSpecialLocations } from '../../lib/filter-locations'; import { useHistory } from '../../lib/history'; import { formatHtml } from '../../lib/html-formatter'; @@ -57,7 +57,7 @@ import { SpacePreAllocationView } from './SpacePreAllocationView'; export default function SelectLocation() { const history = useHistory(); - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); const { saveScrollPosition, resetScrollPositions, @@ -85,13 +85,17 @@ export default function SelectLocation() { const onClearProviders = useCallback(async () => { resetScrollPositions(); - await updateRelaySettings({ normal: { providers: [] } }); - }, [resetScrollPositions]); + if (relaySettings) { + await relaySettingsUpdater((settings) => ({ ...settings, providers: [] })); + } + }, [relaySettingsUpdater, resetScrollPositions, relaySettings]); const onClearOwnership = useCallback(async () => { resetScrollPositions(); - await updateRelaySettings({ normal: { ownership: Ownership.any } }); - }, [resetScrollPositions]); + if (relaySettings) { + await relaySettingsUpdater((settings) => ({ ...settings, ownership: Ownership.any })); + } + }, [relaySettingsUpdater, resetScrollPositions, relaySettings]); const changeLocationType = useCallback( (locationType: LocationType) => { diff --git a/gui/src/renderer/components/select-location/select-location-hooks.ts b/gui/src/renderer/components/select-location/select-location-hooks.ts index 105e701524..48d81e594c 100644 --- a/gui/src/renderer/components/select-location/select-location-hooks.ts +++ b/gui/src/renderer/components/select-location/select-location-hooks.ts @@ -4,30 +4,33 @@ import BridgeSettingsBuilder from '../../../shared/bridge-settings-builder'; import { BridgeSettings, RelayLocation, - RelaySettingsUpdate, + RelaySettings, + wrapConstraint, } from '../../../shared/daemon-rpc-types'; import log from '../../../shared/logging'; -import RelaySettingsBuilder from '../../../shared/relay-settings-builder'; import { useAppContext } from '../../context'; -import { createWireguardRelayUpdater } from '../../lib/constraint-updater'; +import { useRelaySettingsModifier } from '../../lib/constraint-updater'; import { useHistory } from '../../lib/history'; -import { useSelector } from '../../redux/store'; import { LocationType, SpecialBridgeLocationType } from './select-location-types'; import { useSelectLocationContext } from './SelectLocationContainer'; export function useOnSelectExitLocation() { const onSelectLocation = useOnSelectLocation(); const history = useHistory(); + const relaySettingsModifier = useRelaySettingsModifier(); const { connectTunnel } = useAppContext(); const onSelectRelay = useCallback( async (relayLocation: RelayLocation) => { + const settings = relaySettingsModifier((settings) => ({ + ...settings, + location: wrapConstraint(relayLocation), + })); history.pop(); - const relayUpdate = RelaySettingsBuilder.normal().location.fromRaw(relayLocation).build(); - await onSelectLocation(relayUpdate); + await onSelectLocation({ normal: settings }); await connectTunnel(); }, - [history], + [history, relaySettingsModifier], ); const onSelectSpecial = useCallback((_location: undefined) => { @@ -40,36 +43,44 @@ export function useOnSelectExitLocation() { export function useOnSelectEntryLocation() { const onSelectLocation = useOnSelectLocation(); const { setLocationType } = useSelectLocationContext(); - const baseRelaySettings = useSelector((state) => state.settings.relaySettings); + const relaySettingsModifier = useRelaySettingsModifier(); - const onSelectRelay = useCallback(async (entryLocation: RelayLocation) => { - setLocationType(LocationType.exit); - const relayUpdate = createWireguardRelayUpdater(baseRelaySettings) - .tunnel.wireguard((wireguard) => wireguard.entryLocation.exact(entryLocation)) - .build(); - await onSelectLocation(relayUpdate); - }, []); + const onSelectRelay = useCallback( + async (entryLocation: RelayLocation) => { + setLocationType(LocationType.exit); + const settings = relaySettingsModifier((settings) => { + settings.wireguardConstraints.entryLocation = wrapConstraint(entryLocation); + return settings; + }); + await onSelectLocation({ normal: settings }); + }, + [relaySettingsModifier], + ); - const onSelectSpecial = useCallback(async (_location: 'any') => { - setLocationType(LocationType.exit); - const relayUpdate = createWireguardRelayUpdater(baseRelaySettings) - .tunnel.wireguard((wireguard) => wireguard.entryLocation.any()) - .build(); - await onSelectLocation(relayUpdate); - }, []); + const onSelectSpecial = useCallback( + async (_location: 'any') => { + setLocationType(LocationType.exit); + const settings = relaySettingsModifier((settings) => { + settings.wireguardConstraints.entryLocation = 'any'; + return settings; + }); + await onSelectLocation({ normal: settings }); + }, + [relaySettingsModifier], + ); return [onSelectRelay, onSelectSpecial] as const; } function useOnSelectLocation() { - const { updateRelaySettings } = useAppContext(); + const { setRelaySettings } = useAppContext(); - return useCallback(async (relayUpdate: RelaySettingsUpdate) => { + return useCallback(async (relaySettings: RelaySettings) => { try { - await updateRelaySettings(relayUpdate); + await setRelaySettings(relaySettings); } catch (e) { const error = e as Error; - log.error(`Failed to select the exit location: ${error.message}`); + log.error(`Failed to select the location: ${error.message}`); } }, []); } diff --git a/gui/src/renderer/lib/constraint-updater.ts b/gui/src/renderer/lib/constraint-updater.ts index 3ebbcccbc0..054f063465 100644 --- a/gui/src/renderer/lib/constraint-updater.ts +++ b/gui/src/renderer/lib/constraint-updater.ts @@ -1,36 +1,89 @@ -import RelaySettingsBuilder from '../../shared/relay-settings-builder'; -import { RelaySettingsRedux } from '../redux/settings/reducers'; +import { useCallback } from 'react'; -export function createWireguardRelayUpdater( - relaySettings: RelaySettingsRedux, -): ReturnType<typeof RelaySettingsBuilder['normal']> { - if ('normal' in relaySettings) { - const constraints = relaySettings.normal.wireguard; +import { + IOpenVpnConstraints, + IRelaySettingsNormal, + IWireguardConstraints, + Ownership, + wrapConstraint, +} from '../../shared/daemon-rpc-types'; +import { useAppContext } from '../context'; +import { NormalRelaySettingsRedux } from '../redux/settings/reducers'; +import { useNormalRelaySettings } from './utilityHooks'; - const relayUpdate = RelaySettingsBuilder.normal().tunnel.wireguard((wireguard) => { - if (constraints.port === 'any') { - wireguard.port.any(); - } else { - wireguard.port.exact(constraints.port); - } +export function wrapRelaySettingsOrDefault( + relaySettings?: NormalRelaySettingsRedux, +): IRelaySettingsNormal<IOpenVpnConstraints, IWireguardConstraints> { + if (relaySettings) { + const openvpnPort = wrapConstraint(relaySettings.openvpn.port); + const openvpnProtocol = wrapConstraint(relaySettings.openvpn.protocol); + const wgPort = wrapConstraint(relaySettings.wireguard.port); + const wgIpVersion = wrapConstraint(relaySettings.wireguard.ipVersion); + const wgEntryLocation = wrapConstraint(relaySettings.wireguard.entryLocation); + const location = wrapConstraint(relaySettings.location); + const tunnelProtocol = wrapConstraint(relaySettings.tunnelProtocol); - if (constraints.ipVersion === 'any') { - wireguard.ipVersion.any(); - } else { - wireguard.ipVersion.exact(constraints.ipVersion); - } + return { + providers: [...relaySettings.providers], + ownership: relaySettings.ownership, + tunnelProtocol, + openvpnConstraints: { + port: openvpnPort, + protocol: openvpnProtocol, + }, + wireguardConstraints: { + port: wgPort, + ipVersion: wgIpVersion, + useMultihop: relaySettings.wireguard.useMultihop, + entryLocation: wgEntryLocation, + }, + location, + }; + } + + return { + location: 'any', + tunnelProtocol: 'any', + providers: [], + ownership: Ownership.any, + openvpnConstraints: { + port: 'any', + protocol: 'any', + }, + wireguardConstraints: { + port: 'any', + ipVersion: 'any', + useMultihop: false, + entryLocation: 'any', + }, + }; +} - wireguard.useMultihop(constraints.useMultihop); +type UpdateFunction = ( + settings: IRelaySettingsNormal<IOpenVpnConstraints, IWireguardConstraints>, +) => IRelaySettingsNormal<IOpenVpnConstraints, IWireguardConstraints>; - if (constraints.entryLocation === 'any') { - wireguard.entryLocation.any(); - } else if (constraints.entryLocation !== undefined) { - wireguard.entryLocation.exact(constraints.entryLocation); - } - }); +export function useRelaySettingsModifier() { + const relaySettings = useNormalRelaySettings(); - return relayUpdate; - } else { - return RelaySettingsBuilder.normal(); - } + return useCallback( + (fn: UpdateFunction) => { + const settings = wrapRelaySettingsOrDefault(relaySettings); + return fn(settings); + }, + [relaySettings], + ); +} + +export function useRelaySettingsUpdater() { + const { setRelaySettings } = useAppContext(); + const modifyRelaySettings = useRelaySettingsModifier(); + + return useCallback( + async (fn: UpdateFunction) => { + const modifiedSettings = modifyRelaySettings(fn); + await setRelaySettings({ normal: modifiedSettings }); + }, + [setRelaySettings, modifyRelaySettings], + ); } diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts index 51c1d67c0d..6977be4375 100644 --- a/gui/src/shared/daemon-rpc-types.ts +++ b/gui/src/shared/daemon-rpc-types.ts @@ -112,6 +112,14 @@ export type LiftedConstraint<T> = 'any' | T; export function liftConstraint<T>(constraint: Constraint<T>): LiftedConstraint<T> { return constraint === 'any' ? constraint : constraint.only; } +export function wrapConstraint<T>( + constraint: LiftedConstraint<T> | undefined | null, +): Constraint<T> { + if (constraint) { + return constraint === 'any' ? 'any' : { only: constraint }; + } + return 'any'; +} export type ProxyType = 'shadowsocks' | 'custom'; export function proxyTypeToString(proxy: ProxyType): string { @@ -267,19 +275,6 @@ export type RelaySettings = customTunnelEndpoint: IRelaySettingsCustom; }; -// types describing the partial update of RelaySettings -export type RelaySettingsNormalUpdate = Partial< - IRelaySettingsNormal<Partial<IOpenVpnConstraints>, Partial<IWireguardConstraints>> ->; - -export type RelaySettingsUpdate = - | { - normal: RelaySettingsNormalUpdate; - } - | { - customTunnelEndpoint: IRelaySettingsCustom; - }; - export interface IRelayListWithEndpointData { relayList: IRelayList; wireguardEndpointData: IWireguardEndpointData; diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts index 946b4fa99a..994bacdcd6 100644 --- a/gui/src/shared/ipc-schema.ts +++ b/gui/src/shared/ipc-schema.ts @@ -19,7 +19,7 @@ import { IRelayListWithEndpointData, ISettings, ObfuscationSettings, - RelaySettingsUpdate, + RelaySettings, TunnelState, VoucherResponse, } from './daemon-rpc-types'; @@ -172,7 +172,7 @@ export const ipcSchema = { setOpenVpnMssfix: invoke<number | undefined, void>(), setWireguardMtu: invoke<number | undefined, void>(), setWireguardQuantumResistant: invoke<boolean | undefined, void>(), - updateRelaySettings: invoke<RelaySettingsUpdate, void>(), + setRelaySettings: invoke<RelaySettings, void>(), updateBridgeSettings: invoke<BridgeSettings, void>(), setDnsOptions: invoke<IDnsOptions, void>(), setObfuscationSettings: invoke<ObfuscationSettings, void>(), diff --git a/gui/src/shared/relay-settings-builder.ts b/gui/src/shared/relay-settings-builder.ts deleted file mode 100644 index e4c11e5132..0000000000 --- a/gui/src/shared/relay-settings-builder.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { - Constraint, - IOpenVpnConstraints, - IpVersion, - IWireguardConstraints, - RelayLocation, - RelayProtocol, - RelaySettingsNormalUpdate, - RelaySettingsUpdate, - TunnelProtocol, -} from './daemon-rpc-types'; -import makeLocationBuilder, { ILocationBuilder } from './relay-location-builder'; - -interface IExactOrAny<T, Self> { - exact(value: T): Self; - any(): Self; -} - -interface IOpenVPNConfigurator { - port: IExactOrAny<number, IOpenVPNConfigurator>; - protocol: IExactOrAny<RelayProtocol, IOpenVPNConfigurator>; -} - -interface IWireguardConfigurator { - port: IExactOrAny<number, IWireguardConfigurator>; - ipVersion: IExactOrAny<IpVersion, IWireguardConfigurator>; - useMultihop: (value: boolean) => IWireguardConfigurator; - entryLocation: IExactOrAny<RelayLocation, IWireguardConfigurator>; -} - -interface ITunnelProtocolConfigurator { - tunnelProtocol: IExactOrAny<TunnelProtocol, ITunnelProtocolConfigurator>; -} - -interface ITunnelBuilder { - openvpn( - configurator: (openVpnConfigurator: IOpenVPNConfigurator) => void, - ): NormalRelaySettingsBuilder; - wireguard( - configurator: (wireguardConfigurator: IWireguardConfigurator) => void, - ): NormalRelaySettingsBuilder; - tunnelProtocol( - configurator: (tunnelProtocolConfigurator: ITunnelProtocolConfigurator) => void, - ): NormalRelaySettingsBuilder; -} - -class NormalRelaySettingsBuilder { - private payload: RelaySettingsNormalUpdate = {}; - - public build(): RelaySettingsUpdate { - return { - normal: this.payload, - }; - } - - get location(): ILocationBuilder<NormalRelaySettingsBuilder> { - return makeLocationBuilder(this, (location) => { - this.payload.location = location; - }); - } - - get tunnel(): ITunnelBuilder { - const updateOpenvpn = (next: Partial<IOpenVpnConstraints>) => { - if (this.payload.openvpnConstraints === undefined) { - this.payload.openvpnConstraints = next; - } else { - const prev = this.payload.openvpnConstraints; - this.payload.openvpnConstraints = { - ...prev, - ...next, - }; - } - }; - - const updateWireguard = (next: Partial<IWireguardConstraints>) => { - if (this.payload.wireguardConstraints === undefined) { - this.payload.wireguardConstraints = next; - } else { - const prev = this.payload.wireguardConstraints; - this.payload.wireguardConstraints = { - ...prev, - ...next, - }; - } - }; - - const updateTunnelProtocol = (next?: Constraint<TunnelProtocol>) => { - this.payload.tunnelProtocol = next; - }; - - return { - openvpn: (configurator: (configurator: IOpenVPNConfigurator) => void) => { - const openvpnBuilder: IOpenVPNConfigurator = { - get port() { - const apply = (port: Constraint<number>) => { - updateOpenvpn({ port }); - return this; - }; - return { - exact: (value: number) => apply({ only: value }), - any: () => apply('any'), - }; - }, - get protocol() { - const apply = (protocol: Constraint<RelayProtocol>) => { - updateOpenvpn({ protocol }); - return this; - }; - return { - exact: (value: RelayProtocol) => apply({ only: value }), - any: () => apply('any'), - }; - }, - }; - - configurator(openvpnBuilder); - - return this; - }, - - wireguard: (configurator: (configurator: IWireguardConfigurator) => void) => { - const wireguardBuilder: IWireguardConfigurator = { - get port() { - const apply = (port: Constraint<number>) => { - updateWireguard({ port }); - return this; - }; - return { - exact: (value: number) => apply({ only: value }), - any: () => apply('any'), - }; - }, - get ipVersion() { - const apply = (ipVersion: Constraint<IpVersion>) => { - updateWireguard({ ipVersion }); - return this; - }; - return { - exact: (value: IpVersion) => apply({ only: value }), - any: () => apply('any'), - }; - }, - get useMultihop() { - return (useMultihop: boolean) => { - updateWireguard({ useMultihop }); - return this; - }; - }, - get entryLocation() { - const apply = (entryLocation: Constraint<RelayLocation> | undefined) => { - updateWireguard({ entryLocation }); - return this; - }; - return { - exact: (entryLocation: RelayLocation) => apply({ only: entryLocation }), - any: () => apply('any'), - }; - }, - }; - configurator(wireguardBuilder); - return this; - }, - - tunnelProtocol: (configurator: (configurator: ITunnelProtocolConfigurator) => void) => { - const tunnelProtocolBuilder = { - get tunnelProtocol() { - return { - exact: (value: TunnelProtocol) => { - updateTunnelProtocol({ only: value }); - return this; - }, - any: () => { - updateTunnelProtocol('any'); - return this; - }, - }; - }, - }; - - configurator(tunnelProtocolBuilder); - return this; - }, - }; - } -} - -export default { - normal: () => new NormalRelaySettingsBuilder(), -}; diff --git a/gui/test/unit/relay-settings-builder.spec.ts b/gui/test/unit/relay-settings-builder.spec.ts deleted file mode 100644 index eeba0828b7..0000000000 --- a/gui/test/unit/relay-settings-builder.spec.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { expect } from 'chai'; -import { it, describe } from 'mocha'; -import RelaySettingsBuilder from '../../src/shared/relay-settings-builder'; - -describe('Relay settings builder', () => { - it('should set location to any', () => { - expect(RelaySettingsBuilder.normal().location.any().build()).to.deep.equal({ - normal: { - location: 'any', - }, - }); - }); - - it('should bound location to city', () => { - expect(RelaySettingsBuilder.normal().location.city('se', 'mma').build()).to.deep.equal({ - normal: { - location: { - only: { - country: 'se', city: 'mma', - }, - }, - }, - }); - }); - - it('should bound location to country', () => { - expect(RelaySettingsBuilder.normal().location.country('se').build()).to.deep.equal({ - normal: { - location: { - only: { country: 'se' }, - }, - }, - }); - }); - - it('should set openvpn settings to any', () => { - expect( - RelaySettingsBuilder.normal() - .tunnel.openvpn((openvpn) => { - openvpn.port.any().protocol.any(); - }) - .build(), - ).to.deep.equal({ - normal: { - openvpnConstraints: { - port: 'any', - protocol: 'any', - }, - }, - }); - }); - - it('should set openvpn settings to exact values', () => { - expect( - RelaySettingsBuilder.normal() - .tunnel.openvpn((openvpn) => { - openvpn.port.exact(80).protocol.exact('tcp'); - }) - .build(), - ).to.deep.equal({ - normal: { - openvpnConstraints: { - port: { only: 80 }, - protocol: { only: 'tcp' }, - }, - }, - }); - }); - - it('should set location from raw RelayLocation', () => { - expect(RelaySettingsBuilder.normal().location.fromRaw('any').build()).to.deep.equal({ - normal: { - location: 'any', - }, - }); - - expect(RelaySettingsBuilder.normal().location.fromRaw({ country: 'se' }).build()).to.deep.equal( - { - normal: { - location: { - only: { country: 'se' }, - }, - }, - }, - ); - - expect( - RelaySettingsBuilder.normal() - .location.fromRaw({ country: 'se', city: 'mma' }) - .build(), - ).to.deep.equal({ - normal: { - location: { - only: { country: 'se', city: 'mma' }, - }, - }, - }); - }); -}); diff --git a/mullvad-cli/src/cmds/relay.rs b/mullvad-cli/src/cmds/relay.rs index 2bccbbc24e..6d1b487126 100644 --- a/mullvad-cli/src/cmds/relay.rs +++ b/mullvad-cli/src/cmds/relay.rs @@ -6,8 +6,8 @@ use mullvad_types::{ location::Location, relay_constraints::{ Constraint, GeographicLocationConstraint, LocationConstraint, LocationConstraintFormatter, - Match, OpenVpnConstraints, Ownership, Provider, Providers, RelayConstraintsUpdate, - RelaySettings, RelaySettingsUpdate, TransportPort, WireguardConstraints, + Match, OpenVpnConstraints, Ownership, Provider, Providers, RelayConstraints, RelaySettings, + TransportPort, WireguardConstraints, }, relay_list::{RelayEndpointData, RelayListCountry}, ConnectionConfig, CustomTunnelEndpoint, @@ -339,9 +339,21 @@ impl Relay { /// Get active relays which are not bridges. - async fn update_constraints(update: RelaySettingsUpdate) -> Result<()> { + async fn update_constraints(update_fn: impl FnOnce(&mut RelayConstraints)) -> Result<()> { let mut rpc = MullvadProxyClient::new().await?; - rpc.update_relay_settings(update).await?; + let settings = rpc.get_settings().await?; + + let relay_settings = settings.get_relay_settings(); + let mut constraints = match relay_settings { + RelaySettings::Normal(normal) => normal, + RelaySettings::CustomTunnelEndpoint(_custom) => { + println!("Removing custom relay settings"); + RelayConstraints::default() + } + }; + update_fn(&mut constraints); + rpc.set_relay_settings(RelaySettings::Normal(constraints)) + .await?; println!("Relay constraints updated"); Ok(()) } @@ -408,7 +420,11 @@ impl Relay { .await? } }; - Self::update_constraints(RelaySettingsUpdate::CustomTunnelEndpoint(custom_endpoint)).await + let mut rpc = MullvadProxyClient::new().await?; + rpc.set_relay_settings(RelaySettings::CustomTunnelEndpoint(custom_endpoint)) + .await?; + println!("Relay constraints updated"); + Ok(()) } fn read_custom_openvpn_relay( @@ -507,10 +523,9 @@ impl Relay { location_constraint.map(LocationConstraint::Location) }; - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(constraint), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.location = constraint; + }) .await } @@ -519,12 +534,10 @@ impl Relay { let list_id = super::custom_list::find_list_by_name(&mut rpc, &custom_list_name) .await? .id; - rpc.update_relay_settings(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(Constraint::Only(LocationConstraint::CustomList { list_id })), - ..Default::default() - })) - .await?; - Ok(()) + Self::update_constraints(|constraints| { + constraints.location = Constraint::Only(LocationConstraint::CustomList { list_id }); + }) + .await } async fn set_providers(providers: Vec<String>) -> Result<()> { @@ -533,18 +546,16 @@ impl Relay { } else { Constraint::Only(Providers::new(providers.into_iter()).unwrap()) }; - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - providers: Some(providers), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.providers = providers; + }) .await } async fn set_ownership(ownership: Constraint<Ownership>) -> Result<()> { - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - ownership: Some(ownership), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.ownership = ownership; + }) .await } @@ -558,10 +569,9 @@ impl Relay { }; openvpn_constraints.port = parse_transport_port(port, protocol, &openvpn_constraints.port); - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - openvpn_constraints: Some(openvpn_constraints), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.openvpn_constraints = openvpn_constraints; + }) .await } @@ -628,10 +638,9 @@ impl Relay { None => (), } - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - wireguard_constraints: Some(wireguard_constraints), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.wireguard_constraints = wireguard_constraints; + }) .await } @@ -648,10 +657,9 @@ impl Relay { } async fn set_tunnel_protocol(protocol: Constraint<TunnelType>) -> Result<()> { - Self::update_constraints(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(protocol), - ..Default::default() - })) + Self::update_constraints(|constraints| { + constraints.tunnel_protocol = protocol; + }) .await } } diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs index 1077185ca3..8ee8e58fd6 100644 --- a/mullvad-daemon/src/lib.rs +++ b/mullvad-daemon/src/lib.rs @@ -47,7 +47,7 @@ use mullvad_types::{ custom_list::CustomList, device::{Device, DeviceEvent, DeviceEventCause, DeviceId, DeviceState, RemoveDeviceEvent}, location::GeoIpLocation, - relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettingsUpdate}, + relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettings}, relay_list::RelayList, settings::{DnsOptions, Settings}, states::{TargetState, TunnelState}, @@ -232,7 +232,7 @@ pub enum DaemonCommand { /// Remove device from a given account. RemoveDevice(ResponseTx<(), Error>, AccountToken, DeviceId), /// Place constraints on the type of tunnel and relay - UpdateRelaySettings(ResponseTx<(), settings::Error>, RelaySettingsUpdate), + SetRelaySettings(ResponseTx<(), settings::Error>, RelaySettings), /// Set the allow LAN setting. SetAllowLan(ResponseTx<(), settings::Error>, bool), /// Set the beta program setting. @@ -1055,7 +1055,7 @@ where } GetAccountHistory(tx) => self.on_get_account_history(tx), ClearAccountHistory(tx) => self.on_clear_account_history(tx).await, - UpdateRelaySettings(tx, update) => self.on_update_relay_settings(tx, update).await, + SetRelaySettings(tx, update) => self.on_set_relay_settings(tx, update).await, SetAllowLan(tx, allow_lan) => self.on_set_allow_lan(tx, allow_lan).await, SetShowBetaReleases(tx, enabled) => self.on_set_show_beta_releases(tx, enabled).await, SetBlockWhenDisconnected(tx, block_when_disconnected) => { @@ -1817,18 +1817,18 @@ where } } - async fn on_update_relay_settings( + async fn on_set_relay_settings( &mut self, tx: ResponseTx<(), settings::Error>, - update: RelaySettingsUpdate, + update: RelaySettings, ) { match self .settings - .update(move |settings| settings.update_relay_settings(update)) + .update(move |settings| settings.set_relay_settings(update)) .await { Ok(settings_changed) => { - Self::oneshot_send(tx, Ok(()), "update_relay_settings response"); + Self::oneshot_send(tx, Ok(()), "set_relay_settings response"); if settings_changed { self.event_listener .notify_settings(self.settings.to_settings()); @@ -1840,7 +1840,7 @@ where } Err(e) => { log::error!("{}", e.display_chain_with_msg("Unable to save settings")); - Self::oneshot_send(tx, Err(e), "update_relay_settings response"); + Self::oneshot_send(tx, Err(e), "set_relay_settings response"); } } } diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs index b494c53fbb..79466d8878 100644 --- a/mullvad-daemon/src/management_interface.rs +++ b/mullvad-daemon/src/management_interface.rs @@ -13,7 +13,7 @@ use mullvad_paths; use mullvad_types::settings::DnsOptions; use mullvad_types::{ account::AccountToken, - relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettingsUpdate}, + relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettings}, relay_list::RelayList, settings::Settings, states::{TargetState, TunnelState}, @@ -164,16 +164,16 @@ impl ManagementService for ManagementServiceImpl { Ok(Response::new(())) } - async fn update_relay_settings( + async fn set_relay_settings( &self, - request: Request<types::RelaySettingsUpdate>, + request: Request<types::RelaySettings>, ) -> ServiceResult<()> { - log::debug!("update_relay_settings"); + log::debug!("set_relay_settings"); let (tx, rx) = oneshot::channel(); let constraints_update = - RelaySettingsUpdate::try_from(request.into_inner()).map_err(map_protobuf_type_err)?; + RelaySettings::try_from(request.into_inner()).map_err(map_protobuf_type_err)?; - let message = DaemonCommand::UpdateRelaySettings(tx, constraints_update); + let message = DaemonCommand::SetRelaySettings(tx, constraints_update); self.send_command_to_daemon(message)?; self.wait_for_result(rx) .await? diff --git a/mullvad-jni/src/classes.rs b/mullvad-jni/src/classes.rs index 45dc21a4a2..d39cb156d8 100644 --- a/mullvad-jni/src/classes.rs +++ b/mullvad-jni/src/classes.rs @@ -55,9 +55,6 @@ pub const CLASSES: &[&str] = &[ "net/mullvad/mullvadvpn/model/RelayListCountry", "net/mullvad/mullvadvpn/model/RelaySettings$CustomTunnelEndpoint", "net/mullvad/mullvadvpn/model/RelaySettings$Normal", - "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$CustomTunnelEndpoint", - "net/mullvad/mullvadvpn/model/RelaySettingsUpdate$Normal", - "net/mullvad/mullvadvpn/model/RelayConstraintsUpdate", "net/mullvad/mullvadvpn/model/SelectedObfuscation", "net/mullvad/mullvadvpn/model/Settings", "net/mullvad/mullvadvpn/model/TunnelState$Error", diff --git a/mullvad-jni/src/daemon_interface.rs b/mullvad-jni/src/daemon_interface.rs index c64c94041e..236c864a01 100644 --- a/mullvad-jni/src/daemon_interface.rs +++ b/mullvad-jni/src/daemon_interface.rs @@ -4,7 +4,7 @@ use mullvad_types::{ account::{AccountData, AccountToken, PlayPurchase, VoucherSubmission}, device::{Device, DeviceState}, location::GeoIpLocation, - relay_constraints::{ObfuscationSettings, RelaySettingsUpdate}, + relay_constraints::{ObfuscationSettings, RelaySettings}, relay_list::RelayList, settings::{DnsOptions, Settings}, states::{TargetState, TunnelState}, @@ -327,10 +327,10 @@ impl DaemonInterface { .map_err(Error::from) } - pub fn update_relay_settings(&self, update: RelaySettingsUpdate) -> Result<()> { + pub fn set_relay_settings(&self, update: RelaySettings) -> Result<()> { let (tx, rx) = oneshot::channel(); - self.send_command(DaemonCommand::UpdateRelaySettings(tx, update))?; + self.send_command(DaemonCommand::SetRelaySettings(tx, update))?; block_on(rx) .map_err(|_| Error::NoResponse)? diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index a40bf73fc1..a2c3586431 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -1306,19 +1306,19 @@ pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_verifyP #[no_mangle] #[allow(non_snake_case)] -pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_updateRelaySettings( +pub extern "system" fn Java_net_mullvad_mullvadvpn_service_MullvadDaemon_setRelaySettings( env: JNIEnv<'_>, _: JObject<'_>, daemon_interface_address: jlong, - relaySettingsUpdate: JObject<'_>, + relaySettings: JObject<'_>, ) { let env = JnixEnv::from(env); // SAFETY: The address points to an instance valid for the duration of this function call if let Some(daemon_interface) = unsafe { get_daemon_interface(daemon_interface_address) } { - let update = FromJava::from_java(&env, relaySettingsUpdate); + let update = FromJava::from_java(&env, relaySettings); - if let Err(error) = daemon_interface.update_relay_settings(update) { + if let Err(error) = daemon_interface.set_relay_settings(update) { log::error!( "{}", error.display_chain_with_msg("Failed to update relay settings") diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto index 4846f896e2..35417584b3 100644 --- a/mullvad-management-interface/proto/management_interface.proto +++ b/mullvad-management-interface/proto/management_interface.proto @@ -28,9 +28,9 @@ service ManagementService { // Relays and tunnel constraints rpc UpdateRelayLocations(google.protobuf.Empty) returns (google.protobuf.Empty) {} - rpc UpdateRelaySettings(RelaySettingsUpdate) returns (google.protobuf.Empty) {} rpc GetRelayLocations(google.protobuf.Empty) returns (RelayList) {} rpc GetCurrentLocation(google.protobuf.Empty) returns (GeoIpLocation) {} + rpc SetRelaySettings(RelaySettings) returns (google.protobuf.Empty) {} rpc SetBridgeSettings(BridgeSettings) returns (google.protobuf.Empty) {} rpc SetBridgeState(BridgeState) returns (google.protobuf.Empty) {} rpc SetObfuscationSettings(ObfuscationSettings) returns (google.protobuf.Empty) {} @@ -101,13 +101,6 @@ service ManagementService { message UUID { string value = 1; } -message RelaySettingsUpdate { - oneof type { - CustomRelaySettings custom = 1; - NormalRelaySettingsUpdate normal = 2; - } -} - message AccountData { google.protobuf.Timestamp expiry = 1; } message AccountHistory { google.protobuf.StringValue token = 1; } @@ -419,20 +412,6 @@ message NormalRelaySettings { Ownership ownership = 6; } -// Constraints are only updated for fields that are provided -message NormalRelaySettingsUpdate { - LocationConstraint location = 1; - ProviderUpdate providers = 2; - TunnelTypeUpdate tunnel_type = 3; - WireguardConstraints wireguard_constraints = 4; - OpenvpnConstraints openvpn_constraints = 5; - OwnershipUpdate ownership = 6; -} - -message ProviderUpdate { repeated string providers = 1; } - -message TunnelTypeUpdate { optional TunnelType tunnel_type = 2; } - message TransportPort { TransportProtocol protocol = 1; optional uint32 port = 2; @@ -440,8 +419,6 @@ message TransportPort { message OpenvpnConstraints { TransportPort port = 1; } -message OwnershipUpdate { Ownership ownership = 1; } - enum IpVersion { V4 = 0; V6 = 1; diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs index 417083e161..1c15a169cd 100644 --- a/mullvad-management-interface/src/client.rs +++ b/mullvad-management-interface/src/client.rs @@ -8,7 +8,7 @@ use mullvad_types::{ custom_list::{CustomList, Id}, device::{Device, DeviceEvent, DeviceId, DeviceState, RemoveDeviceEvent}, location::GeoIpLocation, - relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettingsUpdate}, + relay_constraints::{BridgeSettings, BridgeState, ObfuscationSettings, RelaySettings}, relay_list::RelayList, settings::{DnsOptions, Settings}, states::TunnelState, @@ -221,10 +221,10 @@ impl MullvadProxyClient { Ok(()) } - pub async fn update_relay_settings(&mut self, update: RelaySettingsUpdate) -> Result<()> { - let update = types::RelaySettingsUpdate::from(update); + pub async fn set_relay_settings(&mut self, update: RelaySettings) -> Result<()> { + let update = types::RelaySettings::from(update); self.0 - .update_relay_settings(update) + .set_relay_settings(update) .await .map_err(Error::Rpc)?; Ok(()) diff --git a/mullvad-management-interface/src/types/conversions/relay_constraints.rs b/mullvad-management-interface/src/types/conversions/relay_constraints.rs index b33bf3c165..cff2bb5847 100644 --- a/mullvad-management-interface/src/types/conversions/relay_constraints.rs +++ b/mullvad-management-interface/src/types/conversions/relay_constraints.rs @@ -1,10 +1,9 @@ use crate::types::{conversions::net::try_tunnel_type_from_i32, proto, FromProtobufTypeError}; use mullvad_types::{ custom_list::Id, - relay_constraints::{Constraint, GeographicLocationConstraint, RelaySettingsUpdate}, + relay_constraints::{Constraint, GeographicLocationConstraint}, }; use std::str::FromStr; -use talpid_types::net::TunnelType; impl TryFrom<&proto::WireguardConstraints> for mullvad_types::relay_constraints::WireguardConstraints @@ -131,176 +130,6 @@ impl TryFrom<proto::RelaySettings> for mullvad_types::relay_constraints::RelaySe } } -impl From<RelaySettingsUpdate> for proto::RelaySettingsUpdate { - fn from(relay_settings_update: RelaySettingsUpdate) -> Self { - match relay_settings_update { - RelaySettingsUpdate::Normal(constraints) => proto::RelaySettingsUpdate { - r#type: Some(proto::relay_settings_update::Type::Normal( - proto::NormalRelaySettingsUpdate { - location: constraints - .location - .and_then(|constraint| match constraint { - Constraint::Any => None, - Constraint::Only(location) => { - Some(proto::LocationConstraint::from(location)) - } - }), - providers: constraints - .providers - .map(|constraint| proto::ProviderUpdate { - providers: convert_providers_constraint(&constraint), - }), - ownership: constraints - .ownership - .map(|ownership| proto::OwnershipUpdate { - ownership: i32::from(convert_ownership_constraint(&ownership)), - }), - tunnel_type: constraints.tunnel_protocol.map(|protocol| { - proto::TunnelTypeUpdate { - tunnel_type: protocol - .map(|protocol| { - i32::from(match protocol { - TunnelType::Wireguard => proto::TunnelType::Wireguard, - TunnelType::OpenVpn => proto::TunnelType::Openvpn, - }) - }) - .option(), - } - }), - wireguard_constraints: constraints.wireguard_constraints.map( - |wireguard_constraints| proto::WireguardConstraints { - port: wireguard_constraints.port.map(u32::from).option(), - ip_version: wireguard_constraints - .ip_version - .option() - .map(|ipv| i32::from(proto::IpVersion::from(ipv))), - use_multihop: wireguard_constraints.use_multihop, - entry_location: wireguard_constraints - .entry_location - .option() - .map(proto::LocationConstraint::from), - }, - ), - openvpn_constraints: constraints.openvpn_constraints.map( - |openvpn_constraints| proto::OpenvpnConstraints { - port: openvpn_constraints - .port - .option() - .map(proto::TransportPort::from), - }, - ), - }, - )), - }, - RelaySettingsUpdate::CustomTunnelEndpoint(endpoint) => proto::RelaySettingsUpdate { - r#type: Some(proto::relay_settings_update::Type::Custom( - proto::CustomRelaySettings { - host: endpoint.host.to_string(), - config: Some(proto::ConnectionConfig::from(endpoint.config)), - }, - )), - }, - } - } -} - -impl TryFrom<proto::RelaySettingsUpdate> for mullvad_types::relay_constraints::RelaySettingsUpdate { - type Error = FromProtobufTypeError; - - fn try_from( - settings: proto::RelaySettingsUpdate, - ) -> Result<mullvad_types::relay_constraints::RelaySettingsUpdate, Self::Error> { - use mullvad_types::{relay_constraints as mullvad_constraints, CustomTunnelEndpoint}; - - let update_value = settings - .r#type - .ok_or(FromProtobufTypeError::InvalidArgument( - "missing relay settings", - ))?; - - match update_value { - proto::relay_settings_update::Type::Custom(settings) => { - let config = settings - .config - .ok_or(FromProtobufTypeError::InvalidArgument( - "missing relay connection config", - ))?; - let config = mullvad_types::ConnectionConfig::try_from(config)?; - Ok( - mullvad_constraints::RelaySettingsUpdate::CustomTunnelEndpoint( - CustomTunnelEndpoint { - host: settings.host, - config, - }, - ), - ) - } - - proto::relay_settings_update::Type::Normal(settings) => { - // If `location` isn't provided, no changes are made. - // If `location` is provided, but is an empty vector, - // then the constraint is set to `Constraint::Any`. - let location = settings.location.and_then(|loc| { - Constraint::<mullvad_types::relay_constraints::LocationConstraint>::try_from( - loc, - ) - .ok() - }); - let providers = if let Some(ref provider_update) = settings.providers { - Some(try_providers_constraint_from_proto( - &provider_update.providers, - )?) - } else { - None - }; - let ownership = if let Some(ref ownership_update) = settings.ownership { - Some(try_ownership_constraint_from_i32( - ownership_update.ownership, - )?) - } else { - None - }; - let tunnel_protocol = if let Some(update) = settings.tunnel_type { - Some(Constraint::from( - update - .tunnel_type - .map(try_tunnel_type_from_i32) - .transpose()?, - )) - } else { - None - }; - let openvpn_constraints = - if let Some(ref constraints) = settings.openvpn_constraints { - Some(mullvad_constraints::OpenVpnConstraints::try_from( - constraints, - )?) - } else { - None - }; - let wireguard_constraints = - if let Some(ref constraints) = settings.wireguard_constraints { - Some(mullvad_constraints::WireguardConstraints::try_from( - constraints, - )?) - } else { - None - }; - Ok(mullvad_constraints::RelaySettingsUpdate::Normal( - mullvad_constraints::RelayConstraintsUpdate { - location, - providers, - ownership, - tunnel_protocol, - wireguard_constraints, - openvpn_constraints, - }, - )) - } - } - } -} - impl From<mullvad_types::relay_constraints::BridgeState> for proto::BridgeState { fn from(state: mullvad_types::relay_constraints::BridgeState) -> Self { use mullvad_types::relay_constraints::BridgeState; diff --git a/mullvad-relay-selector/src/lib.rs b/mullvad-relay-selector/src/lib.rs index 0ce93f7fcd..1046624af7 100644 --- a/mullvad-relay-selector/src/lib.rs +++ b/mullvad-relay-selector/src/lib.rs @@ -1292,8 +1292,8 @@ mod test { use mullvad_types::{ custom_list::CustomListsSettings, relay_constraints::{ - BridgeConstraints, GeographicLocationConstraint, RelayConstraints, - RelayConstraintsUpdate, RelaySettingsUpdate, WireguardConstraints, + BridgeConstraints, GeographicLocationConstraint, RelayConstraints, RelaySettings, + WireguardConstraints, }, relay_list::{ OpenVpnEndpoint, OpenVpnEndpointData, Relay, RelayListCity, RelayListCountry, @@ -2180,15 +2180,13 @@ mod test { ] { { let mut config = relay_selector.config.lock(); - config.relay_settings = config.relay_settings.merge(RelaySettingsUpdate::Normal( - RelayConstraintsUpdate { - tunnel_protocol: Some(tunnel_protocol), - location: Some(Constraint::Only(LocationConstraint::from( - GeographicLocationConstraint::Country("se".to_string()), - ))), - ..Default::default() - }, - )); + config.relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol, + location: Constraint::Only(LocationConstraint::from( + GeographicLocationConstraint::Country("se".to_string()), + )), + ..RelayConstraints::default() + }); } let mut actual_ports = HashSet::new(); @@ -2267,13 +2265,10 @@ mod test { // Verify that bridges are ignored when tunnel protocol is WireGuard { let mut config = relay_selector.config.lock(); - config.relay_settings = - config - .relay_settings - .merge(RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::Wireguard)), - ..Default::default() - })); + config.relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::Wireguard), + ..RelayConstraints::default() + }); } for i in 0..20 { let (_relay, bridge, _obfs) = relay_selector.get_relay(i).unwrap(); diff --git a/mullvad-types/src/custom_tunnel.rs b/mullvad-types/src/custom_tunnel.rs index 4fe3e54111..9b6ab9bff3 100644 --- a/mullvad-types/src/custom_tunnel.rs +++ b/mullvad-types/src/custom_tunnel.rs @@ -1,6 +1,6 @@ use crate::settings::TunnelOptions; #[cfg(target_os = "android")] -use jnix::IntoJava; +use jnix::{jni::objects::JObject, FromJava, IntoJava, JnixEnv}; use serde::{Deserialize, Serialize}; use std::{ fmt, io, @@ -91,6 +91,20 @@ impl fmt::Display for CustomTunnelEndpoint { } } +#[cfg(target_os = "android")] +impl<'env, 'sub_env> FromJava<'env, JObject<'sub_env>> for CustomTunnelEndpoint +where + 'env: 'sub_env, +{ + const JNI_SIGNATURE: &'static str = "Lnet/mullvad/mullvadvpn/model/CustomTunnelEndpoint;"; + + fn from_java(_env: &JnixEnv<'env>, _object: JObject<'sub_env>) -> Self { + panic!( + "Attempting to convert from CustomTunnelEndpoint java class. This should never happen!" + ); + } +} + /// Does a DNS lookup if the host isn't an IP. /// Returns the first IPv4 address if one exists, otherwise the first IPv6 address. /// Rust only provides means to resolve a socket addr, not just a host, for some reason. So diff --git a/mullvad-types/src/relay_constraints.rs b/mullvad-types/src/relay_constraints.rs index d0178c3c98..fffc6e03de 100644 --- a/mullvad-types/src/relay_constraints.rs +++ b/mullvad-types/src/relay_constraints.rs @@ -197,7 +197,7 @@ where /// relay. #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(rename_all = "snake_case")] -#[cfg_attr(target_os = "android", derive(IntoJava))] +#[cfg_attr(target_os = "android", derive(IntoJava, FromJava))] #[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub enum RelaySettings { CustomTunnelEndpoint(CustomTunnelEndpoint), @@ -205,17 +205,22 @@ pub enum RelaySettings { } impl RelaySettings { - pub fn merge(&self, update: RelaySettingsUpdate) -> Self { - match update { - RelaySettingsUpdate::CustomTunnelEndpoint(relay) => { - RelaySettings::CustomTunnelEndpoint(relay) + /// Returns false if the specified relay settings update explicitly do not allow for bridging + /// (i.e. use UDP instead of TCP) + pub fn supports_bridge(&self) -> bool { + match &self { + RelaySettings::CustomTunnelEndpoint(endpoint) => { + endpoint.endpoint().protocol == TransportProtocol::Tcp } - RelaySettingsUpdate::Normal(constraint_update) => RelaySettings::Normal(match *self { - RelaySettings::CustomTunnelEndpoint(_) => { - RelayConstraints::default().merge(constraint_update) + RelaySettings::Normal(update) => !matches!( + &update.openvpn_constraints, + OpenVpnConstraints { + port: Constraint::Only(TransportPort { + protocol: TransportProtocol::Udp, + .. + }) } - RelaySettings::Normal(ref constraint) => constraint.merge(constraint_update), - }), + ), } } } @@ -362,9 +367,8 @@ impl<'a> fmt::Display for LocationConstraintFormatter<'a> { } /// Limits the set of [`crate::relay_list::Relay`]s that a `RelaySelector` may select. -#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[derive(Default, Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] #[serde(default)] -#[cfg_attr(not(target_os = "android"), derive(Default))] #[cfg_attr(target_os = "android", derive(IntoJava))] #[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] pub struct RelayConstraints { @@ -378,37 +382,6 @@ pub struct RelayConstraints { pub openvpn_constraints: OpenVpnConstraints, } -#[cfg(target_os = "android")] -impl Default for RelayConstraints { - fn default() -> Self { - RelayConstraints { - tunnel_protocol: Constraint::Only(TunnelType::Wireguard), - location: Constraint::default(), - providers: Constraint::default(), - ownership: Constraint::default(), - wireguard_constraints: WireguardConstraints::default(), - openvpn_constraints: OpenVpnConstraints::default(), - } - } -} - -impl RelayConstraints { - pub fn merge(&self, update: RelayConstraintsUpdate) -> Self { - RelayConstraints { - location: update.location.unwrap_or_else(|| self.location.clone()), - providers: update.providers.unwrap_or_else(|| self.providers.clone()), - ownership: update.ownership.unwrap_or(self.ownership), - tunnel_protocol: update.tunnel_protocol.unwrap_or(self.tunnel_protocol), - wireguard_constraints: update - .wireguard_constraints - .unwrap_or_else(|| self.wireguard_constraints.clone()), - openvpn_constraints: update - .openvpn_constraints - .unwrap_or(self.openvpn_constraints), - } - } -} - pub struct RelayConstraintsFormatter<'a> { pub constraints: &'a RelayConstraints, pub custom_lists: &'a CustomListsSettings, @@ -442,6 +415,77 @@ impl<'a> fmt::Display for RelayConstraintsFormatter<'a> { } } +#[cfg(target_os = "android")] +impl<'env, 'sub_env> FromJava<'env, JObject<'sub_env>> for RelayConstraints +where + 'env: 'sub_env, +{ + const JNI_SIGNATURE: &'static str = "Lnet/mullvad/mullvadvpn/model/RelayConstraints;"; + + fn from_java(env: &JnixEnv<'env>, object: JObject<'sub_env>) -> Self { + let object_location = env + .call_method( + object, + "component1", + "()Lnet/mullvad/mullvadvpn/model/Constraint;", + &[], + ) + .expect("missing RelayConstraints.location") + .l() + .expect("RelayConstraints.location did not return an object"); + + let location: Constraint<LocationConstraint> = Constraint::from_java(env, object_location); + + let object_providers = env + .call_method( + object, + "component2", + "()Lnet/mullvad/mullvadvpn/model/Constraint;", + &[], + ) + .expect("missing RelayConstraints.providers") + .l() + .expect("RelayConstraints.providers did not return an object"); + + let providers: Constraint<Providers> = Constraint::from_java(env, object_providers); + + let object_ownership = env + .call_method( + object, + "component3", + "()Lnet/mullvad/mullvadvpn/model/Constraint;", + &[], + ) + .expect("missing RelayConstraints.providers") + .l() + .expect("RelayConstraints.providers did not return an object"); + + let ownership: Constraint<Ownership> = Constraint::from_java(env, object_ownership); + + let object_wireguard_constraints = env + .call_method( + object, + "component4", + "()Lnet/mullvad/mullvadvpn/model/WireguardConstraints;", + &[], + ) + .expect("missing RelayConstraints.wireguard_constraints") + .l() + .expect("RelayConstraints.wireguard_constraints did not return an object"); + + let wireguard_constraints: WireguardConstraints = + WireguardConstraints::from_java(env, object_wireguard_constraints); + + RelayConstraints { + location, + providers, + ownership, + wireguard_constraints, + ..Default::default() + } + } +} + /// Limits the set of [`crate::relay_list::Relay`]s used by a `RelaySelector` based on /// location. #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, PartialOrd, Ord)] @@ -947,51 +991,3 @@ pub struct InternalBridgeConstraints { pub ownership: Constraint<Ownership>, pub transport_protocol: Constraint<TransportProtocol>, } - -/// Used to update the [`RelaySettings`] used in `mullvad-daemon`. -#[derive(Debug, Deserialize, Serialize)] -#[cfg_attr(target_os = "android", derive(FromJava))] -#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] -#[serde(rename_all = "snake_case")] -pub enum RelaySettingsUpdate { - #[cfg_attr(target_os = "android", jnix(deny))] - CustomTunnelEndpoint(CustomTunnelEndpoint), - Normal(RelayConstraintsUpdate), -} - -impl RelaySettingsUpdate { - /// Returns false if the specified relay settings update explicitly do not allow for bridging - /// (i.e. use UDP instead of TCP) - pub fn supports_bridge(&self) -> bool { - match &self { - RelaySettingsUpdate::CustomTunnelEndpoint(endpoint) => { - endpoint.endpoint().protocol == TransportProtocol::Tcp - } - RelaySettingsUpdate::Normal(update) => !matches!( - &update.openvpn_constraints, - Some(OpenVpnConstraints { - port: Constraint::Only(TransportPort { - protocol: TransportProtocol::Udp, - .. - }) - }) - ), - } - } -} - -/// Used in [`RelaySettings`] to change relay constraints in the daemon. -#[derive(Debug, Default, Deserialize, Serialize)] -#[cfg_attr(target_os = "android", derive(FromJava))] -#[cfg_attr(target_os = "android", jnix(package = "net.mullvad.mullvadvpn.model"))] -#[serde(default)] -pub struct RelayConstraintsUpdate { - pub location: Option<Constraint<LocationConstraint>>, - pub providers: Option<Constraint<Providers>>, - pub ownership: Option<Constraint<Ownership>>, - #[cfg_attr(target_os = "android", jnix(default))] - pub tunnel_protocol: Option<Constraint<TunnelType>>, - pub wireguard_constraints: Option<WireguardConstraints>, - #[cfg_attr(target_os = "android", jnix(default))] - pub openvpn_constraints: Option<OpenVpnConstraints>, -} diff --git a/mullvad-types/src/settings/mod.rs b/mullvad-types/src/settings/mod.rs index 6ade7dea32..5978c6a736 100644 --- a/mullvad-types/src/settings/mod.rs +++ b/mullvad-types/src/settings/mod.rs @@ -4,7 +4,7 @@ use crate::{ relay_constraints::{ BridgeConstraints, BridgeSettings, BridgeState, Constraint, GeographicLocationConstraint, LocationConstraint, ObfuscationSettings, RelayConstraints, RelaySettings, - RelaySettingsFormatter, RelaySettingsUpdate, SelectedObfuscation, WireguardConstraints, + RelaySettingsFormatter, SelectedObfuscation, WireguardConstraints, }, wireguard, }; @@ -150,11 +150,9 @@ impl Settings { self.relay_settings.clone() } - pub fn update_relay_settings(&mut self, update: RelaySettingsUpdate) { - let update_supports_bridge = update.supports_bridge(); - let new_settings = self.relay_settings.merge(update); + pub fn set_relay_settings(&mut self, new_settings: RelaySettings) { if self.relay_settings != new_settings { - if !update_supports_bridge && BridgeState::On == self.bridge_state { + if !new_settings.supports_bridge() && BridgeState::On == self.bridge_state { self.bridge_state = BridgeState::Auto; } diff --git a/test/Cargo.lock b/test/Cargo.lock index b23c26adee..b2fc6bcb73 100644 --- a/test/Cargo.lock +++ b/test/Cargo.lock @@ -1442,9 +1442,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jnix" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aecfa741840d59de75e6e9e2985ee44b6794cbc0b2074899089be6bf7ffa0afc" +checksum = "5fd797d41e48568eb956ded20d7e5e3f2df1c02980d9e5b9aab9b47bd3a9f599" dependencies = [ "jni", "jnix-macros", diff --git a/test/test-manager/src/tests/dns.rs b/test/test-manager/src/tests/dns.rs index 69de367b88..310d5eb0dc 100644 --- a/test/test-manager/src/tests/dns.rs +++ b/test/test-manager/src/tests/dns.rs @@ -6,9 +6,7 @@ use std::{ use itertools::Itertools; use mullvad_management_interface::{types, ManagementServiceClient}; -use mullvad_types::{ - relay_constraints::RelaySettingsUpdate, ConnectionConfig, CustomTunnelEndpoint, -}; +use mullvad_types::{relay_constraints::RelaySettings, ConnectionConfig, CustomTunnelEndpoint}; use talpid_types::net::wireguard; use test_macro::test_function; use test_rpc::{Interface, ServiceClient}; @@ -24,7 +22,7 @@ use crate::vm::network::{ CUSTOM_TUN_REMOTE_TUN_ADDR, NON_TUN_GATEWAY, }; -use super::helpers::update_relay_settings; +use super::helpers::set_relay_settings; /// How long to wait for expected "DNS queries" to appear const MONITOR_TIMEOUT: Duration = Duration::from_secs(5); @@ -631,7 +629,7 @@ async fn connect_local_wg_relay(mullvad_client: &mut ManagementServiceClient) -> CUSTOM_TUN_REMOTE_REAL_PORT, ); - let relay_settings = RelaySettingsUpdate::CustomTunnelEndpoint(CustomTunnelEndpoint { + let relay_settings = RelaySettings::CustomTunnelEndpoint(CustomTunnelEndpoint { host: peer_addr.ip().to_string(), config: ConnectionConfig::Wireguard(wireguard::ConnectionConfig { tunnel: wireguard::TunnelConfig { @@ -652,7 +650,7 @@ async fn connect_local_wg_relay(mullvad_client: &mut ManagementServiceClient) -> }), }); - update_relay_settings(mullvad_client, relay_settings) + set_relay_settings(mullvad_client, relay_settings) .await .expect("failed to update relay settings"); diff --git a/test/test-manager/src/tests/helpers.rs b/test/test-manager/src/tests/helpers.rs index c51f6875da..e7c2e12d0f 100644 --- a/test/test-manager/src/tests/helpers.rs +++ b/test/test-manager/src/tests/helpers.rs @@ -5,7 +5,7 @@ use mullvad_management_interface::{types, ManagementServiceClient}; use mullvad_types::{ relay_constraints::{ BridgeState, Constraint, GeographicLocationConstraint, LocationConstraint, - ObfuscationSettings, OpenVpnConstraints, RelayConstraintsUpdate, RelaySettingsUpdate, + ObfuscationSettings, OpenVpnConstraints, RelayConstraints, RelaySettings, WireguardConstraints, }, states::TunnelState, @@ -321,7 +321,7 @@ impl<T> Drop for AbortOnDrop<T> { /// Disconnect and reset all relay, bridge, and obfuscation settings. /// -/// See [`mullvad_types::relay_constraints::RelayConstraintsUpdate`] for details, but in short: +/// See [`mullvad_types::relay_constraints::RelayConstraints`] for details, but in short: /// * Location constraint is [`Constraint::Any`] /// * Provider constraint is [`Constraint::Any`] /// * Ownership constraint is [`Constraint::Any`] @@ -335,18 +335,18 @@ pub async fn reset_relay_settings( ) -> Result<(), Error> { disconnect_and_wait(mullvad_client).await?; - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(Constraint::Any), - tunnel_protocol: Some(Constraint::Any), - openvpn_constraints: Some(OpenVpnConstraints::default()), - wireguard_constraints: Some(WireguardConstraints::default()), - providers: Some(Constraint::Any), - ownership: Some(Constraint::Any), + let relay_settings = RelaySettings::Normal(RelayConstraints { + location: Constraint::Any, + tunnel_protocol: Constraint::Any, + openvpn_constraints: OpenVpnConstraints::default(), + wireguard_constraints: WireguardConstraints::default(), + providers: Constraint::Any, + ownership: Constraint::Any, }); let bridge_state = BridgeState::Auto; let obfuscation_settings = ObfuscationSettings::default(); - update_relay_settings(mullvad_client, relay_settings) + set_relay_settings(mullvad_client, relay_settings) .await .map_err(|error| { Error::DaemonError(format!("Failed to reset relay settings: {}", error)) @@ -365,14 +365,14 @@ pub async fn reset_relay_settings( Ok(()) } -pub async fn update_relay_settings( +pub async fn set_relay_settings( mullvad_client: &mut ManagementServiceClient, - relay_settings_update: RelaySettingsUpdate, + relay_settings: RelaySettings, ) -> Result<(), Error> { - let update = types::RelaySettingsUpdate::from(relay_settings_update); + let new_settings = types::RelaySettings::from(relay_settings); mullvad_client - .update_relay_settings(update) + .set_relay_settings(new_settings) .await .map_err(|error| Error::DaemonError(format!("Failed to set relay settings: {}", error)))?; Ok(()) @@ -493,17 +493,10 @@ pub fn flatten_relaylist(relays: types::RelayList) -> Vec<types::Relay> { /// Convenience function for constructing a constraint from a given [`Relay`]. /// -/// Returns an [`Option`] because a [`Relay`] is not guaranteed to be poplutaed with a location -/// vaule. -pub fn into_constraint(relay: &types::Relay) -> Option<Constraint<LocationConstraint>> { - into_locationconstraint(relay).map(Constraint::Only) -} - -/// Convenience function for constructing a location constraint from a given [`Relay`]. +/// # Panics /// -/// Returns an [`Option`] because a [`Relay`] is not guaranteed to be poplutaed with a location -/// vaule. -pub fn into_locationconstraint(relay: &types::Relay) -> Option<LocationConstraint> { +/// The relay must have a location set. +pub fn into_constraint(relay: &types::Relay) -> Constraint<LocationConstraint> { relay .location .as_ref() @@ -521,4 +514,6 @@ pub fn into_locationconstraint(relay: &types::Relay) -> Option<LocationConstrain }, ) .map(LocationConstraint::Location) + .map(Constraint::Only) + .expect("relay is missing location") } diff --git a/test/test-manager/src/tests/tunnel.rs b/test/test-manager/src/tests/tunnel.rs index 99e30b087c..1592f7c2a3 100644 --- a/test/test-manager/src/tests/tunnel.rs +++ b/test/test-manager/src/tests/tunnel.rs @@ -1,4 +1,4 @@ -use super::helpers::{self, connect_and_wait, disconnect_and_wait, update_relay_settings}; +use super::helpers::{self, connect_and_wait, disconnect_and_wait, set_relay_settings}; use super::{Error, TestContext}; use std::net::IpAddr; @@ -6,8 +6,8 @@ use crate::network_monitor::{start_packet_monitor, MonitorOptions}; use mullvad_management_interface::{types, ManagementServiceClient}; use mullvad_types::relay_constraints::{ BridgeConstraints, BridgeSettings, BridgeState, Constraint, ObfuscationSettings, - OpenVpnConstraints, RelayConstraintsUpdate, RelaySettingsUpdate, SelectedObfuscation, - TransportPort, Udp2TcpObfuscationSettings, WireguardConstraints, + OpenVpnConstraints, RelayConstraints, RelaySettings, SelectedObfuscation, TransportPort, + Udp2TcpObfuscationSettings, WireguardConstraints, }; use mullvad_types::wireguard; use pnet_packet::ip::IpNextHeaderProtocols; @@ -48,13 +48,13 @@ pub async fn test_openvpn_tunnel( for (protocol, constraint) in CONSTRAINTS { log::info!("Connect to {protocol} OpenVPN endpoint"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::OpenVpn)), - openvpn_constraints: Some(OpenVpnConstraints { port: constraint }), + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::OpenVpn), + openvpn_constraints: OpenVpnConstraints { port: constraint }, ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -88,16 +88,16 @@ pub async fn test_wireguard_tunnel( for (port, should_succeed) in PORTS { log::info!("Connect to WireGuard endpoint on port {port}"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::Wireguard)), - wireguard_constraints: Some(WireguardConstraints { + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::Wireguard), + wireguard_constraints: WireguardConstraints { port: Constraint::Only(port), ..Default::default() - }), + }, ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -143,12 +143,12 @@ pub async fn test_udp2tcp_tunnel( .await .expect("failed to enable udp2tcp"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::Wireguard)), + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::Wireguard), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -230,23 +230,20 @@ pub async fn test_bridge( mullvad_client .set_bridge_settings(types::BridgeSettings::from(BridgeSettings::Normal( BridgeConstraints { - location: helpers::into_constraint(&entry).expect(&format!( - "Could not resolve location constraint: {:?}", - entry - )), + location: helpers::into_constraint(&entry), ..Default::default() }, ))) .await .expect("failed to update bridge settings"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { + let relay_settings = RelaySettings::Normal(RelayConstraints { location: helpers::into_constraint(&exit), - tunnel_protocol: Some(Constraint::Only(TunnelType::OpenVpn)), + tunnel_protocol: Constraint::Only(TunnelType::OpenVpn), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -312,20 +309,19 @@ pub async fn test_multihop( }; let (entry, exit) = helpers::random_entry_and_exit(&mut mullvad_client, relay_filter).await?; let exit_constraint = helpers::into_constraint(&exit); - let entry_constraint = - helpers::into_constraint(&entry).map(|entry_location| WireguardConstraints { - use_multihop: true, - entry_location, - ..Default::default() - }); + let wireguard_constraints = WireguardConstraints { + use_multihop: true, + entry_location: helpers::into_constraint(&entry), + ..Default::default() + }; - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { + let relay_settings = RelaySettings::Normal(RelayConstraints { location: exit_constraint, - wireguard_constraints: entry_constraint, + wireguard_constraints, ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -381,12 +377,12 @@ pub async fn test_wireguard_autoconnect( ) -> Result<(), Error> { log::info!("Setting tunnel protocol to WireGuard"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::Wireguard)), + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::Wireguard), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -423,12 +419,12 @@ pub async fn test_openvpn_autoconnect( ) -> Result<(), Error> { log::info!("Setting tunnel protocol to OpenVPN"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::OpenVpn)), + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::OpenVpn), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -481,11 +477,11 @@ pub async fn test_quantum_resistant_tunnel( log::info!("Setting tunnel protocol to WireGuard"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - tunnel_protocol: Some(Constraint::Only(TunnelType::Wireguard)), + let relay_settings = RelaySettings::Normal(RelayConstraints { + tunnel_protocol: Constraint::Only(TunnelType::Wireguard), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("Failed to update relay settings"); @@ -564,8 +560,8 @@ pub async fn test_quantum_resistant_multihop_udp2tcp_tunnel( .expect("Failed to enable obfuscation"); mullvad_client - .update_relay_settings(types::RelaySettingsUpdate::from( - RelaySettingsUpdate::Normal(RelayConstraintsUpdate { + .set_relay_settings(types::RelaySettings::from(RelaySettings::Normal( + RelayConstraints { wireguard_constraints: WireguardConstraints { use_multihop: true, ..Default::default() @@ -573,8 +569,8 @@ pub async fn test_quantum_resistant_multihop_udp2tcp_tunnel( .into(), tunnel_protocol: Constraint::Only(TunnelType::Wireguard).into(), ..Default::default() - }), - )) + }, + ))) .await .expect("Failed to update relay settings"); diff --git a/test/test-manager/src/tests/tunnel_state.rs b/test/test-manager/src/tests/tunnel_state.rs index 55b1d2074e..cf0b7f4efe 100644 --- a/test/test-manager/src/tests/tunnel_state.rs +++ b/test/test-manager/src/tests/tunnel_state.rs @@ -1,6 +1,6 @@ use super::helpers::{ self, connect_and_wait, disconnect_and_wait, get_tunnel_state, send_guest_probes, - unreachable_wireguard_tunnel, update_relay_settings, wait_for_tunnel_state, + set_relay_settings, unreachable_wireguard_tunnel, wait_for_tunnel_state, }; use super::{ui, Error, TestContext}; use crate::assert_tunnel_state; @@ -10,9 +10,7 @@ use mullvad_management_interface::{types, ManagementServiceClient}; use mullvad_types::relay_constraints::GeographicLocationConstraint; use mullvad_types::CustomTunnelEndpoint; use mullvad_types::{ - relay_constraints::{ - Constraint, LocationConstraint, RelayConstraintsUpdate, RelaySettingsUpdate, - }, + relay_constraints::{Constraint, LocationConstraint, RelayConstraints, RelaySettings}, states::TunnelState, }; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -88,12 +86,12 @@ pub async fn test_connecting_state( log::info!("Verify tunnel state: disconnected"); assert_tunnel_state!(&mut mullvad_client, TunnelState::Disconnected); - let relay_settings = RelaySettingsUpdate::CustomTunnelEndpoint(CustomTunnelEndpoint { + let relay_settings = RelaySettings::CustomTunnelEndpoint(CustomTunnelEndpoint { host: "1.3.3.7".to_owned(), config: mullvad_types::ConnectionConfig::Wireguard(unreachable_wireguard_tunnel()), }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -154,15 +152,6 @@ pub async fn test_connecting_state( disconnect_and_wait(&mut mullvad_client).await?; - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(Constraint::Any), - ..Default::default() - }); - - update_relay_settings(&mut mullvad_client, relay_settings) - .await - .expect("failed to update relay settings"); - Ok(()) } @@ -188,10 +177,10 @@ pub async fn test_error_state( log::info!("Enter error state"); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(Constraint::Only(LocationConstraint::Location( + let relay_settings = RelaySettings::Normal(RelayConstraints { + location: Constraint::Only(LocationConstraint::Location( GeographicLocationConstraint::Country("xx".to_string()), - ))), + )), ..Default::default() }); @@ -200,7 +189,7 @@ pub async fn test_error_state( .await .expect("failed to disable LAN sharing"); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); @@ -244,15 +233,6 @@ pub async fn test_error_state( disconnect_and_wait(&mut mullvad_client).await?; - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { - location: Some(Constraint::Any), - ..Default::default() - }); - - update_relay_settings(&mut mullvad_client, relay_settings) - .await - .expect("failed to update relay settings"); - Ok(()) } @@ -286,12 +266,12 @@ pub async fn test_connected_state( .pop() .unwrap(); - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { + let relay_settings = RelaySettings::Normal(RelayConstraints { location: helpers::into_constraint(&relay), ..Default::default() }); - update_relay_settings(&mut mullvad_client, relay_settings) + set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); diff --git a/test/test-manager/src/tests/ui.rs b/test/test-manager/src/tests/ui.rs index 1e97430061..91f124338f 100644 --- a/test/test-manager/src/tests/ui.rs +++ b/test/test-manager/src/tests/ui.rs @@ -2,7 +2,7 @@ use super::config::TEST_CONFIG; use super::helpers; use super::{Error, TestContext}; use mullvad_management_interface::{types, ManagementServiceClient}; -use mullvad_types::relay_constraints::{RelayConstraintsUpdate, RelaySettingsUpdate}; +use mullvad_types::relay_constraints::{RelayConstraints, RelaySettings}; use std::{ collections::BTreeMap, fmt::Debug, @@ -95,12 +95,12 @@ pub async fn test_ui_tunnel_settings( .unwrap(); // The test expects us to be disconnected and logged in but to have a specific relay selected - let relay_settings = RelaySettingsUpdate::Normal(RelayConstraintsUpdate { + let relay_settings = RelaySettings::Normal(RelayConstraints { location: helpers::into_constraint(&entry), ..Default::default() }); - helpers::update_relay_settings(&mut mullvad_client, relay_settings) + helpers::set_relay_settings(&mut mullvad_client, relay_settings) .await .expect("failed to update relay settings"); |
