diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2018-11-14 16:10:10 +0100 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2018-11-15 11:14:43 +0100 |
| commit | 3f70ef611126c008202b1665fc684d5a04b7e72d (patch) | |
| tree | 35c2042d8ca38be3f93ebc03202264ec1f5b8d9d | |
| parent | f004183e5e6a043afe839885643a6c7776fbb9f2 (diff) | |
| download | mullvadvpn-3f70ef611126c008202b1665fc684d5a04b7e72d.tar.xz mullvadvpn-3f70ef611126c008202b1665fc684d5a04b7e72d.zip | |
Move DaemonRPC to main and establish a temp bridge using DaemonRPCProxy
29 files changed, 435 insertions, 99 deletions
diff --git a/gui/packages/desktop/src/renderer/lib/daemon-rpc.js b/gui/packages/desktop/src/main/daemon-rpc.js index a37ebdd5a8..1811fa1e36 100644 --- a/gui/packages/desktop/src/renderer/lib/daemon-rpc.js +++ b/gui/packages/desktop/src/main/daemon-rpc.js @@ -5,7 +5,7 @@ import JsonRpcClient, { TimeOutError as JsonRpcTimeOutError, SocketTransport, } from './jsonrpc-client'; -import { CommunicationError, InvalidAccountError, NoDaemonError } from '../errors'; +import { CommunicationError, InvalidAccountError, NoDaemonError } from './errors'; import { object, diff --git a/gui/packages/desktop/src/renderer/errors.js b/gui/packages/desktop/src/main/errors.js index 67f87501dd..67f87501dd 100644 --- a/gui/packages/desktop/src/renderer/errors.js +++ b/gui/packages/desktop/src/main/errors.js diff --git a/gui/packages/desktop/src/main/index.js b/gui/packages/desktop/src/main/index.js index 2950cd9e01..50a4815544 100644 --- a/gui/packages/desktop/src/main/index.js +++ b/gui/packages/desktop/src/main/index.js @@ -11,14 +11,24 @@ import { app, screen, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'el import TrayIconController from './tray-icon-controller'; import WindowController from './window-controller'; import ShutdownCoordinator from './shutdown-coordinator'; +import { DaemonRpc, ConnectionObserver, SubscriptionListener } from './daemon-rpc'; +import type { TunnelStateTransition, Settings } from './daemon-rpc'; +import ReconnectionBackoff from './reconnection-backoff'; import { resolveBin } from './proc'; import type { TrayIconType } from './tray-icon-controller'; +const DAEMON_RPC_PATH = + process.platform === 'win32' ? '//./pipe/Mullvad VPN' : '/var/run/mullvad-vpn'; + const ApplicationMain = { _windowController: (null: ?WindowController), _trayIconController: (null: ?TrayIconController), + _daemonRpc: new DaemonRpc(), + _reconnectBackoff: new ReconnectionBackoff(), + _connectedToDaemon: false, + _logFilePath: '', _oldLogFilePath: (null: ?string), _connectionFilePollInterval: (null: ?IntervalID), @@ -48,6 +58,18 @@ const ApplicationMain = { app.on('ready', () => this._onReady()); app.on('window-all-closed', () => app.quit()); app.on('before-quit', () => this._onBeforeQuit()); + + const connectionObserver = new ConnectionObserver( + () => { + this._onDaemonConnected(); + }, + (error) => { + this._onDaemonDisconnected(error); + }, + ); + + this._daemonRpc.addConnectionObserver(connectionObserver); + this._connectToDaemon(); }, _ensureSingleInstance() { @@ -130,9 +152,8 @@ const ApplicationMain = { }, _onActivate() { - const windowController = this._windowController; - if (windowController) { - windowController.show(); + if (this._windowController) { + this._windowController.show(); } }, @@ -140,9 +161,8 @@ const ApplicationMain = { this._shouldQuit = true; if (process.env.NODE_ENV === 'development') { - const windowController = this._windowController; - if (windowController) { - windowController.window.closeDevTools(); + if (this._windowController) { + this._windowController.window.closeDevTools(); } } @@ -190,6 +210,79 @@ const ApplicationMain = { window.loadFile(path.resolve(path.join(__dirname, '../renderer/index.html'))); }, + async _onDaemonConnected() { + this._connectedToDaemon = true; + + // reset the reconnect backoff when connection established. + this._reconnectBackoff.reset(); + + if (this._windowController) { + this._windowController.send('daemon-connected'); + } + + const stateListener = new SubscriptionListener( + (newState: TunnelStateTransition) => { + this._onStateChange(newState); + }, + (error: Error) => { + log.error(`Cannot deserialize the new state: ${error.message}`); + }, + ); + + const settingsListener = new SubscriptionListener( + (newSettings: Settings) => { + this._onSettingsChange(newSettings); + }, + (error: Error) => { + log.error(`Cannot deserialize the new settings: ${error.message}`); + }, + ); + + try { + await Promise.all([ + this._daemonRpc.subscribeStateListener(stateListener), + this._daemonRpc.subscribeSettingsListener(settingsListener), + ]); + } catch (error) { + log.error(`Failed to subscribe: ${error.message}`); + } + }, + + _onDaemonDisconnected(error: ?Error) { + // recover connection on error + if (error) { + log.debug(`Lost connection to daemon: ${error.message}`); + + this._reconnectBackoff.attempt(() => { + this._connectToDaemon(); + }); + } else { + log.info(`Disconnected from the daemon`); + } + + this._connectedToDaemon = false; + + if (this._windowController) { + this._windowController.send('daemon-disconnected', error ? error.message : null); + } + }, + + _connectToDaemon() { + this._daemonRpc.connect({ path: DAEMON_RPC_PATH }); + }, + + _onStateChange(newState: TunnelStateTransition) { + if (this._windowController) { + this._windowController.send('state-changed', newState); + } + }, + + _onSettingsChange(newSettings: Settings) { + if (this._windowController) { + this._windowController.send('settings-changed', newSettings); + } + }, + _registerWindowListener(windowController: WindowController) { const window = windowController.window; @@ -197,6 +290,31 @@ const ApplicationMain = { }, _registerIpcListeners() { + ipcMain.on('daemon-rpc-call', async (event, id: string, method: string, payload: any) => { + log.debug(`Got daemon-rpc-call: ${id} ${method} ${payload}`); + + try { + // $FlowFixMe: flow does not like index accessors. + const result = await this._daemonRpc[method](payload); + + log.debug(`Reply to ${id} ${method} with success: ${JSON.stringify(result)}`); + event.sender.send(`daemon-rpc-reply-${id}`, result); + } catch (error) { + log.debug(`Reply to ${id} ${method} with error: ${error.message}`); + event.sender.send(`daemon-rpc-reply-${id}`, undefined, { + className: error.constructor.name || '', + data: { + message: error.message, + ...JSON.parse(JSON.stringify(error)), + }, + }); + } + }); + + ipcMain.on('daemon-connection-status', (event) => { + event.sender.send('daemon-connection-status-reply', this._connectedToDaemon); + }); + ipcMain.on('show-window', () => { const windowController = this._windowController; if (windowController) { diff --git a/gui/packages/desktop/src/renderer/lib/jsonrpc-client.js b/gui/packages/desktop/src/main/jsonrpc-client.js index 0f51ca57cb..0f51ca57cb 100644 --- a/gui/packages/desktop/src/renderer/lib/jsonrpc-client.js +++ b/gui/packages/desktop/src/main/jsonrpc-client.js diff --git a/gui/packages/desktop/src/renderer/lib/reconnection-backoff.js b/gui/packages/desktop/src/main/reconnection-backoff.js index d777e86e57..d777e86e57 100644 --- a/gui/packages/desktop/src/renderer/lib/reconnection-backoff.js +++ b/gui/packages/desktop/src/main/reconnection-backoff.js diff --git a/gui/packages/desktop/src/main/window-controller.js b/gui/packages/desktop/src/main/window-controller.js index 5950ab4716..0943364dab 100644 --- a/gui/packages/desktop/src/main/window-controller.js +++ b/gui/packages/desktop/src/main/window-controller.js @@ -175,6 +175,10 @@ export default class WindowController { } } + send(event: string, ...data: Array<mixed>): void { + this._window.webContents.send(event, ...data); + } + _showImmediately() { const window = this._window; diff --git a/gui/packages/desktop/src/renderer/app.js b/gui/packages/desktop/src/renderer/app.js index 8e4328f66a..0b9352a5c1 100644 --- a/gui/packages/desktop/src/renderer/app.js +++ b/gui/packages/desktop/src/renderer/app.js @@ -12,10 +12,8 @@ import { } from 'connected-react-router'; import { createMemoryHistory } from 'history'; -import { InvalidAccountError } from './errors'; +import { InvalidAccountError } from '../main/errors'; import makeRoutes from './routes'; -import ReconnectionBackoff from './lib/reconnection-backoff'; -import { DaemonRpc, ConnectionObserver } from './lib/daemon-rpc'; import NotificationController from './lib/notification-controller'; import setShutdownHandler from './lib/shutdown-handler'; @@ -38,9 +36,11 @@ import type { RelaySettingsUpdate, RelaySettings, TunnelState, - DaemonRpcProtocol, AccountData, -} from './lib/daemon-rpc'; +} from './lib/daemon-rpc-proxy'; + +import DaemonRpcProxy from './lib/daemon-rpc-proxy'; + import type { ReduxStore } from './redux/store'; import type { TrayIconType } from '../main/tray-icon-controller'; @@ -48,19 +48,10 @@ const RELAY_LIST_UPDATE_INTERVAL = 60 * 60 * 1000; export default class AppRenderer { _notificationController = new NotificationController(); - _daemonRpc: DaemonRpcProtocol = new DaemonRpc(); - _connectionObserver = new ConnectionObserver( - () => { - this._onOpenConnection(); - }, - (error) => { - this._onCloseConnection(error); - }, - ); - _reconnectBackoff = new ReconnectionBackoff(); _memoryHistory = createMemoryHistory(); _reduxStore: ReduxStore; _reduxActions: *; + _daemonRpc = new DaemonRpcProxy(); _accountDataCache = new AccountDataCache( (accountToken) => { return this._daemonRpc.getAccountData(accountToken); @@ -106,8 +97,6 @@ export default class AppRenderer { ), }; - this._daemonRpc.addConnectionObserver(this._connectionObserver); - setShutdownHandler(async () => { log.info('Executing a shutdown handler'); try { @@ -125,10 +114,30 @@ export default class AppRenderer { }); ipcRenderer.on('window-shown', () => { - this.updateAccountExpiry(); + if (this._connectedToDaemon) { + this.updateAccountExpiry(); + } + this._notificationController.cancelPendingNotifications(); }); + ipcRenderer.on('daemon-connected', () => { + this._onDaemonConnected(); + }); + + ipcRenderer.on('daemon-disconnected', (errorMessage: ?string) => { + this._onDaemonDisconnected(errorMessage ? new Error(errorMessage) : null); + }); + + // Request the initial daemon connection status + ipcRenderer.once('daemon-connection-status-reply', (isConnected: boolean) => { + if (isConnected) { + this._onDaemonConnected(); + } + }); + + ipcRenderer.send('daemon-connection-status'); + // disable pinch to zoom webFrame.setVisualZoomLevelLimits(1, 1); } @@ -141,14 +150,6 @@ export default class AppRenderer { ); } - connect() { - this._daemonRpc.connect({ path: getIpcPath() }); - } - - disconnect() { - this._daemonRpc.disconnect(); - } - async login(accountToken: AccountToken) { const actions = this._reduxActions; const history = this._memoryHistory; @@ -294,10 +295,9 @@ export default class AppRenderer { async updateAccountExpiry() { const settings = await this._settingsProxy.fetch(); - const accountDataCache = this._accountDataCache; if (settings && settings.accountToken) { - accountDataCache.fetch(settings.accountToken); + this._accountDataCache.fetch(settings.accountToken); } } @@ -435,12 +435,9 @@ export default class AppRenderer { }); } - async _onOpenConnection() { + async _onDaemonConnected() { this._connectedToDaemon = true; - // reset the reconnect backoff when connection established. - this._reconnectBackoff.reset(); - try { await this._runPrimaryApplicationFlow(); } catch (error) { @@ -448,6 +445,23 @@ export default class AppRenderer { } } + _onDaemonDisconnected(error: ?Error) { + const actions = this._reduxActions; + + this._relayListCache.stopUpdating(); + + // recover connection on error + if (error) { + // only send to the connecting to daemon view if the daemon was + // connnected previously + if (this._connectedToDaemon) { + actions.history.replace('/'); + } + } + + this._connectedToDaemon = false; + } + async _runPrimaryApplicationFlow() { // fetch initial state and subscribe for changes try { @@ -554,30 +568,6 @@ export default class AppRenderer { } } - _onCloseConnection(error: ?Error) { - const actions = this._reduxActions; - - this._relayListCache.stopUpdating(); - - // recover connection on error - if (error) { - log.debug(`Lost connection to daemon: ${error.message}`); - - this._reconnectBackoff.attempt(() => { - this.connect(); - }); - - // only send to the connecting to daemon view if the daemon was - // connnected previously - if (this._connectedToDaemon) { - actions.history.replace('/'); - } - } else { - log.info(`Disconnected from the daemon`); - } - this._connectedToDaemon = false; - } - _setTunnelState(tunnelState: TunnelStateTransition) { log.debug(`Tunnel state: ${tunnelState.state}`); @@ -797,11 +787,3 @@ class RelayListCache { } } } - -function getIpcPath(): string { - if (process.platform === 'win32') { - return '//./pipe/Mullvad VPN'; - } else { - return '/var/run/mullvad-vpn'; - } -} diff --git a/gui/packages/desktop/src/renderer/components/Account.js b/gui/packages/desktop/src/renderer/components/Account.js index 0792e58343..8db9887993 100644 --- a/gui/packages/desktop/src/renderer/components/Account.js +++ b/gui/packages/desktop/src/renderer/components/Account.js @@ -9,7 +9,7 @@ import { Layout, Container } from './Layout'; import { NavigationBar, BackBarItem } from './NavigationBar'; import styles from './AccountStyles'; -import type { AccountToken } from '../lib/daemon-rpc'; +import type { AccountToken } from '../lib/daemon-rpc-proxy'; type Props = { accountToken: AccountToken, diff --git a/gui/packages/desktop/src/renderer/components/Connect.js b/gui/packages/desktop/src/renderer/components/Connect.js index baacce3a8b..021dbd579f 100644 --- a/gui/packages/desktop/src/renderer/components/Connect.js +++ b/gui/packages/desktop/src/renderer/components/Connect.js @@ -10,7 +10,7 @@ import * as AppButton from './AppButton'; import TunnelControl from './TunnelControl'; import Map from './Map'; import styles from './ConnectStyles'; -import { NoCreditError, NoInternetError } from '../errors'; +import { NoCreditError, NoInternetError } from '../../main/errors'; import type { RelayOutAddress, RelayInAddress } from './TunnelControl'; import type { ConnectionReduxState } from '../redux/connection/reducers'; diff --git a/gui/packages/desktop/src/renderer/components/Login.js b/gui/packages/desktop/src/renderer/components/Login.js index c89ec100d3..972b0e3f18 100644 --- a/gui/packages/desktop/src/renderer/components/Login.js +++ b/gui/packages/desktop/src/renderer/components/Login.js @@ -10,7 +10,7 @@ import styles from './LoginStyles'; import { colors } from '../../config'; import type { LoginState } from '../redux/account/reducers'; -import type { AccountToken } from '../lib/daemon-rpc'; +import type { AccountToken } from '../lib/daemon-rpc-proxy'; type Props = { accountToken: ?AccountToken, diff --git a/gui/packages/desktop/src/renderer/components/NotificationArea.js b/gui/packages/desktop/src/renderer/components/NotificationArea.js index a3d4625be8..8c99c31e26 100644 --- a/gui/packages/desktop/src/renderer/components/NotificationArea.js +++ b/gui/packages/desktop/src/renderer/components/NotificationArea.js @@ -12,7 +12,7 @@ import { } from './NotificationBanner'; import { AuthFailure } from '../lib/auth-failure'; -import type { BlockReason, TunnelStateTransition } from '../lib/daemon-rpc'; +import type { BlockReason, TunnelStateTransition } from '../lib/daemon-rpc-proxy'; import type { VersionReduxState } from '../redux/version/reducers'; type Props = { diff --git a/gui/packages/desktop/src/renderer/components/SelectLocation.js b/gui/packages/desktop/src/renderer/components/SelectLocation.js index d1933a37e5..153984529c 100644 --- a/gui/packages/desktop/src/renderer/components/SelectLocation.js +++ b/gui/packages/desktop/src/renderer/components/SelectLocation.js @@ -21,7 +21,7 @@ import type { RelayLocationCityRedux, RelayLocationRelayRedux, } from '../redux/settings/reducers'; -import type { RelayLocation } from '../lib/daemon-rpc'; +import type { RelayLocation } from '../lib/daemon-rpc-proxy'; import { colors } from '../../config'; type Props = { diff --git a/gui/packages/desktop/src/renderer/components/Support.js b/gui/packages/desktop/src/renderer/components/Support.js index 9a61fb0a1c..cdc0346fee 100644 --- a/gui/packages/desktop/src/renderer/components/Support.js +++ b/gui/packages/desktop/src/renderer/components/Support.js @@ -8,7 +8,7 @@ import { Layout, Container } from './Layout'; import { NavigationBar, BackBarItem } from './NavigationBar'; import styles from './SupportStyles'; -import type { AccountToken } from '../lib/daemon-rpc'; +import type { AccountToken } from '../lib/daemon-rpc-proxy'; import type { SupportReportForm } from '../redux/support/actions'; type SupportState = { email: string, diff --git a/gui/packages/desktop/src/renderer/components/TunnelControl.js b/gui/packages/desktop/src/renderer/components/TunnelControl.js index b8e0a45b98..c2788501fe 100644 --- a/gui/packages/desktop/src/renderer/components/TunnelControl.js +++ b/gui/packages/desktop/src/renderer/components/TunnelControl.js @@ -6,7 +6,7 @@ import { ConnectionInfo, SecuredLabel, SecuredDisplayStyle, ImageView } from '@m import * as AppButton from './AppButton'; import { colors } from '../../config'; -import type { TunnelState, RelayProtocol } from '../lib/daemon-rpc'; +import type { TunnelState, RelayProtocol } from '../lib/daemon-rpc-proxy'; export type RelayInAddress = { ip: string, diff --git a/gui/packages/desktop/src/renderer/index.js b/gui/packages/desktop/src/renderer/index.js index 39553123fc..eea0c96fc9 100644 --- a/gui/packages/desktop/src/renderer/index.js +++ b/gui/packages/desktop/src/renderer/index.js @@ -6,8 +6,6 @@ import App from './app'; const app = new App(); const view = app.renderView(); -app.connect(); - RX.App.initialize(true, true); RX.UserInterface.setMainView(view); RX.UserInterface.useCustomScrollbars(true); diff --git a/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js b/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js new file mode 100644 index 0000000000..df2c5b72b6 --- /dev/null +++ b/gui/packages/desktop/src/renderer/lib/daemon-rpc-proxy.js @@ -0,0 +1,237 @@ +// @flow + +import { ipcRenderer } from 'electron'; +import log from 'electron-log'; +import uuid from 'uuid'; + +export type { + AccountToken, + AccountData, + AppVersionInfo, + Settings, + TunnelStateTransition, + RelayList, + RelaySettingsUpdate, + RelaySettings, + RelaySettingsCustom, + RelaySettingsNormalUpdate, + RelayLocation, + RelayProtocol, + Ip, + Location, + TunnelEndpoint, + BlockReason, + AfterDisconnect, + ResponseParseError, + TunnelState, + DaemonRpcProtocol, +} from '../../main/daemon-rpc'; + +export { ConnectionObserver, SubscriptionListener } from '../../main/daemon-rpc'; + +import { + NoCreditError, + NoInternetError, + NoDaemonError, + InvalidAccountError, + CommunicationError, +} from '../../main/errors'; + +import { TimeOutError, RemoteError } from '../../main/jsonrpc-client'; + +import type { + AccountToken, + AccountData, + AppVersionInfo, + DaemonRpcProtocol, + RelaySettingsUpdate, + RelayList, + TunnelStateTransition, + Settings, + Location, +} from '../../main/daemon-rpc'; +import { ConnectionObserver, SubscriptionListener } from '../../main/daemon-rpc'; + +type ErrorInfo = { + className: string, + data: Object, +}; + +export default class DaemonRpcProxy implements DaemonRpcProtocol { + _connectionObservers: Array<ConnectionObserver> = []; + _stateListeners: Array<SubscriptionListener<TunnelStateTransition>> = []; + _settingsListeners: Array<SubscriptionListener<Settings>> = []; + + constructor() { + ipcRenderer.on('connected-daemon', () => { + for (const observer of this._connectionObservers) { + observer._onOpen(); + } + }); + + ipcRenderer.on('disconnected-daemon', (_event: Event, error: ?Error) => { + for (const observer of this._connectionObservers) { + observer._onClose(error); + } + }); + + ipcRenderer.on('state-changed', (_event: Event, newState: TunnelStateTransition) => { + for (const listener of this._stateListeners) { + listener._onEvent(newState); + } + }); + + ipcRenderer.on('settings-changed', (_event: Event, newSettings: Settings) => { + for (const listener of this._settingsListeners) { + listener._onEvent(newSettings); + } + }); + } + + connect(_connectionInfo: { path: string }): void { + throw new Error('Do not call this method.'); + } + + disconnect(): void { + throw new Error('Do not call this method.'); + } + + getAccountData(accountToken: AccountToken): Promise<AccountData> { + return this._sendMessage('getAccountData', accountToken); + } + + getRelayLocations(): Promise<RelayList> { + return this._sendMessage('getRelayLocations'); + } + + setAccount(accountToken: ?AccountToken): Promise<void> { + return this._sendMessage('setAccount', accountToken); + } + + updateRelaySettings(update: RelaySettingsUpdate): Promise<void> { + return this._sendMessage('updateRelaySettings', update); + } + + setAllowLan(allowLan: boolean): Promise<void> { + return this._sendMessage('setAllowLan', allowLan); + } + + setEnableIpv6(enableIpv6: boolean): Promise<void> { + return this._sendMessage('setEnableIpv6', enableIpv6); + } + + setOpenVpnMssfix(mssfix: ?number): Promise<void> { + return this._sendMessage('setOpenVpnMssfix', mssfix); + } + + setAutoConnect(autoConnect: boolean): Promise<void> { + return this._sendMessage('setAutoConnect', autoConnect); + } + + connectTunnel(): Promise<void> { + return this._sendMessage('connectTunnel'); + } + + disconnectTunnel(): Promise<void> { + return this._sendMessage('disconnectTunnel'); + } + + getLocation(): Promise<Location> { + return this._sendMessage('getLocation'); + } + + getState(): Promise<TunnelStateTransition> { + return this._sendMessage('getState'); + } + + getSettings(): Promise<Settings> { + return this._sendMessage('getSettings'); + } + + subscribeStateListener(listener: SubscriptionListener<TunnelStateTransition>): Promise<void> { + this._stateListeners.push(listener); + return Promise.resolve(); + } + + subscribeSettingsListener(listener: SubscriptionListener<Settings>): Promise<void> { + this._settingsListeners.push(listener); + return Promise.resolve(); + } + + addConnectionObserver(observer: ConnectionObserver): void { + this._connectionObservers.push(observer); + } + + removeConnectionObserver(observer: ConnectionObserver): void { + const index = this._connectionObservers.indexOf(observer); + if (index !== -1) { + this._connectionObservers.splice(index, 1); + } + } + + getAccountHistory(): Promise<Array<AccountToken>> { + return this._sendMessage('getAccountHistory'); + } + + removeAccountFromHistory(accountToken: AccountToken): Promise<void> { + return this._sendMessage('removeAccountFromHistory', accountToken); + } + + getCurrentVersion(): Promise<string> { + return this._sendMessage('getCurrentVersion'); + } + + getVersionInfo(): Promise<AppVersionInfo> { + return this._sendMessage('getVersionInfo'); + } + + _sendMessage<T, R>(method: string, payload: ?T): Promise<R> { + const promise: Promise<R> = new Promise((resolve, reject) => { + const id = uuid.v4(); + + ipcRenderer.once( + `daemon-rpc-reply-${id}`, + (_event: Event, result: R, errorInfo: ?ErrorInfo) => { + log.debug( + `Got daemon-rpc-reply: ${id} ${method} ${JSON.stringify(result)} ${JSON.stringify( + errorInfo, + )}`, + ); + + if (errorInfo) { + const error = this._deserializeError(errorInfo.className, errorInfo.data); + log.debug(`Deserialized an error to instance of ${error.constructor.name}`); + reject(error); + } else { + resolve(result); + } + }, + ); + + ipcRenderer.send(`daemon-rpc-call`, id, method, payload); + }); + + return promise; + } + + _deserializeError(className: string, data: Object): Error { + switch (className) { + case 'RemoteError': + return new RemoteError(data.code, data.details); + case 'TimeOutError': + return new TimeOutError(data._jsonRpcMessage); + case 'NoCreditError': + return new NoCreditError(); + case 'NoInternetError': + return new NoInternetError(); + case 'NoDaemonError': + return new NoDaemonError(); + case 'InvalidAccountError': + return new InvalidAccountError(); + case 'CommunicationError': + return new CommunicationError(); + default: + return new Error(data.message || ''); + } + } +} diff --git a/gui/packages/desktop/src/renderer/lib/notification-controller.js b/gui/packages/desktop/src/renderer/lib/notification-controller.js index cd829de90e..06118b3562 100644 --- a/gui/packages/desktop/src/renderer/lib/notification-controller.js +++ b/gui/packages/desktop/src/renderer/lib/notification-controller.js @@ -4,7 +4,7 @@ import { remote } from 'electron'; import log from 'electron-log'; import config from '../../config'; -import type { TunnelStateTransition } from './daemon-rpc'; +import type { TunnelStateTransition } from './daemon-rpc-proxy'; export default class NotificationController { _lastTunnelStateNotification: ?Notification; diff --git a/gui/packages/desktop/src/renderer/lib/relay-settings-builder.js b/gui/packages/desktop/src/renderer/lib/relay-settings-builder.js index dc865472d5..ba85fe26ed 100644 --- a/gui/packages/desktop/src/renderer/lib/relay-settings-builder.js +++ b/gui/packages/desktop/src/renderer/lib/relay-settings-builder.js @@ -6,7 +6,7 @@ import type { RelaySettingsUpdate, RelaySettingsNormalUpdate, RelaySettingsCustom, -} from './daemon-rpc'; +} from './daemon-rpc-proxy'; type LocationBuilder<Self> = { country: (country: string) => Self, diff --git a/gui/packages/desktop/src/renderer/lib/subscription-proxy/base-proxy.js b/gui/packages/desktop/src/renderer/lib/subscription-proxy/base-proxy.js index b3ebfd2595..5d34ff8839 100644 --- a/gui/packages/desktop/src/renderer/lib/subscription-proxy/base-proxy.js +++ b/gui/packages/desktop/src/renderer/lib/subscription-proxy/base-proxy.js @@ -1,8 +1,8 @@ // @flow import log from 'electron-log'; -import { ConnectionObserver, SubscriptionListener, ResponseParseError } from '../daemon-rpc'; -import type { DaemonRpcProtocol } from '../daemon-rpc'; +import { ConnectionObserver, SubscriptionListener, ResponseParseError } from '../daemon-rpc-proxy'; +import type { DaemonRpcProtocol } from '../daemon-rpc-proxy'; export default class BaseSubscriptionProxy<T> { _rpc: DaemonRpcProtocol; diff --git a/gui/packages/desktop/src/renderer/lib/subscription-proxy/settings-proxy.js b/gui/packages/desktop/src/renderer/lib/subscription-proxy/settings-proxy.js index 6dc3e7e9b7..c7fb9b3b3b 100644 --- a/gui/packages/desktop/src/renderer/lib/subscription-proxy/settings-proxy.js +++ b/gui/packages/desktop/src/renderer/lib/subscription-proxy/settings-proxy.js @@ -1,8 +1,8 @@ // @flow import BaseSubscriptionProxy from './base-proxy'; -import { SubscriptionListener } from '../daemon-rpc'; -import type { DaemonRpcProtocol, Settings } from '../daemon-rpc'; +import { SubscriptionListener } from '../daemon-rpc-proxy'; +import type { DaemonRpcProtocol, Settings } from '../daemon-rpc-proxy'; export default class SettingsProxy extends BaseSubscriptionProxy<Settings> { static subscribeValueListener(rpc: DaemonRpcProtocol, listener: SubscriptionListener<Settings>) { diff --git a/gui/packages/desktop/src/renderer/lib/subscription-proxy/tunnel-state-proxy.js b/gui/packages/desktop/src/renderer/lib/subscription-proxy/tunnel-state-proxy.js index 520885fe98..4c1afa66d6 100644 --- a/gui/packages/desktop/src/renderer/lib/subscription-proxy/tunnel-state-proxy.js +++ b/gui/packages/desktop/src/renderer/lib/subscription-proxy/tunnel-state-proxy.js @@ -1,8 +1,8 @@ // @flow import BaseSubscriptionProxy from './base-proxy'; -import { SubscriptionListener } from '../daemon-rpc'; -import type { DaemonRpcProtocol, TunnelStateTransition } from '../daemon-rpc'; +import { SubscriptionListener } from '../daemon-rpc-proxy'; +import type { DaemonRpcProtocol, TunnelStateTransition } from '../daemon-rpc-proxy'; export default class TunnelStateProxy extends BaseSubscriptionProxy<TunnelStateTransition> { static subscribeValueListener( diff --git a/gui/packages/desktop/src/renderer/redux/account/actions.js b/gui/packages/desktop/src/renderer/redux/account/actions.js index 5f336b5955..a5dfd13412 100644 --- a/gui/packages/desktop/src/renderer/redux/account/actions.js +++ b/gui/packages/desktop/src/renderer/redux/account/actions.js @@ -1,6 +1,6 @@ // @flow -import type { AccountToken } from '../../lib/daemon-rpc'; +import type { AccountToken } from '../../lib/daemon-rpc-proxy'; type StartLoginAction = { type: 'START_LOGIN', diff --git a/gui/packages/desktop/src/renderer/redux/account/reducers.js b/gui/packages/desktop/src/renderer/redux/account/reducers.js index 7263b51166..01405d0fef 100644 --- a/gui/packages/desktop/src/renderer/redux/account/reducers.js +++ b/gui/packages/desktop/src/renderer/redux/account/reducers.js @@ -1,7 +1,7 @@ // @flow import type { ReduxAction } from '../store'; -import type { AccountToken } from '../../lib/daemon-rpc'; +import type { AccountToken } from '../../lib/daemon-rpc-proxy'; export type LoginState = 'none' | 'logging in' | 'failed' | 'ok'; export type AccountReduxState = { diff --git a/gui/packages/desktop/src/renderer/redux/connection/actions.js b/gui/packages/desktop/src/renderer/redux/connection/actions.js index 6f8a297678..54ae56746a 100644 --- a/gui/packages/desktop/src/renderer/redux/connection/actions.js +++ b/gui/packages/desktop/src/renderer/redux/connection/actions.js @@ -1,6 +1,6 @@ // @flow -import type { AfterDisconnect, BlockReason, TunnelEndpoint } from '../../lib/daemon-rpc'; +import type { AfterDisconnect, BlockReason, TunnelEndpoint } from '../../lib/daemon-rpc-proxy'; type ConnectingAction = { type: 'CONNECTING', diff --git a/gui/packages/desktop/src/renderer/redux/connection/reducers.js b/gui/packages/desktop/src/renderer/redux/connection/reducers.js index 622663dc14..ab9c8df75c 100644 --- a/gui/packages/desktop/src/renderer/redux/connection/reducers.js +++ b/gui/packages/desktop/src/renderer/redux/connection/reducers.js @@ -1,7 +1,7 @@ // @flow import type { ReduxAction } from '../store'; -import type { TunnelStateTransition, Ip } from '../../lib/daemon-rpc'; +import type { TunnelStateTransition, Ip } from '../../lib/daemon-rpc-proxy'; export type ConnectionReduxState = { status: TunnelStateTransition, diff --git a/gui/packages/desktop/src/renderer/redux/settings/reducers.js b/gui/packages/desktop/src/renderer/redux/settings/reducers.js index c733475cb6..eba3341e7a 100644 --- a/gui/packages/desktop/src/renderer/redux/settings/reducers.js +++ b/gui/packages/desktop/src/renderer/redux/settings/reducers.js @@ -1,7 +1,7 @@ // @flow import type { ReduxAction } from '../store'; -import type { RelayProtocol, RelayLocation } from '../../lib/daemon-rpc'; +import type { RelayProtocol, RelayLocation } from '../../lib/daemon-rpc-proxy'; export type RelaySettingsRedux = | {| diff --git a/gui/packages/desktop/src/renderer/redux/version/actions.js b/gui/packages/desktop/src/renderer/redux/version/actions.js index 4eee3fcc61..a3e07502d4 100644 --- a/gui/packages/desktop/src/renderer/redux/version/actions.js +++ b/gui/packages/desktop/src/renderer/redux/version/actions.js @@ -1,6 +1,6 @@ // @flow -import type { AppVersionInfo } from '../../lib/daemon-rpc'; +import type { AppVersionInfo } from '../../lib/daemon-rpc-proxy'; type UpdateLatestActionPayload = { upToDate: boolean, diff --git a/gui/packages/desktop/test/account-data-cache.spec.js b/gui/packages/desktop/test/account-data-cache.spec.js index 821de1af9b..17770fac77 100644 --- a/gui/packages/desktop/test/account-data-cache.spec.js +++ b/gui/packages/desktop/test/account-data-cache.spec.js @@ -1,7 +1,7 @@ // @flow import { AccountDataCache } from '../src/renderer/app'; -import type { AccountData } from '../src/renderer/lib/daemon-rpc'; +import type { AccountData } from '../src/renderer/lib/daemon-rpc-proxy'; describe('AccountData cache', () => { const dummyAccountToken = '9876543210'; diff --git a/gui/packages/desktop/test/jsonrpc-transport.spec.js b/gui/packages/desktop/test/jsonrpc-transport.spec.js index ea07e060b8..42d6de7c23 100644 --- a/gui/packages/desktop/test/jsonrpc-transport.spec.js +++ b/gui/packages/desktop/test/jsonrpc-transport.spec.js @@ -1,10 +1,7 @@ // @flow import jsonrpc from 'jsonrpc-lite'; import { Server } from 'mock-socket'; -import JsonRpcClient, { - WebsocketTransport, - TimeOutError, -} from '../src/renderer/lib/jsonrpc-client'; +import JsonRpcClient, { WebsocketTransport, TimeOutError } from '../src/main/jsonrpc-client'; describe('JSON RPC transport', () => { const WEBSOCKET_URL = 'ws://localhost:8080'; |
