diff options
author | Feross Aboukhadijeh <feross@feross.org> | 2016-05-19 09:01:52 +0300 |
---|---|---|
committer | Feross Aboukhadijeh <feross@feross.org> | 2016-05-19 09:01:52 +0300 |
commit | e8dea8e588045b43c7a5d4931cde692fd135a21d (patch) | |
tree | 4788e98a58dd23bb5e0e5a84fdddd48beae95fc9 | |
parent | 389402479e9d9b2f5343f3eed6d3f5eb111666df (diff) |
Fixes for PR #799
- Support multiple &xs= params in parallel
- Fail on 'error' 'warning' events
-rw-r--r-- | lib/torrent.js | 130 | ||||
-rw-r--r-- | test/node/download-metadata.js | 19 |
2 files changed, 101 insertions, 48 deletions
diff --git a/lib/torrent.js b/lib/torrent.js index 431e2ee..33eecc3 100644 --- a/lib/torrent.js +++ b/lib/torrent.js @@ -114,7 +114,7 @@ function Torrent (torrentId, client, opts) { // for cleanup this._servers = [] - this._xsRequest = null + this._xsRequests = [] // TODO: remove this and expose a hook instead // optimization: don't recheck every file if it hasn't changed @@ -271,38 +271,6 @@ Torrent.prototype._onParsedTorrent = function (parsedTorrent) { self._onListening() }) } - - if (parsedTorrent.xs && !self.info) { - // TODO: Could try multiple in parallel here - var src = parsedTorrent.xs instanceof Array ? parsedTorrent.xs[0] : parsedTorrent.xs - var isHTTP = src.substring(0, 7) === 'http://' || src.substring(0, 8) === 'https://' - - if (isHTTP) { - var opts = { - url: src, - method: 'GET', - headers: { - 'user-agent': 'WebTorrent (http://webtorrent.io)' - } - } - this._xsRequest = get.concat(opts, function (err, res, torrent) { - if (err || res.statusCode !== 200 || !torrent.length) return - - var parsedTorrent - try { - parsedTorrent = parseTorrent(torrent) - } catch (err) {} - - if (parsedTorrent) { - if (parsedTorrent.infoHash !== self.infoHash) { - return - } - - self._onMetadata(parsedTorrent) - } - }) - } - } } Torrent.prototype._processParsedTorrent = function (parsedTorrent) { @@ -395,9 +363,81 @@ Torrent.prototype._onListening = function () { self.emit('warning', err) } - // if full metadata was included in initial torrent id, use it immediately. Otherwise, - // wait for torrent-discovery to find peers and ut_metadata to get the metadata. - if (self.info) self._onMetadata(self) + if (self.info) { + // if full metadata was included in initial torrent id, use it immediately. Otherwise, + // wait for torrent-discovery to find peers and ut_metadata to get the metadata. + self._onMetadata(self) + } else if (self.xs) { + self._getMetadataFromServer() + } +} + +Torrent.prototype._getMetadataFromServer = function () { + var self = this + var urls = Array.isArray(self.xs) ? self.xs : [ self.xs ] + + var tasks = urls.map(function (url) { + return function (cb) { + getMetadataFromURL(url, cb) + } + }) + parallel(tasks) + + function getMetadataFromURL (url, cb) { + if (url.indexOf('http://') !== 0 && url.indexOf('https://') !== 0) { + self._debug('skipping non-http xs param: %s', url) + return cb(null) + } + + var opts = { + url: url, + method: 'GET', + headers: { + 'user-agent': 'WebTorrent (https://webtorrent.io)' + } + } + var req + try { + req = get.concat(opts, onResponse) + } catch (err) { + self._debug('skipping invalid url xs param: %s', url) + return cb(null) + } + + self._xsRequests.push(req) + + function onResponse (err, res, torrent) { + if (self.destroyed) return cb(null) + if (self.metadata) return cb(null) + + if (err) { + self._debug('http error from xs param: %s', url) + return cb(null) + } + if (res.statusCode !== 200) { + self._debug('non-200 status code from xs param: %s', url) + return cb(null) + } + + var parsedTorrent + try { + parsedTorrent = parseTorrent(torrent) + } catch (err) {} + + if (!parsedTorrent) { + self._debug('got invalid torrent file from xs param: %s', url) + return cb(null) + } + + if (parsedTorrent.infoHash !== self.infoHash) { + self._debug('got torrent file with incorrect info hash from xs param: %s', url) + return cb(null) + } + + self._onMetadata(parsedTorrent) + cb(null) + } + } } /** @@ -405,13 +445,14 @@ Torrent.prototype._onListening = function () { */ Torrent.prototype._onMetadata = function (metadata) { var self = this - if (self._xsRequest) { - self._xsRequest.abort() - self._xsRequest = null - } if (self.metadata || self.destroyed) return self._debug('got metadata') + self._xsRequests.forEach(function (req) { + req.abort() + }) + self._xsRequests = [] + var parsedTorrent if (metadata && metadata.infoHash) { // `metadata` is a parsed torrent (from parse-torrent module) @@ -591,13 +632,14 @@ Torrent.prototype._destroy = function (err, cb) { self.destroyed = true self._debug('destroy') - if (self._xsRequest) { - self._xsRequest.abort() - } self.client._remove(self) clearInterval(self._rechokeIntervalId) + self._xsRequests.forEach(function (req) { + req.abort() + }) + if (self._rarityMap) { self._rarityMap.destroy() } @@ -653,7 +695,7 @@ Torrent.prototype._destroy = function (err, cb) { self._rarityMap = null self._peers = null self._servers = null - self._xsRequest = null + self._xsRequests = null } Torrent.prototype.addPeer = function (peer) { diff --git a/test/node/download-metadata.js b/test/node/download-metadata.js index 07b605a..59936cb 100644 --- a/test/node/download-metadata.js +++ b/test/node/download-metadata.js @@ -25,9 +25,12 @@ test('Download metadata for magnet URI with xs parameter', function (t) { var client = new WebTorrent({ dht: false, tracker: false }) + client.on('error', function (err) { t.fail(err) }) + client.on('warning', function (err) { t.fail(err) }) + createServer(fixtures.leaves.torrent, function (url, next) { client.add(fixtures.leaves.magnetURI + '&xs=' + encodeURIComponent(url), function (torrent) { - t.equal(torrent.name, 'Leaves of Grass by Walt Whitman.epub') + t.equal(torrent.files[0].name, 'Leaves of Grass by Walt Whitman.epub') client.destroy(function (err) { t.error(err, 'client destroyed') }) next() @@ -40,12 +43,15 @@ test('Download metadata for magnet URI with xs parameter', function (t) { var client = new WebTorrent({ dht: false, tracker: false }) + client.on('error', function (err) { t.fail(err) }) + client.on('warning', function (err) { t.fail(err) }) + createServer(fixtures.leaves.torrent, function (url, next) { var encoded = encodeURIComponent(url) var uri = fixtures.leaves.magnetURI + '&xs=' + encoded + '&xs=' + encoded + '2' client.add(uri, function (torrent) { - t.equal(torrent.name, 'Leaves of Grass by Walt Whitman.epub') + t.equal(torrent.files[0].name, 'Leaves of Grass by Walt Whitman.epub') client.destroy(function (err) { t.error(err, 'client destroyed') }) next() @@ -54,12 +60,17 @@ test('Download metadata for magnet URI with xs parameter', function (t) { }) test('Download metadata magnet URI with unsupported protocol in xs parameter', function (t) { - t.plan(2) + t.plan(1) var client = new WebTorrent({ dht: false, tracker: false }) + + client.on('error', function (err) { t.fail(err) }) + client.on('warning', function (err) { t.fail(err) }) + client.add(fixtures.leaves.magnetURI + '&xs=' + encodeURIComponent('invalidurl:example')) + setTimeout(function () { - t.ok(true, 'no crash') + // no crash by now client.destroy(function (err) { t.error(err, 'client destroyed') }) }, 100) }) |