diff --git a/client.js b/client.js index 6782130..38ce764 100644 --- a/client.js +++ b/client.js @@ -1,7 +1,7 @@ module.exports = Client -var BN = require('bn.js') var bencode = require('bencode') +var BN = require('bn.js') var common = require('./lib/common') var compact2string = require('compact2string') var concat = require('concat-stream') @@ -12,6 +12,7 @@ var extend = require('extend.js') var hat = require('hat') var http = require('http') var inherits = require('inherits') +var once = require('once') var querystring = require('querystring') var url = require('url') @@ -59,6 +60,31 @@ function Client (peerId, port, torrent, opts) { }) } +/** + * Simple convenience function to scrape a tracker for an infoHash without + * needing to create a Client, pass it a parsed torrent, etc. + * @param {string} announceUrl + * @param {string} infoHash + * @param {function} cb + */ +Client.scrape = function (announceUrl, infoHash, cb) { + cb = once(cb) + var dummy = { + peerId: new Buffer('01234567890123456789'), + port: 6881, + torrent: { + infoHash: infoHash, + announce: [ announceUrl ] + } + } + var client = new Client(dummy.peerId, dummy.port, dummy.torrent) + client.once('error', cb) + client.once('scrape', function (data) { + cb(null, data) + }) + client.scrape() +} + Client.prototype.start = function (opts) { var self = this self._trackers.forEach(function (tracker) { diff --git a/package.json b/package.json index ff5691c..d80963c 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "hat": "0.0.3", "inherits": "^2.0.1", "ip": "^0.3.0", + "once": "^1.3.0", "querystring": "^0.2.0", "run-parallel": "^1.0.0", "string2compact": "^1.1.1" diff --git a/test/client-magnet.js b/test/client-magnet.js index a28e397..aa4d25b 100644 --- a/test/client-magnet.js +++ b/test/client-magnet.js @@ -25,7 +25,7 @@ test('magnet + udp: client.start/update/stop()', function (t) { portfinder.getPort(function (err, port) { t.error(err, 'found free port') server.listen(port) - var announceUrl = 'udp://127.0.0.1:' + port // TODO: shouldn't rely on an external server! + var announceUrl = 'udp://127.0.0.1:' + port // remove all tracker servers except a single UDP one, for now parsedTorrent.announce = [ announceUrl ] diff --git a/test/client.js b/test/client.js index 6906007..f069159 100644 --- a/test/client.js +++ b/test/client.js @@ -1,8 +1,7 @@ var Client = require('../') +var common = require('./common') var fs = require('fs') var parseTorrent = require('parse-torrent') -var portfinder = require('portfinder') -var Server = require('../').Server var test = require('tape') var torrent = fs.readFileSync(__dirname + '/torrents/bitlove-intro.torrent') @@ -13,35 +12,10 @@ var peerId3 = new Buffer('23456789012345678901') var announceUrl = '' var port = 6881 -function createServer (t, serverType, cb) { - var opts = serverType === 'http' ? { udp: false } : { http: false } - var server = new Server(opts) - - server.on('error', function (err) { - t.error(err) - }) - - server.on('warning', function (err) { - t.error(err) - }) - - portfinder.getPort(function (err, port) { - if (err) return t.error(err) - - announceUrl = serverType === 'http' - ? 'http://127.0.0.1:' + port + '/announce' - : 'udp://127.0.0.1:' + port - - parsedTorrent.announce = [ announceUrl ] - - server.listen(port) - cb(server) - }) -} - function testClientStart (t, serverType) { t.plan(5) - createServer(t, serverType, function (server) { + common.createServer(t, serverType, function (server, announceUrl) { + parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent) client.on('error', function (err) { @@ -83,7 +57,8 @@ test('udp: client.start()', function (t) { function testClientStop (t, serverType) { t.plan(4) - createServer(t, serverType, function (server) { + common.createServer(t, serverType, function (server, announceUrl) { + parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent) client.on('error', function (err) { @@ -124,7 +99,8 @@ test('udp: client.stop()', function (t) { function testClientUpdate (t, serverType) { t.plan(4) - createServer(t, serverType, function (server) { + common.createServer(t, serverType, function (server, announceUrl) { + parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent, { interval: 5000 }) client.on('error', function (err) { @@ -166,7 +142,8 @@ test('udp: client.update()', function (t) { function testClientScrape (t, serverType) { t.plan(5) - createServer(t, serverType, function (server) { + common.createServer(t, serverType, function (server, announceUrl) { + parsedTorrent.announce = [ announceUrl ] var client = new Client(peerId1, port, parsedTorrent) client.on('error', function (err) { @@ -202,7 +179,8 @@ test('udp: client.scrape()', function (t) { function testClientAnnounceWithNumWant (t, serverType) { t.plan(1) - createServer(t, serverType, function (server) { + common.createServer(t, serverType, function (server, announceUrl) { + parsedTorrent.announce = [ announceUrl ] var client1 = new Client(peerId1, port, parsedTorrent) client1.on('error', function (err) { t.error(err) diff --git a/test/common.js b/test/common.js new file mode 100644 index 0000000..5adf94a --- /dev/null +++ b/test/common.js @@ -0,0 +1,26 @@ +var portfinder = require('portfinder') +var Server = require('../').Server + +exports.createServer = function (t, serverType, cb) { + var opts = serverType === 'http' ? { udp: false } : { http: false } + var server = new Server(opts) + + server.on('error', function (err) { + t.error(err) + }) + + server.on('warning', function (err) { + t.error(err) + }) + + portfinder.getPort(function (err, port) { + if (err) return t.error(err) + + announceUrl = serverType === 'http' + ? 'http://127.0.0.1:' + port + '/announce' + : 'udp://127.0.0.1:' + port + + server.listen(port) + cb(server, announceUrl) + }) +} diff --git a/test/scrape.js b/test/scrape.js index 2c01aee..29b0f52 100644 --- a/test/scrape.js +++ b/test/scrape.js @@ -1,6 +1,7 @@ var bencode = require('bencode') var Client = require('../') -var common = require('../lib/common') +var commonLib = require('../lib/common') +var commonTest = require('./common') var concat = require('concat-stream') var fs = require('fs') var http = require('http') @@ -25,46 +26,59 @@ var binaryBitlove = hexToBinary(parsedBitlove.infoHash) var peerId = new Buffer('01234567890123456789') -test('server: single info_hash scrape', function (t) { - var server = new Server({ udp: false }) - server.on('error', function (err) { - t.error(err) - }) - server.on('warning', function (err) { - t.error(err) - }) - - portfinder.getPort(function (err, port) { - t.error(err) - server.listen(port) - var scrapeUrl = 'http://127.0.0.1:' + port + '/scrape' - +function testSingle (t, serverType) { + commonTest.createServer(t, serverType, function (server, announceUrl) { + var scrapeUrl = announceUrl.replace('announce', 'scrape') server.once('listening', function () { - var url = scrapeUrl + '?' + common.querystringStringify({ - info_hash: binaryInfoHash1 - }) - http.get(url, function (res) { - t.equal(res.statusCode, 200) - res.pipe(concat(function (data) { - data = bencode.decode(data) - t.ok(data.files) - t.equal(Object.keys(data.files).length, 1) - t.ok(data.files[binaryInfoHash1]) - t.equal(typeof data.files[binaryInfoHash1].complete, 'number') - t.equal(typeof data.files[binaryInfoHash1].incomplete, 'number') - t.equal(typeof data.files[binaryInfoHash1].downloaded, 'number') - - server.close(function () { - t.end() - }) - })) - }).on('error', function (e) { + Client.scrape(announceUrl, infoHash1, function (err, data) { t.error(err) + t.equal(data.announce, announceUrl) + t.equal(typeof data.complete, 'number') + t.equal(typeof data.incomplete, 'number') + t.equal(typeof data.downloaded, 'number') + server.close(function () { + t.end() + }) }) }) }) +} + +test('http: single info_hash scrape', function (t) { + testSingle(t, 'http') }) +test('udp: single info_hash scrape', function (t) { + testSingle(t, 'udp') +}) + +function clientScrapeStatic (t, serverType) { + commonTest.createServer(t, serverType, function (server, announceUrl) { + server.once('listening', function () { + Client.scrape(announceUrl, infoHash1, function (err, data) { + t.error(err) + t.equal(data.announce, announceUrl) + t.equal(typeof data.complete, 'number') + t.equal(typeof data.incomplete, 'number') + t.equal(typeof data.downloaded, 'number') + server.close(function () { + t.end() + }) + }) + }) + }) +} + +test('http: scrape using Client.scrape static method', function (t) { + clientScrapeStatic(t, 'http') +}) + +test('udp: scrape using Client.scrape static method', function (t) { + clientScrapeStatic(t, 'udp') +}) + +// TODO: test client for multiple scrape for UDP trackers + test('server: multiple info_hash scrape', function (t) { var server = new Server({ udp: false }) server.on('error', function (err) { @@ -80,7 +94,7 @@ test('server: multiple info_hash scrape', function (t) { var scrapeUrl = 'http://127.0.0.1:' + port + '/scrape' server.once('listening', function () { - var url = scrapeUrl + '?' + common.querystringStringify({ + var url = scrapeUrl + '?' + commonLib.querystringStringify({ info_hash: [ binaryInfoHash1, binaryInfoHash2 ] }) http.get(url, function (res) {