diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2019-09-12 18:34:27 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2019-09-13 16:00:58 +0200 |
| commit | 5105fe058780d6ebde2106da3f244f198bed5856 (patch) | |
| tree | 6c8e4a28a38e038964c482a67cc7a6380a66f8c6 /gui/src/shared | |
| parent | ee6500b5026b1da2ac25d99cb4e8ec79ea186e35 (diff) | |
| download | mullvadvpn-5105fe058780d6ebde2106da3f244f198bed5856.tar.xz mullvadvpn-5105fe058780d6ebde2106da3f244f198bed5856.zip | |
Add "Closest to exit server" option in bridge selector
Diffstat (limited to 'gui/src/shared')
| -rw-r--r-- | gui/src/shared/bridge-settings-builder.ts | 24 | ||||
| -rw-r--r-- | gui/src/shared/ipc-event-channel.ts | 12 | ||||
| -rw-r--r-- | gui/src/shared/relay-location-builder.ts | 41 | ||||
| -rw-r--r-- | gui/src/shared/relay-settings-builder.ts | 158 |
4 files changed, 229 insertions, 6 deletions
diff --git a/gui/src/shared/bridge-settings-builder.ts b/gui/src/shared/bridge-settings-builder.ts new file mode 100644 index 0000000000..28e701ec0a --- /dev/null +++ b/gui/src/shared/bridge-settings-builder.ts @@ -0,0 +1,24 @@ +import { BridgeSettings, IBridgeConstraints } from './daemon-rpc-types'; +import makeLocationBuilder, { ILocationBuilder } from './relay-location-builder'; + +export default class BridgeSettingsBuilder { + private payload: Partial<IBridgeConstraints> = {}; + + public build(): BridgeSettings { + if (this.payload.location) { + return { + normal: { + location: this.payload.location, + }, + }; + } else { + throw new Error('Unsupported configuration'); + } + } + + get location(): ILocationBuilder<BridgeSettingsBuilder> { + return makeLocationBuilder(this, (location) => { + this.payload.location = location; + }); + } +} diff --git a/gui/src/shared/ipc-event-channel.ts b/gui/src/shared/ipc-event-channel.ts index 3df81c2eea..2800ab50ea 100644 --- a/gui/src/shared/ipc-event-channel.ts +++ b/gui/src/shared/ipc-event-channel.ts @@ -8,6 +8,7 @@ import { IAppUpgradeInfo, ICurrentAppVersionInfo } from '../main/index'; import { IWindowShapeParameters } from '../main/window-controller'; import { AccountToken, + BridgeSettings, BridgeState, IAccountData, ILocation, @@ -15,7 +16,6 @@ import { ISettings, IWireguardPublicKey, KeygenEvent, - RelayLocation, RelaySettingsUpdate, TunnelState, } from './daemon-rpc-types'; @@ -71,7 +71,7 @@ interface ISettingsMethods extends IReceiver<ISettings> { setBridgeState(state: BridgeState): Promise<void>; setOpenVpnMssfix(mssfix?: number): Promise<void>; updateRelaySettings(update: RelaySettingsUpdate): Promise<void>; - updateBridgeLocation(location: RelayLocation): Promise<void>; + updateBridgeSettings(bridgeSettings: BridgeSettings): Promise<void>; } interface ISettingsHandlers extends ISender<ISettings> { @@ -81,7 +81,7 @@ interface ISettingsHandlers extends ISender<ISettings> { handleBridgeState(fn: (state: BridgeState) => Promise<void>): void; handleOpenVpnMssfix(fn: (mssfix?: number) => Promise<void>): void; handleUpdateRelaySettings(fn: (update: RelaySettingsUpdate) => Promise<void>): void; - handleUpdateBridgeLocation(fn: (location: RelayLocation) => Promise<void>): void; + handleUpdateBridgeSettings(fn: (bridgeSettings: BridgeSettings) => Promise<void>): void; } interface IGuiSettingsMethods extends IReceiver<IGuiSettingsState> { @@ -154,7 +154,7 @@ const SET_BLOCK_WHEN_DISCONNECTED = 'set-block-when-disconnected'; const SET_BRIDGE_STATE = 'set-bridge-state'; const SET_OPENVPN_MSSFIX = 'set-openvpn-mssfix'; const UPDATE_RELAY_SETTINGS = 'update-relay-settings'; -const UPDATE_BRIDGE_LOCATION = 'update-bridge-location'; +const UPDATE_BRIDGE_SETTINGS = 'update-bridge-location'; const LOCATION_CHANGED = 'location-changed'; const RELAYS_CHANGED = 'relays-changed'; @@ -223,7 +223,7 @@ export class IpcRendererEventChannel { setBridgeState: requestSender(SET_BRIDGE_STATE), setOpenVpnMssfix: requestSender(SET_OPENVPN_MSSFIX), updateRelaySettings: requestSender(UPDATE_RELAY_SETTINGS), - updateBridgeLocation: requestSender(UPDATE_BRIDGE_LOCATION), + updateBridgeSettings: requestSender(UPDATE_BRIDGE_SETTINGS), }; public static location: IReceiver<ILocation> = { @@ -313,7 +313,7 @@ export class IpcMainEventChannel { handleBridgeState: requestHandler(SET_BRIDGE_STATE), handleOpenVpnMssfix: requestHandler(SET_OPENVPN_MSSFIX), handleUpdateRelaySettings: requestHandler(UPDATE_RELAY_SETTINGS), - handleUpdateBridgeLocation: requestHandler(UPDATE_BRIDGE_LOCATION), + handleUpdateBridgeSettings: requestHandler(UPDATE_BRIDGE_SETTINGS), }; public static relays: ISender<IRelayListPair> = { diff --git a/gui/src/shared/relay-location-builder.ts b/gui/src/shared/relay-location-builder.ts new file mode 100644 index 0000000000..14bf72b65f --- /dev/null +++ b/gui/src/shared/relay-location-builder.ts @@ -0,0 +1,41 @@ +import { Constraint, LiftedConstraint, RelayLocation } from './daemon-rpc-types'; + +export interface ILocationBuilder<Self> { + country(country: string): Self; + city(country: string, city: string): Self; + hostname(country: string, city: string, hostname: string): Self; + any(): Self; + fromRaw(location: LiftedConstraint<RelayLocation>): Self; +} + +export default function makeLocationBuilder<T>( + context: T, + receiver: (constraint: Constraint<RelayLocation>) => void, +): ILocationBuilder<T> { + return { + country: (country: string) => { + receiver({ only: { country } }); + return context; + }, + city: (country: string, city: string) => { + receiver({ only: { city: [country, city] } }); + return context; + }, + hostname: (country: string, city: string, hostname: string) => { + receiver({ only: { hostname: [country, city, hostname] } }); + return context; + }, + any: () => { + receiver('any'); + return context; + }, + fromRaw(location: LiftedConstraint<RelayLocation>) { + if (location === 'any') { + return this.any(); + } else { + receiver({ only: location }); + return context; + } + }, + }; +} diff --git a/gui/src/shared/relay-settings-builder.ts b/gui/src/shared/relay-settings-builder.ts new file mode 100644 index 0000000000..182e44063f --- /dev/null +++ b/gui/src/shared/relay-settings-builder.ts @@ -0,0 +1,158 @@ +import { + Constraint, + IOpenVpnConstraints, + IWireguardConstraints, + 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>; +} + +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'), + }; + }, + }; + 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(), +}; |
