diff --git a/www/js/callbacks.js b/www/js/callbacks.js index d9c60199..9ab90a54 100644 --- a/www/js/callbacks.js +++ b/www/js/callbacks.js @@ -1296,7 +1296,7 @@ function checkLetsEncrypt(socketConfig, nonLetsEncryptError) { } function initWS() { - window.socket = new WSShim(new WebSocket('ws://localhost:3000/')); + window.socket = new WSShim('ws://localhost:3000/'); setupCallbacks(); } diff --git a/www/js/util.js b/www/js/util.js index 5f2ed1bb..f5c59d95 100644 --- a/www/js/util.js +++ b/www/js/util.js @@ -3304,13 +3304,13 @@ function maybePromptToUpgradeUserscript() { function backoffRetry(fn, cb, options) { var jitter = options.jitter || 0; var factor = options.factor || 1; + var currentFactor = factor; var isRetryable = options.isRetryable || function () { return true; }; var maxDelay = options.maxDelay || Infinity; var tries = 0; function callback(error, result) { tries++; - factor *= factor; if (error) { if (tries >= options.maxTries) { console.log('Max tries exceeded'); @@ -3318,7 +3318,7 @@ function backoffRetry(fn, cb, options) { } else if (isRetryable(error)) { var offset = Math.random() * jitter; var delay = Math.min( - options.delay * factor, + options.delay * currentFactor, maxDelay ) + offset; console.log('Retrying on error: ' + error); @@ -3331,6 +3331,8 @@ function backoffRetry(fn, cb, options) { } else { cb(error, result); } + + currentFactor *= factor; } fn(callback); diff --git a/www/js/ws.js b/www/js/ws.js index e51a3437..2adf1efc 100644 --- a/www/js/ws.js +++ b/www/js/ws.js @@ -2,17 +2,15 @@ var TYPE_FRAME = 0; var TYPE_ACK = 1; - function WSShim(ws) { - this._ws = ws; + function WSShim(url) { + this._url = url; this._listeners = Object.create(null); this._connected = false; - this._ws.onopen = this._onopen.bind(this); - this._ws.onclose = this._onclose.bind(this); - this._ws.onmessage = this._onmessage.bind(this); - this._ackId = 0; this._pendingAcks = Object.create(null); + + this._openWS(); } WSShim.prototype.listeners = function listeners(frame) { @@ -78,17 +76,23 @@ return; } + this._connected = false; this._emit('disconnect'); + // TODO: checking for KICKED here is insufficient; + // need to have some sort of explicit disconnect vs. connection loss + // check if (!KICKED) { - function reconnectAsync(cb) { - initWS(); + var self = this; - window.socket._ws.addEventListener('open', function () { + function reconnectAsync(cb) { + self._openWS(); + + self._ws.addEventListener('open', function () { cb(null); }); - window.socket._ws.addEventListener('error', function (error) { + self._ws.addEventListener('error', function (error) { cb(error); }); } @@ -128,5 +132,17 @@ } }; + WSShim.prototype._openWS = function _openWS() { + if (this._connected) { + throw new Error('Cannot _openWS() when already connected'); + } + + this._ws = new WebSocket(this._url); + this._ws.onopen = this._onopen.bind(this); + this._ws.onclose = this._onclose.bind(this); + this._ws.onmessage = this._onmessage.bind(this); + this._connected = false; + }; + window.WSShim = WSShim; })();