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 | |
| parent | 6218d88d9cc45a49a9cd37ecdf53ddee71aaab46 (diff) | |
| parent | 57e718385501b4a42a29633889ba6740b5ce5064 (diff) | |
| download | mullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.tar.xz mullvadvpn-9e2e6c728f6b1bcdfc171772300ff3b787db2aed.zip | |
Merge branch 'new-backend-api'
Diffstat (limited to 'app')
| -rw-r--r-- | app/lib/backend-redux-actions.js | 3 | ||||
| -rw-r--r-- | app/lib/backend.js | 75 | ||||
| -rw-r--r-- | app/lib/ipc.js | 93 | ||||
| -rw-r--r-- | app/lib/keyframe-animation.js | 2 |
4 files changed, 103 insertions, 70 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/backend.js b/app/lib/backend.js index 38adc6cf14..cfd6596bdb 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -1,4 +1,3 @@ -import moment from 'moment'; import log from 'electron-log'; import Enum from './enum'; import { EventEmitter } from 'events'; @@ -180,26 +179,13 @@ export default class Backend extends EventEmitter { this._registerIpcListeners(); } - /** - * Tells whether account has credits - * - * @type {bool} - * @readonly - * - * @memberOf Backend - */ - get hasCredits() { - return this._paidUntil !== null && - moment(this._paidUntil).isAfter(moment()); - } - sync() { log.info('Syncing with the backend...'); - this._ipc.send('get_connection') - .then( connectionInfo => { - log.info('Got connection info', connectionInfo); - this.emit(Backend.EventType.updatedIp, connectionInfo.ip); + this._ipc.send('get_ip') + .then( ip => { + log.info('Got ip', ip); + this.emit(Backend.EventType.updatedIp, ip); }) .catch(e => { log.info('Failed syncing with the backend', e); @@ -282,22 +268,30 @@ export default class Backend extends EventEmitter { */ login(account) { log.info('Attempting to login with account number', account); - this._paidUntil = null; // emit: logging in this.emit(Backend.EventType.logging, { account }, null); - this._ipc.send('login', { - accountNumber: account, - }).then(response => { - log.info('Successfully logged in', response); - this._paidUntil = response.paidUntil; - this.emit(Backend.EventType.login, response, undefined); - }).catch(e => { - console.warn('Failed to log in', e); - const err = new BackendError(Backend.ErrorType.invalidAccount); - this.emit(Backend.EventType.login, {}, err); - }); + + + this._ipc.send('get_account_data', account) + .then(response => { + log.info('Account exists', response); + + return this._ipc.send('set_account', account) + .then(() => response ); + }).then( accountData => { + log.info('Log in complete'); + + this.emit(Backend.EventType.login, { + paidUntil: accountData.paid_until, + }, undefined); + + }).catch(e => { + log.error('Failed to log in', e); + const err = new BackendError(Backend.ErrorType.invalidAccount); + this.emit(Backend.EventType.login, {}, err); + }); } /** @@ -308,15 +302,13 @@ export default class Backend extends EventEmitter { */ logout() { // @TODO: What does it mean for a logout to be successful or failed? - this._ipc.send('logout') + this._ipc.send('set_account', '') .then(() => { - this._paidUntil = null; - // emit event this.emit(Backend.EventType.logout); // disconnect user during logout - this.disconnect(); + return this.disconnect(); }) .catch(e => { log.info('Failed to logout', e); @@ -333,15 +325,14 @@ export default class Backend extends EventEmitter { * @memberOf Backend */ connect(addr) { - // do not attempt to connect when no credits available - if(!this.hasCredits) { - return; - } // emit: connecting this.emit(Backend.EventType.connecting, addr); - this._ipc.send('connect', { address: addr }) + this._ipc.send('set_country', addr) + .then( () => { + return this._ipc.send('connect'); + }) .then(() => { this.emit(Backend.EventType.connect, addr); this.sync(); // TODO: This is a pooooooor way of updating the location and the IP and stuff @@ -360,12 +351,6 @@ export default class Backend extends EventEmitter { */ disconnect() { // @TODO: Failure modes - this._ipc.send('cancelConnection') - .catch(e => { - log.info('Failed cancelling connection', e); - }); - - // @TODO: Failure modes this._ipc.send('disconnect') .then(() => { // emit: disconnect 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 +} |
