diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2016-04-21 10:17:59 +0300 |
---|---|---|
committer | Feross Aboukhadijeh <feross@feross.org> | 2016-04-21 10:17:59 +0300 |
commit | a47d2ce4b27896a4c2e2e3820f69c712c2a0de3e (patch) | |
tree | 8ed140199cacd628c1e656dddcd5e9f81afa68d4 /lib | |
parent | 891e7e3fc2a0780cab9fdf64f699e713207b9604 (diff) |
cleanup torrent reference leaks
Diffstat (limited to 'lib')
-rw-r--r-- | lib/server.js | 38 | ||||
-rw-r--r-- | lib/webconn.js | 40 |
2 files changed, 50 insertions, 28 deletions
diff --git a/lib/server.js b/lib/server.js index 27a645e..cfa883f 100644 --- a/lib/server.js +++ b/lib/server.js @@ -12,19 +12,22 @@ function Server (torrent, opts) { var server = http.createServer(opts) var sockets = [] + var pendingReady = [] var closed = false - server.on('connection', function (socket) { - socket.setTimeout(36000000) - sockets.push(socket) - socket.on('close', function () { - arrayRemove(sockets, sockets.indexOf(socket)) - }) - }) + server.on('connection', onConnection) + server.on('request', onRequest) var _close = server.close server.close = function (cb) { closed = true + torrent = null + server.removeListener('connection', onConnection) + server.removeListener('request', onRequest) + while (pendingReady.length) { + var onReady = pendingReady.pop() + torrent.removeListener('ready', onReady) + } _close.call(server, cb) } @@ -38,7 +41,15 @@ function Server (torrent, opts) { else server.close(cb) } - server.on('request', function (req, res) { + function onConnection (socket) { + socket.setTimeout(36000000) + sockets.push(socket) + socket.once('close', function () { + arrayRemove(sockets, sockets.indexOf(socket)) + }) + } + + function onRequest (req, res) { debug('onRequest') // Allow CORS requests to specify arbitrary headers, e.g. 'Range', @@ -61,10 +72,15 @@ function Server (torrent, opts) { var pathname = url.parse(req.url).pathname if (pathname === '/favicon.ico') return res.end() - if (torrent.ready) onReady() - else torrent.once('ready', onReady) + if (torrent.ready) { + onReady() + } else { + pendingReady.push(onReady) + torrent.once('ready', onReady) + } function onReady () { + arrayRemove(pendingReady, pendingReady.indexOf(onReady)) if (pathname === '/') { res.setHeader('Content-Type', 'text/html') var listHtml = torrent.files.map(function (file, i) { @@ -112,7 +128,7 @@ function Server (torrent, opts) { if (req.method === 'HEAD') res.end() pump(file.createReadStream(range), res) } - }) + } return server } diff --git a/lib/webconn.js b/lib/webconn.js index e3e3a27..a45ca68 100644 --- a/lib/webconn.js +++ b/lib/webconn.js @@ -1,6 +1,3 @@ -// TODO: cleanup events -// TODO: cleanup reference to parsedTorrent (i.e. Torrent object) - module.exports = WebConn var BitField = require('bitfield') @@ -15,21 +12,26 @@ inherits(WebConn, Wire) /** * Converts requests for torrent blocks into http range requests. * @param {string} url web seed url - * @param {Object} parsedTorrent + * @param {Object} torrent */ -function WebConn (url, parsedTorrent) { - var self = this +function WebConn (url, torrent) { Wire.call(this) - self.url = url - self.webPeerId = sha1.sync(url) - self.parsedTorrent = parsedTorrent + this.url = url + this.webPeerId = sha1.sync(url) + this._torrent = torrent + + this._init() +} +WebConn.prototype._init = function () { + var self = this self.setKeepAlive(true) - self.on('handshake', function (infoHash, peerId) { + self.once('handshake', function (infoHash, peerId) { + if (self.destroyed) return self.handshake(infoHash, self.webPeerId) - var numPieces = self.parsedTorrent.pieces.length + var numPieces = self._torrent.pieces.length var bitfield = new BitField(numPieces) for (var i = 0; i <= numPieces; i++) { bitfield.set(i, true) @@ -37,15 +39,14 @@ function WebConn (url, parsedTorrent) { self.bitfield(bitfield) }) - self.on('choke', function () { debug('choke') }) - self.on('unchoke', function () { debug('unchoke') }) - self.once('interested', function () { debug('interested') self.unchoke() }) - self.on('uninterested', function () { debug('uninterested') }) + self.on('uninterested', function () { debug('uninterested') }) + self.on('choke', function () { debug('choke') }) + self.on('unchoke', function () { debug('unchoke') }) self.on('bitfield', function () { debug('bitfield') }) self.on('request', function (pieceIndex, offset, length, callback) { @@ -56,14 +57,14 @@ function WebConn (url, parsedTorrent) { WebConn.prototype.httpRequest = function (pieceIndex, offset, length, cb) { var self = this - var pieceOffset = pieceIndex * self.parsedTorrent.pieceLength + var pieceOffset = pieceIndex * self._torrent.pieceLength var rangeStart = pieceOffset + offset /* offset within whole torrent */ var rangeEnd = rangeStart + length - 1 // Web seed URL format: // For single-file torrents, make HTTP range requests directly to the web seed URL // For multi-file torrents, add the torrent folder and file name to the URL - var files = self.parsedTorrent.files + var files = self._torrent.files var requests if (files.length <= 1) { requests = [{ @@ -138,3 +139,8 @@ WebConn.prototype.httpRequest = function (pieceIndex, offset, length, cb) { }) }) } + +WebConn.prototype.destroy = function () { + Wire.prototype.destroy.call(this) + this._torrent = null +} |