summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/RelayListListener.kt27
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModel.kt6
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModel.kt5
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/SelectLocationViewModelTest.kt2
-rw-r--r--android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/VpnSettingsViewModelTest.kt6
-rw-r--r--android/lib/ipc/src/main/kotlin/net/mullvad/mullvadvpn/lib/ipc/Request.kt4
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelayConstraintsUpdate.kt8
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettings.kt4
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/model/RelaySettingsUpdate.kt7
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt11
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/endpoint/RelayListListener.kt28
-rw-r--r--gui/src/main/daemon-rpc.ts80
-rw-r--r--gui/src/main/settings.ts4
-rw-r--r--gui/src/renderer/app.tsx9
-rw-r--r--gui/src/renderer/components/Filter.tsx12
-rw-r--r--gui/src/renderer/components/OpenVpnSettings.tsx66
-rw-r--r--gui/src/renderer/components/VpnSettings.tsx37
-rw-r--r--gui/src/renderer/components/WireguardSettings.tsx53
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx16
-rw-r--r--gui/src/renderer/components/select-location/select-location-hooks.ts63
-rw-r--r--gui/src/renderer/lib/constraint-updater.ts111
-rw-r--r--gui/src/shared/daemon-rpc-types.ts21
-rw-r--r--gui/src/shared/ipc-schema.ts4
-rw-r--r--gui/src/shared/relay-settings-builder.ts189
-rw-r--r--gui/test/unit/relay-settings-builder.spec.ts99
-rw-r--r--mullvad-cli/src/cmds/relay.rs78
-rw-r--r--mullvad-daemon/src/lib.rs16
-rw-r--r--mullvad-daemon/src/management_interface.rs12
-rw-r--r--mullvad-jni/src/classes.rs3
-rw-r--r--mullvad-jni/src/daemon_interface.rs6
-rw-r--r--mullvad-jni/src/lib.rs8
-rw-r--r--mullvad-management-interface/proto/management_interface.proto25
-rw-r--r--mullvad-management-interface/src/client.rs8
-rw-r--r--mullvad-management-interface/src/types/conversions/relay_constraints.rs173
-rw-r--r--mullvad-relay-selector/src/lib.rs31
-rw-r--r--mullvad-types/src/custom_tunnel.rs16
-rw-r--r--mullvad-types/src/relay_constraints.rs178
-rw-r--r--mullvad-types/src/settings/mod.rs8
-rw-r--r--test/Cargo.lock4
-rw-r--r--test/test-manager/src/tests/dns.rs10
-rw-r--r--test/test-manager/src/tests/helpers.rs43
-rw-r--r--test/test-manager/src/tests/tunnel.rs84
-rw-r--r--test/test-manager/src/tests/tunnel_state.rs40
-rw-r--r--test/test-manager/src/tests/ui.rs6
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");