client: socketPool should not be shared across clients

Caught this issue because of the new eviction tests. Essentially, this
change moves the socketPool into the client instance instead of a
reused variable at the module level.

When a client sends stop (or is evicted) the server will close the
websocket connection if that client is not in any other swarms (based
on peerId). However, if we are using a single socket for multiple
clients (as was the case before this commit), then other clients will
have their sockets unintentionally closed by the server.
This commit is contained in:
Feross Aboukhadijeh 2017-02-08 13:20:41 -08:00
parent 806ce1d18b
commit 3f3db7deb1
2 changed files with 13 additions and 13 deletions

View File

@ -69,6 +69,11 @@ function Client (opts) {
// See: https://github.com/feross/webtorrent-hybrid/issues/46 // See: https://github.com/feross/webtorrent-hybrid/issues/46
self._wrtc = typeof opts.wrtc === 'function' ? opts.wrtc() : opts.wrtc self._wrtc = typeof opts.wrtc === 'function' ? opts.wrtc() : opts.wrtc
// Use a socket pool, so WebSocket tracker clients share WebSocket objects for
// the same server. In practice, WebSockets are pretty slow to establish, so this
// gives a nice performance boost, and saves browser resources.
self._socketPool = {}
var announce = typeof opts.announce === 'string' var announce = typeof opts.announce === 'string'
? [ opts.announce ] ? [ opts.announce ]
: opts.announce == null ? [] : opts.announce : opts.announce == null ? [] : opts.announce

View File

@ -10,11 +10,6 @@ var Socket = require('simple-websocket')
var common = require('../common') var common = require('../common')
var Tracker = require('./tracker') var Tracker = require('./tracker')
// Use a socket pool, so tracker clients share WebSocket objects for the same server.
// In practice, WebSockets are pretty slow to establish, so this gives a nice performance
// boost, and saves browser resources.
var socketPool = {}
var RECONNECT_MINIMUM = 15 * 1000 var RECONNECT_MINIMUM = 15 * 1000
var RECONNECT_MAXIMUM = 30 * 60 * 1000 var RECONNECT_MAXIMUM = 30 * 60 * 1000
var RECONNECT_VARIANCE = 30 * 1000 var RECONNECT_VARIANCE = 30 * 1000
@ -129,15 +124,15 @@ WebSocketTracker.prototype.destroy = function (cb) {
self._onSocketDataBound = null self._onSocketDataBound = null
self._onSocketCloseBound = null self._onSocketCloseBound = null
if (socketPool[self.announceUrl]) { if (self.client._socketPool[self.announceUrl]) {
socketPool[self.announceUrl].consumers -= 1 self.client._socketPool[self.announceUrl].consumers -= 1
} }
// Other instances are using the socket, so there's nothing left to do here // Other instances are using the socket, so there's nothing left to do here
if (socketPool[self.announceUrl].consumers > 0) return cb() if (self.client._socketPool[self.announceUrl].consumers > 0) return cb()
var socket = socketPool[self.announceUrl] var socket = self.client._socketPool[self.announceUrl]
delete socketPool[self.announceUrl] delete self.client._socketPool[self.announceUrl]
socket.on('error', noop) // ignore all future errors socket.on('error', noop) // ignore all future errors
socket.once('close', cb) socket.once('close', cb)
@ -182,11 +177,11 @@ WebSocketTracker.prototype._openSocket = function () {
self._onSocketClose() self._onSocketClose()
} }
self.socket = socketPool[self.announceUrl] self.socket = self.client._socketPool[self.announceUrl]
if (self.socket) { if (self.socket) {
socketPool[self.announceUrl].consumers += 1 self.client._socketPool[self.announceUrl].consumers += 1
} else { } else {
self.socket = socketPool[self.announceUrl] = new Socket(self.announceUrl) self.socket = self.client._socketPool[self.announceUrl] = new Socket(self.announceUrl)
self.socket.consumers = 1 self.socket.consumers = 1
self.socket.once('connect', self._onSocketConnectBound) self.socket.once('connect', self._onSocketConnectBound)
} }