ws client: better offline reconnect behavior

Fixes https://github.com/feross/webtorrent/issues/318
This commit is contained in:
Feross Aboukhadijeh 2015-05-17 00:07:21 -07:00
parent f842a34f54
commit 0482c01a47

View File

@ -11,6 +11,9 @@ var Socket = require('simple-websocket')
var common = require('./common') var common = require('./common')
var RECONNECT_VARIANCE = 30 * 1000
var RECONNECT_MINIMUM = 5 * 1000
inherits(WebSocketTracker, EventEmitter) inherits(WebSocketTracker, EventEmitter)
function WebSocketTracker (client, announceUrl, opts) { function WebSocketTracker (client, announceUrl, opts) {
@ -27,18 +30,13 @@ function WebSocketTracker (client, announceUrl, opts) {
self._intervalMs = self.client._intervalMs // use client interval initially self._intervalMs = self.client._intervalMs // use client interval initially
self._interval = null self._interval = null
self._onSocketErrorBound = self._onSocketError.bind(self) self._openSocket()
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)
} }
WebSocketTracker.prototype.announce = function (opts) { WebSocketTracker.prototype.announce = function (opts) {
var self = this var self = this
if (!self._socket.connected) { 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') opts.info_hash = self.client._infoHash.toString('binary')
@ -80,15 +78,28 @@ WebSocketTracker.prototype.destroy = function () {
var self = this var self = this
if (self.destroyed) return if (self.destroyed) return
self.destroyed = true self.destroyed = true
self._socket.removeListener('error', self._onSocketErrorBound)
self._socket.removeListener('data', self._onSocketDataBound) 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 var self = this
if (self.destroyed) return self._onSocketErrorBound = self._onSocketError.bind(self)
self.client.emit('error', err) 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) { 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) { WebSocketTracker.prototype._send = function (params) {
var self = this var self = this
if (self.destroyed) return if (self.destroyed) return