diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2016-04-21 11:10:30 +0300 |
---|---|---|
committer | Feross Aboukhadijeh <feross@feross.org> | 2016-04-21 11:10:30 +0300 |
commit | 63e4aee7bd016f258d81708af9c03cf608968816 (patch) | |
tree | 9b28e5e486c8a0bcd53d18a1eed2eb57a879f2b0 /index.js | |
parent | a47d2ce4b27896a4c2e2e3820f69c712c2a0de3e (diff) |
More thorough object cleanup
- Only pass `torrent.infoHash` to the Chunk Store constructor, instead
of the `Torrent`
instance itself, to prevent accidental memory leaks of the `Torrent`
object by the
store. (Open an issue if you were using other properties. They can be
re-added.)
- Non-fatal errors with a single torrent will be emitted at
`torrent.on('error')`. You
should listen to this event. Previously, all torrent errors were also
emitted on
`client.on('error')` and handling `torrent.on('error')` was optional.
This design is
better since now it is possible to distinguish between fatal client
errors
(`client.on('error')`) when the whole client becomes unusable versus
recoverable errors
where only a single torrent fails (`torrent.on('error')`) but the
client can continue to
be used. However, if there is no `torrent.on('error')` event, then
the error will be
forwarded to `client.on('error')`. This prevents crashing the client
when the user
only has a listener on the client, but it makes it impossible for
them to determine
a client error versus a torrent error.
- Errors creating a torrent with `client.seed` are now emitted on the
returned `torrent`
object instead of the client (unless there is no event listeners on
`torrent.on('error')` as previously discussed). The torrent object is
now also destroyed
automatically for the user, as was probably expected.
- If `client.get` is passed a `Torrent` instance, it now only returns
it if it is present
in the client.
Diffstat (limited to 'index.js')
-rw-r--r-- | index.js | 48 |
1 files changed, 32 insertions, 16 deletions
@@ -93,8 +93,7 @@ function WebTorrent (opts) { // use a single DHT instance for all torrents, so the routing table can be reused self.dht = new DHT(extend({ nodeId: self.nodeId }, opts.dht)) self.dht.once('error', function (err) { - self.emit('error', err) - self._destroy() + self._destroy(err) }) // Ignore warning when there are > 10 torrents in the client @@ -171,17 +170,25 @@ Object.defineProperty(WebTorrent.prototype, 'ratio', { */ WebTorrent.prototype.get = function (torrentId) { var self = this - if (torrentId instanceof Torrent) return torrentId + var i, torrent + var len = self.torrents.length - var parsed - try { parsed = parseTorrent(torrentId) } catch (err) {} + if (torrentId instanceof Torrent) { + for (i = 0; i < len; i++) { + torrent = self.torrents[i] + if (torrent === torrentId) return torrent + } + } else { + var parsed + try { parsed = parseTorrent(torrentId) } catch (err) {} - if (!parsed) return null - if (!parsed.infoHash) throw new Error('Invalid torrent identifier') + if (!parsed) return null + if (!parsed.infoHash) throw new Error('Invalid torrent identifier') - for (var i = 0, len = self.torrents.length; i < len; i++) { - var torrent = self.torrents[i] - if (torrent.infoHash === parsed.infoHash) return torrent + for (i = 0; i < len; i++) { + torrent = self.torrents[i] + if (torrent.infoHash === parsed.infoHash) return torrent + } } return null } @@ -209,6 +216,7 @@ WebTorrent.prototype.add = function (torrentId, opts, ontorrent) { self.torrents.push(torrent) torrent.once('infoHash', function () { + if (self.destroyed) return for (var i = 0, len = self.torrents.length; i < len; i++) { var t = self.torrents[i] if (t.infoHash === torrent.infoHash && t !== torrent) { @@ -257,20 +265,20 @@ WebTorrent.prototype.seed = function (input, opts, onseed) { else cb(null, item) } }), function (err, input) { - if (err) return self.emit('error', err, torrent) + if (err) return torrent._destroy(err) if (self.destroyed) return createTorrent.parseInput(input, opts, function (err, files) { - if (err) return self.emit('error', err, torrent) + if (err) return torrent._destroy(err) if (self.destroyed) return streams = files.map(function (file) { return file.getStream }) createTorrent(input, opts, function (err, torrentBuf) { - if (err) return self.emit('error', err, torrent) + if (err) return torrent._destroy(err) if (self.destroyed) return var existingTorrent = self.get(torrentBuf) if (existingTorrent) { - torrent.destroy() + torrent._destroy(new Error('Cannot add duplicate torrent ' + torrent.infoHash)) _onseed(existingTorrent) } else { torrent._onTorrentId(torrentBuf) @@ -292,7 +300,7 @@ WebTorrent.prototype.seed = function (input, opts, onseed) { } parallel(tasks, function (err) { if (self.destroyed) return - if (err) return self.emit('error', err, torrent) + if (err) return torrent._destroy(err) _onseed(torrent) }) } @@ -313,10 +321,14 @@ WebTorrent.prototype.seed = function (input, opts, onseed) { */ WebTorrent.prototype.remove = function (torrentId, cb) { debug('remove') - var torrent = this.get(torrentId) if (!torrent) throw new Error('No torrent with id ' + torrentId) + this._remove(torrentId, cb) +} +WebTorrent.prototype._remove = function (torrentId, cb) { + var torrent = this.get(torrentId) + if (!torrent) return this.torrents.splice(this.torrents.indexOf(torrent), 1) torrent.destroy(cb) } @@ -363,6 +375,10 @@ WebTorrent.prototype._destroy = function (err, cb) { parallel(tasks, cb) if (err) self.emit('error', err) + + self.torrents = [] + self._tcpPool = null + self.dht = null } WebTorrent.prototype._onListening = function () { |