Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement exact source (xs) for magnet URIs #799

Merged
merged 1 commit into from May 19, 2016
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -12,6 +12,7 @@ var extend = require('xtend')
var extendMutable = require('xtend/mutable')
var fs = require('fs')
var FSChunkStore = require('fs-chunk-store') // browser: `memory-chunk-store`
var get = require('simple-get')
var ImmediateChunkStore = require('immediate-chunk-store')
var inherits = require('inherits')
var MultiStream = require('multistream')
@@ -113,6 +114,7 @@ function Torrent (torrentId, client, opts) {

// for cleanup
this._servers = []
this._xsRequest = null

// TODO: remove this and expose a hook instead
// optimization: don't recheck every file if it hasn't changed
@@ -269,6 +271,38 @@ 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

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

Array.isArray() is the right way to check if something is an Array.

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

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

No need to check for !torrent.length since that will make parseTorrent throw below anyway.

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

Would be nice to add a log here with debug for debugging purposes.


var parsedTorrent
try {
parsedTorrent = parseTorrent(torrent)
} catch (err) {}

if (parsedTorrent) {
if (parsedTorrent.infoHash !== self.infoHash) {
return

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

Debug log here too

}

self._onMetadata(parsedTorrent)
}
})
}
}
}

Torrent.prototype._processParsedTorrent = function (parsedTorrent) {
@@ -371,6 +405,10 @@ Torrent.prototype._onListening = function () {
*/
Torrent.prototype._onMetadata = function (metadata) {
var self = this
if (self._xsRequest) {
self._xsRequest.abort()
self._xsRequest = null
}

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

This should go after the next line.

if (self.metadata || self.destroyed) return
self._debug('got metadata')

@@ -553,6 +591,9 @@ 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)
@@ -612,6 +653,7 @@ Torrent.prototype._destroy = function (err, cb) {
self._rarityMap = null
self._peers = null
self._servers = null
self._xsRequest = null
}

Torrent.prototype.addPeer = function (peer) {
@@ -0,0 +1,65 @@
var fixtures = require('webtorrent-fixtures')
var http = require('http')
var test = require('tape')
var WebTorrent = require('../../')

function createServer (data, cb) {
var server = http.createServer(function (req, res) {
res.end(data)
}).listen(function () {
var address = server.address()
if (address.family === 'IPv6') {
address.address = '[' + address.address + ']'
}
var url = 'http://' + address.address + ':' + address.port + '/'
cb(url, next)
})

function next () {
server.close()
}
}

test('Download metadata for magnet URI with xs parameter', function (t) {
t.plan(2)

var client = new WebTorrent({ dht: false, tracker: false })

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')

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

The name is also in the magnet URI as the &dn parameter. Might be better to check for another parameter.


client.destroy(function (err) { t.error(err, 'client destroyed') })
next()
})
})
})

test('Download metadata for magnet URI with xs parameter', function (t) {
t.plan(2)

var client = new WebTorrent({ dht: false, tracker: false })

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')

client.destroy(function (err) { t.error(err, 'client destroyed') })
next()
})
})
})

test('Download metadata magnet URI with unsupported protocol in xs parameter', function (t) {
t.plan(2)

var client = new WebTorrent({ dht: false, tracker: false })
client.add(fixtures.leaves.magnetURI + '&xs=' + encodeURIComponent('invalidurl:example'))
setTimeout(function () {
t.ok(true, 'no crash')

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

No need for this. The tests will fail if there's a thrown exception. We should add listeners for 'error' and 'warning' events to all these tests though.

This comment has been minimized.

Copy link
@feross

feross May 19, 2016

Member

Nevermind, I see what you were doing.

client.destroy(function (err) { t.error(err, 'client destroyed') })
}, 100)
})
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.