diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..6098b8e6 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,36 @@ +name: Release + +on: + push: + branches: + - master + +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + persist-credentials: false + - name: Setup Node.js + uses: actions/setup-node@v2 + with: + node-version: 14 + - name: Cache + uses: actions/cache@v2 + with: + path: ~/.npm + key: ${{ runner.os }}-npm-${{ hashFiles('**/package.json') }} + restore-keys: | + ${{ runner.os }}-npm- + - name: Install dependencies + run: npm i + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: npx semantic-release diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..72597d8e --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,23 @@ +name: Mark stale issues and pull requests + +on: + schedule: + - cron: '0 12 * * *' + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v4 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?' + stale-pr-message: 'Is this still relevant? If so, what is blocking it? Is there anything you can do to help move it forward?' + exempt-issue-labels: accepted,blocked,bug,dependency,enhancement,'help wanted',question,security,meta + exempt-pr-labels: accepted,blocked,bug,dependency,enhancement,'help wanted',question,security,meta + stale-issue-label: 'stale' + stale-pr-label: 'stale' diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..504afef8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +package-lock.json diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 43c97e71..00000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -package-lock=false diff --git a/AUTHORS.md b/AUTHORS.md index acf8e9f7..e9a486a8 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -50,5 +50,12 @@ - Koushik Dutta (koush@koushikdutta.com) - KayleePop (34007889+KayleePop@users.noreply.github.com) - Diego Rodriguez Baquero (diego.baquero@pager.com) +- Diego Rodríguez Baquero (github@diegorbaquero.com) +- Renovate Bot (bot@renovateapp.com) +- Diego Rodríguez Baquero (diego@mothership.com) +- Diego Rodriguez Baquero (diego@arc.io) +- semantic-release-bot (semantic-release-bot@martynus.net) +- renovate[bot] (29139614+renovate[bot]@users.noreply.github.com) +- Jocelyn Liu (yrliou@gmail.com) #### Generated by tools/update-authors.sh. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..69e62a38 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,56 @@ +## [9.18.2](https://github.com/webtorrent/bittorrent-tracker/compare/v9.18.1...v9.18.2) (2021-09-02) + + +### Bug Fixes + +* **deps:** update dependency socks to v2 ([#394](https://github.com/webtorrent/bittorrent-tracker/issues/394)) ([353e1f4](https://github.com/webtorrent/bittorrent-tracker/commit/353e1f40093a5e74cb54219abbae8ef0cc3d9e0b)) + +## [9.18.1](https://github.com/webtorrent/bittorrent-tracker/compare/v9.18.0...v9.18.1) (2021-09-01) + + +### Bug Fixes + +* disable socks in chromeapp ([#398](https://github.com/webtorrent/bittorrent-tracker/issues/398)) ([7fd5877](https://github.com/webtorrent/bittorrent-tracker/commit/7fd587789548453a852ea01e54900a5e9155db67)) + +# [9.18.0](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.4...v9.18.0) (2021-08-20) + + +### Features + +* add proxy support for tracker clients ([#356](https://github.com/webtorrent/bittorrent-tracker/issues/356)) ([ad64dc3](https://github.com/webtorrent/bittorrent-tracker/commit/ad64dc3a68cddccc2c1f05d0d8bb833f2c4860b2)) + +## [9.17.4](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.3...v9.17.4) (2021-07-22) + + +### Bug Fixes + +* if websocket closed, don't produce a response ([ca88435](https://github.com/webtorrent/bittorrent-tracker/commit/ca88435617e59714a456031c75b3a329897d97bd)) + +## [9.17.3](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.2...v9.17.3) (2021-07-02) + + +### Bug Fixes + +* auto update authors on version ([b5ffc70](https://github.com/webtorrent/bittorrent-tracker/commit/b5ffc708ada0bef66e7fa0cd1872527ea6dd8d53)) + +## [9.17.2](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.1...v9.17.2) (2021-06-15) + + +### Bug Fixes + +* modernize ([e5994d2](https://github.com/webtorrent/bittorrent-tracker/commit/e5994d2ebdec10fe2165e31f5b498382eeeaaf5f)) + +## [9.17.1](https://github.com/webtorrent/bittorrent-tracker/compare/v9.17.0...v9.17.1) (2021-06-15) + + +### Bug Fixes + +* add package-lock ([0e486b0](https://github.com/webtorrent/bittorrent-tracker/commit/0e486b09d80d30e1c13d4624e29c4251000d4092)) +* **deps:** update dependency bn.js to ^5.2.0 ([2d36e4a](https://github.com/webtorrent/bittorrent-tracker/commit/2d36e4ae60b1bac51773f2dca81c1a158b51cb28)) +* **deps:** update dependency chrome-dgram to ^3.0.6 ([a82aaaa](https://github.com/webtorrent/bittorrent-tracker/commit/a82aaaa31963a0d9adb640166f417142c5d7b970)) +* **deps:** update dependency run-parallel to ^1.2.0 ([fcf25ed](https://github.com/webtorrent/bittorrent-tracker/commit/fcf25ed40e1fd64e630b10a0281bc09604b901d3)) +* **deps:** update dependency run-series to ^1.1.9 ([fa2c33f](https://github.com/webtorrent/bittorrent-tracker/commit/fa2c33fc91f8ef0a47d0f40b7a046ae179ee328a)) +* **deps:** update dependency simple-websocket to ^9.1.0 ([96fedbd](https://github.com/webtorrent/bittorrent-tracker/commit/96fedbdf56ddcf6627eb373a33589db885cb4fb7)) +* **deps:** update dependency ws to ^7.4.5 ([6ad7ead](https://github.com/webtorrent/bittorrent-tracker/commit/6ad7ead994e5cb99980a406aea908e4b9ff6151c)) +* **deps:** update webtorrent ([1e8d47d](https://github.com/webtorrent/bittorrent-tracker/commit/1e8d47dcd8f5f53b42aa75265a129f950d16feef)) +* UDP url parsing ([8e24a8c](https://github.com/webtorrent/bittorrent-tracker/commit/8e24a8c97b55bbaaf2c92a496d1cd30b0c008934)) diff --git a/README.md b/README.md index 1ac36057..a7a5724d 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,12 @@ var requiredOpts = { } var optionalOpts = { + // RTCPeerConnection config object (only used in browser) + rtcConfig: {}, + // User-Agent header for http requests + userAgent: '', + // Custom webrtc impl, useful in node to specify [wrtc](https://npmjs.com/package/wrtc) + wrtc: {}, getAnnounceOpts: function () { // Provide a callback that will be called whenever announce() is called // internally (on timer), or by the user @@ -75,12 +81,44 @@ var optionalOpts = { customParam: 'blah' // custom parameters supported } }, - // RTCPeerConnection config object (only used in browser) - rtcConfig: {}, - // User-Agent header for http requests - userAgent: '', - // Custom webrtc impl, useful in node to specify [wrtc](https://npmjs.com/package/wrtc) - wrtc: {}, + // Proxy config object + proxyOpts: { + // Socks proxy options (used to proxy requests in node) + socksProxy: { + // Configuration from socks module (https://github.com/JoshGlazebrook/socks) + proxy: { + // IP Address of Proxy (Required) + ipaddress: "1.2.3.4", + // TCP Port of Proxy (Required) + port: 1080, + // Proxy Type [4, 5] (Required) + // Note: 4 works for both 4 and 4a. + // Type 4 does not support UDP association relay + type: 5, + + // SOCKS 4 Specific: + + // UserId used when making a SOCKS 4/4a request. (Optional) + userid: "someuserid", + + // SOCKS 5 Specific: + + // Authentication used for SOCKS 5 (when it's required) (Optional) + authentication: { + username: "Josh", + password: "somepassword" + } + }, + + // Amount of time to wait for a connection to be established. (Optional) + // - defaults to 10000ms (10 seconds) + timeout: 10000 + }, + // NodeJS HTTP agents (used to proxy HTTP and Websocket requests in node) + // Populated with Socks.Agent if socksProxy is provided + httpAgent: {}, + httpsAgent: {} + }, } var client = new Client(requiredOpts) diff --git a/bin/cmd.js b/bin/cmd.js index 089c649e..965e00f7 100755 --- a/bin/cmd.js +++ b/bin/cmd.js @@ -39,7 +39,7 @@ if (argv.version) { } if (argv.help) { - console.log(function () { + console.log((() => { /* bittorrent-tracker - Start a bittorrent tracker server @@ -64,7 +64,7 @@ if (argv.help) { -v, --version print the current version */ - }.toString().split(/\n/).slice(2, -2).join('\n')) + }).toString().split(/\n/).slice(2, -2).join('\n')) process.exit(0) } @@ -85,23 +85,23 @@ const server = new Server({ ws: argv.ws }) -server.on('error', function (err) { - if (!argv.silent) console.error('ERROR: ' + err.message) +server.on('error', err => { + if (!argv.silent) console.error(`ERROR: ${err.message}`) }) -server.on('warning', function (err) { - if (!argv.quiet) console.log('WARNING: ' + err.message) +server.on('warning', err => { + if (!argv.quiet) console.log(`WARNING: ${err.message}`) }) -server.on('update', function (addr) { - if (!argv.quiet) console.log('update: ' + addr) +server.on('update', addr => { + if (!argv.quiet) console.log(`update: ${addr}`) }) -server.on('complete', function (addr) { - if (!argv.quiet) console.log('complete: ' + addr) +server.on('complete', addr => { + if (!argv.quiet) console.log(`complete: ${addr}`) }) -server.on('start', function (addr) { - if (!argv.quiet) console.log('start: ' + addr) +server.on('start', addr => { + if (!argv.quiet) console.log(`start: ${addr}`) }) -server.on('stop', function (addr) { - if (!argv.quiet) console.log('stop: ' + addr) +server.on('stop', addr => { + if (!argv.quiet) console.log(`stop: ${addr}`) }) const hostname = { @@ -110,35 +110,35 @@ const hostname = { udp6: argv['udp6-hostname'] } -server.listen(argv.port, hostname, function () { +server.listen(argv.port, hostname, () => { if (server.http && argv.http && !argv.quiet) { const httpAddr = server.http.address() const httpHost = httpAddr.address !== '::' ? httpAddr.address : 'localhost' const httpPort = httpAddr.port - console.log('HTTP tracker: http://' + httpHost + ':' + httpPort + '/announce') + console.log(`HTTP tracker: http://${httpHost}:${httpPort}/announce`) } if (server.udp && !argv.quiet) { const udpAddr = server.udp.address() const udpHost = udpAddr.address const udpPort = udpAddr.port - console.log('UDP tracker: udp://' + udpHost + ':' + udpPort) + console.log(`UDP tracker: udp://${udpHost}:${udpPort}`) } if (server.udp6 && !argv.quiet) { const udp6Addr = server.udp6.address() const udp6Host = udp6Addr.address !== '::' ? udp6Addr.address : 'localhost' const udp6Port = udp6Addr.port - console.log('UDP6 tracker: udp://' + udp6Host + ':' + udp6Port) + console.log(`UDP6 tracker: udp://${udp6Host}:${udp6Port}`) } if (server.ws && !argv.quiet) { const wsAddr = server.http.address() const wsHost = wsAddr.address !== '::' ? wsAddr.address : 'localhost' const wsPort = wsAddr.port - console.log('WebSocket tracker: ws://' + wsHost + ':' + wsPort) + console.log(`WebSocket tracker: ws://${wsHost}:${wsPort}`) } if (server.http && argv.stats && !argv.quiet) { const statsAddr = server.http.address() const statsHost = statsAddr.address !== '::' ? statsAddr.address : 'localhost' const statsPort = statsAddr.port - console.log('Tracker stats: http://' + statsHost + ':' + statsPort + '/stats') + console.log(`Tracker stats: http://${statsHost}:${statsPort}/stats`) } }) diff --git a/client.js b/client.js index 75bdf26d..c091c319 100644 --- a/client.js +++ b/client.js @@ -24,6 +24,7 @@ const WebSocketTracker = require('./lib/client/websocket-tracker') * @param {number} opts.rtcConfig RTCPeerConnection configuration object * @param {number} opts.userAgent User-Agent header for http requests * @param {number} opts.wrtc custom webrtc impl (useful in node.js) + * @param {object} opts.proxyOpts proxy options (useful in node.js) */ class Client extends EventEmitter { constructor (opts = {}) { @@ -54,6 +55,7 @@ class Client extends EventEmitter { this._getAnnounceOpts = opts.getAnnounceOpts this._rtcConfig = opts.rtcConfig this._userAgent = opts.userAgent + this._proxyOpts = opts.proxyOpts // Support lazy 'wrtc' module initialization // See: https://github.com/webtorrent/webtorrent-hybrid/issues/46 @@ -281,9 +283,7 @@ Client.scrape = (opts, cb) => { }) opts.infoHash = Array.isArray(opts.infoHash) - ? opts.infoHash.map(infoHash => { - return Buffer.from(infoHash, 'hex') - }) + ? opts.infoHash.map(infoHash => Buffer.from(infoHash, 'hex')) : Buffer.from(opts.infoHash, 'hex') client.scrape({ infoHash: opts.infoHash }) return client diff --git a/examples/express-embed/server.js b/examples/express-embed/server.js index ff72147a..cfdbbec8 100755 --- a/examples/express-embed/server.js +++ b/examples/express-embed/server.js @@ -13,7 +13,7 @@ const server = new Server({ http: false, // we do our own udp: false, // not interested ws: false, // not interested - filter: function (params) { + filter (params) { // black/whitelist for disallowing/allowing specific clients [default=allow all] // this example only allows the uTorrent client const client = params.peer_id[1] + params.peer_id[2] diff --git a/lib/client/http-tracker.js b/lib/client/http-tracker.js index f611a9ec..604c6823 100644 --- a/lib/client/http-tracker.js +++ b/lib/client/http-tracker.js @@ -1,8 +1,10 @@ const arrayRemove = require('unordered-array-remove') const bencode = require('bencode') +const clone = require('clone') const compact2string = require('compact2string') const debug = require('debug')('bittorrent-tracker:http-tracker') const get = require('simple-get') +const Socks = require('socks') const common = require('../common') const Tracker = require('./tracker') @@ -17,7 +19,7 @@ const HTTP_SCRAPE_SUPPORT = /\/(announce)[^/]*$/ * @param {Object} opts options object */ class HTTPTracker extends Tracker { - constructor (client, announceUrl, opts) { + constructor (client, announceUrl) { super(client, announceUrl) debug('new http tracker %s', announceUrl) @@ -62,9 +64,7 @@ class HTTPTracker extends Tracker { } const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) - ? opts.infoHash.map(infoHash => { - return infoHash.toString('binary') - }) + ? opts.infoHash.map(infoHash => infoHash.toString('binary')) : (opts.infoHash && opts.infoHash.toString('binary')) || this.client._infoHashBinary const params = { info_hash: infoHashes @@ -112,13 +112,20 @@ class HTTPTracker extends Tracker { _request (requestUrl, params, cb) { const self = this - const u = requestUrl + (!requestUrl.includes('?') ? '?' : '&') + - common.querystringStringify(params) + const parsedUrl = new URL(requestUrl + (requestUrl.indexOf('?') === -1 ? '?' : '&') + common.querystringStringify(params)) + let agent + if (this.client._proxyOpts) { + agent = parsedUrl.protocol === 'https:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent + if (!agent && this.client._proxyOpts.socksProxy) { + agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'https:')) + } + } this.cleanupFns.push(cleanup) let request = get.concat({ - url: u, + url: parsedUrl.toString(), + agent: agent, timeout: common.REQUEST_TIMEOUT, headers: { 'user-agent': this.client._userAgent || '' diff --git a/lib/client/udp-tracker.js b/lib/client/udp-tracker.js index 093ed4c8..79f777c4 100644 --- a/lib/client/udp-tracker.js +++ b/lib/client/udp-tracker.js @@ -1,9 +1,11 @@ const arrayRemove = require('unordered-array-remove') const BN = require('bn.js') +const clone = require('clone') const compact2string = require('compact2string') const debug = require('debug')('bittorrent-tracker:udp-tracker') const dgram = require('dgram') const randombytes = require('randombytes') +const Socks = require('socks') const common = require('../common') const Tracker = require('./tracker') @@ -16,7 +18,7 @@ const Tracker = require('./tracker') * @param {Object} opts options object */ class UDPTracker extends Tracker { - constructor (client, announceUrl, opts) { + constructor (client, announceUrl) { super(client, announceUrl) debug('new udp tracker %s', announceUrl) @@ -77,27 +79,65 @@ class UDPTracker extends Tracker { let { hostname, port } = common.parseUrl(this.announceUrl) if (port === '') port = 80 + let timeout + // Socket used to connect to the socks server to create a relay, null if socks is disabled + let proxySocket + // Socket used to connect to the tracker or to the socks relay if socks is enabled + let socket + // Contains the host/port of the socks relay + let relay + let transactionId = genTransactionId() - let socket = dgram.createSocket('udp4') - let timeout = setTimeout(() => { - // does not matter if `stopped` event arrives, so supress errors - if (opts.event === 'stopped') cleanup() - else onError(new Error(`tracker request timed out (${opts.event})`)) - timeout = null - }, common.REQUEST_TIMEOUT) - if (timeout.unref) timeout.unref() + const proxyOpts = this.client._proxyOpts && clone(this.client._proxyOpts.socksProxy) + if (proxyOpts) { + if (!proxyOpts.proxy) proxyOpts.proxy = {} + // UDP requests uses the associate command + proxyOpts.proxy.command = 'associate' + if (!proxyOpts.target) { + // This should contain client IP and port but can be set to 0 if we don't have this information + proxyOpts.target = { + host: '0.0.0.0', + port: 0 + } + } + + if (proxyOpts.proxy.type === 5) { + Socks.createConnection(proxyOpts, onGotConnection) + } else { + debug('Ignoring Socks proxy for UDP request because type 5 is required') + onGotConnection(null) + } + } else { + onGotConnection(null) + } this.cleanupFns.push(cleanup) - send(Buffer.concat([ - common.CONNECTION_ID, - common.toUInt32(common.ACTIONS.CONNECT), - transactionId - ])) + function onGotConnection (err, s, info) { + if (err) return onError(err) - socket.once('error', onError) - socket.on('message', onSocketMessage) + proxySocket = s + socket = dgram.createSocket('udp4') + relay = info + + timeout = setTimeout(() => { + // does not matter if `stopped` event arrives, so supress errors + if (opts.event === 'stopped') cleanup() + else onError(new Error(`tracker request timed out (${opts.event})`)) + timeout = null + }, common.REQUEST_TIMEOUT) + if (timeout.unref) timeout.unref() + + send(Buffer.concat([ + common.CONNECTION_ID, + common.toUInt32(common.ACTIONS.CONNECT), + transactionId + ]), relay) + + socket.once('error', onError) + socket.on('message', onSocketMessage) + } function cleanup () { if (timeout) { @@ -111,6 +151,10 @@ class UDPTracker extends Tracker { socket.on('error', noop) // ignore all future errors try { socket.close() } catch (err) {} socket = null + if (proxySocket) { + try { proxySocket.close() } catch (err) {} + proxySocket = null + } } if (self.maybeDestroyCleanup) self.maybeDestroyCleanup() } @@ -128,6 +172,7 @@ class UDPTracker extends Tracker { } function onSocketMessage (msg) { + if (proxySocket) msg = msg.slice(10) if (msg.length < 8 || msg.readUInt32BE(4) !== transactionId.readUInt32BE(0)) { return onError(new Error('tracker sent invalid transaction id')) } @@ -181,7 +226,7 @@ class UDPTracker extends Tracker { return onError(new Error('invalid scrape message')) } const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) - ? opts.infoHash.map(infoHash => { return infoHash.toString('hex') }) + ? opts.infoHash.map(infoHash => infoHash.toString('hex')) : [(opts.infoHash && opts.infoHash.toString('hex')) || self.client.infoHash] for (let i = 0, len = (msg.length - 8) / 12; i < len; i += 1) { @@ -211,8 +256,13 @@ class UDPTracker extends Tracker { } } - function send (message) { - socket.send(message, 0, message.length, port, hostname) + function send (message, proxyInfo) { + if (proxyInfo) { + const pack = Socks.createUDPFrame({ host: hostname, port: port }, message) + socket.send(pack, 0, pack.length, proxyInfo.port, proxyInfo.host) + } else { + socket.send(message, 0, message.length, port, hostname) + } } function announce (connectionId, opts) { @@ -232,7 +282,7 @@ class UDPTracker extends Tracker { common.toUInt32(0), // key (optional) common.toUInt32(opts.numwant), toUInt16(self.client._port) - ])) + ]), relay) } function scrape (connectionId) { @@ -247,7 +297,7 @@ class UDPTracker extends Tracker { common.toUInt32(common.ACTIONS.SCRAPE), transactionId, infoHash - ])) + ]), relay) } } } diff --git a/lib/client/websocket-tracker.js b/lib/client/websocket-tracker.js index 815b0341..480f7ded 100644 --- a/lib/client/websocket-tracker.js +++ b/lib/client/websocket-tracker.js @@ -1,7 +1,9 @@ +const clone = require('clone') const debug = require('debug')('bittorrent-tracker:websocket-tracker') const Peer = require('simple-peer') const randombytes = require('randombytes') const Socket = require('simple-websocket') +const Socks = require('socks') const common = require('../common') const Tracker = require('./tracker') @@ -17,7 +19,7 @@ const RECONNECT_VARIANCE = 5 * 60 * 1000 const OFFER_TIMEOUT = 50 * 1000 class WebSocketTracker extends Tracker { - constructor (client, announceUrl, opts) { + constructor (client, announceUrl) { super(client, announceUrl) debug('new websocket tracker %s', announceUrl) @@ -76,9 +78,7 @@ class WebSocketTracker extends Tracker { } const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) - ? opts.infoHash.map(infoHash => { - return infoHash.toString('binary') - }) + ? opts.infoHash.map(infoHash => infoHash.toString('binary')) : (opts.infoHash && opts.infoHash.toString('binary')) || this.client._infoHashBinary const params = { action: 'scrape', @@ -178,7 +178,15 @@ class WebSocketTracker extends Tracker { this._onSocketConnectBound() } } else { - this.socket = socketPool[this.announceUrl] = new Socket(this.announceUrl) + const parsedUrl = new URL(this.announceUrl) + let agent + if (this.client._proxyOpts) { + agent = parsedUrl.protocol === 'wss:' ? this.client._proxyOpts.httpsAgent : this.client._proxyOpts.httpAgent + if (!agent && this.client._proxyOpts.socksProxy) { + agent = new Socks.Agent(clone(this.client._proxyOpts.socksProxy), (parsedUrl.protocol === 'wss:')) + } + } + this.socket = socketPool[this.announceUrl] = new Socket({ url: this.announceUrl, agent: agent }) this.socket.consumers = 1 this.socket.once('connect', this._onSocketConnectBound) } diff --git a/lib/common-node.js b/lib/common-node.js index 12f57756..b570f2b1 100644 --- a/lib/common-node.js +++ b/lib/common-node.js @@ -50,9 +50,7 @@ exports.toUInt32 = toUInt32 * @param {string} q * @return {Object} */ -exports.querystringParse = function (q) { - return querystring.parse(q, null, null, { decodeURIComponent: unescape }) -} +exports.querystringParse = q => querystring.parse(q, null, null, { decodeURIComponent: unescape }) /** * `querystring.stringify` using `escape` instead of encodeURIComponent, since bittorrent @@ -60,11 +58,9 @@ exports.querystringParse = function (q) { * @param {Object} obj * @return {string} */ -exports.querystringStringify = function (obj) { +exports.querystringStringify = obj => { let ret = querystring.stringify(obj, null, null, { encodeURIComponent: escape }) - ret = ret.replace(/[@*/+]/g, function (char) { - // `escape` doesn't encode the characters @*/+ so we do it manually - return '%' + char.charCodeAt(0).toString(16).toUpperCase() - }) + ret = ret.replace(/[@*/+]/g, char => // `escape` doesn't encode the characters @*/+ so we do it manually + `%${char.charCodeAt(0).toString(16).toUpperCase()}`) return ret } diff --git a/lib/common.js b/lib/common.js index 105f43ad..0a2026bc 100644 --- a/lib/common.js +++ b/lib/common.js @@ -5,14 +5,14 @@ exports.DEFAULT_ANNOUNCE_PEERS = 50 exports.MAX_ANNOUNCE_PEERS = 82 -exports.binaryToHex = function (str) { +exports.binaryToHex = str => { if (typeof str !== 'string') { str = String(str) } return Buffer.from(str, 'binary').toString('hex') } -exports.hexToBinary = function (str) { +exports.hexToBinary = str => { if (typeof str !== 'string') { str = String(str) } @@ -31,7 +31,7 @@ exports.hexToBinary = function (str) { // Bug reports: // - Chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=734880 // - Firefox: https://bugzilla.mozilla.org/show_bug.cgi?id=1374505 -exports.parseUrl = function (str) { +exports.parseUrl = str => { const url = new URL(str.replace(/^udp:/, 'http:')) if (str.match(/^udp:/)) { diff --git a/lib/server/parse-http.js b/lib/server/parse-http.js index 763bc53d..7b2d5e2c 100644 --- a/lib/server/parse-http.js +++ b/lib/server/parse-http.js @@ -36,7 +36,7 @@ function parseHttpRequest (req, opts) { params.ip = opts.trustProxy ? req.headers['x-forwarded-for'] || req.connection.remoteAddress : req.connection.remoteAddress.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '') // force ipv4 - params.addr = (common.IPV6_RE.test(params.ip) ? '[' + params.ip + ']' : params.ip) + ':' + params.port + params.addr = `${common.IPV6_RE.test(params.ip) ? `[${params.ip}]` : params.ip}:${params.port}` params.headers = req.headers } else if (opts.action === 'scrape' || s[0] === '/scrape') { @@ -44,7 +44,7 @@ function parseHttpRequest (req, opts) { if (typeof params.info_hash === 'string') params.info_hash = [params.info_hash] if (Array.isArray(params.info_hash)) { - params.info_hash = params.info_hash.map(function (binaryInfoHash) { + params.info_hash = params.info_hash.map(binaryInfoHash => { if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) { throw new Error('invalid info_hash') } @@ -52,7 +52,7 @@ function parseHttpRequest (req, opts) { }) } } else { - throw new Error('invalid action in HTTP request: ' + req.url) + throw new Error(`invalid action in HTTP request: ${req.url}`) } return params diff --git a/lib/server/parse-udp.js b/lib/server/parse-udp.js index 24028637..939bcb5d 100644 --- a/lib/server/parse-udp.js +++ b/lib/server/parse-udp.js @@ -44,7 +44,7 @@ function parseUdpRequest (msg, rinfo) { ) params.port = msg.readUInt16BE(96) || rinfo.port // optional - params.addr = params.ip + ':' + params.port // TODO: ipv6 brackets + params.addr = `${params.ip}:${params.port}` // TODO: ipv6 brackets params.compact = 1 // udp is always compact } else if (params.action === common.ACTIONS.SCRAPE) { // scrape message if ((msg.length - 16) % 20 !== 0) throw new Error('invalid scrape message') @@ -54,7 +54,7 @@ function parseUdpRequest (msg, rinfo) { params.info_hash.push(infoHash) } } else { - throw new Error('Invalid action in UDP packet: ' + params.action) + throw new Error(`Invalid action in UDP packet: ${params.action}`) } return params diff --git a/lib/server/parse-websocket.js b/lib/server/parse-websocket.js index c0e3431f..21b48fcb 100644 --- a/lib/server/parse-websocket.js +++ b/lib/server/parse-websocket.js @@ -41,7 +41,7 @@ function parseWebSocketRequest (socket, opts, params) { if (typeof params.info_hash === 'string') params.info_hash = [params.info_hash] if (Array.isArray(params.info_hash)) { - params.info_hash = params.info_hash.map(function (binaryInfoHash) { + params.info_hash = params.info_hash.map(binaryInfoHash => { if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) { throw new Error('invalid info_hash') } @@ -49,7 +49,7 @@ function parseWebSocketRequest (socket, opts, params) { }) } } else { - throw new Error('invalid action in WS request: ' + params.action) + throw new Error(`invalid action in WS request: ${params.action}`) } // On first parse, save important data from `socket.upgradeReq` and delete it @@ -60,7 +60,7 @@ function parseWebSocketRequest (socket, opts, params) { : socket.upgradeReq.connection.remoteAddress.replace(common.REMOVE_IPV4_MAPPED_IPV6_RE, '') // force ipv4 socket.port = socket.upgradeReq.connection.remotePort if (socket.port) { - socket.addr = (common.IPV6_RE.test(socket.ip) ? '[' + socket.ip + ']' : socket.ip) + ':' + socket.port + socket.addr = `${common.IPV6_RE.test(socket.ip) ? `[${socket.ip}]` : socket.ip}:${socket.port}` } socket.headers = socket.upgradeReq.headers diff --git a/lib/server/swarm.js b/lib/server/swarm.js index 4cde412a..8194270f 100644 --- a/lib/server/swarm.js +++ b/lib/server/swarm.js @@ -1,5 +1,3 @@ -module.exports = Swarm - const arrayRemove = require('unordered-array-remove') const debug = require('debug')('bittorrent-tracker:swarm') const LRU = require('lru') @@ -7,142 +5,147 @@ const randomIterate = require('random-iterate') // Regard this as the default implementation of an interface that you // need to support when overriding Server.createSwarm() and Server.getSwarm() -function Swarm (infoHash, server) { - const self = this - self.infoHash = infoHash - self.complete = 0 - self.incomplete = 0 - - self.peers = new LRU({ - max: server.peersCacheLength || 1000, - maxAge: server.peersCacheTtl || 20 * 60 * 1000 // 20 minutes - }) - - // When a peer is evicted from the LRU store, send a synthetic 'stopped' event - // so the stats get updated correctly. - self.peers.on('evict', function (data) { - const peer = data.value - const params = { - type: peer.type, - event: 'stopped', - numwant: 0, - peer_id: peer.peerId - } - self._onAnnounceStopped(params, peer, peer.peerId) - peer.socket = null - }) -} - -Swarm.prototype.announce = function (params, cb) { - const self = this - const id = params.type === 'ws' ? params.peer_id : params.addr - // Mark the source peer as recently used in cache - const peer = self.peers.get(id) - - if (params.event === 'started') { - self._onAnnounceStarted(params, peer, id) - } else if (params.event === 'stopped') { - self._onAnnounceStopped(params, peer, id) - } else if (params.event === 'completed') { - self._onAnnounceCompleted(params, peer, id) - } else if (params.event === 'update') { - self._onAnnounceUpdate(params, peer, id) - } else { - cb(new Error('invalid event')) - return +class Swarm { + constructor (infoHash, server) { + const self = this + self.infoHash = infoHash + self.complete = 0 + self.incomplete = 0 + + self.peers = new LRU({ + max: server.peersCacheLength || 1000, + maxAge: server.peersCacheTtl || 20 * 60 * 1000 // 20 minutes + }) + + // When a peer is evicted from the LRU store, send a synthetic 'stopped' event + // so the stats get updated correctly. + self.peers.on('evict', data => { + const peer = data.value + const params = { + type: peer.type, + event: 'stopped', + numwant: 0, + peer_id: peer.peerId + } + self._onAnnounceStopped(params, peer, peer.peerId) + peer.socket = null + }) } - cb(null, { - complete: self.complete, - incomplete: self.incomplete, - peers: self._getPeers(params.numwant, params.peer_id, !!params.socket) - }) -} - -Swarm.prototype.scrape = function (params, cb) { - cb(null, { - complete: this.complete, - incomplete: this.incomplete - }) -} -Swarm.prototype._onAnnounceStarted = function (params, peer, id) { - if (peer) { - debug('unexpected `started` event from peer that is already in swarm') - return this._onAnnounceUpdate(params, peer, id) // treat as an update + announce (params, cb) { + const self = this + const id = params.type === 'ws' ? params.peer_id : params.addr + // Mark the source peer as recently used in cache + const peer = self.peers.get(id) + + if (params.event === 'started') { + self._onAnnounceStarted(params, peer, id) + } else if (params.event === 'stopped') { + self._onAnnounceStopped(params, peer, id) + if (!cb) return // when websocket is closed + } else if (params.event === 'completed') { + self._onAnnounceCompleted(params, peer, id) + } else if (params.event === 'update') { + self._onAnnounceUpdate(params, peer, id) + } else { + cb(new Error('invalid event')) + return + } + cb(null, { + complete: self.complete, + incomplete: self.incomplete, + peers: self._getPeers(params.numwant, params.peer_id, !!params.socket) + }) } - if (params.left === 0) this.complete += 1 - else this.incomplete += 1 - this.peers.set(id, { - type: params.type, - complete: params.left === 0, - peerId: params.peer_id, // as hex - ip: params.ip, - port: params.port, - socket: params.socket // only websocket - }) -} - -Swarm.prototype._onAnnounceStopped = function (params, peer, id) { - if (!peer) { - debug('unexpected `stopped` event from peer that is not in swarm') - return // do nothing + scrape (params, cb) { + cb(null, { + complete: this.complete, + incomplete: this.incomplete + }) } - if (peer.complete) this.complete -= 1 - else this.incomplete -= 1 + _onAnnounceStarted (params, peer, id) { + if (peer) { + debug('unexpected `started` event from peer that is already in swarm') + return this._onAnnounceUpdate(params, peer, id) // treat as an update + } - // If it's a websocket, remove this swarm's infohash from the list of active - // swarms that this peer is participating in. - if (peer.socket && !peer.socket.destroyed) { - const index = peer.socket.infoHashes.indexOf(this.infoHash) - arrayRemove(peer.socket.infoHashes, index) + if (params.left === 0) this.complete += 1 + else this.incomplete += 1 + this.peers.set(id, { + type: params.type, + complete: params.left === 0, + peerId: params.peer_id, // as hex + ip: params.ip, + port: params.port, + socket: params.socket // only websocket + }) } - this.peers.remove(id) -} + _onAnnounceStopped (params, peer, id) { + if (!peer) { + debug('unexpected `stopped` event from peer that is not in swarm') + return // do nothing + } -Swarm.prototype._onAnnounceCompleted = function (params, peer, id) { - if (!peer) { - debug('unexpected `completed` event from peer that is not in swarm') - return this._onAnnounceStarted(params, peer, id) // treat as a start - } - if (peer.complete) { - debug('unexpected `completed` event from peer that is already completed') - return this._onAnnounceUpdate(params, peer, id) // treat as an update - } + if (peer.complete) this.complete -= 1 + else this.incomplete -= 1 - this.complete += 1 - this.incomplete -= 1 - peer.complete = true - this.peers.set(id, peer) -} + // If it's a websocket, remove this swarm's infohash from the list of active + // swarms that this peer is participating in. + if (peer.socket && !peer.socket.destroyed) { + const index = peer.socket.infoHashes.indexOf(this.infoHash) + arrayRemove(peer.socket.infoHashes, index) + } -Swarm.prototype._onAnnounceUpdate = function (params, peer, id) { - if (!peer) { - debug('unexpected `update` event from peer that is not in swarm') - return this._onAnnounceStarted(params, peer, id) // treat as a start + this.peers.remove(id) } - if (!peer.complete && params.left === 0) { + _onAnnounceCompleted (params, peer, id) { + if (!peer) { + debug('unexpected `completed` event from peer that is not in swarm') + return this._onAnnounceStarted(params, peer, id) // treat as a start + } + if (peer.complete) { + debug('unexpected `completed` event from peer that is already completed') + return this._onAnnounceUpdate(params, peer, id) // treat as an update + } + this.complete += 1 this.incomplete -= 1 peer.complete = true + this.peers.set(id, peer) } - this.peers.set(id, peer) -} -Swarm.prototype._getPeers = function (numwant, ownPeerId, isWebRTC) { - const peers = [] - const ite = randomIterate(this.peers.keys) - let peerId - while ((peerId = ite()) && peers.length < numwant) { - // Don't mark the peer as most recently used on announce - const peer = this.peers.peek(peerId) - if (!peer) continue - if (isWebRTC && peer.peerId === ownPeerId) continue // don't send peer to itself - if ((isWebRTC && peer.type !== 'ws') || (!isWebRTC && peer.type === 'ws')) continue // send proper peer type - peers.push(peer) + _onAnnounceUpdate (params, peer, id) { + if (!peer) { + debug('unexpected `update` event from peer that is not in swarm') + return this._onAnnounceStarted(params, peer, id) // treat as a start + } + + if (!peer.complete && params.left === 0) { + this.complete += 1 + this.incomplete -= 1 + peer.complete = true + } + this.peers.set(id, peer) + } + + _getPeers (numwant, ownPeerId, isWebRTC) { + const peers = [] + const ite = randomIterate(this.peers.keys) + let peerId + while ((peerId = ite()) && peers.length < numwant) { + // Don't mark the peer as most recently used on announce + const peer = this.peers.peek(peerId) + if (!peer) continue + if (isWebRTC && peer.peerId === ownPeerId) continue // don't send peer to itself + if ((isWebRTC && peer.type !== 'ws') || (!isWebRTC && peer.type === 'ws')) continue // send proper peer type + peers.push(peer) + } + return peers } - return peers } + +module.exports = Swarm diff --git a/package.json b/package.json index 401c7970..eb387f27 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bittorrent-tracker", "description": "Simple, robust, BitTorrent tracker (client & server) implementation", - "version": "9.17.0", + "version": "9.18.2", "author": { "name": "WebTorrent LLC", "email": "feross@webtorrent.io", @@ -14,47 +14,53 @@ "./lib/common-node.js": false, "./lib/client/http-tracker.js": false, "./lib/client/udp-tracker.js": false, - "./server.js": false + "./server.js": false, + "socks": false }, "chromeapp": { "./server.js": false, - "dgram": "chrome-dgram" + "dgram": "chrome-dgram", + "socks": false }, "bugs": { "url": "https://github.com/webtorrent/bittorrent-tracker/issues" }, "dependencies": { "bencode": "^2.0.1", - "bittorrent-peerid": "^1.3.2", - "bn.js": "^5.1.1", - "chrome-dgram": "^3.0.4", + "bittorrent-peerid": "^1.3.3", + "bn.js": "^5.2.0", + "chrome-dgram": "^3.0.6", + "clone": "^1.0.2", "compact2string": "^1.4.1", "debug": "^4.1.1", "ip": "^1.1.5", "lru": "^3.1.0", "minimist": "^1.2.5", "once": "^1.4.0", - "queue-microtask": "^1.2.2", + "queue-microtask": "^1.2.3", "random-iterate": "^1.0.1", "randombytes": "^2.1.0", - "run-parallel": "^1.1.9", - "run-series": "^1.1.8", + "run-parallel": "^1.2.0", + "run-series": "^1.1.9", "simple-get": "^4.0.0", - "simple-peer": "^9.7.1", - "simple-websocket": "^9.0.0", + "simple-peer": "^9.11.0", + "simple-websocket": "^9.1.0", + "socks": "^2.0.0", "string2compact": "^1.3.0", "unordered-array-remove": "^1.0.2", - "ws": "^7.3.0" + "ws": "^7.4.5" }, "devDependencies": { - "magnet-uri": "^5.2.4", + "@webtorrent/semantic-release-config": "1.0.7", + "magnet-uri": "6.2.0", + "semantic-release": "17.4.7", "standard": "*", - "tape": "^5.0.0", - "webtorrent-fixtures": "^1.7.3", - "wrtc": "^0.4.4" + "tape": "5.3.1", + "webtorrent-fixtures": "1.7.5", + "wrtc": "0.4.7" }, "engines": { - "node": ">=10" + "node": ">=12" }, "keywords": [ "bittorrent", @@ -69,14 +75,15 @@ "license": "MIT", "main": "index.js", "optionalDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "bufferutil": "^4.0.3", + "utf-8-validate": "^5.0.5" }, "repository": { "type": "git", "url": "git://github.com/webtorrent/bittorrent-tracker.git" }, "scripts": { + "preversion": "npm run update-authors", "test": "standard && tape test/*.js", "update-authors": "./tools/update-authors.sh" }, @@ -97,9 +104,9 @@ "renovate": { "extends": [ "github>webtorrent/renovate-config" - ], - "lockFileMaintenance": { - "enabled": false - } + ] + }, + "release": { + "extends": "@webtorrent/semantic-release-config" } } diff --git a/server.js b/server.js index e490d7a5..3bdbea71 100644 --- a/server.js +++ b/server.js @@ -239,11 +239,11 @@ class Server extends EventEmitter { }) }) - const isSeederOnly = peer => { return peer.seeder && peer.leecher === false } - const isLeecherOnly = peer => { return peer.leecher && peer.seeder === false } - const isSeederAndLeecher = peer => { return peer.seeder && peer.leecher } - const isIPv4 = peer => { return peer.ipv4 } - const isIPv6 = peer => { return peer.ipv6 } + const isSeederOnly = peer => peer.seeder && peer.leecher === false + const isLeecherOnly = peer => peer.leecher && peer.seeder === false + const isSeederAndLeecher = peer => peer.seeder && peer.leecher + const isIPv4 = peer => peer.ipv4 + const isIPv6 = peer => peer.ipv6 const stats = { torrents: infoHashes.length, @@ -588,7 +588,7 @@ class Server extends EventEmitter { event: 'stopped', numwant: 0, peer_id: socket.peerId - }, noop) + }) } }) } @@ -678,26 +678,16 @@ class Server extends EventEmitter { const peers = response.peers // Find IPv4 peers - response.peers = string2compact(peers.filter(peer => { - return common.IPV4_RE.test(peer.ip) - }).map(peer => { - return `${peer.ip}:${peer.port}` - })) + response.peers = string2compact(peers.filter(peer => common.IPV4_RE.test(peer.ip)).map(peer => `${peer.ip}:${peer.port}`)) // Find IPv6 peers - response.peers6 = string2compact(peers.filter(peer => { - return common.IPV6_RE.test(peer.ip) - }).map(peer => { - return `[${peer.ip}]:${peer.port}` - })) + response.peers6 = string2compact(peers.filter(peer => common.IPV6_RE.test(peer.ip)).map(peer => `[${peer.ip}]:${peer.port}`)) } else if (params.compact === 0) { // IPv6 peers are not separate for non-compact responses - response.peers = response.peers.map(peer => { - return { - 'peer id': common.hexToBinary(peer.peerId), - ip: peer.ip, - port: peer.port - } - }) + response.peers = response.peers.map(peer => ({ + 'peer id': common.hexToBinary(peer.peerId), + ip: peer.ip, + port: peer.port + })) } // else, return full peer objects (used for websocket responses) cb(null, response) @@ -712,24 +702,22 @@ class Server extends EventEmitter { params.info_hash = Object.keys(this.torrents) } - series(params.info_hash.map(infoHash => { - return cb => { - this.getSwarm(infoHash, (err, swarm) => { - if (err) return cb(err) - if (swarm) { - swarm.scrape(params, (err, scrapeInfo) => { - if (err) return cb(err) - cb(null, { - infoHash, - complete: (scrapeInfo && scrapeInfo.complete) || 0, - incomplete: (scrapeInfo && scrapeInfo.incomplete) || 0 - }) + series(params.info_hash.map(infoHash => cb => { + this.getSwarm(infoHash, (err, swarm) => { + if (err) return cb(err) + if (swarm) { + swarm.scrape(params, (err, scrapeInfo) => { + if (err) return cb(err) + cb(null, { + infoHash, + complete: (scrapeInfo && scrapeInfo.complete) || 0, + incomplete: (scrapeInfo && scrapeInfo.incomplete) || 0 }) - } else { - cb(null, { infoHash, complete: 0, incomplete: 0 }) - } - }) - } + }) + } else { + cb(null, { infoHash, complete: 0, incomplete: 0 }) + } + }) }), (err, results) => { if (err) return cb(err) diff --git a/test/client-large-torrent.js b/test/client-large-torrent.js index cec42a08..a72f9cb0 100644 --- a/test/client-large-torrent.js +++ b/test/client-large-torrent.js @@ -8,7 +8,7 @@ const peerId = Buffer.from('01234567890123456789') function testLargeTorrent (t, serverType) { t.plan(9) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.sintel.parsedTorrent.infoHash, peerId, @@ -18,24 +18,24 @@ function testLargeTorrent (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.update() - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') @@ -50,14 +50,14 @@ function testLargeTorrent (t, serverType) { }) } -test('http: large torrent: client.start()', function (t) { +test('http: large torrent: client.start()', t => { testLargeTorrent(t, 'http') }) -test('udp: large torrent: client.start()', function (t) { +test('udp: large torrent: client.start()', t => { testLargeTorrent(t, 'udp') }) -test('ws: large torrent: client.start()', function (t) { +test('ws: large torrent: client.start()', t => { testLargeTorrent(t, 'ws') }) diff --git a/test/client-magnet.js b/test/client-magnet.js index 8bbe9052..7138cbd9 100644 --- a/test/client-magnet.js +++ b/test/client-magnet.js @@ -11,7 +11,7 @@ function testMagnet (t, serverType) { const parsedTorrent = magnet(fixtures.leaves.magnetURI) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: parsedTorrent.infoHash, announce: announceUrl, @@ -21,24 +21,24 @@ function testMagnet (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.update() - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') @@ -53,14 +53,14 @@ function testMagnet (t, serverType) { }) } -test('http: magnet: client.start/update/stop()', function (t) { +test('http: magnet: client.start/update/stop()', t => { testMagnet(t, 'http') }) -test('udp: magnet: client.start/update/stop()', function (t) { +test('udp: magnet: client.start/update/stop()', t => { testMagnet(t, 'udp') }) -test('ws: magnet: client.start/update/stop()', function (t) { +test('ws: magnet: client.start/update/stop()', t => { testMagnet(t, 'ws') }) diff --git a/test/client-ws-socket-pool.js b/test/client-ws-socket-pool.js index 605dce66..4c041c2a 100644 --- a/test/client-ws-socket-pool.js +++ b/test/client-ws-socket-pool.js @@ -6,10 +6,10 @@ const test = require('tape') const peerId = Buffer.from('01234567890123456789') const port = 6681 -test('ensure client.destroy() callback is called with re-used websockets in socketPool', function (t) { +test('ensure client.destroy() callback is called with re-used websockets in socketPool', t => { t.plan(4) - common.createServer(t, 'ws', function (server, announceUrl) { + common.createServer(t, 'ws', (server, announceUrl) => { const client1 = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -19,12 +19,12 @@ test('ensure client.destroy() callback is called with re-used websockets in sock }) common.mockWebsocketTracker(client1) - client1.on('error', function (err) { t.error(err) }) - client1.on('warning', function (err) { t.error(err) }) + client1.on('error', err => { t.error(err) }) + client1.on('warning', err => { t.error(err) }) client1.start() - client1.once('update', function () { + client1.once('update', () => { t.pass('got client1 update') // second ws client using same announce url will re-use the same websocket const client2 = new Client({ @@ -36,16 +36,16 @@ test('ensure client.destroy() callback is called with re-used websockets in sock }) common.mockWebsocketTracker(client2) - client2.on('error', function (err) { t.error(err) }) - client2.on('warning', function (err) { t.error(err) }) + client2.on('error', err => { t.error(err) }) + client2.on('warning', err => { t.error(err) }) client2.start() - client2.once('update', function () { + client2.once('update', () => { t.pass('got client2 update') - client1.destroy(function (err) { + client1.destroy(err => { t.error(err, 'got client1 destroy callback') - client2.destroy(function (err) { + client2.destroy(err => { t.error(err, 'got client2 destroy callback') server.close() }) diff --git a/test/client.js b/test/client.js index c34a27b6..8afab8b5 100644 --- a/test/client.js +++ b/test/client.js @@ -1,6 +1,8 @@ const Client = require('../') const common = require('./common') +const http = require('http') const fixtures = require('webtorrent-fixtures') +const net = require('net') const test = require('tape') const peerId1 = Buffer.from('01234567890123456789') @@ -11,7 +13,7 @@ const port = 6881 function testClientStart (t, serverType) { t.plan(4) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -21,17 +23,17 @@ function testClientStart (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function () { + client.once('update', () => { t.pass('got response to stop') server.close() client.destroy() @@ -42,22 +44,22 @@ function testClientStart (t, serverType) { }) } -test('http: client.start()', function (t) { +test('http: client.start()', t => { testClientStart(t, 'http') }) -test('udp: client.start()', function (t) { +test('udp: client.start()', t => { testClientStart(t, 'udp') }) -test('ws: client.start()', function (t) { +test('ws: client.start()', t => { testClientStart(t, 'ws') }) function testClientStop (t, serverType) { t.plan(4) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -67,17 +69,17 @@ function testClientStop (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - client.once('update', function () { + client.once('update', () => { t.pass('client received response to "start" message') client.stop() - client.once('update', function (data) { + client.once('update', data => { // receive one final update after calling stop t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') @@ -90,22 +92,22 @@ function testClientStop (t, serverType) { }) } -test('http: client.stop()', function (t) { +test('http: client.stop()', t => { testClientStop(t, 'http') }) -test('udp: client.stop()', function (t) { +test('udp: client.stop()', t => { testClientStop(t, 'udp') }) -test('ws: client.stop()', function (t) { +test('ws: client.stop()', t => { testClientStop(t, 'ws') }) function testClientStopDestroy (t, serverType) { t.plan(2) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -115,26 +117,26 @@ function testClientStopDestroy (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - client.once('update', function () { + client.once('update', () => { t.pass('client received response to "start" message') client.stop() - client.on('update', function () { t.fail('client should not receive update after destroy is called') }) + client.on('update', () => { t.fail('client should not receive update after destroy is called') }) // Call destroy() in the same tick as stop(), but the message should still // be received by the server, though obviously the client won't receive the // response. client.destroy() - server.once('stop', function (peer, params) { + server.once('stop', (peer, params) => { t.pass('server received "stop" message') - setTimeout(function () { + setTimeout(() => { // give the websocket server time to finish in progress (stream) messages // to peers server.close() @@ -144,22 +146,22 @@ function testClientStopDestroy (t, serverType) { }) } -test('http: client.stop(); client.destroy()', function (t) { +test('http: client.stop(); client.destroy()', t => { testClientStopDestroy(t, 'http') }) -test('udp: client.stop(); client.destroy()', function (t) { +test('udp: client.stop(); client.destroy()', t => { testClientStopDestroy(t, 'udp') }) -test('ws: client.stop(); client.destroy()', function (t) { +test('ws: client.stop(); client.destroy()', t => { testClientStopDestroy(t, 'ws') }) function testClientUpdate (t, serverType) { t.plan(4) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -169,25 +171,25 @@ function testClientUpdate (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.setInterval(500) client.start() - client.once('update', function () { + client.once('update', () => { client.setInterval(500) // after interval, we should get another update - client.once('update', function (data) { + client.once('update', data => { // received an update! t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function () { + client.once('update', () => { t.pass('got response to stop') server.close() client.destroy() @@ -197,22 +199,22 @@ function testClientUpdate (t, serverType) { }) } -test('http: client.update()', function (t) { +test('http: client.update()', t => { testClientUpdate(t, 'http') }) -test('udp: client.update()', function (t) { +test('udp: client.update()', t => { testClientUpdate(t, 'udp') }) -test('ws: client.update()', function (t) { +test('ws: client.update()', t => { testClientUpdate(t, 'ws') }) function testClientScrape (t, serverType) { t.plan(4) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -222,10 +224,10 @@ function testClientScrape (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('scrape', function (data) { + client.once('scrape', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') @@ -239,22 +241,22 @@ function testClientScrape (t, serverType) { }) } -test('http: client.scrape()', function (t) { +test('http: client.scrape()', t => { testClientScrape(t, 'http') }) -test('udp: client.scrape()', function (t) { +test('udp: client.scrape()', t => { testClientScrape(t, 'udp') }) -test('ws: client.scrape()', function (t) { +test('ws: client.scrape()', t => { testClientScrape(t, 'ws') }) function testClientAnnounceWithParams (t, serverType) { t.plan(5) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -263,22 +265,22 @@ function testClientAnnounceWithParams (t, serverType) { wrtc: {} }) - server.on('start', function (peer, params) { + server.on('start', (peer, params) => { t.equal(params.testParam, 'this is a test') }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function () { + client.once('update', () => { t.pass('got response to stop') server.close() client.destroy() @@ -291,24 +293,24 @@ function testClientAnnounceWithParams (t, serverType) { }) } -test('http: client.announce() with params', function (t) { +test('http: client.announce() with params', t => { testClientAnnounceWithParams(t, 'http') }) -test('ws: client.announce() with params', function (t) { +test('ws: client.announce() with params', t => { testClientAnnounceWithParams(t, 'ws') }) function testClientGetAnnounceOpts (t, serverType) { t.plan(5) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, peerId: peerId1, port, - getAnnounceOpts: function () { + getAnnounceOpts () { return { testParam: 'this is a test' } @@ -316,22 +318,22 @@ function testClientGetAnnounceOpts (t, serverType) { wrtc: {} }) - server.on('start', function (peer, params) { + server.on('start', (peer, params) => { t.equal(params.testParam, 'this is a test') }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') client.stop() - client.once('update', function () { + client.once('update', () => { t.pass('got response to stop') server.close() client.destroy() @@ -342,18 +344,18 @@ function testClientGetAnnounceOpts (t, serverType) { }) } -test('http: client `opts.getAnnounceOpts`', function (t) { +test('http: client `opts.getAnnounceOpts`', t => { testClientGetAnnounceOpts(t, 'http') }) -test('ws: client `opts.getAnnounceOpts`', function (t) { +test('ws: client `opts.getAnnounceOpts`', t => { testClientGetAnnounceOpts(t, 'ws') }) function testClientAnnounceWithNumWant (t, serverType) { t.plan(4) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client1 = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: [announceUrl], @@ -363,11 +365,11 @@ function testClientAnnounceWithNumWant (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client1) - client1.on('error', function (err) { t.error(err) }) - client1.on('warning', function (err) { t.error(err) }) + client1.on('error', err => { t.error(err) }) + client1.on('warning', err => { t.error(err) }) client1.start() - client1.once('update', function () { + client1.once('update', () => { const client2 = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -377,11 +379,11 @@ function testClientAnnounceWithNumWant (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client2) - client2.on('error', function (err) { t.error(err) }) - client2.on('warning', function (err) { t.error(err) }) + client2.on('error', err => { t.error(err) }) + client2.on('warning', err => { t.error(err) }) client2.start() - client2.once('update', function () { + client2.once('update', () => { const client3 = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -391,11 +393,11 @@ function testClientAnnounceWithNumWant (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client3) - client3.on('error', function (err) { t.error(err) }) - client3.on('warning', function (err) { t.error(err) }) + client3.on('error', err => { t.error(err) }) + client3.on('warning', err => { t.error(err) }) client3.start({ numwant: 1 }) - client3.on('peer', function () { + client3.on('peer', () => { t.pass('got one peer (this should only fire once)') let num = 3 @@ -405,19 +407,19 @@ function testClientAnnounceWithNumWant (t, serverType) { } client1.stop() - client1.once('update', function () { + client1.once('update', () => { t.pass('got response to stop (client1)') client1.destroy() tryCloseServer() }) client2.stop() - client2.once('update', function () { + client2.once('update', () => { t.pass('got response to stop (client2)') client2.destroy() tryCloseServer() }) client3.stop() - client3.once('update', function () { + client3.once('update', () => { t.pass('got response to stop (client3)') client3.destroy() tryCloseServer() @@ -428,21 +430,21 @@ function testClientAnnounceWithNumWant (t, serverType) { }) } -test('http: client announce with numwant', function (t) { +test('http: client announce with numwant', t => { testClientAnnounceWithNumWant(t, 'http') }) -test('udp: client announce with numwant', function (t) { +test('udp: client announce with numwant', t => { testClientAnnounceWithNumWant(t, 'udp') }) -test('http: userAgent', function (t) { +test('http: userAgent', t => { t.plan(2) - common.createServer(t, 'http', function (server, announceUrl) { + common.createServer(t, 'http', (server, announceUrl) => { // Confirm that user-agent header is set - server.http.on('request', function (req, res) { - t.ok(req.headers['user-agent'].indexOf('WebTorrent') !== -1) + server.http.on('request', (req, res) => { + t.ok(req.headers['user-agent'].includes('WebTorrent')) }) const client = new Client({ @@ -454,10 +456,10 @@ test('http: userAgent', function (t) { wrtc: {} }) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function (data) { + client.once('update', data => { t.equal(data.announce, announceUrl) server.close() @@ -471,7 +473,7 @@ test('http: userAgent', function (t) { function testSupportedTracker (t, serverType) { t.plan(1) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -481,12 +483,12 @@ function testSupportedTracker (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - client.once('update', function (data) { + client.once('update', data => { t.pass('tracker is valid') server.close() @@ -495,15 +497,15 @@ function testSupportedTracker (t, serverType) { }) } -test('http: valid tracker port', function (t) { +test('http: valid tracker port', t => { testSupportedTracker(t, 'http') }) -test('udp: valid tracker port', function (t) { +test('udp: valid tracker port', t => { testSupportedTracker(t, 'udp') }) -test('ws: valid tracker port', function (t) { +test('ws: valid tracker port', t => { testSupportedTracker(t, 'ws') }) @@ -518,50 +520,103 @@ function testUnsupportedTracker (t, announceUrl) { wrtc: {} }) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.ok(err.message.includes('tracker'), 'got warning') client.destroy() }) } -test('unsupported tracker protocol', function (t) { +test('unsupported tracker protocol', t => { testUnsupportedTracker(t, 'badprotocol://127.0.0.1:8080/announce') }) -test('http: invalid tracker port', function (t) { +test('http: invalid tracker port', t => { testUnsupportedTracker(t, 'http://127.0.0.1:69691337/announce') }) -test('http: invalid tracker url', function (t) { +test('http: invalid tracker url', t => { testUnsupportedTracker(t, 'http:') }) -test('http: invalid tracker url with slash', function (t) { +test('http: invalid tracker url with slash', t => { testUnsupportedTracker(t, 'http://') }) -test('udp: invalid tracker port', function (t) { +test('udp: invalid tracker port', t => { testUnsupportedTracker(t, 'udp://127.0.0.1:69691337') }) -test('udp: invalid tracker url', function (t) { +test('udp: invalid tracker url', t => { testUnsupportedTracker(t, 'udp:') }) -test('udp: invalid tracker url with slash', function (t) { +test('udp: invalid tracker url with slash', t => { testUnsupportedTracker(t, 'udp://') }) -test('ws: invalid tracker port', function (t) { +test('ws: invalid tracker port', t => { testUnsupportedTracker(t, 'ws://127.0.0.1:69691337') }) -test('ws: invalid tracker url', function (t) { +test('ws: invalid tracker url', t => { testUnsupportedTracker(t, 'ws:') }) -test('ws: invalid tracker url with slash', function (t) { +test('ws: invalid tracker url with slash', t => { testUnsupportedTracker(t, 'ws://') }) + +function testClientStartHttpAgent (t, serverType) { + t.plan(5) + + common.createServer(t, serverType, function (server, announceUrl) { + const agent = new http.Agent() + let agentUsed = false + agent.createConnection = function (opts, fn) { + agentUsed = true + return net.createConnection(opts, fn) + } + const client = new Client({ + infoHash: fixtures.leaves.parsedTorrent.infoHash, + announce: announceUrl, + peerId: peerId1, + port: port, + wrtc: {}, + proxyOpts: { + httpAgent: agent + } + }) + + if (serverType === 'ws') common.mockWebsocketTracker(client) + client.on('error', function (err) { t.error(err) }) + client.on('warning', function (err) { t.error(err) }) + + client.once('update', function (data) { + t.equal(data.announce, announceUrl) + t.equal(typeof data.complete, 'number') + t.equal(typeof data.incomplete, 'number') + + t.ok(agentUsed) + + client.stop() + + client.once('update', function () { + t.pass('got response to stop') + server.close() + client.destroy() + }) + }) + + client.start() + }) +} + +test('http: client.start(httpAgent)', function (t) { + testClientStartHttpAgent(t, 'http') +}) + +test('ws: client.start(httpAgent)', function (t) { + testClientStartHttpAgent(t, 'ws') +}) diff --git a/test/common.js b/test/common.js index 9282284d..9bd098ed 100644 --- a/test/common.js +++ b/test/common.js @@ -1,6 +1,6 @@ const Server = require('../').Server -exports.createServer = function (t, opts, cb) { +exports.createServer = (t, opts, cb) => { if (typeof opts === 'string') opts = { serverType: opts } opts.http = (opts.serverType === 'http') @@ -9,31 +9,31 @@ exports.createServer = function (t, opts, cb) { const server = new Server(opts) - server.on('error', function (err) { t.error(err) }) - server.on('warning', function (err) { t.error(err) }) + server.on('error', err => { t.error(err) }) + server.on('warning', err => { t.error(err) }) - server.listen(0, function () { + server.listen(0, () => { const port = server[opts.serverType].address().port let announceUrl if (opts.serverType === 'http') { - announceUrl = 'http://127.0.0.1:' + port + '/announce' + announceUrl = `http://127.0.0.1:${port}/announce` } else if (opts.serverType === 'udp') { - announceUrl = 'udp://127.0.0.1:' + port + announceUrl = `udp://127.0.0.1:${port}` } else if (opts.serverType === 'ws') { - announceUrl = 'ws://127.0.0.1:' + port + announceUrl = `ws://127.0.0.1:${port}` } cb(server, announceUrl) }) } -exports.mockWebsocketTracker = function (client) { - client._trackers[0]._generateOffers = function (numwant, cb) { +exports.mockWebsocketTracker = client => { + client._trackers[0]._generateOffers = (numwant, cb) => { const offers = [] for (let i = 0; i < numwant; i++) { - offers.push({ fake_offer: 'fake_offer_' + i }) + offers.push({ fake_offer: `fake_offer_${i}` }) } - process.nextTick(function () { + process.nextTick(() => { cb(offers) }) } diff --git a/test/destroy.js b/test/destroy.js index 5888491c..27d47605 100644 --- a/test/destroy.js +++ b/test/destroy.js @@ -9,7 +9,7 @@ const port = 6881 function testNoEventsAfterDestroy (t, serverType) { t.plan(1) - common.createServer(t, serverType, function (server, announceUrl) { + common.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -19,10 +19,10 @@ function testNoEventsAfterDestroy (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) - client.once('update', function () { + client.once('update', () => { t.fail('no "update" event should fire, since client is destroyed') }) @@ -30,21 +30,21 @@ function testNoEventsAfterDestroy (t, serverType) { client.update() client.destroy() - setTimeout(function () { + setTimeout(() => { t.pass('wait to see if any events are fired') server.close() }, 1000) }) } -test('http: no "update" events after destroy()', function (t) { +test('http: no "update" events after destroy()', t => { testNoEventsAfterDestroy(t, 'http') }) -test('udp: no "update" events after destroy()', function (t) { +test('udp: no "update" events after destroy()', t => { testNoEventsAfterDestroy(t, 'udp') }) -test('ws: no "update" events after destroy()', function (t) { +test('ws: no "update" events after destroy()', t => { testNoEventsAfterDestroy(t, 'ws') }) diff --git a/test/evict.js b/test/evict.js index 75d590ce..a256a916 100644 --- a/test/evict.js +++ b/test/evict.js @@ -20,11 +20,11 @@ function serverTest (t, serverType, serverFamily) { peersCacheLength: 2 // LRU cache can only contain a max of 2 peers } - common.createServer(t, opts, function (server) { + common.createServer(t, opts, server => { // Not using announceUrl param from `common.createServer()` since we // want to control IPv4 vs IPv6. const port = server[serverType].address().port - const announceUrl = serverType + '://' + hostname + ':' + port + '/announce' + const announceUrl = `${serverType}://${hostname}:${port}/announce` const client1 = new Client({ infoHash, @@ -37,7 +37,7 @@ function serverTest (t, serverType, serverFamily) { client1.start() - client1.once('update', function (data) { + client1.once('update', data => { const client2 = new Client({ infoHash, announce: [announceUrl], @@ -49,15 +49,15 @@ function serverTest (t, serverType, serverFamily) { client2.start() - client2.once('update', function (data) { - server.getSwarm(infoHash, function (err, swarm) { + client2.once('update', data => { + server.getSwarm(infoHash, (err, swarm) => { t.error(err) t.equal(swarm.complete + swarm.incomplete, 2) // Ensure that first peer is evicted when a third one is added let evicted = false - swarm.peers.once('evict', function (evictedPeer) { + swarm.peers.once('evict', evictedPeer => { t.equal(evictedPeer.value.peerId, peerId.toString('hex')) t.equal(swarm.complete + swarm.incomplete, 2) evicted = true @@ -74,23 +74,23 @@ function serverTest (t, serverType, serverFamily) { client3.start() - client3.once('update', function (data) { + client3.once('update', data => { t.ok(evicted, 'client1 was evicted from server before client3 gets response') t.equal(swarm.complete + swarm.incomplete, 2) - client1.destroy(function () { + client1.destroy(() => { t.pass('client1 destroyed') }) - client2.destroy(function () { + client2.destroy(() => { t.pass('client3 destroyed') }) - client3.destroy(function () { + client3.destroy(() => { t.pass('client3 destroyed') }) - server.close(function () { + server.close(() => { t.pass('server destroyed') }) }) @@ -100,18 +100,18 @@ function serverTest (t, serverType, serverFamily) { }) } -test('evict: ipv4 server', function (t) { +test('evict: ipv4 server', t => { serverTest(t, 'http', 'inet') }) -test('evict: http ipv6 server', function (t) { +test('evict: http ipv6 server', t => { serverTest(t, 'http', 'inet6') }) -test('evict: udp server', function (t) { +test('evict: udp server', t => { serverTest(t, 'udp', 'inet') }) -test('evict: ws server', function (t) { +test('evict: ws server', t => { serverTest(t, 'ws', 'inet') }) diff --git a/test/filter.js b/test/filter.js index 21bb4d0b..fee7dd77 100644 --- a/test/filter.js +++ b/test/filter.js @@ -9,8 +9,8 @@ function testFilterOption (t, serverType) { t.plan(8) const opts = { serverType } // this is test-suite-only option - opts.filter = function (infoHash, params, cb) { - process.nextTick(function () { + opts.filter = (infoHash, params, cb) => { + process.nextTick(() => { if (infoHash === fixtures.alice.parsedTorrent.infoHash) { cb(new Error('disallowed info_hash (Alice)')) } else { @@ -19,7 +19,7 @@ function testFilterOption (t, serverType) { }) } - common.createServer(t, opts, function (server, announceUrl) { + common.createServer(t, opts, (server, announceUrl) => { const client1 = new Client({ infoHash: fixtures.alice.parsedTorrent.infoHash, announce: announceUrl, @@ -28,13 +28,13 @@ function testFilterOption (t, serverType) { wrtc: {} }) - client1.on('error', function (err) { t.error(err) }) + client1.on('error', err => { t.error(err) }) if (serverType === 'ws') common.mockWebsocketTracker(client1) - client1.once('warning', function (err) { + client1.once('warning', err => { t.ok(err.message.includes('disallowed info_hash (Alice)'), 'got client warning') - client1.destroy(function () { + client1.destroy(() => { t.pass('client1 destroyed') const client2 = new Client({ @@ -46,16 +46,16 @@ function testFilterOption (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client2) - client2.on('error', function (err) { t.error(err) }) - client2.on('warning', function (err) { t.error(err) }) + client2.on('error', err => { t.error(err) }) + client2.on('warning', err => { t.error(err) }) - client2.on('update', function () { + client2.on('update', () => { t.pass('got announce') - client2.destroy(function () { t.pass('client2 destroyed') }) - server.close(function () { t.pass('server closed') }) + client2.destroy(() => { t.pass('client2 destroyed') }) + server.close(() => { t.pass('server closed') }) }) - server.on('start', function () { + server.on('start', () => { t.equal(Object.keys(server.torrents).length, 1) }) @@ -64,7 +64,7 @@ function testFilterOption (t, serverType) { }) server.removeAllListeners('warning') - server.once('warning', function (err) { + server.once('warning', err => { t.ok(err.message.includes('disallowed info_hash (Alice)'), 'got server warning') t.equal(Object.keys(server.torrents).length, 0) }) @@ -73,15 +73,15 @@ function testFilterOption (t, serverType) { }) } -test('http: filter option blocks tracker from tracking torrent', function (t) { +test('http: filter option blocks tracker from tracking torrent', t => { testFilterOption(t, 'http') }) -test('udp: filter option blocks tracker from tracking torrent', function (t) { +test('udp: filter option blocks tracker from tracking torrent', t => { testFilterOption(t, 'udp') }) -test('ws: filter option blocks tracker from tracking torrent', function (t) { +test('ws: filter option blocks tracker from tracking torrent', t => { testFilterOption(t, 'ws') }) @@ -89,8 +89,8 @@ function testFilterCustomError (t, serverType) { t.plan(8) const opts = { serverType } // this is test-suite-only option - opts.filter = function (infoHash, params, cb) { - process.nextTick(function () { + opts.filter = (infoHash, params, cb) => { + process.nextTick(() => { if (infoHash === fixtures.alice.parsedTorrent.infoHash) { cb(new Error('alice blocked')) } else { @@ -99,7 +99,7 @@ function testFilterCustomError (t, serverType) { }) } - common.createServer(t, opts, function (server, announceUrl) { + common.createServer(t, opts, (server, announceUrl) => { const client1 = new Client({ infoHash: fixtures.alice.parsedTorrent.infoHash, announce: announceUrl, @@ -108,13 +108,13 @@ function testFilterCustomError (t, serverType) { wrtc: {} }) - client1.on('error', function (err) { t.error(err) }) + client1.on('error', err => { t.error(err) }) if (serverType === 'ws') common.mockWebsocketTracker(client1) - client1.once('warning', function (err) { + client1.once('warning', err => { t.ok(/alice blocked/.test(err.message), 'got client warning') - client1.destroy(function () { + client1.destroy(() => { t.pass('client1 destroyed') const client2 = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, @@ -125,16 +125,16 @@ function testFilterCustomError (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client2) - client2.on('error', function (err) { t.error(err) }) - client2.on('warning', function (err) { t.error(err) }) + client2.on('error', err => { t.error(err) }) + client2.on('warning', err => { t.error(err) }) - client2.on('update', function () { + client2.on('update', () => { t.pass('got announce') - client2.destroy(function () { t.pass('client2 destroyed') }) - server.close(function () { t.pass('server closed') }) + client2.destroy(() => { t.pass('client2 destroyed') }) + server.close(() => { t.pass('server closed') }) }) - server.on('start', function () { + server.on('start', () => { t.equal(Object.keys(server.torrents).length, 1) }) @@ -143,7 +143,7 @@ function testFilterCustomError (t, serverType) { }) server.removeAllListeners('warning') - server.once('warning', function (err) { + server.once('warning', err => { t.ok(/alice blocked/.test(err.message), 'got server warning') t.equal(Object.keys(server.torrents).length, 0) }) @@ -152,14 +152,14 @@ function testFilterCustomError (t, serverType) { }) } -test('http: filter option with custom error', function (t) { +test('http: filter option with custom error', t => { testFilterCustomError(t, 'http') }) -test('udp: filter option filter option with custom error', function (t) { +test('udp: filter option filter option with custom error', t => { testFilterCustomError(t, 'udp') }) -test('ws: filter option filter option with custom error', function (t) { +test('ws: filter option filter option with custom error', t => { testFilterCustomError(t, 'ws') }) diff --git a/test/querystring.js b/test/querystring.js index a507c360..2ce20fe2 100644 --- a/test/querystring.js +++ b/test/querystring.js @@ -2,7 +2,7 @@ const common = require('../lib/common') const test = require('tape') // https://github.com/webtorrent/webtorrent/issues/196 -test('encode special chars +* in http tracker urls', function (t) { +test('encode special chars +* in http tracker urls', t => { const q = Object.create(null) q.info_hash = Buffer.from('a2a15537542b22925ad10486bf7a8b2a9c42f0d1', 'hex').toString('binary') diff --git a/test/request-handler.js b/test/request-handler.js index 9eecb998..b60f9674 100644 --- a/test/request-handler.js +++ b/test/request-handler.js @@ -13,11 +13,11 @@ function testRequestHandler (t, serverType) { class Swarm extends Server.Swarm { announce (params, cb) { - super.announce(params, function (err, response) { - if (err) return cb(response) + super.announce(params, (err, response) => { + if (cb && err) return cb(response) response.complete = 246 response.extraData = 'hi' - cb(null, response) + if (cb) cb(null, response) }) } } @@ -25,11 +25,11 @@ function testRequestHandler (t, serverType) { // Use a custom Swarm implementation for this test only const OldSwarm = Server.Swarm Server.Swarm = Swarm - t.on('end', function () { + t.on('end', () => { Server.Swarm = OldSwarm }) - common.createServer(t, opts, function (server, announceUrl) { + common.createServer(t, opts, (server, announceUrl) => { const client1 = new Client({ infoHash: fixtures.alice.parsedTorrent.infoHash, announce: announceUrl, @@ -38,22 +38,22 @@ function testRequestHandler (t, serverType) { wrtc: {} }) - client1.on('error', function (err) { t.error(err) }) + client1.on('error', err => { t.error(err) }) if (serverType === 'ws') common.mockWebsocketTracker(client1) - server.once('start', function () { + server.once('start', () => { t.pass('got start message from client1') }) - client1.once('update', function (data) { + client1.once('update', data => { t.equal(data.complete, 246) t.equal(data.extraData.toString(), 'hi') - client1.destroy(function () { + client1.destroy(() => { t.pass('client1 destroyed') }) - server.close(function () { + server.close(() => { t.pass('server destroyed') }) }) @@ -62,11 +62,11 @@ function testRequestHandler (t, serverType) { }) } -test('http: request handler option intercepts announce requests and responses', function (t) { +test('http: request handler option intercepts announce requests and responses', t => { testRequestHandler(t, 'http') }) -test('ws: request handler option intercepts announce requests and responses', function (t) { +test('ws: request handler option intercepts announce requests and responses', t => { testRequestHandler(t, 'ws') }) diff --git a/test/scrape.js b/test/scrape.js index 9323f85e..047d2495 100644 --- a/test/scrape.js +++ b/test/scrape.js @@ -10,7 +10,7 @@ const test = require('tape') const peerId = Buffer.from('01234567890123456789') function testSingle (t, serverType) { - commonTest.createServer(t, serverType, function (server, announceUrl) { + commonTest.createServer(t, serverType, (server, announceUrl) => { const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, announce: announceUrl, @@ -20,51 +20,51 @@ function testSingle (t, serverType) { }) if (serverType === 'ws') common.mockWebsocketTracker(client) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.scrape() - client.on('scrape', function (data) { + client.on('scrape', data => { t.equal(data.announce, announceUrl) t.equal(data.infoHash, fixtures.leaves.parsedTorrent.infoHash) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') t.equal(typeof data.downloaded, 'number') client.destroy() - server.close(function () { + server.close(() => { t.end() }) }) }) } -test('http: single info_hash scrape', function (t) { +test('http: single info_hash scrape', t => { testSingle(t, 'http') }) -test('udp: single info_hash scrape', function (t) { +test('udp: single info_hash scrape', t => { testSingle(t, 'udp') }) -test('ws: single info_hash scrape', function (t) { +test('ws: single info_hash scrape', t => { testSingle(t, 'ws') }) function clientScrapeStatic (t, serverType) { - commonTest.createServer(t, serverType, function (server, announceUrl) { + commonTest.createServer(t, serverType, (server, announceUrl) => { const client = Client.scrape({ announce: announceUrl, infoHash: fixtures.leaves.parsedTorrent.infoHash, wrtc: {} - }, function (err, data) { + }, (err, data) => { t.error(err) t.equal(data.announce, announceUrl) t.equal(data.infoHash, fixtures.leaves.parsedTorrent.infoHash) t.equal(typeof data.complete, 'number') t.equal(typeof data.incomplete, 'number') t.equal(typeof data.downloaded, 'number') - server.close(function () { + server.close(() => { t.end() }) }) @@ -72,43 +72,43 @@ function clientScrapeStatic (t, serverType) { }) } -test('http: scrape using Client.scrape static method', function (t) { +test('http: scrape using Client.scrape static method', t => { clientScrapeStatic(t, 'http') }) -test('udp: scrape using Client.scrape static method', function (t) { +test('udp: scrape using Client.scrape static method', t => { clientScrapeStatic(t, 'udp') }) -test('ws: scrape using Client.scrape static method', function (t) { +test('ws: scrape using Client.scrape static method', t => { clientScrapeStatic(t, 'ws') }) // Ensure the callback function gets called when an invalid url is passed function clientScrapeStaticInvalid (t, serverType) { - let announceUrl = serverType + '://invalid.lol' + let announceUrl = `${serverType}://invalid.lol` if (serverType === 'http') announceUrl += '/announce' const client = Client.scrape({ announce: announceUrl, infoHash: fixtures.leaves.parsedTorrent.infoHash, wrtc: {} - }, function (err, data) { + }, (err, data) => { t.ok(err instanceof Error) t.end() }) if (serverType === 'ws') common.mockWebsocketTracker(client) } -test('http: scrape using Client.scrape static method (invalid url)', function (t) { +test('http: scrape using Client.scrape static method (invalid url)', t => { clientScrapeStaticInvalid(t, 'http') }) -test('udp: scrape using Client.scrape static method (invalid url)', function (t) { +test('udp: scrape using Client.scrape static method (invalid url)', t => { clientScrapeStaticInvalid(t, 'udp') }) -test('ws: scrape using Client.scrape static method (invalid url)', function (t) { +test('ws: scrape using Client.scrape static method (invalid url)', t => { clientScrapeStaticInvalid(t, 'ws') }) @@ -116,11 +116,11 @@ function clientScrapeMulti (t, serverType) { const infoHash1 = fixtures.leaves.parsedTorrent.infoHash const infoHash2 = fixtures.alice.parsedTorrent.infoHash - commonTest.createServer(t, serverType, function (server, announceUrl) { + commonTest.createServer(t, serverType, (server, announceUrl) => { Client.scrape({ infoHash: [infoHash1, infoHash2], announce: announceUrl - }, function (err, results) { + }, (err, results) => { t.error(err) t.equal(results[infoHash1].announce, announceUrl) @@ -135,35 +135,35 @@ function clientScrapeMulti (t, serverType) { t.equal(typeof results[infoHash2].incomplete, 'number') t.equal(typeof results[infoHash2].downloaded, 'number') - server.close(function () { + server.close(() => { t.end() }) }) }) } -test('http: MULTI scrape using Client.scrape static method', function (t) { +test('http: MULTI scrape using Client.scrape static method', t => { clientScrapeMulti(t, 'http') }) -test('udp: MULTI scrape using Client.scrape static method', function (t) { +test('udp: MULTI scrape using Client.scrape static method', t => { clientScrapeMulti(t, 'udp') }) -test('server: multiple info_hash scrape (manual http request)', function (t) { +test('server: multiple info_hash scrape (manual http request)', t => { t.plan(13) const binaryInfoHash1 = commonLib.hexToBinary(fixtures.leaves.parsedTorrent.infoHash) const binaryInfoHash2 = commonLib.hexToBinary(fixtures.alice.parsedTorrent.infoHash) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { const scrapeUrl = announceUrl.replace('/announce', '/scrape') - const url = scrapeUrl + '?' + commonLib.querystringStringify({ - info_hash: [binaryInfoHash1, binaryInfoHash2] - }) + const url = `${scrapeUrl}?${commonLib.querystringStringify({ + info_hash: [binaryInfoHash1, binaryInfoHash2] +})}` - get.concat(url, function (err, res, data) { + get.concat(url, (err, res, data) => { t.error(err) t.equal(res.statusCode, 200) @@ -182,17 +182,17 @@ test('server: multiple info_hash scrape (manual http request)', function (t) { t.equal(typeof data.files[binaryInfoHash2].incomplete, 'number') t.equal(typeof data.files[binaryInfoHash2].downloaded, 'number') - server.close(function () { t.pass('server closed') }) + server.close(() => { t.pass('server closed') }) }) }) }) -test('server: all info_hash scrape (manual http request)', function (t) { +test('server: all info_hash scrape (manual http request)', t => { t.plan(10) const binaryInfoHash = commonLib.hexToBinary(fixtures.leaves.parsedTorrent.infoHash) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { const scrapeUrl = announceUrl.replace('/announce', '/scrape') // announce a torrent to the tracker @@ -202,14 +202,14 @@ test('server: all info_hash scrape (manual http request)', function (t) { peerId, port: 6881 }) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - server.once('start', function () { + server.once('start', () => { // now do a scrape of everything by omitting the info_hash param - get.concat(scrapeUrl, function (err, res, data) { + get.concat(scrapeUrl, (err, res, data) => { t.error(err) t.equal(res.statusCode, 200) @@ -222,8 +222,8 @@ test('server: all info_hash scrape (manual http request)', function (t) { t.equal(typeof data.files[binaryInfoHash].incomplete, 'number') t.equal(typeof data.files[binaryInfoHash].downloaded, 'number') - client.destroy(function () { t.pass('client destroyed') }) - server.close(function () { t.pass('server closed') }) + client.destroy(() => { t.pass('client destroyed') }) + server.close(() => { t.pass('server closed') }) }) }) }) diff --git a/test/server.js b/test/server.js index 0742e953..0acfabd9 100644 --- a/test/server.js +++ b/test/server.js @@ -22,11 +22,11 @@ function serverTest (t, serverType, serverFamily) { serverType } - common.createServer(t, opts, function (server) { + common.createServer(t, opts, server => { // Not using announceUrl param from `common.createServer()` since we // want to control IPv4 vs IPv6. const port = server[serverType].address().port - const announceUrl = serverType + '://' + hostname + ':' + port + '/announce' + const announceUrl = `${serverType}://${hostname}:${port}/announce` const client1 = new Client({ infoHash, @@ -39,16 +39,16 @@ function serverTest (t, serverType, serverFamily) { client1.start() - server.once('start', function () { + server.once('start', () => { t.pass('got start message from client1') }) - client1.once('update', function (data) { + client1.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 0) t.equal(data.incomplete, 1) - server.getSwarm(infoHash, function (err, swarm) { + server.getSwarm(infoHash, (err, swarm) => { t.error(err) t.equal(Object.keys(server.torrents).length, 1) @@ -58,7 +58,7 @@ function serverTest (t, serverType, serverFamily) { const id = serverType === 'ws' ? peerId.toString('hex') - : hostname + ':6881' + : `${hostname}:6881` const peer = swarm.peers.peek(id) t.equal(peer.type, serverType) @@ -75,14 +75,14 @@ function serverTest (t, serverType, serverFamily) { client1.complete() - client1.once('update', function (data) { + client1.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 0) client1.scrape() - client1.once('scrape', function (data) { + client1.once('scrape', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 0) @@ -99,11 +99,11 @@ function serverTest (t, serverType, serverFamily) { client2.start() - server.once('start', function () { + server.once('start', () => { t.pass('got start message from client2') }) - client2.once('update', function (data) { + client2.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 1) @@ -119,38 +119,38 @@ function serverTest (t, serverType, serverFamily) { client3.start() - server.once('start', function () { + server.once('start', () => { t.pass('got start message from client3') }) - client3.once('update', function (data) { + client3.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 2) client2.stop() - client2.once('update', function (data) { + client2.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 1) - client2.destroy(function () { + client2.destroy(() => { t.pass('client2 destroyed') client3.stop() - client3.once('update', function (data) { + client3.once('update', data => { t.equal(data.announce, announceUrl) t.equal(data.complete, 1) t.equal(data.incomplete, 0) - client1.destroy(function () { + client1.destroy(() => { t.pass('client1 destroyed') }) - client3.destroy(function () { + client3.destroy(() => { t.pass('client3 destroyed') }) - server.close(function () { + server.close(() => { t.pass('server destroyed') }) }) @@ -165,18 +165,18 @@ function serverTest (t, serverType, serverFamily) { }) } -test('http ipv4 server', function (t) { +test('http ipv4 server', t => { serverTest(t, 'http', 'inet') }) -test('http ipv6 server', function (t) { +test('http ipv6 server', t => { serverTest(t, 'http', 'inet6') }) -test('udp server', function (t) { +test('udp server', t => { serverTest(t, 'udp', 'inet') }) -test('ws server', function (t) { +test('ws server', t => { serverTest(t, 'ws', 'inet') }) diff --git a/test/stats.js b/test/stats.js index c13667f9..74128c2f 100644 --- a/test/stats.js +++ b/test/stats.js @@ -9,9 +9,7 @@ const unknownPeerId = Buffer.from('01234567890123456789') function parseHtml (html) { const extractValue = /[^v^h](\d+)/ - const array = html.replace('torrents', '\n').split('\n').filter(function (line) { - return line && line.trim().length > 0 - }).map(function (line) { + const array = html.replace('torrents', '\n').split('\n').filter(line => line && line.trim().length > 0).map(line => { const a = extractValue.exec(line) if (a) { return parseInt(a[1]) @@ -31,13 +29,13 @@ function parseHtml (html) { } } -test('server: get empty stats', function (t) { +test('server: get empty stats', t => { t.plan(11) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { const url = announceUrl.replace('/announce', '/stats') - get.concat(url, function (err, res, data) { + get.concat(url, (err, res, data) => { t.error(err) const stats = parseHtml(data.toString()) @@ -51,15 +49,15 @@ test('server: get empty stats', function (t) { t.equal(stats.peersIPv4, 0) t.equal(stats.peersIPv6, 0) - server.close(function () { t.pass('server closed') }) + server.close(() => { t.pass('server closed') }) }) }) }) -test('server: get empty stats with json header', function (t) { +test('server: get empty stats with json header', t => { t.plan(11) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { const opts = { url: announceUrl.replace('/announce', '/stats'), headers: { @@ -68,7 +66,7 @@ test('server: get empty stats with json header', function (t) { json: true } - get.concat(opts, function (err, res, stats) { + get.concat(opts, (err, res, stats) => { t.error(err) t.equal(res.statusCode, 200) @@ -81,21 +79,21 @@ test('server: get empty stats with json header', function (t) { t.equal(stats.peersIPv4, 0) t.equal(stats.peersIPv6, 0) - server.close(function () { t.pass('server closed') }) + server.close(() => { t.pass('server closed') }) }) }) }) -test('server: get empty stats on stats.json', function (t) { +test('server: get empty stats on stats.json', t => { t.plan(11) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { const opts = { url: announceUrl.replace('/announce', '/stats.json'), json: true } - get.concat(opts, function (err, res, stats) { + get.concat(opts, (err, res, stats) => { t.error(err) t.equal(res.statusCode, 200) @@ -108,15 +106,15 @@ test('server: get empty stats on stats.json', function (t) { t.equal(stats.peersIPv4, 0) t.equal(stats.peersIPv6, 0) - server.close(function () { t.pass('server closed') }) + server.close(() => { t.pass('server closed') }) }) }) }) -test('server: get leecher stats.json', function (t) { +test('server: get leecher stats.json', t => { t.plan(11) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { // announce a torrent to the tracker const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, @@ -124,18 +122,18 @@ test('server: get leecher stats.json', function (t) { peerId, port: 6881 }) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - server.once('start', function () { + server.once('start', () => { const opts = { url: announceUrl.replace('/announce', '/stats.json'), json: true } - get.concat(opts, function (err, res, stats) { + get.concat(opts, (err, res, stats) => { t.error(err) t.equal(res.statusCode, 200) @@ -147,17 +145,17 @@ test('server: get leecher stats.json', function (t) { t.equal(stats.peersSeederAndLeecher, 0) t.equal(stats.clients.WebTorrent['0.91'], 1) - client.destroy(function () { t.pass('client destroyed') }) - server.close(function () { t.pass('server closed') }) + client.destroy(() => { t.pass('client destroyed') }) + server.close(() => { t.pass('server closed') }) }) }) }) }) -test('server: get leecher stats.json (unknown peerId)', function (t) { +test('server: get leecher stats.json (unknown peerId)', t => { t.plan(11) - commonTest.createServer(t, 'http', function (server, announceUrl) { + commonTest.createServer(t, 'http', (server, announceUrl) => { // announce a torrent to the tracker const client = new Client({ infoHash: fixtures.leaves.parsedTorrent.infoHash, @@ -165,18 +163,18 @@ test('server: get leecher stats.json (unknown peerId)', function (t) { peerId: unknownPeerId, port: 6881 }) - client.on('error', function (err) { t.error(err) }) - client.on('warning', function (err) { t.error(err) }) + client.on('error', err => { t.error(err) }) + client.on('warning', err => { t.error(err) }) client.start() - server.once('start', function () { + server.once('start', () => { const opts = { url: announceUrl.replace('/announce', '/stats.json'), json: true } - get.concat(opts, function (err, res, stats) { + get.concat(opts, (err, res, stats) => { t.error(err) t.equal(res.statusCode, 200) @@ -188,8 +186,8 @@ test('server: get leecher stats.json (unknown peerId)', function (t) { t.equal(stats.peersSeederAndLeecher, 0) t.equal(stats.clients.unknown['01234567'], 1) - client.destroy(function () { t.pass('client destroyed') }) - server.close(function () { t.pass('server closed') }) + client.destroy(() => { t.pass('client destroyed') }) + server.close(() => { t.pass('server closed') }) }) }) })