diff options
| author | Erik Larkö <erik@mullvad.net> | 2017-05-19 07:10:07 +0200 |
|---|---|---|
| committer | Erik Larkö <erik@mullvad.net> | 2017-05-19 07:10:07 +0200 |
| commit | 9e2e6c728f6b1bcdfc171772300ff3b787db2aed (patch) | |
| tree | 3965d54e89441768c4deb87f059e7d8e462f1343 /app/lib/ipc.js | |
| parent | 6218d88d9cc45a49a9cd37ecdf53ddee71aaab46 (diff) | |
| parent | 57e718385501b4a42a29633889ba6740b5ce5064 (diff) | |
| download | mullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.tar.xz mullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.zip | |
Merge branch 'new-backend-api'
Diffstat (limited to 'app/lib/ipc.js')
| -rw-r--r-- | app/lib/ipc.js | 93 |
1 files changed, 70 insertions, 23 deletions
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(); + }; } } |
