From 0482c01a47b823a5d95e83e6917add7b764762f3 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Sun, 17 May 2015 00:07:21 -0700 Subject: [PATCH] ws client: better offline reconnect behavior Fixes https://github.com/feross/webtorrent/issues/318 --- lib/websocket-tracker.js | 51 ++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/lib/websocket-tracker.js b/lib/websocket-tracker.js index 9b5d176..bb1bc38 100644 --- a/lib/websocket-tracker.js +++ b/lib/websocket-tracker.js @@ -11,6 +11,9 @@ var Socket = require('simple-websocket') var common = require('./common') +var RECONNECT_VARIANCE = 30 * 1000 +var RECONNECT_MINIMUM = 5 * 1000 + inherits(WebSocketTracker, EventEmitter) function WebSocketTracker (client, announceUrl, opts) { @@ -27,18 +30,13 @@ function WebSocketTracker (client, announceUrl, opts) { self._intervalMs = self.client._intervalMs // use client interval initially self._interval = null - self._onSocketErrorBound = self._onSocketError.bind(self) - self._onSocketDataBound = self._onSocketData.bind(self) - - self._socket = new Socket(announceUrl + '?' + hat(40)) - self._socket.on('error', self._onSocketErrorBound) - self._socket.on('data', self._onSocketDataBound) + self._openSocket() } WebSocketTracker.prototype.announce = function (opts) { var self = this if (!self._socket.connected) { - return self._socket.on('connect', self.announce.bind(self, opts)) + return self._socket.once('connect', self.announce.bind(self, opts)) } opts.info_hash = self.client._infoHash.toString('binary') @@ -80,15 +78,28 @@ WebSocketTracker.prototype.destroy = function () { var self = this if (self.destroyed) return self.destroyed = true - self._socket.removeListener('error', self._onSocketErrorBound) + self._socket.removeListener('data', self._onSocketDataBound) - self._socket.close() + self._socket.removeListener('close', self._onSocketCloseBound) + self._socket.removeListener('error', self._onSocketErrorBound) + self._onSocketErrorBound = null + self._onSocketDataBound = null + self._onSocketCloseBound = null + + try { self._socket.close() } catch (e) {} + self._socket = null } -WebSocketTracker.prototype._onSocketError = function (err) { +WebSocketTracker.prototype._openSocket = function () { var self = this - if (self.destroyed) return - self.client.emit('error', err) + self._onSocketErrorBound = self._onSocketError.bind(self) + self._onSocketDataBound = self._onSocketData.bind(self) + self._onSocketCloseBound = self._onSocketClose.bind(self) + + self._socket = new Socket(self._announceUrl + '?' + hat(40)) + self._socket.on('data', self._onSocketDataBound) + self._socket.on('close', self._onSocketCloseBound) + self._socket.on('error', self._onSocketErrorBound) } WebSocketTracker.prototype._onSocketData = function (data) { @@ -167,6 +178,22 @@ WebSocketTracker.prototype._onSocketData = function (data) { } } +WebSocketTracker.prototype._onSocketClose = function () { + var self = this + self.destroy() + var ms = Math.floor(Math.random() * RECONNECT_VARIANCE) + RECONNECT_MINIMUM + setTimeout(function () { + self._openSocket() + }, ms) + debug('reconnecting socket in %s ms', ms) +} + +WebSocketTracker.prototype._onSocketError = function (err) { + var self = this + if (self.destroyed) return + self.client.emit('error', err) +} + WebSocketTracker.prototype._send = function (params) { var self = this if (self.destroyed) return