mirror of
https://github.com/webtorrent/bittorrent-tracker.git
synced 2025-01-31 18:41:36 +00:00
client: Re-use WebSocket connections
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.
This commit is contained in:
parent
340b3faff2
commit
ac2c3d06d8
@ -11,6 +11,11 @@ var Socket = require('simple-websocket')
|
|||||||
|
|
||||||
var common = require('./common')
|
var common = require('./common')
|
||||||
|
|
||||||
|
// 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_VARIANCE = 30 * 1000
|
var RECONNECT_VARIANCE = 30 * 1000
|
||||||
var RECONNECT_MINIMUM = 5 * 1000
|
var RECONNECT_MINIMUM = 5 * 1000
|
||||||
|
|
||||||
@ -26,9 +31,10 @@ function WebSocketTracker (client, announceUrl, opts) {
|
|||||||
|
|
||||||
self._opts = opts
|
self._opts = opts
|
||||||
|
|
||||||
|
if (announceUrl[announceUrl.length - 1] === '/') {
|
||||||
|
announceUrl = announceUrl.substring(0, announceUrl.length - 1)
|
||||||
|
}
|
||||||
self._announceUrl = announceUrl
|
self._announceUrl = announceUrl
|
||||||
if (self._announceUrl[self._announceUrl.length - 1] !== '/') self._announceUrl += '/'
|
|
||||||
self._announceUrl += '?' + hat(40)
|
|
||||||
|
|
||||||
self._peers = {} // peers (offer id -> peer)
|
self._peers = {} // peers (offer id -> peer)
|
||||||
self._socket = null
|
self._socket = null
|
||||||
@ -102,7 +108,11 @@ WebSocketTracker.prototype._openSocket = function () {
|
|||||||
self._onSocketDataBound = self._onSocketData.bind(self)
|
self._onSocketDataBound = self._onSocketData.bind(self)
|
||||||
self._onSocketCloseBound = self._onSocketClose.bind(self)
|
self._onSocketCloseBound = self._onSocketClose.bind(self)
|
||||||
|
|
||||||
self._socket = new Socket(self._announceUrl)
|
self._socket = socketPool[self._announceUrl]
|
||||||
|
if (!self._socket) {
|
||||||
|
self._socket = socketPool[self._announceUrl] = new Socket(self._announceUrl)
|
||||||
|
}
|
||||||
|
|
||||||
self._socket.on('data', self._onSocketDataBound)
|
self._socket.on('data', self._onSocketDataBound)
|
||||||
self._socket.on('close', self._onSocketCloseBound)
|
self._socket.on('close', self._onSocketCloseBound)
|
||||||
self._socket.on('error', self._onSocketErrorBound)
|
self._socket.on('error', self._onSocketErrorBound)
|
||||||
@ -117,10 +127,22 @@ WebSocketTracker.prototype._onSocketData = function (data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (data.info_hash !== self.client._infoHashBinary) {
|
if (data.info_hash !== self.client._infoHashBinary) {
|
||||||
return self.client.emit('warning', new Error('Invalid tracker response'))
|
debug(
|
||||||
|
'ignoring websocket data from %s for %s (looking for %s: reused socket)',
|
||||||
|
self._announceUrl, common.binaryToHex(data.info_hash), self.client._infoHashHex
|
||||||
|
)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
debug('received %s from %s', JSON.stringify(data), self._announceUrl)
|
if (data.peer_id && data.peer_id === self.client._peerIdBinary) {
|
||||||
|
// ignore offers/answers from this client
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(
|
||||||
|
'received %s from %s for %s',
|
||||||
|
JSON.stringify(data), self._announceUrl, self.client._infoHashHex
|
||||||
|
)
|
||||||
|
|
||||||
var failure = data['failure reason']
|
var failure = data['failure reason']
|
||||||
if (failure) return self.client.emit('warning', new Error(failure))
|
if (failure) return self.client.emit('warning', new Error(failure))
|
||||||
@ -149,13 +171,8 @@ WebSocketTracker.prototype._onSocketData = function (data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.client._peerIdHex === common.binaryToHex(data.peer_id)) {
|
|
||||||
// ignore offers/answers from this client
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var peer
|
var peer
|
||||||
if (data.offer) {
|
if (data.offer && data.peer_id) {
|
||||||
peer = new Peer({
|
peer = new Peer({
|
||||||
trickle: false,
|
trickle: false,
|
||||||
config: self.client._rtcConfig,
|
config: self.client._rtcConfig,
|
||||||
@ -177,7 +194,7 @@ WebSocketTracker.prototype._onSocketData = function (data) {
|
|||||||
self.client.emit('peer', peer)
|
self.client.emit('peer', peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.answer) {
|
if (data.answer && data.peer_id) {
|
||||||
peer = self._peers[common.binaryToHex(data.offer_id)]
|
peer = self._peers[common.binaryToHex(data.offer_id)]
|
||||||
if (peer) {
|
if (peer) {
|
||||||
peer.id = common.binaryToHex(data.peer_id)
|
peer.id = common.binaryToHex(data.peer_id)
|
||||||
@ -191,18 +208,28 @@ WebSocketTracker.prototype._onSocketData = function (data) {
|
|||||||
|
|
||||||
WebSocketTracker.prototype._onSocketClose = function () {
|
WebSocketTracker.prototype._onSocketClose = function () {
|
||||||
var self = this
|
var self = this
|
||||||
|
if (self.destroyed) return
|
||||||
self.destroy()
|
self.destroy()
|
||||||
var ms = Math.floor(Math.random() * RECONNECT_VARIANCE) + RECONNECT_MINIMUM
|
self._startReconnectTimer()
|
||||||
setTimeout(function () {
|
|
||||||
self._openSocket()
|
|
||||||
}, ms)
|
|
||||||
debug('reconnecting socket in %s ms', ms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketTracker.prototype._onSocketError = function (err) {
|
WebSocketTracker.prototype._onSocketError = function (err) {
|
||||||
var self = this
|
var self = this
|
||||||
if (self.destroyed) return
|
if (self.destroyed) return
|
||||||
self.client.emit('error', err)
|
self.destroy()
|
||||||
|
// errors will often happen if a tracker is offline, so don't treat it as fatal
|
||||||
|
self.client.emit('warning', err)
|
||||||
|
self._startReconnectTimer()
|
||||||
|
}
|
||||||
|
|
||||||
|
WebSocketTracker.prototype._startReconnectTimer = function () {
|
||||||
|
var self = this
|
||||||
|
var ms = Math.floor(Math.random() * RECONNECT_VARIANCE) + RECONNECT_MINIMUM
|
||||||
|
setTimeout(function () {
|
||||||
|
self.destroyed = false
|
||||||
|
self._openSocket()
|
||||||
|
}, ms)
|
||||||
|
debug('reconnecting socket in %s ms', ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketTracker.prototype._send = function (params) {
|
WebSocketTracker.prototype._send = function (params) {
|
||||||
|
Loading…
Reference in New Issue
Block a user