summaryrefslogtreecommitdiffhomepage
path: root/app/lib/ipc.js
diff options
context:
space:
mode:
authorErik Larkö <erik@mullvad.net>2017-05-19 07:10:07 +0200
committerErik Larkö <erik@mullvad.net>2017-05-19 07:10:07 +0200
commit9e2e6c728f6b1bcdfc171772300ff3b787db2aed (patch)
tree3965d54e89441768c4deb87f059e7d8e462f1343 /app/lib/ipc.js
parent6218d88d9cc45a49a9cd37ecdf53ddee71aaab46 (diff)
parent57e718385501b4a42a29633889ba6740b5ce5064 (diff)
downloadmullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.tar.xz
mullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.zip
Merge branch 'new-backend-api'
Diffstat (limited to 'app/lib/ipc.js')
-rw-r--r--app/lib/ipc.js93
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();
+ };
}
}