summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt8
-rw-r--r--android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt1
-rw-r--r--android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt1
-rw-r--r--gui/locales/messages.pot39
-rw-r--r--gui/src/main/daemon-rpc.ts4
-rw-r--r--gui/src/main/grpc-type-convertions.ts2
-rw-r--r--gui/src/main/settings.ts4
-rw-r--r--gui/src/renderer/app.tsx4
-rw-r--r--gui/src/renderer/components/DaitaSettings.tsx47
-rw-r--r--gui/src/renderer/components/main-view/FeatureIndicators.tsx35
-rw-r--r--gui/src/renderer/components/select-location/RelayListContext.tsx6
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx6
-rw-r--r--gui/src/renderer/lib/filter-locations.ts8
-rw-r--r--gui/src/shared/daemon-rpc-types.ts3
-rw-r--r--gui/src/shared/ipc-schema.ts2
-rw-r--r--mullvad-cli/src/cmds/tunnel.rs18
-rw-r--r--mullvad-daemon/src/lib.rs33
-rw-r--r--mullvad-daemon/src/management_interface.rs24
-rw-r--r--mullvad-management-interface/proto/management_interface.proto5
-rw-r--r--mullvad-management-interface/src/client.rs4
-rw-r--r--mullvad-management-interface/src/types/conversions/features.rs2
-rw-r--r--mullvad-management-interface/src/types/conversions/wireguard.rs4
-rw-r--r--mullvad-relay-selector/src/relay_selector/mod.rs23
-rw-r--r--mullvad-relay-selector/src/relay_selector/query.rs15
-rw-r--r--mullvad-relay-selector/tests/relay_selector.rs20
-rw-r--r--mullvad-types/src/features.rs107
-rw-r--r--mullvad-types/src/wireguard.rs28
-rw-r--r--test/test-manager/src/tests/daita.rs20
28 files changed, 255 insertions, 218 deletions
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
index 7961b5460c..024091c9dc 100644
--- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
+++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/ManagementService.kt
@@ -511,7 +511,13 @@ class ManagementService(
suspend fun setDaitaEnabled(enabled: Boolean): Either<SetDaitaSettingsError, Unit> =
Either.catch {
val daitaSettings =
- ManagementInterface.DaitaSettings.newBuilder().setEnabled(enabled).build()
+ ManagementInterface.DaitaSettings.newBuilder()
+ .setEnabled(enabled)
+ // Before Multihop is supported on Android, calling `setDirectOnly` with
+ // false will cause undefined behaviour. Will be fixed by as part of
+ // DROID-1412.
+ .setDirectOnly(true)
+ .build()
grpc.setDaitaSettings(daitaSettings)
}
.mapLeft(SetDaitaSettingsError::Unknown)
diff --git a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
index 4a8ee04683..2f6a08eede 100644
--- a/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
+++ b/android/lib/daemon-grpc/src/main/kotlin/net/mullvad/mullvadvpn/lib/daemon/grpc/mapper/ToDomain.kt
@@ -621,7 +621,6 @@ internal fun ManagementInterface.FeatureIndicator.toDomain() =
ManagementInterface.FeatureIndicator.CUSTOM_MTU -> FeatureIndicator.CUSTOM_MTU
ManagementInterface.FeatureIndicator.DAITA -> FeatureIndicator.DAITA
ManagementInterface.FeatureIndicator.SHADOWSOCKS -> FeatureIndicator.SHADOWSOCKS
- ManagementInterface.FeatureIndicator.DAITA_SMART_ROUTING,
ManagementInterface.FeatureIndicator.LOCKDOWN_MODE,
ManagementInterface.FeatureIndicator.MULTIHOP,
ManagementInterface.FeatureIndicator.BRIDGE_MODE,
diff --git a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
index 74fea07326..3c8df824f4 100644
--- a/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
+++ b/android/lib/model/src/main/kotlin/net/mullvad/mullvadvpn/lib/model/FeatureIndicator.kt
@@ -3,7 +3,6 @@ package net.mullvad.mullvadvpn.lib.model
// The order of the variants match the priority order and can be sorted on.
enum class FeatureIndicator {
DAITA,
- // DAITA_SMART_ROUTING
QUANTUM_RESISTANCE,
// MULTIHOP,
SPLIT_TUNNELING,
diff --git a/gui/locales/messages.pot b/gui/locales/messages.pot
index e9ef237a3a..174688cf27 100644
--- a/gui/locales/messages.pot
+++ b/gui/locales/messages.pot
@@ -5,11 +5,6 @@ msgstr ""
msgid "%(amount)d more..."
msgstr ""
-#. This refers to the Smart Routing setting in the VPN settings view.
-#. This is displayed when both Smart Routing and DAITA features are on.
-msgid "%(daita)s: Smart routing"
-msgstr ""
-
msgid "%(duration)s was added, account paid until %(expiry)s."
msgstr ""
@@ -127,10 +122,10 @@ msgstr ""
msgid "Delete list"
msgstr ""
-msgid "Disable"
+msgid "Direct only"
msgstr ""
-msgid "Disable anyway"
+msgid "Disable"
msgstr ""
msgid "Disconnect"
@@ -157,6 +152,9 @@ msgstr ""
msgid "Enable"
msgstr ""
+msgid "Enable \"Direct only\""
+msgstr ""
+
msgid "Enable anyway"
msgstr ""
@@ -253,9 +251,6 @@ msgstr ""
msgid "Settings"
msgstr ""
-msgid "Smart routing"
-msgstr ""
-
msgid "System default"
msgstr ""
@@ -1956,13 +1951,13 @@ msgctxt "vpn-settings-view"
msgid "Lockdown mode"
msgstr ""
+#. Label for settings that enables malware blocking.
msgctxt "vpn-settings-view"
-msgid "Makes it possible to use %(daita)s with any server and is automatically enabled."
+msgid "Malware"
msgstr ""
-#. Label for settings that enables malware blocking.
msgctxt "vpn-settings-view"
-msgid "Malware"
+msgid "Manually choose which %(daita)s-enabled server to use."
msgstr ""
msgctxt "vpn-settings-view"
@@ -2071,7 +2066,15 @@ msgid "%(wireguard)s settings"
msgstr ""
msgctxt "wireguard-settings-view"
-msgid "Can only be used with WireGuard. Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed."
+msgid "Attention: Be cautious if you have a limited data plan as this feature will increase your network traffic. This feature can only be used with WireGuard."
+msgstr ""
+
+msgctxt "wireguard-settings-view"
+msgid "By enabling “Direct only” you will have to manually select a server that is %(daita)s-enabled. This can cause you to end up in a blocked state until you have selected a compatible server in the “Select location” view."
+msgstr ""
+
+msgctxt "wireguard-settings-view"
+msgid "Cancel"
msgstr ""
msgctxt "wireguard-settings-view"
@@ -2104,11 +2107,11 @@ msgstr ""
#. Warning text in a dialog that is displayed after a setting is toggled.
msgctxt "wireguard-settings-view"
-msgid "Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after disabling, or you can continue using %(daita)s with Smart routing."
+msgid "Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after enabling."
msgstr ""
msgctxt "wireguard-settings-view"
-msgid "Not all our servers are %(daita)s-enabled. Smart routing allows %(daita)s to be used at any location. It does this by using multihop in the background to route your traffic via the closest %(daita)s-enabled server first."
+msgid "Not all our servers are %(daita)s-enabled. We use multihop automatically to use %(daita)s with any server."
msgstr ""
msgctxt "wireguard-settings-view"
@@ -2181,10 +2184,6 @@ msgctxt "wireguard-settings-view"
msgid "UDP-over-TCP port"
msgstr ""
-msgctxt "wireguard-settings-view"
-msgid "Use Smart routing"
-msgstr ""
-
#. Text describing the valid port range for a port selector.
msgctxt "wireguard-settings-view"
msgid "Valid range: %(min)s - %(max)s"
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts
index c504efe2b9..c86bed047f 100644
--- a/gui/src/main/daemon-rpc.ts
+++ b/gui/src/main/daemon-rpc.ts
@@ -464,8 +464,8 @@ export class DaemonRpc extends GrpcClient {
await this.callBool(this.client.setEnableDaita, value);
}
- public async setDaitaSmartRouting(value: boolean): Promise<void> {
- await this.callBool(this.client.setDaitaSmartRouting, value);
+ public async setDaitaDirectOnly(value: boolean): Promise<void> {
+ await this.callBool(this.client.setDaitaDirectOnly, value);
}
public async listDevices(accountNumber: AccountNumber): Promise<Array<IDevice>> {
diff --git a/gui/src/main/grpc-type-convertions.ts b/gui/src/main/grpc-type-convertions.ts
index d37dd3a9b8..6511f10c67 100644
--- a/gui/src/main/grpc-type-convertions.ts
+++ b/gui/src/main/grpc-type-convertions.ts
@@ -381,8 +381,6 @@ function convertFromFeatureIndicator(
return FeatureIndicator.customMssFix;
case grpcTypes.FeatureIndicator.DAITA:
return FeatureIndicator.daita;
- case grpcTypes.FeatureIndicator.DAITA_SMART_ROUTING:
- return FeatureIndicator.daitaSmartRouting;
case grpcTypes.FeatureIndicator.SHADOWSOCKS:
return FeatureIndicator.shadowsocks;
}
diff --git a/gui/src/main/settings.ts b/gui/src/main/settings.ts
index 03537ba581..99fb4f2a5a 100644
--- a/gui/src/main/settings.ts
+++ b/gui/src/main/settings.ts
@@ -110,8 +110,8 @@ export default class Settings implements Readonly<ISettings> {
IpcMainEventChannel.settings.handleSetEnableDaita((value) => {
return this.daemonRpc.setEnableDaita(value);
});
- IpcMainEventChannel.settings.handleSetDaitaSmartRouting((value) => {
- return this.daemonRpc.setDaitaSmartRouting(value);
+ IpcMainEventChannel.settings.handleSetDaitaDirectOnly((value) => {
+ return this.daemonRpc.setDaitaDirectOnly(value);
});
IpcMainEventChannel.guiSettings.handleSetEnableSystemNotifications((flag: boolean) => {
diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx
index 6c40b0e908..d36c27aa14 100644
--- a/gui/src/renderer/app.tsx
+++ b/gui/src/renderer/app.tsx
@@ -349,8 +349,8 @@ export default class AppRenderer {
IpcRendererEventChannel.settings.setObfuscationSettings(obfuscationSettings);
public setEnableDaita = (value: boolean) =>
IpcRendererEventChannel.settings.setEnableDaita(value);
- public setDaitaSmartRouting = (value: boolean) =>
- IpcRendererEventChannel.settings.setDaitaSmartRouting(value);
+ public setDaitaDirectOnly = (value: boolean) =>
+ IpcRendererEventChannel.settings.setDaitaDirectOnly(value);
public collectProblemReport = (toRedact: string | undefined) =>
IpcRendererEventChannel.problemReport.collectLogs(toRedact);
public viewLog = (path: string) => IpcRendererEventChannel.problemReport.viewLog(path);
diff --git a/gui/src/renderer/components/DaitaSettings.tsx b/gui/src/renderer/components/DaitaSettings.tsx
index b4ee10c94d..2d09a3996e 100644
--- a/gui/src/renderer/components/DaitaSettings.tsx
+++ b/gui/src/renderer/components/DaitaSettings.tsx
@@ -95,9 +95,18 @@ export default function DaitaSettings() {
)}
</StyledHeaderSubTitle>
<StyledHeaderSubTitle>
+ {sprintf(
+ messages.pgettext(
+ 'wireguard-settings-view',
+ 'Not all our servers are %(daita)s-enabled. We use multihop automatically to use %(daita)s with any server.',
+ ),
+ { daita: strings.daita, daitaFull: strings.daitaFull },
+ )}
+ </StyledHeaderSubTitle>
+ <StyledHeaderSubTitle>
{messages.pgettext(
'wireguard-settings-view',
- 'Can only be used with WireGuard. Since this increases your total network traffic, be cautious if you have a limited data plan. It can also negatively impact your network speed.',
+ 'Attention: Be cautious if you have a limited data plan as this feature will increase your network traffic. This feature can only be used with WireGuard.',
)}
</StyledHeaderSubTitle>
</React.Fragment>,
@@ -119,12 +128,10 @@ export default function DaitaSettings() {
}
function DaitaToggle() {
- const { setEnableDaita, setDaitaSmartRouting } = useAppContext();
+ const { setEnableDaita, setDaitaDirectOnly } = useAppContext();
const relaySettings = useSelector((state) => state.settings.relaySettings);
const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false);
- const smartRouting = useSelector(
- (state) => state.settings.wireguard.daita?.smartRouting ?? false,
- );
+ const directOnly = useSelector((state) => state.settings.wireguard.daita?.directOnly ?? false);
const [confirmationDialogVisible, showConfirmationDialog, hideConfirmationDialog] = useBoolean();
@@ -135,16 +142,16 @@ function DaitaToggle() {
void setEnableDaita(value);
}, []);
- const setSmartRouting = useCallback((value: boolean) => {
+ const setDirectOnly = useCallback((value: boolean) => {
if (value) {
- void setDaitaSmartRouting(value);
- } else {
showConfirmationDialog();
+ } else {
+ void setDaitaDirectOnly(value);
}
}, []);
- const confirmDisableSmartRouting = useCallback(() => {
- void setDaitaSmartRouting(false);
+ const confirmEnableDirectOnly = useCallback(() => {
+ void setDaitaDirectOnly(true);
hideConfirmationDialog();
}, []);
@@ -170,13 +177,13 @@ function DaitaToggle() {
<AriaInputGroup>
<Cell.Container disabled={!daita || unavailable}>
<AriaLabel>
- <Cell.InputLabel>{messages.gettext('Smart routing')}</Cell.InputLabel>
+ <Cell.InputLabel>{messages.gettext('Direct only')}</Cell.InputLabel>
</AriaLabel>
<InfoButton>
- <SmartRoutingModalMessage />
+ <DirectOnlyModalMessage />
</InfoButton>
<AriaInput>
- <Cell.Switch isOn={smartRouting && !unavailable} onChange={setSmartRouting} />
+ <Cell.Switch isOn={directOnly && !unavailable} onChange={setDirectOnly} />
</AriaInput>
</Cell.Container>
<Cell.CellFooter>
@@ -185,7 +192,7 @@ function DaitaToggle() {
{sprintf(
messages.pgettext(
'vpn-settings-view',
- 'Makes it possible to use %(daita)s with any server and is automatically enabled.',
+ 'Manually choose which %(daita)s-enabled server to use.',
),
{ daita: strings.daita },
)}
@@ -199,12 +206,12 @@ function DaitaToggle() {
gridButtons={[
<SmallButton
key="confirm"
- onClick={confirmDisableSmartRouting}
+ onClick={confirmEnableDirectOnly}
color={SmallButtonColor.blue}>
- {messages.gettext('Disable anyway')}
+ {messages.gettext('Enable "Direct only"')}
</SmallButton>,
<SmallButton key="cancel" onClick={hideConfirmationDialog} color={SmallButtonColor.blue}>
- {messages.pgettext('wireguard-settings-view', 'Use Smart routing')}
+ {messages.pgettext('wireguard-settings-view', 'Cancel')}
</SmallButton>,
]}
close={hideConfirmationDialog}>
@@ -213,7 +220,7 @@ function DaitaToggle() {
// TRANSLATORS: Warning text in a dialog that is displayed after a setting is toggled.
messages.pgettext(
'wireguard-settings-view',
- 'Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after disabling, or you can continue using %(daita)s with Smart routing.',
+ 'Not all our servers are %(daita)s-enabled. In order to use the internet, you might have to select a new location after enabling.',
),
{ daita: strings.daita },
)}
@@ -223,13 +230,13 @@ function DaitaToggle() {
);
}
-export function SmartRoutingModalMessage() {
+function DirectOnlyModalMessage() {
return (
<ModalMessage>
{sprintf(
messages.pgettext(
'wireguard-settings-view',
- 'Not all our servers are %(daita)s-enabled. Smart routing allows %(daita)s to be used at any location. It does this by using multihop in the background to route your traffic via the closest %(daita)s-enabled server first.',
+ 'By enabling “Direct only” you will have to manually select a server that is %(daita)s-enabled. This can cause you to end up in a blocked state until you have selected a compatible server in the “Select location” view.',
),
{
daita: strings.daita,
diff --git a/gui/src/renderer/components/main-view/FeatureIndicators.tsx b/gui/src/renderer/components/main-view/FeatureIndicators.tsx
index a4bf8659c6..2d7914fd87 100644
--- a/gui/src/renderer/components/main-view/FeatureIndicators.tsx
+++ b/gui/src/renderer/components/main-view/FeatureIndicators.tsx
@@ -5,13 +5,10 @@ import styled from 'styled-components';
import { colors, strings } from '../../../config.json';
import { FeatureIndicator } from '../../../shared/daemon-rpc-types';
import { messages } from '../../../shared/gettext';
-import { useBoolean, useStyledRef } from '../../lib/utilityHooks';
+import { useStyledRef } from '../../lib/utilityHooks';
import { useSelector } from '../../redux/store';
import { tinyText } from '../common-styles';
-import { SmartRoutingModalMessage } from '../DaitaSettings';
import { InfoIcon } from '../InfoButton';
-import { ModalAlert, ModalAlertType } from '../Modal';
-import { SmallButton, SmallButtonColor } from '../SmallButton';
import { ConnectionPanelAccordion } from './styles';
const LINE_HEIGHT = 22;
@@ -102,11 +99,6 @@ interface FeatureIndicatorsProps {
// we can count those and add another ellipsis element which is visible and place it after the last
// visible indicator.
export default function FeatureIndicators(props: FeatureIndicatorsProps) {
- const [
- daitaSmartRoutingDialogueVisible,
- showDaitaSmartRoutingDialogue,
- hideDaitaSmartRoutingDialogue,
- ] = useBoolean();
const tunnelState = useSelector((state) => state.connection.status);
const ellipsisRef = useStyledRef<HTMLSpanElement>();
const ellipsisSpacerRef = useStyledRef<HTMLSpanElement>();
@@ -127,9 +119,8 @@ export default function FeatureIndicators(props: FeatureIndicatorsProps) {
// Returns an optional callback for clickable feature indicators, or undefined.
const getFeatureIndicatorOnClick = (indicator: FeatureIndicator) => {
+ // NOTE: With the "smart routing" feature indicator removed, this function now does nothing, should it be removed?
switch (indicator) {
- case FeatureIndicator.daitaSmartRouting:
- return showDaitaSmartRoutingDialogue;
default:
return undefined;
}
@@ -231,21 +222,6 @@ export default function FeatureIndicators(props: FeatureIndicatorsProps) {
/>
</StyledFeatureIndicators>
</StyledFeatureIndicatorsContainer>
-
- <ModalAlert
- isOpen={daitaSmartRoutingDialogueVisible}
- type={ModalAlertType.info}
- gridButtons={[
- <SmallButton
- key="dismiss"
- onClick={hideDaitaSmartRoutingDialogue}
- color={SmallButtonColor.blue}>
- {messages.gettext('Got it!')}
- </SmallButton>,
- ]}
- close={hideDaitaSmartRoutingDialogue}>
- <SmartRoutingModalMessage />
- </ModalAlert>
</StyledAccordion>
);
}
@@ -276,13 +252,6 @@ function getFeatureIndicatorLabel(indicator: FeatureIndicator) {
switch (indicator) {
case FeatureIndicator.daita:
return strings.daita;
- case FeatureIndicator.daitaSmartRouting:
- return sprintf(
- // TRANSLATORS: This refers to the Smart Routing setting in the VPN settings view.
- // TRANSLATORS: This is displayed when both Smart Routing and DAITA features are on.
- messages.gettext('%(daita)s: Smart routing'),
- { daita: strings.daita },
- );
case FeatureIndicator.udp2tcp:
case FeatureIndicator.shadowsocks:
return messages.pgettext('wireguard-settings-view', 'Obfuscation');
diff --git a/gui/src/renderer/components/select-location/RelayListContext.tsx b/gui/src/renderer/components/select-location/RelayListContext.tsx
index 241d11fbdc..e41b04c17e 100644
--- a/gui/src/renderer/components/select-location/RelayListContext.tsx
+++ b/gui/src/renderer/components/select-location/RelayListContext.tsx
@@ -62,9 +62,7 @@ interface RelayListContextProviderProps {
export function RelayListContextProvider(props: RelayListContextProviderProps) {
const { locationType, searchTerm } = useSelectLocationContext();
const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false);
- const smartRouting = useSelector(
- (state) => state.settings.wireguard.daita?.smartRouting ?? false,
- );
+ const directOnly = useSelector((state) => state.settings.wireguard.daita?.directOnly ?? false);
const fullRelayList = useSelector((state) => state.settings.relayLocations);
const relaySettings = useNormalRelaySettings();
@@ -81,7 +79,7 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
return filterLocationsByDaita(
relayListForEndpointType,
daita,
- smartRouting,
+ directOnly,
locationType,
relaySettings?.tunnelProtocol ?? 'any',
relaySettings?.wireguard.useMultihop ?? false,
diff --git a/gui/src/renderer/components/select-location/SelectLocation.tsx b/gui/src/renderer/components/select-location/SelectLocation.tsx
index 9cd66f98f4..01297f5630 100644
--- a/gui/src/renderer/components/select-location/SelectLocation.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocation.tsx
@@ -68,12 +68,10 @@ export default function SelectLocation() {
const providers = relaySettings?.providers ?? [];
const filteredProviders = useFilteredProviders(providers, ownership);
const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false);
- const smartRouting = useSelector(
- (state) => state.settings.wireguard.daita?.smartRouting ?? false,
- );
+ const directOnly = useSelector((state) => state.settings.wireguard.daita?.directOnly ?? false);
const showDaitaFilter = daitaFilterActive(
daita,
- smartRouting,
+ directOnly,
locationType,
relaySettings?.tunnelProtocol ?? 'any',
relaySettings?.wireguard.useMultihop ?? false,
diff --git a/gui/src/renderer/lib/filter-locations.ts b/gui/src/renderer/lib/filter-locations.ts
index 661d8ecc29..e559e64096 100644
--- a/gui/src/renderer/lib/filter-locations.ts
+++ b/gui/src/renderer/lib/filter-locations.ts
@@ -37,19 +37,19 @@ export function filterLocationsByEndPointType(
export function filterLocationsByDaita(
locations: IRelayLocationCountryRedux[],
daita: boolean,
- smartRouting: boolean,
+ directOnly: boolean,
locationType: LocationType,
tunnelProtocol: LiftedConstraint<TunnelProtocol>,
multihop: boolean,
): IRelayLocationCountryRedux[] {
- return daitaFilterActive(daita, smartRouting, locationType, tunnelProtocol, multihop)
+ return daitaFilterActive(daita, directOnly, locationType, tunnelProtocol, multihop)
? filterLocationsImpl(locations, (relay: IRelayLocationRelayRedux) => relay.daita)
: locations;
}
export function daitaFilterActive(
daita: boolean,
- smartRouting: boolean,
+ directOnly: boolean,
locationType: LocationType,
tunnelProtocol: LiftedConstraint<TunnelProtocol>,
multihop: boolean,
@@ -57,7 +57,7 @@ export function daitaFilterActive(
const isEntry = multihop
? locationType === LocationType.entry
: locationType === LocationType.exit;
- return daita && (!smartRouting || multihop) && isEntry && tunnelProtocol !== 'openvpn';
+ return daita && (directOnly || multihop) && isEntry && tunnelProtocol !== 'openvpn';
}
export function filterLocations(
diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts
index a22021a1d0..bd8f99711b 100644
--- a/gui/src/shared/daemon-rpc-types.ts
+++ b/gui/src/shared/daemon-rpc-types.ts
@@ -183,7 +183,6 @@ export interface ITunnelStateRelayInfo {
// The order of the variants match the priority order and can be sorted on.
export enum FeatureIndicator {
daita,
- daitaSmartRouting,
quantumResistance,
multihop,
bridgeMode,
@@ -552,7 +551,7 @@ export interface RelayOverride {
export interface IDaitaSettings {
enabled: boolean;
- smartRouting: boolean;
+ directOnly: boolean;
}
export function parseSocketAddress(socketAddrStr: string): ISocketAddress {
diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts
index b10c79623e..954dce1680 100644
--- a/gui/src/shared/ipc-schema.ts
+++ b/gui/src/shared/ipc-schema.ts
@@ -195,7 +195,7 @@ export const ipcSchema = {
testCustomApiAccessMethod: invoke<CustomProxy, boolean>(),
clearAllRelayOverrides: invoke<void, void>(),
setEnableDaita: invoke<boolean, void>(),
- setDaitaSmartRouting: invoke<boolean, void>(),
+ setDaitaDirectOnly: invoke<boolean, void>(),
},
guiSettings: {
'': notifyRenderer<IGuiSettingsState>(),
diff --git a/mullvad-cli/src/cmds/tunnel.rs b/mullvad-cli/src/cmds/tunnel.rs
index da66cac5d5..118fd63a8d 100644
--- a/mullvad-cli/src/cmds/tunnel.rs
+++ b/mullvad-cli/src/cmds/tunnel.rs
@@ -41,9 +41,9 @@ pub enum TunnelOptions {
/// Configure whether to enable DAITA
#[arg(long)]
daita: Option<BooleanOption>,
- /// Configure whether to enable DAITA smart routing
+ /// Configure whether to enable DAITA direct only
#[arg(long)]
- daita_smart_routing: Option<BooleanOption>,
+ daita_direct_only: Option<BooleanOption>,
/// The key rotation interval. Number of hours, or 'any'
#[arg(long)]
rotation_interval: Option<Constraint<RotationInterval>>,
@@ -138,7 +138,7 @@ impl Tunnel {
mtu,
quantum_resistant,
daita,
- daita_smart_routing,
+ daita_direct_only,
rotation_interval,
rotate_key,
} => {
@@ -146,7 +146,7 @@ impl Tunnel {
mtu,
quantum_resistant,
daita,
- daita_smart_routing,
+ daita_direct_only,
rotation_interval,
rotate_key,
)
@@ -178,7 +178,7 @@ impl Tunnel {
mtu: Option<Constraint<u16>>,
quantum_resistant: Option<QuantumResistantState>,
daita: Option<BooleanOption>,
- daita_smart_routing: Option<BooleanOption>,
+ daita_direct_only: Option<BooleanOption>,
rotation_interval: Option<Constraint<RotationInterval>>,
rotate_key: Option<RotateKey>,
) -> Result<()> {
@@ -197,12 +197,12 @@ impl Tunnel {
if let Some(enable_daita) = daita {
rpc.set_enable_daita(*enable_daita).await?;
println!("DAITA setting has been updated");
- println!("Smart routing setting has been updated");
+ println!("Direct only setting has been updated");
}
- if let Some(daita_smart_routing) = daita_smart_routing {
- rpc.set_daita_smart_routing(*daita_smart_routing).await?;
- println!("Smart routing setting has been updated");
+ if let Some(daita_direct_only) = daita_direct_only {
+ rpc.set_daita_direct_only(*daita_direct_only).await?;
+ println!("Direct only setting has been updated");
}
if let Some(interval) = rotation_interval {
diff --git a/mullvad-daemon/src/lib.rs b/mullvad-daemon/src/lib.rs
index e833f1b82c..dd6c828802 100644
--- a/mullvad-daemon/src/lib.rs
+++ b/mullvad-daemon/src/lib.rs
@@ -266,7 +266,7 @@ pub enum DaemonCommand {
#[cfg(daita)]
SetEnableDaita(ResponseTx<(), settings::Error>, bool),
#[cfg(daita)]
- SetDaitaSmartRouting(ResponseTx<(), settings::Error>, bool),
+ SetDaitaUseMultihopIfNecessary(ResponseTx<(), settings::Error>, bool),
#[cfg(daita)]
SetDaitaSettings(ResponseTx<(), settings::Error>, DaitaSettings),
/// Set DNS options or servers to use
@@ -1261,7 +1261,9 @@ impl Daemon {
#[cfg(daita)]
SetEnableDaita(tx, value) => self.on_set_daita_enabled(tx, value).await,
#[cfg(daita)]
- SetDaitaSmartRouting(tx, value) => self.on_set_daita_smart_routing(tx, value).await,
+ SetDaitaUseMultihopIfNecessary(tx, value) => {
+ self.on_set_daita_use_multihop_if_necessary(tx, value).await
+ }
#[cfg(daita)]
SetDaitaSettings(tx, daita_settings) => {
self.on_set_daita_settings(tx, daita_settings).await
@@ -2343,11 +2345,6 @@ impl Daemon {
.settings
.update(|settings| {
settings.tunnel_options.wireguard.daita.enabled = value;
-
- // enable smart-routing automatically with daita
- if cfg!(not(target_os = "android")) {
- settings.tunnel_options.wireguard.daita.smart_routing = value
- }
})
.await;
@@ -2376,7 +2373,7 @@ impl Daemon {
}
#[cfg(daita)]
- async fn on_set_daita_smart_routing(
+ async fn on_set_daita_use_multihop_if_necessary(
&mut self,
tx: ResponseTx<(), settings::Error>,
value: bool,
@@ -2385,11 +2382,17 @@ impl Daemon {
match self
.settings
- .update(|settings| settings.tunnel_options.wireguard.daita.smart_routing = value)
+ .update(|settings| {
+ settings
+ .tunnel_options
+ .wireguard
+ .daita
+ .use_multihop_if_necessary = value
+ })
.await
{
Ok(settings_changed) => {
- Self::oneshot_send(tx, Ok(()), "set_daita_smart_routing response");
+ Self::oneshot_send(tx, Ok(()), "set_daita_use_multihop_if_necessary response");
let RelaySettings::Normal(constraints) = &self.settings.relay_settings else {
return; // DAITA is not supported for custom relays
@@ -2410,7 +2413,7 @@ impl Daemon {
}
Err(e) => {
log::error!("{}", e.display_chain_with_msg("Unable to save settings"));
- Self::oneshot_send(tx, Err(e), "set_daita_smart_routing response");
+ Self::oneshot_send(tx, Err(e), "set_daita_use_multihop_if_necessary response");
}
}
}
@@ -3024,12 +3027,16 @@ fn new_selector_config(settings: &Settings) -> SelectorConfig {
#[cfg(daita)]
daita: settings.tunnel_options.wireguard.daita.enabled,
#[cfg(daita)]
- daita_smart_routing: settings.tunnel_options.wireguard.daita.smart_routing,
+ daita_use_multihop_if_necessary: settings
+ .tunnel_options
+ .wireguard
+ .daita
+ .use_multihop_if_necessary,
#[cfg(not(daita))]
daita: false,
#[cfg(not(daita))]
- daita_smart_routing: false,
+ daita_use_multihop_if_necessary: false,
quantum_resistant: settings.tunnel_options.wireguard.quantum_resistant,
},
diff --git a/mullvad-daemon/src/management_interface.rs b/mullvad-daemon/src/management_interface.rs
index b52c214a01..eadfd99806 100644
--- a/mullvad-daemon/src/management_interface.rs
+++ b/mullvad-daemon/src/management_interface.rs
@@ -343,20 +343,23 @@ impl ManagementService for ManagementServiceImpl {
#[cfg(daita)]
async fn set_enable_daita(&self, request: Request<bool>) -> ServiceResult<()> {
- let value = request.into_inner();
- log::debug!("set_enable_daita({value})");
+ let daita_enabled = request.into_inner();
+ log::debug!("set_enable_daita({daita_enabled})");
let (tx, rx) = oneshot::channel();
- self.send_command_to_daemon(DaemonCommand::SetEnableDaita(tx, value))?;
+ self.send_command_to_daemon(DaemonCommand::SetEnableDaita(tx, daita_enabled))?;
self.wait_for_result(rx).await?.map(Response::new)?;
Ok(Response::new(()))
}
#[cfg(daita)]
- async fn set_daita_smart_routing(&self, request: Request<bool>) -> ServiceResult<()> {
- let value = request.into_inner();
- log::debug!("set_daita_smart_routing({value})");
+ async fn set_daita_direct_only(&self, request: Request<bool>) -> ServiceResult<()> {
+ let direct_only_enabled = request.into_inner();
+ log::debug!("set_daita_direct_only({direct_only_enabled})");
let (tx, rx) = oneshot::channel();
- self.send_command_to_daemon(DaemonCommand::SetDaitaSmartRouting(tx, value))?;
+ self.send_command_to_daemon(DaemonCommand::SetDaitaUseMultihopIfNecessary(
+ tx,
+ !direct_only_enabled,
+ ))?;
self.wait_for_result(rx).await?.map(Response::new)?;
Ok(Response::new(()))
}
@@ -381,7 +384,7 @@ impl ManagementService for ManagementServiceImpl {
}
#[cfg(not(daita))]
- async fn set_daita_smart_routing(&self, _: Request<bool>) -> ServiceResult<()> {
+ async fn set_daita_direct_only(&self, _: Request<bool>) -> ServiceResult<()> {
Ok(Response::new(()))
}
@@ -1135,8 +1138,9 @@ impl ManagementInterfaceServer {
})
}
- /// Wait for the server to shut down gracefully. If that does not happend within [`RPC_SERVER_SHUTDOWN_TIMEOUT`],
- /// the gRPC server is aborted and we yield the async execution.
+ /// Wait for the server to shut down gracefully. If that does not happend within
+ /// [`RPC_SERVER_SHUTDOWN_TIMEOUT`], the gRPC server is aborted and we yield the async
+ /// execution.
pub async fn stop(mut self) {
use futures::SinkExt;
// Send a singal to the underlying RPC server to shut down.
diff --git a/mullvad-management-interface/proto/management_interface.proto b/mullvad-management-interface/proto/management_interface.proto
index 70d9e1ad2b..b57d63dcf3 100644
--- a/mullvad-management-interface/proto/management_interface.proto
+++ b/mullvad-management-interface/proto/management_interface.proto
@@ -49,7 +49,7 @@ service ManagementService {
rpc SetEnableIpv6(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetQuantumResistantTunnel(QuantumResistantState) returns (google.protobuf.Empty) {}
rpc SetEnableDaita(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
- rpc SetDaitaSmartRouting(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
+ rpc SetDaitaDirectOnly(google.protobuf.BoolValue) returns (google.protobuf.Empty) {}
rpc SetDaitaSettings(DaitaSettings) returns (google.protobuf.Empty) {}
rpc SetDnsOptions(DnsOptions) returns (google.protobuf.Empty) {}
rpc SetRelayOverride(RelayOverride) returns (google.protobuf.Empty) {}
@@ -264,7 +264,6 @@ enum FeatureIndicator {
CUSTOM_MTU = 11;
CUSTOM_MSS_FIX = 12;
DAITA = 13;
- DAITA_SMART_ROUTING = 14;
}
message ObfuscationEndpoint {
@@ -546,7 +545,7 @@ message QuantumResistantState {
message DaitaSettings {
bool enabled = 1;
- bool smart_routing = 2;
+ bool direct_only = 2;
}
message TunnelOptions {
diff --git a/mullvad-management-interface/src/client.rs b/mullvad-management-interface/src/client.rs
index 73bff561a4..0b74f9d9d6 100644
--- a/mullvad-management-interface/src/client.rs
+++ b/mullvad-management-interface/src/client.rs
@@ -385,9 +385,9 @@ impl MullvadProxyClient {
}
#[cfg(daita)]
- pub async fn set_daita_smart_routing(&mut self, value: bool) -> Result<()> {
+ pub async fn set_daita_direct_only(&mut self, value: bool) -> Result<()> {
self.0
- .set_daita_smart_routing(value)
+ .set_daita_direct_only(value)
.await
.map_err(Error::Rpc)?;
Ok(())
diff --git a/mullvad-management-interface/src/types/conversions/features.rs b/mullvad-management-interface/src/types/conversions/features.rs
index 85c85b8b77..ac235d8163 100644
--- a/mullvad-management-interface/src/types/conversions/features.rs
+++ b/mullvad-management-interface/src/types/conversions/features.rs
@@ -18,7 +18,6 @@ impl From<mullvad_types::features::FeatureIndicator> for proto::FeatureIndicator
mullvad_types::features::FeatureIndicator::CustomMtu => CustomMtu,
mullvad_types::features::FeatureIndicator::CustomMssFix => CustomMssFix,
mullvad_types::features::FeatureIndicator::Daita => Daita,
- mullvad_types::features::FeatureIndicator::DaitaSmartRouting => DaitaSmartRouting,
}
}
}
@@ -40,7 +39,6 @@ impl From<proto::FeatureIndicator> for mullvad_types::features::FeatureIndicator
proto::FeatureIndicator::CustomMtu => Self::CustomMtu,
proto::FeatureIndicator::CustomMssFix => Self::CustomMssFix,
proto::FeatureIndicator::Daita => Self::Daita,
- proto::FeatureIndicator::DaitaSmartRouting => Self::DaitaSmartRouting,
}
}
}
diff --git a/mullvad-management-interface/src/types/conversions/wireguard.rs b/mullvad-management-interface/src/types/conversions/wireguard.rs
index 9e40b4b526..3e896da22d 100644
--- a/mullvad-management-interface/src/types/conversions/wireguard.rs
+++ b/mullvad-management-interface/src/types/conversions/wireguard.rs
@@ -78,7 +78,7 @@ impl From<mullvad_types::wireguard::DaitaSettings> for proto::DaitaSettings {
fn from(settings: mullvad_types::wireguard::DaitaSettings) -> Self {
proto::DaitaSettings {
enabled: settings.enabled,
- smart_routing: settings.smart_routing,
+ direct_only: !settings.use_multihop_if_necessary,
}
}
}
@@ -88,7 +88,7 @@ impl From<proto::DaitaSettings> for mullvad_types::wireguard::DaitaSettings {
fn from(settings: proto::DaitaSettings) -> Self {
mullvad_types::wireguard::DaitaSettings {
enabled: settings.enabled,
- smart_routing: settings.smart_routing,
+ use_multihop_if_necessary: !settings.direct_only,
}
}
}
diff --git a/mullvad-relay-selector/src/relay_selector/mod.rs b/mullvad-relay-selector/src/relay_selector/mod.rs
index 6233e2da05..b94a5812a0 100644
--- a/mullvad-relay-selector/src/relay_selector/mod.rs
+++ b/mullvad-relay-selector/src/relay_selector/mod.rs
@@ -126,7 +126,7 @@ pub struct AdditionalWireguardConstraints {
/// If true and multihop is disabled, will set up multihop with an automatic entry relay if
/// DAITA is enabled.
- pub daita_smart_routing: bool,
+ pub daita_use_multihop_if_necessary: bool,
/// If enabled, select relays that support PQ.
pub quantum_resistant: QuantumResistantState,
@@ -349,7 +349,7 @@ impl<'a> TryFrom<NormalSelectorConfig<'a>> for RelayQuery {
} = wireguard_constraints;
let AdditionalWireguardConstraints {
daita,
- daita_smart_routing,
+ daita_use_multihop_if_necessary,
quantum_resistant,
} = additional_constraints;
WireguardRelayQuery {
@@ -359,7 +359,7 @@ impl<'a> TryFrom<NormalSelectorConfig<'a>> for RelayQuery {
entry_location,
obfuscation: ObfuscationQuery::from(obfuscation_settings),
daita: Constraint::Only(daita),
- daita_smart_routing: Constraint::Only(daita_smart_routing),
+ daita_use_multihop_if_necessary: Constraint::Only(daita_use_multihop_if_necessary),
quantum_resistant,
}
}
@@ -738,18 +738,23 @@ impl RelaySelector {
Result::<_, Error>::Ok(!candidates.is_empty())
};
- // is `smart_routing` enabled?
- let smart_routing = || {
+ // is `use_multihop_if_necessary` enabled?
+ let use_multihop_if_necessary = || {
query
.wireguard_constraints()
- .daita_smart_routing
+ .daita_use_multihop_if_necessary
.intersection(Constraint::Only(true))
.is_some()
};
- // if we found no matching relays because DAITA was enabled, and `smart_routing` is enabled,
- // try enabling multihop and connecting using an automatically selected entry relay.
- if candidates.is_empty() && using_daita() && no_relay_because_daita()? && smart_routing() {
+ // if we found no matching relays because DAITA was enabled, and `use_multihop_if_necessary`
+ // is enabled, try enabling multihop and connecting using an automatically selected
+ // entry relay.
+ if candidates.is_empty()
+ && using_daita()
+ && no_relay_because_daita()?
+ && use_multihop_if_necessary()
+ {
return Self::get_wireguard_auto_multihop_config(query, custom_lists, parsed_relays);
}
diff --git a/mullvad-relay-selector/src/relay_selector/query.rs b/mullvad-relay-selector/src/relay_selector/query.rs
index 2dc81b0833..570a2212cb 100644
--- a/mullvad-relay-selector/src/relay_selector/query.rs
+++ b/mullvad-relay-selector/src/relay_selector/query.rs
@@ -268,7 +268,7 @@ pub struct WireguardRelayQuery {
pub entry_location: Constraint<LocationConstraint>,
pub obfuscation: ObfuscationQuery,
pub daita: Constraint<bool>,
- pub daita_smart_routing: Constraint<bool>,
+ pub daita_use_multihop_if_necessary: Constraint<bool>,
pub quantum_resistant: QuantumResistantState,
}
@@ -354,7 +354,7 @@ impl WireguardRelayQuery {
entry_location: Constraint::Any,
obfuscation: ObfuscationQuery::Auto,
daita: Constraint::Any,
- daita_smart_routing: Constraint::Any,
+ daita_use_multihop_if_necessary: Constraint::Any,
quantum_resistant: QuantumResistantState::Auto,
}
}
@@ -673,9 +673,14 @@ pub mod builder {
impl<Multihop, Obfuscation, QuantumResistant>
RelayQueryBuilder<Wireguard<Multihop, Obfuscation, bool, QuantumResistant>>
{
- /// Enable DAITA smart routing.
- pub fn daita_smart_routing(mut self, constraint: impl Into<Constraint<bool>>) -> Self {
- self.query.wireguard_constraints.daita_smart_routing = constraint.into();
+ /// Enable DAITA 'use_multihop_if_necessary'.
+ pub fn daita_use_multihop_if_necessary(
+ mut self,
+ constraint: impl Into<Constraint<bool>>,
+ ) -> Self {
+ self.query
+ .wireguard_constraints
+ .daita_use_multihop_if_necessary = constraint.into();
self
}
}
diff --git a/mullvad-relay-selector/tests/relay_selector.rs b/mullvad-relay-selector/tests/relay_selector.rs
index dc05d04eb2..1ce69b0591 100644
--- a/mullvad-relay-selector/tests/relay_selector.rs
+++ b/mullvad-relay-selector/tests/relay_selector.rs
@@ -1451,7 +1451,7 @@ fn test_daita() {
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(false)
+ .daita_use_multihop_if_necessary(false)
.build();
let relay = unwrap_entry_relay(relay_selector.get_relay_by_query(query).unwrap());
assert!(
@@ -1463,23 +1463,23 @@ fn test_daita() {
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(false)
+ .daita_use_multihop_if_necessary(false)
.location(NON_DAITA_RELAY_LOCATION.clone())
.build();
relay_selector
.get_relay_by_query(query)
.expect_err("Expected to find no matching relay");
- // Should be able to connect to non-DAITA relay with smart_routing
+ // Should be able to connect to non-DAITA relay with use_multihop_if_necessary
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(true)
+ .daita_use_multihop_if_necessary(true)
.location(NON_DAITA_RELAY_LOCATION.clone())
.build();
let relay = relay_selector
.get_relay_by_query(query)
- .expect("Expected to find a relay with daita_smart_routing");
+ .expect("Expected to find a relay with daita_use_multihop_if_necessary");
match relay {
GetRelay::Wireguard {
inner: WireguardConfig::Multihop { exit, entry },
@@ -1493,16 +1493,16 @@ fn test_daita() {
),
}
- // Should be able to connect to DAITA relay with smart_routing
+ // Should be able to connect to DAITA relay with use_multihop_if_necessary
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(true)
+ .daita_use_multihop_if_necessary(true)
.location(DAITA_RELAY_LOCATION.clone())
.build();
let relay = relay_selector
.get_relay_by_query(query)
- .expect("Expected to find a relay with daita_smart_routing");
+ .expect("Expected to find a relay with daita_use_multihop_if_necessary");
match relay {
GetRelay::Wireguard {
inner: WireguardConfig::Singlehop { exit },
@@ -1537,7 +1537,7 @@ fn test_daita() {
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(false)
+ .daita_use_multihop_if_necessary(false)
.multihop()
.build();
let relay = relay_selector.get_relay_by_query(query).unwrap();
@@ -1557,7 +1557,7 @@ fn test_daita() {
let query = RelayQueryBuilder::new()
.wireguard()
.daita()
- .daita_smart_routing(false)
+ .daita_use_multihop_if_necessary(false)
.multihop()
.location(NON_DAITA_RELAY_LOCATION.clone())
.build();
diff --git a/mullvad-types/src/features.rs b/mullvad-types/src/features.rs
index ba40e42d18..0e25f5a59c 100644
--- a/mullvad-types/src/features.rs
+++ b/mullvad-types/src/features.rs
@@ -1,4 +1,7 @@
-use std::{collections::HashSet, fmt::Display};
+use std::{
+ collections::HashSet,
+ fmt::{Debug, Display},
+};
use crate::settings::{DnsState, Settings};
use serde::{Deserialize, Serialize};
@@ -8,9 +11,20 @@ use talpid_types::net::{ObfuscationType, TunnelEndpoint, TunnelType};
/// what is affecting their connection at any given time.
///
/// Note that the feature indicators are not ordered.
-#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct FeatureIndicators(HashSet<FeatureIndicator>);
+impl Debug for FeatureIndicators {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ let mut indicators: Vec<&str> = self.0.iter().map(|feature| feature.to_str()).collect();
+ // Sort the features alphabetically (Just to have some order, arbitrarily chosen)
+ indicators.sort();
+ f.debug_tuple("FeatureIndicators")
+ .field(&indicators)
+ .finish()
+ }
+}
+
impl FeatureIndicators {
pub fn is_empty(&self) -> bool {
self.0.is_empty()
@@ -65,14 +79,7 @@ pub enum FeatureIndicator {
ServerIpOverride,
CustomMtu,
CustomMssFix,
-
- /// Whether DAITA (without smart routing) is in use.
- /// Mutually exclusive with [FeatureIndicator::DaitaSmartRouting].
Daita,
-
- /// Whether DAITA (with smart routing) is in use.
- /// Mutually exclusive with [FeatureIndicator::Daita].
- DaitaSmartRouting,
}
impl FeatureIndicator {
@@ -92,7 +99,6 @@ impl FeatureIndicator {
FeatureIndicator::CustomMtu => "Custom MTU",
FeatureIndicator::CustomMssFix => "Custom MSS",
FeatureIndicator::Daita => "DAITA",
- FeatureIndicator::DaitaSmartRouting => "DAITA: Smart Routing",
}
}
}
@@ -165,28 +171,13 @@ pub fn compute_feature_indicators(
let mtu = settings.tunnel_options.wireguard.mtu.is_some();
- let mut daita_smart_routing = false;
- let mut multihop = false;
+ let mut daita = false;
+ let multihop = endpoint.entry_endpoint.is_some();
- if let crate::relay_constraints::RelaySettings::Normal(constraints) =
- &settings.relay_settings
- {
- multihop = endpoint.entry_endpoint.is_some()
- && constraints.wireguard_constraints.use_multihop;
-
- #[cfg(daita)]
- {
- // Detect whether we're using "smart_routing" by checking if multihop is
- // in use but not explicitly enabled.
- daita_smart_routing = endpoint.daita
- && endpoint.entry_endpoint.is_some()
- && !constraints.wireguard_constraints.use_multihop
- }
- };
-
- // Daita is mutually exclusive with DaitaSmartRouting
#[cfg(daita)]
- let daita = endpoint.daita && !daita_smart_routing;
+ if endpoint.daita {
+ daita = true;
+ }
vec![
(quantum_resistant, FeatureIndicator::QuantumResistance),
@@ -194,9 +185,7 @@ pub fn compute_feature_indicators(
(udp_tcp, FeatureIndicator::Udp2Tcp),
(shadowsocks, FeatureIndicator::Shadowsocks),
(mtu, FeatureIndicator::CustomMtu),
- #[cfg(daita)]
(daita, FeatureIndicator::Daita),
- (daita_smart_routing, FeatureIndicator::DaitaSmartRouting),
]
}
};
@@ -328,13 +317,18 @@ mod tests {
expected_indicators
);
+ if let RelaySettings::Normal(constraints) = &mut settings.relay_settings {
+ constraints.wireguard_constraints.use_multihop = true;
+ };
+ assert_eq!(
+ compute_feature_indicators(&settings, &endpoint, false),
+ expected_indicators,
+ "The multihop feature indicator should be enabled by the endpoint, not the settings"
+ );
endpoint.entry_endpoint = Some(Endpoint {
address: SocketAddr::from(([1, 2, 3, 4], 443)),
protocol: TransportProtocol::Tcp,
});
- if let RelaySettings::Normal(constraints) = &mut settings.relay_settings {
- constraints.wireguard_constraints.use_multihop = true;
- };
expected_indicators.0.insert(FeatureIndicator::Multihop);
assert_eq!(
compute_feature_indicators(&settings, &endpoint, false),
@@ -370,25 +364,57 @@ mod tests {
#[cfg(daita)]
{
+ // Multihop and DAITA on
endpoint.daita = true;
+ settings
+ .tunnel_options
+ .wireguard
+ .daita
+ .use_multihop_if_necessary = true;
+
expected_indicators.0.insert(FeatureIndicator::Daita);
assert_eq!(
compute_feature_indicators(&settings, &endpoint, false),
expected_indicators
);
+ // Should not change regardless of whether `use_multihop_if_necessary` is true, since
+ // multihop is enabled explicitly
+ settings
+ .tunnel_options
+ .wireguard
+ .daita
+ .use_multihop_if_necessary = false;
+ assert_eq!(
+ compute_feature_indicators(&settings, &endpoint, false),
+ expected_indicators,
+ );
+
+ // Here we mock that multihop was automatically enabled by DAITA.
+ // We enable `use_multihop_if_necessary` again and disable the multihop setting, while
+ // keeping the entry relay. In this scenario, we should still get a Multihop
+ // indicator.
+ settings
+ .tunnel_options
+ .wireguard
+ .daita
+ .use_multihop_if_necessary = true;
if let RelaySettings::Normal(constraints) = &mut settings.relay_settings {
constraints.wireguard_constraints.use_multihop = false;
};
- expected_indicators
- .0
- .insert(FeatureIndicator::DaitaSmartRouting);
- expected_indicators.0.remove(&FeatureIndicator::Daita);
+ assert_eq!(
+ compute_feature_indicators(&settings, &endpoint, false),
+ expected_indicators,
+ "DaitaDirectOnly should be enabled"
+ );
+
+ // If we also remove the entry relay, we should not get a multihop indicator
+ endpoint.entry_endpoint = None;
expected_indicators.0.remove(&FeatureIndicator::Multihop);
assert_eq!(
compute_feature_indicators(&settings, &endpoint, false),
expected_indicators,
- "DaitaSmartRouting should be enabled"
+ "DaitaDirectOnly should be enabled"
);
}
@@ -409,7 +435,6 @@ mod tests {
FeatureIndicator::CustomMtu => {}
FeatureIndicator::CustomMssFix => {}
FeatureIndicator::Daita => {}
- FeatureIndicator::DaitaSmartRouting => {}
}
}
}
diff --git a/mullvad-types/src/wireguard.rs b/mullvad-types/src/wireguard.rs
index c6ec6cec5f..12f68566bd 100644
--- a/mullvad-types/src/wireguard.rs
+++ b/mullvad-types/src/wireguard.rs
@@ -81,12 +81,34 @@ impl FromStr for QuantumResistantState {
pub struct QuantumResistantStateParseError;
#[cfg(daita)]
-#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq)]
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DaitaSettings {
pub enabled: bool,
- #[serde(default)]
- pub smart_routing: bool,
+ #[cfg_attr(target_os = "android", serde(skip))]
+ #[serde(default = "DaitaSettings::default_use_multihop_if_necessary")]
+ /// Whether to use multihop if the selected relay is not DAITA-compatible. Note that this is
+ /// the inverse of of "Direct only" in the GUI.
+ pub use_multihop_if_necessary: bool,
+}
+
+#[cfg(daita)]
+impl DaitaSettings {
+ /// This setting should be enabled by default, expect on Android where multihop is not
+ /// supported.
+ const fn default_use_multihop_if_necessary() -> bool {
+ cfg!(not(target_os = "android"))
+ }
+}
+
+#[cfg(daita)]
+impl Default for DaitaSettings {
+ fn default() -> Self {
+ Self {
+ enabled: false,
+ use_multihop_if_necessary: Self::default_use_multihop_if_necessary(),
+ }
+ }
}
/// Contains account specific wireguard data
diff --git a/test/test-manager/src/tests/daita.rs b/test/test-manager/src/tests/daita.rs
index 912c811ecc..24f5f4b0df 100644
--- a/test/test-manager/src/tests/daita.rs
+++ b/test/test-manager/src/tests/daita.rs
@@ -12,10 +12,10 @@ use test_rpc::ServiceClient;
use super::{helpers, Error, TestContext};
-/// Test that daita and daita_smart_routing works by connecting
+/// Test that daita and daita_direct_only works by connecting
/// - to a non-DAITA relay with singlehop (should block)
/// - to a DAITA relay with singlehop
-/// - to a DAITA relay with auto-multihop using smart_routing
+/// - to a DAITA relay with auto-multihop by disabling direct_only
/// - to a DAITA relay with explicit multihop
/// - to a non-DAITA relay with multihop (should block)
///
@@ -90,25 +90,25 @@ pub async fn test_daita(
.await?
.inspect(|event| log::debug!("New daemon event: {event:?}"));
- log::info!("Connecting to non-daita relay with DAITA smart routing");
+ log::info!("Connecting to non-daita relay with DAITA by automatically using multihop");
{
helpers::set_relay_settings(&mut mullvad_client, non_daita_location_query.clone()).await?;
mullvad_client.set_enable_daita(true).await?;
mullvad_client.connect_tunnel().await?;
let state = wait_for_daemon_reconnect(&mut events)
.await
- .context("Failed to connect with smart_routing enabled")?;
+ .context("Failed to connect with 'direct only' disabled")?;
let endpoint: &TunnelEndpoint = state.endpoint().ok_or(anyhow!("No endpoint"))?;
ensure!(endpoint.daita, "DAITA must be used");
ensure!(endpoint.entry_endpoint.is_some(), "multihop must be used");
- log::info!("Successfully multihopped with use smart_routing");
+ log::info!("Successfully multihopped with 'direct only' disabled");
}
- log::info!("Connecting to non-daita relay with DAITA but no smart routing");
+ log::info!("Connecting to non-daita relay with 'DAITA: direct only'");
{
- mullvad_client.set_daita_smart_routing(false).await?;
+ mullvad_client.set_daita_direct_only(true).await?;
let result = wait_for_daemon_reconnect(&mut events).await;
let Err(Error::UnexpectedErrorState(state)) = result else {
@@ -121,13 +121,13 @@ pub async fn test_daita(
log::info!("Failed to connect, this is expected!");
}
- log::info!("Connecting to daita relay with smart_routing");
+ log::info!("Connecting to daita relay with 'direct_only' disabled");
{
helpers::set_relay_settings(&mut mullvad_client, daita_location_query).await?;
let state = wait_for_daemon_reconnect(&mut events)
.await
- .context("Failed to connect to daita location with smart_routing enabled")?;
+ .context("Failed to connect to daita location with 'direct_only' disabled")?;
let endpoint = state.endpoint().context("No endpoint")?;
ensure!(endpoint.daita, "DAITA must be used");
@@ -136,7 +136,7 @@ pub async fn test_daita(
"multihop must not be used"
);
- log::info!("Successfully singlehopped with smart_routing");
+ log::info!("Successfully singlehopped with 'direct_only' disabled");
}
log::info!("Connecting to daita relay with multihop");