diff options
| author | Erik Larkö <erik@mullvad.net> | 2017-05-18 01:02:30 +0200 |
|---|---|---|
| committer | Erik Larkö <erik@mullvad.net> | 2017-05-19 06:05:44 +0200 |
| commit | 5d81ffed027675e143488cc9757f4303378778f7 (patch) | |
| tree | 81f82b3331e7412027a2a2047b1f06fddebbdcd5 | |
| parent | 6218d88d9cc45a49a9cd37ecdf53ddee71aaab46 (diff) | |
| download | mullvadvpn-5d81ffed027675e143488cc9757f4303378778f7.tar.xz mullvadvpn-5d81ffed027675e143488cc9757f4303378778f7.zip | |
Use a websocket as the IPC channel
| -rw-r--r-- | app/lib/backend-redux-actions.js | 3 | ||||
| -rw-r--r-- | app/lib/ipc.js | 93 | ||||
| -rw-r--r-- | app/lib/keyframe-animation.js | 2 |
3 files changed, 73 insertions, 25 deletions
diff --git a/app/lib/backend-redux-actions.js b/app/lib/backend-redux-actions.js index 66688bc4d0..66300613d2 100644 --- a/app/lib/backend-redux-actions.js +++ b/app/lib/backend-redux-actions.js @@ -2,6 +2,7 @@ import userActions from '../actions/user'; import connectActions from '../actions/connect'; import Backend from './backend'; import { LoginState, ConnectionState } from '../enums'; +import log from 'electron-log'; /** * Add event listeners to translate backend events to redux dispatch. @@ -28,7 +29,7 @@ export default function mapBackendEventsToReduxActions(backend, store) { const onConnect = (serverAddress, error) => { if (error) { - console.error('UNABLE TO CONNECT TO', serverAddress, error); + log.error('Unable to connect to', serverAddress, error); } else { store.dispatch(connectActions.connectionChange({ status: ConnectionState.connected })); } diff --git a/app/lib/ipc.js b/app/lib/ipc.js index 570abc2cec..6b548b8414 100644 --- a/app/lib/ipc.js +++ b/app/lib/ipc.js @@ -5,40 +5,87 @@ import log from 'electron-log'; export default class Ipc { constructor(connectionString) { - this.connectionString = connectionString; + this._connectionString = connectionString; + this._onConnect = []; + this._unansweredRequests = {}; + + this._reconnect(); } on(event/*, listener*/) { log.info('Adding a listener to', event); } - send(action, data) { - const id = uuid.v4(); - const jsonrpcMessage = jsonrpc.request(id, action, data); + send(action, ...data) { + return this._getWebSocket() + .then(ws => this._send(ws, action, data)) + .catch(e => { + log.error('Failed sending RPC message "' + action + '":', e); + throw e; + }); + } - return fetch(this.connectionString, { - method: 'POST', - headers: new Headers({ - 'Content-Type': 'application/json', - }), - body: JSON.stringify(jsonrpcMessage), - }).then((res) => { - if (!res.ok) { - throw {msg: 'HTTP request failed', data: res}; + _getWebSocket() { + return new Promise(resolve => { + if (this._websocket.readyState === 1) { // Connected + resolve(this._websocket); + } else { + log.debug('Waiting for websocket to connect'); + this._onConnect.push({ + resolve: () => resolve(this._websocket), + }); } + }); + } + + _send(websocket, action, data) { + return new Promise((resolve, reject) => { + const id = uuid.v4(); + const jsonrpcMessage = jsonrpc.request(id, action, data); + + this._unansweredRequests[id] = {resolve: resolve, reject: reject}; + log.debug('Sending message', id, action); + websocket.send(jsonrpcMessage); + }); + } - return res.json(); - }).then(json => { + _onMessage(message) { + const json = JSON.parse(message); + const c = jsonrpc.parseObject(json); - const c = jsonrpc.parseObject(json); - if (c.type === 'error') { - throw c.payload.error.message; + const id = c.payload.id; + const request = this._unansweredRequests[id]; + delete this._unansweredRequests[id]; + + log.debug('Got answer to', id, c.type); + if (c.type === 'error') { + request.reject(c.payload.error.message); + } else { + const reply = c.payload.result; + request.resolve(reply); + } + } + + _reconnect() { + if (!this._connectionString) return; + + log.info('Connecting to websocket', this._connectionString); + this._websocket = new WebSocket(this._connectionString); + + this._websocket.onopen = () => { + log.debug('Websocket is connected'); + while(this._onConnect.length > 0) { + this._onConnect.pop().resolve(); } - return c.payload.result; + }; - }).catch(e => { - console.error('IPC call failed', action, data, e); - throw e; - }); + this._websocket.onmessage = (evt) => { + this._onMessage(evt.data); + }; + + this._websocket.onclose = () => { + log.warn('The websocket connetion closed, attempting to reconnect it'); + this._reconnect(); + }; } } diff --git a/app/lib/keyframe-animation.js b/app/lib/keyframe-animation.js index 688d578ad4..6f253b9bfd 100644 --- a/app/lib/keyframe-animation.js +++ b/app/lib/keyframe-animation.js @@ -346,4 +346,4 @@ export default class KeyframeAnimation { return cur; } -}
\ No newline at end of file +} |
