From db1b63dec9e4b44f80af1144b0e89f7fb1fadb70 Mon Sep 17 00:00:00 2001 From: John Hiesey Date: Wed, 27 Jan 2021 19:27:39 -0800 Subject: [PATCH 01/10] Support ws noServer option and server option objects --- server.js | 58 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/server.js b/server.js index 1ec53da..c705e7f 100644 --- a/server.js +++ b/server.js @@ -23,14 +23,14 @@ const hasOwnProperty = Object.prototype.hasOwnProperty * metrics from clients that help the tracker keep overall statistics about the torrent. * Responses include a peer list that helps the client participate in the torrent. * - * @param {Object} opts options object - * @param {Number} opts.interval tell clients to announce on this interval (ms) - * @param {Number} opts.trustProxy trust 'x-forwarded-for' header from reverse proxy - * @param {boolean} opts.http start an http server? (default: true) - * @param {boolean} opts.udp start a udp server? (default: true) - * @param {boolean} opts.ws start a websocket server? (default: true) - * @param {boolean} opts.stats enable web-based statistics? (default: true) - * @param {function} opts.filter black/whitelist fn for disallowing/allowing torrents + * @param {Object} opts options object + * @param {Number} opts.interval tell clients to announce on this interval (ms) + * @param {Number} opts.trustProxy trust 'x-forwarded-for' header from reverse proxy + * @param {boolean|Object} opts.http start an http server?, or options for http.createServer (default: true) + * @param {boolean|Object} opts.udp start a udp server?, or extra options for dgram.createSocket (default: true) + * @param {boolean|Object} opts.ws start a websocket server?, or extra options for new WebSocketServer (default: true) + * @param {boolean} opts.stats enable web-based statistics? (default: true) + * @param {function} opts.filter black/whitelist fn for disallowing/allowing torrents */ class Server extends EventEmitter { constructor (opts = {}) { @@ -59,7 +59,7 @@ class Server extends EventEmitter { // start an http tracker unless the user explictly says no if (opts.http !== false) { - this.http = http.createServer() + this.http = http.createServer(isObject(opts.http) ? opts.http : undefined) this.http.on('error', err => { this._onError(err) }) this.http.on('listening', onListening) @@ -75,18 +75,20 @@ class Server extends EventEmitter { // start a udp tracker unless the user explicitly says no if (opts.udp !== false) { - const isNode10 = /^v0.10./.test(process.version) - - this.udp4 = this.udp = dgram.createSocket( - isNode10 ? 'udp4' : { type: 'udp4', reuseAddr: true } - ) + this.udp4 = this.udp = dgram.createSocket({ + type: 'udp4', + reuseAddr: true, + ...(isObject(opts.udp) ? opts.udp : undefined) + }) this.udp4.on('message', (msg, rinfo) => { this.onUdpRequest(msg, rinfo) }) this.udp4.on('error', err => { this._onError(err) }) this.udp4.on('listening', onListening) - this.udp6 = dgram.createSocket( - isNode10 ? 'udp6' : { type: 'udp6', reuseAddr: true } - ) + this.udp6 = dgram.createSocket({ + type: 'udp6', + reuseAddr: true, + ...(isObject(opts.udp) ? opts.udp : undefined) + }) this.udp6.on('message', (msg, rinfo) => { this.onUdpRequest(msg, rinfo) }) this.udp6.on('error', err => { this._onError(err) }) this.udp6.on('listening', onListening) @@ -94,7 +96,8 @@ class Server extends EventEmitter { // start a websocket tracker (for WebTorrent) unless the user explicitly says no if (opts.ws !== false) { - if (!this.http) { + const noServer = isObject(opts.ws) && opts.ws.noServer + if (!this.http && !noServer) { this.http = http.createServer() this.http.on('error', err => { this._onError(err) }) this.http.on('listening', onListening) @@ -112,12 +115,15 @@ class Server extends EventEmitter { }) } this.ws = new WebSocketServer({ - server: this.http, + server: noServer ? undefined : this.http, perMessageDeflate: false, - clientTracking: false + clientTracking: false, + ...(isObject(opts.ws) ? opts.ws : undefined) }) - this.ws.address = () => { - return this.http.address() + if (!noServer) { + this.ws.address = () => { + return this.http.address() + } } this.ws.on('error', err => { this._onError(err) }) this.ws.on('connection', (socket, req) => { @@ -297,10 +303,6 @@ class Server extends EventEmitter { debug('listen (port: %o hostname: %o)', port, hostname) - function isObject (obj) { - return typeof obj === 'object' && obj !== null - } - const httpPort = isObject(port) ? (port.http || 0) : port const udpPort = isObject(port) ? (port.udp || 0) : port @@ -801,6 +803,10 @@ function makeUdpPacket (params) { return packet } +function isObject (obj) { + return typeof obj === 'object' && obj !== null +} + function toNumber (x) { x = Number(x) return x >= 0 ? x : false From 69976e80d7b761a72479f5b942f1c7d6a4582aec Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Thu, 28 Jan 2021 15:16:53 -0500 Subject: [PATCH 02/10] give user a friendlier error when address() is unavailable due to noServer --- server.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index c705e7f..e490d7a 100644 --- a/server.js +++ b/server.js @@ -120,11 +120,14 @@ class Server extends EventEmitter { clientTracking: false, ...(isObject(opts.ws) ? opts.ws : undefined) }) - if (!noServer) { - this.ws.address = () => { - return this.http.address() + + this.ws.address = () => { + if (noServer) { + throw new Error('address() unavailable with { noServer: true }') } + return this.http.address() } + this.ws.on('error', err => { this._onError(err) }) this.ws.on('connection', (socket, req) => { // Note: socket.upgradeReq was removed in ws@3.0.0, so re-add it. From 0c4911eaea6d0f172e3af4def754fde38b29d49a Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Thu, 28 Jan 2021 15:17:24 -0500 Subject: [PATCH 03/10] 9.16.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fe7d8a3..960fac5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bittorrent-tracker", "description": "Simple, robust, BitTorrent tracker (client & server) implementation", - "version": "9.15.0", + "version": "9.16.0", "author": { "name": "WebTorrent LLC", "email": "feross@webtorrent.io", From d8bb9c53f71d08038da98b236c154e766df5eca5 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Tue, 9 Feb 2021 21:38:01 -0800 Subject: [PATCH 04/10] Use queueMicrotask on client --- client.js | 3 ++- package.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/client.js b/client.js index 6fc2179..fabbf63 100644 --- a/client.js +++ b/client.js @@ -3,6 +3,7 @@ const EventEmitter = require('events') const once = require('once') const parallel = require('run-parallel') const Peer = require('simple-peer') +const queueMicrotask = require('queue-microtask') const common = require('./lib/common') const HTTPTracker = require('./lib/client/http-tracker') // empty object in browser @@ -76,7 +77,7 @@ class Client extends EventEmitter { const webrtcSupport = this._wrtc !== false && (!!this._wrtc || Peer.WEBRTC_SUPPORT) const nextTickWarn = err => { - process.nextTick(() => { + queueMicrotask(() => { this.emit('warning', err) }) } diff --git a/package.json b/package.json index 960fac5..a75fe95 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "lru": "^3.1.0", "minimist": "^1.2.5", "once": "^1.4.0", + "queue-microtask": "^1.2.2", "random-iterate": "^1.0.1", "randombytes": "^2.1.0", "run-parallel": "^1.1.9", From a91a1b6bceb90f346bc961350bdb3d5064ba65b6 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Tue, 9 Feb 2021 21:38:26 -0800 Subject: [PATCH 05/10] github actions --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ .npmignore | 2 +- .travis.yml | 10 ---------- README.md | 6 +++--- 4 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/ci.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..910c8cf --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,23 @@ +name: ci +'on': + - push + - pull_request +jobs: + test: + name: Node ${{ matrix.node }} / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: + - ubuntu-latest + node: + - '14' + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-node@v2 + with: + node-version: ${{ runner.node }} + - run: npm install + - run: npm run build --if-present + - run: npm test diff --git a/.npmignore b/.npmignore index 5a33e81..ae28c20 100644 --- a/.npmignore +++ b/.npmignore @@ -1,6 +1,6 @@ -.travis.yml CONTRIBUTING.md examples/ img/ test/ tools/ +.github/ diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e95e654..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: node_js -sudo: false -node_js: - - lts/* -before_script: - # Add an IPv6 config - see the corresponding Travis issue - # https://github.com/travis-ci/travis-ci/issues/8361 - - if [ "${TRAVIS_OS_NAME}" == "linux" ]; then - sudo sh -c 'echo 0 > /proc/sys/net/ipv6/conf/all/disable_ipv6'; - fi diff --git a/README.md b/README.md index 3e48a53..1ac3605 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ -# bittorrent-tracker [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] +# bittorrent-tracker [![ci][ci-image]][ci-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url] -[travis-image]: https://img.shields.io/travis/webtorrent/bittorrent-tracker/master.svg -[travis-url]: https://travis-ci.org/webtorrent/bittorrent-tracker +[ci-image]: https://img.shields.io/github/workflow/status/webtorrent/bittorrent-tracker/ci/master +[ci-url]: https://github.com/webtorrent/bittorrent-tracker/actions [npm-image]: https://img.shields.io/npm/v/bittorrent-tracker.svg [npm-url]: https://npmjs.org/package/bittorrent-tracker [downloads-image]: https://img.shields.io/npm/dm/bittorrent-tracker.svg From 9801a6300197218cbcc42232bc14139e05a6d58f Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Tue, 9 Feb 2021 21:38:56 -0800 Subject: [PATCH 06/10] 9.16.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a75fe95..213073a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bittorrent-tracker", "description": "Simple, robust, BitTorrent tracker (client & server) implementation", - "version": "9.16.0", + "version": "9.16.1", "author": { "name": "WebTorrent LLC", "email": "feross@webtorrent.io", From ce8ea41f276ddb1251f26107e968ec33cf37966d Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Mon, 12 Apr 2021 15:54:01 -0700 Subject: [PATCH 07/10] Lower the max number of WebRTC peers in an announce to 5 --- lib/client/websocket-tracker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/client/websocket-tracker.js b/lib/client/websocket-tracker.js index 907b5d3..6e71e76 100644 --- a/lib/client/websocket-tracker.js +++ b/lib/client/websocket-tracker.js @@ -56,7 +56,7 @@ class WebSocketTracker extends Tracker { this._send(params) } else { // Limit the number of offers that are generated, since it can be slow - const numwant = Math.min(opts.numwant, 10) + const numwant = Math.min(opts.numwant, 5) this._generateOffers(numwant, offers => { params.numwant = numwant From dd02cddcb80e52d920f8ac889bbfc957020d3ab9 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Mon, 12 Apr 2021 16:13:35 -0700 Subject: [PATCH 08/10] ensure that 'peer' is emitted before 'connect' event fires This is just a defensive code change to ensure that if signal() were somehow able to cause the peer to synchronously emit the 'connect' event that we won't cause the 'error' listener to be unregistered before 'peer' is emitted and the user has a chance to register their own 'error' listener --- lib/client/websocket-tracker.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/client/websocket-tracker.js b/lib/client/websocket-tracker.js index 6e71e76..815b034 100644 --- a/lib/client/websocket-tracker.js +++ b/lib/client/websocket-tracker.js @@ -278,8 +278,8 @@ class WebSocketTracker extends Tracker { if (this._trackerId) params.trackerid = this._trackerId this._send(params) }) - peer.signal(data.offer) this.client.emit('peer', peer) + peer.signal(data.offer) } if (data.answer && data.peer_id) { @@ -287,8 +287,8 @@ class WebSocketTracker extends Tracker { peer = this.peers[offerId] if (peer) { peer.id = common.binaryToHex(data.peer_id) - peer.signal(data.answer) this.client.emit('peer', peer) + peer.signal(data.answer) clearTimeout(peer.trackerTimeout) peer.trackerTimeout = null From 77d409ac2026bd19fbe473cce6bec8a8495dc2b6 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Mon, 12 Apr 2021 16:14:42 -0700 Subject: [PATCH 09/10] 9.17.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 213073a..3050766 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "bittorrent-tracker", "description": "Simple, robust, BitTorrent tracker (client & server) implementation", - "version": "9.16.1", + "version": "9.17.0", "author": { "name": "WebTorrent LLC", "email": "feross@webtorrent.io", From 2a12b752048d88452d91cd5fa4d8f03ac9131074 Mon Sep 17 00:00:00 2001 From: Feross Aboukhadijeh Date: Mon, 12 Apr 2021 16:14:42 -0700 Subject: [PATCH 10/10] package metadata --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 910c8cf..822d21c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 with: - node-version: ${{ runner.node }} + node-version: ${{ matrix.node }} - run: npm install - run: npm run build --if-present - run: npm test