diff --git a/src/js/ripple/remote.js b/src/js/ripple/remote.js index 645c5da6..d6cf93e1 100644 --- a/src/js/ripple/remote.js +++ b/src/js/ripple/remote.js @@ -83,6 +83,7 @@ function Remote(opts, trace) { this.trusted = Boolean(opts.trusted); this.state = 'offline'; // 'online', 'offline' this._server_fatal = false; // True, if we know server exited. + this._allow_partial_history = (typeof opts.allow_partial_history === 'boolean') ? opts.allow_partial_history : true; this.local_sequence = Boolean(opts.local_sequence); // Locally track sequence numbers this.local_fee = (typeof opts.local_fee === 'boolean') ? opts.local_fee : true;// Locally set fees diff --git a/src/js/ripple/server.js b/src/js/ripple/server.js index 3425349f..d7622562 100644 --- a/src/js/ripple/server.js +++ b/src/js/ripple/server.js @@ -76,7 +76,6 @@ function Server(remote, opts) { this._lastLedgerClose = NaN; this._score = 0; - this._scoreWeights = { ledgerclose: 5, response: 1 @@ -354,7 +353,7 @@ Server.prototype.reconnect = function() { if (this.isConnected()) { this.once('disconnect', reconnect); this.disconnect(); - } else { + } else { reconnect(); } } @@ -627,6 +626,12 @@ Server.prototype._handlePathFind = function(message) { */ Server.prototype._handleResponseSubscribe = function(message) { + if (!this._remote._allow_partial_history + && !Server.hasFullLedgerHistory(message)) { + // Server has partial history and Remote has been configured to disallow + // servers with incomplete history + return this.reconnect(); + } if (Server.isLoadStatus(message)) { this._load_base = message.load_base || 256; this._load_factor = message.load_factor || 256; @@ -643,10 +648,25 @@ Server.prototype._handleResponseSubscribe = function(message) { } }; +/** + * Check that server message indicates that server has complete ledger history + * + * @param {Object} message + * @return {Boolean} + */ + +Server.hasFullLedgerHistory = function(message) { + return (typeof message === 'object') + && (message.server_status === 'full') + && (typeof message.validated_ledgers === 'string') + && (message.validated_ledgers.split('-').length === 2); +}; + /** * Check that received message from rippled is valid * - * @api private + * @param {Object} message + * @return {Boolean} */ Server.isValidMessage = function(message) { @@ -655,14 +675,15 @@ Server.isValidMessage = function(message) { }; /** - * Check that received serverStatus message contains - * load status information + * Check that received serverStatus message contains load status information * - * @api private + * @param {Object} message + * @return {Boolean} */ Server.isLoadStatus = function(message) { - return (typeof message.load_base === 'number') + return (typeof message === 'object') + && (typeof message.load_base === 'number') && (typeof message.load_factor === 'number'); }; @@ -683,10 +704,10 @@ Server.prototype._sendMessage = function(message) { }; /** - * Submit a Request object. + * Submit a Request object * - * Requests are indexed by message ID, which is repeated - * in the response from rippled WebSocket server + * Requests are indexed by message ID, which is repeated in the response from + * rippled WebSocket server * * @param {Request} request * @api private diff --git a/test/server-test.js b/test/server-test.js index e0b2fc68..c27fc4fc 100644 --- a/test/server-test.js +++ b/test/server-test.js @@ -478,6 +478,58 @@ describe('Server', function() { Server.websocketConstructor = websocketConstructor; }); + it('Connect - partial history disabled', function(done) { + var wss = new ws.Server({ port: 5748 }); + + wss.once('connection', function(ws) { + ws.once('message', function(message) { + var m = JSON.parse(message); + + assert.deepEqual(m, { + command: 'subscribe', + id: 0, + streams: [ 'ledger', 'server' ] + }); + + ws.send(JSON.stringify({ + id: 0, + status: 'success', + type: 'response', + result: { + fee_base: 10, + fee_ref: 10, + ledger_hash: '1838539EE12463C36F2C53B079D807C697E3D93A1936B717E565A4A912E11776', + ledger_index: 7053695, + ledger_time: 455414390, + load_base: 256, + load_factor: 256, + random: 'E56C9154D9BE94D49C581179356C2E084E16D18D74E8B09093F2D61207625E6A', + reserve_base: 20000000, + reserve_inc: 5000000, + server_status: 'syncing', + validated_ledgers: '3175520-3176615' + } + })); + + wss.close(); + }); + }); + + var server = new Server(new Remote({ allow_partial_history: false }), 'ws://localhost:5748'); + + server.reconnect = function() { + setImmediate(function() { + done(); + }); + }; + + server.once('connect', function() { + assert(false, 'Should not connect'); + }); + + server.connect(); + }); + it('Reconnect', function(done) { var server = new Server(new Remote(), 'ws://localhost:5748'); server._connected = true;