summaryrefslogtreecommitdiffhomepage
path: root/gui/src/shared
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2019-09-12 18:34:27 +0200
committerAndrej Mihajlov <and@mullvad.net>2019-09-13 16:00:58 +0200
commit5105fe058780d6ebde2106da3f244f198bed5856 (patch)
tree6c8e4a28a38e038964c482a67cc7a6380a66f8c6 /gui/src/shared
parentee6500b5026b1da2ac25d99cb4e8ec79ea186e35 (diff)
downloadmullvadvpn-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.ts24
-rw-r--r--gui/src/shared/ipc-event-channel.ts12
-rw-r--r--gui/src/shared/relay-location-builder.ts41
-rw-r--r--gui/src/shared/relay-settings-builder.ts158
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(),
+};