diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/torrent.js | 130 |
1 files changed, 86 insertions, 44 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) { |