diff options
| author | David Lönnhager <david.l@mullvad.net> | 2023-10-26 01:13:39 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-10-31 00:45:17 +0100 |
| commit | fbc8c1675700e1e87d9282ee288e6c0b72c1c7aa (patch) | |
| tree | 85c4cb1d2a5a43826e8f3a0a2552a177e58bbced /gui/src | |
| parent | e02d812d55064fc114d38edbdcbbeda5aca6a6b7 (diff) | |
| download | mullvadvpn-fbc8c1675700e1e87d9282ee288e6c0b72c1c7aa.tar.xz mullvadvpn-fbc8c1675700e1e87d9282ee288e6c0b72c1c7aa.zip | |
Remove RelaySettingsUpdate from gui/
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 80 | ||||
| -rw-r--r-- | gui/src/main/settings.ts | 4 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/components/Filter.tsx | 12 | ||||
| -rw-r--r-- | gui/src/renderer/components/OpenVpnSettings.tsx | 35 | ||||
| -rw-r--r-- | gui/src/renderer/components/VpnSettings.tsx | 37 | ||||
| -rw-r--r-- | gui/src/renderer/components/WireguardSettings.tsx | 53 | ||||
| -rw-r--r-- | gui/src/renderer/components/select-location/SelectLocation.tsx | 16 | ||||
| -rw-r--r-- | gui/src/renderer/components/select-location/select-location-hooks.ts | 61 | ||||
| -rw-r--r-- | gui/src/renderer/lib/constraint-updater.ts | 111 | ||||
| -rw-r--r-- | gui/src/shared/daemon-rpc-types.ts | 21 | ||||
| -rw-r--r-- | gui/src/shared/ipc-schema.ts | 4 | ||||
| -rw-r--r-- | gui/src/shared/relay-settings-builder.ts | 189 |
13 files changed, 234 insertions, 392 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 288bbfd7fc..f1fba53d55 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 updateRelaySettings(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..3f04666df6 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.handleUpdateRelaySettings((relaySettings) => + this.daemonRpc.updateRelaySettings(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..bdfe272061 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,7 +303,7 @@ export default class AppRenderer { public connectTunnel = () => IpcRendererEventChannel.tunnel.connect(); public disconnectTunnel = () => IpcRendererEventChannel.tunnel.disconnect(); public reconnectTunnel = () => IpcRendererEventChannel.tunnel.reconnect(); - public updateRelaySettings = (relaySettings: RelaySettingsUpdate) => + public updateRelaySettings = (relaySettings: RelaySettings) => IpcRendererEventChannel.settings.updateRelaySettings(relaySettings); public updateBridgeSettings = (bridgeSettings: BridgeSettings) => IpcRendererEventChannel.settings.updateBridgeSettings(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..c848f5688b 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'; @@ -177,34 +182,24 @@ function TransportProtocolSelector() { } function useProtocolAndPortUpdater() { - const { updateRelaySettings } = useAppContext(); + const relaySettingsUpdater = useRelaySettingsUpdater(); 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(); - } - + try { + await relaySettingsUpdater((settings) => { + settings.openvpnConstraints.protocol = wrapConstraint(protocol); if (port) { - openvpn.port.exact(port); - } else { - openvpn.port.any(); + settings.openvpnConstraints.port = wrapConstraint(port); } - }) - .build(); - - try { - await updateRelaySettings(relayUpdate); + return settings; + }); } catch (e) { const error = e as Error; log.error('Failed to update relay settings', error.message); } }, - [updateRelaySettings], + [relaySettingsUpdater], ); return updater; 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..0490799123 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,23 +43,31 @@ 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; } @@ -64,12 +75,12 @@ export function useOnSelectEntryLocation() { function useOnSelectLocation() { const { updateRelaySettings } = useAppContext(); - return useCallback(async (relayUpdate: RelaySettingsUpdate) => { + return useCallback(async (relaySettings: RelaySettings) => { try { - await updateRelaySettings(relayUpdate); + await updateRelaySettings(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..4acb351335 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 { updateRelaySettings } = useAppContext(); + const modifyRelaySettings = useRelaySettingsModifier(); + + return useCallback( + async (fn: UpdateFunction) => { + const modifiedSettings = modifyRelaySettings(fn); + await updateRelaySettings({ normal: modifiedSettings }); + }, + [updateRelaySettings, 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..7981250c88 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>(), + updateRelaySettings: 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(), -}; |
