diff options
author | Julen Garcia Leunda <hicom150@gmail.com> | 2021-07-06 19:51:09 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-06 19:51:09 +0300 |
commit | 100a2aebe23420dd70842b3948896f8fecfee235 (patch) | |
tree | 6e651b5a6cd359c83ecaf3a148661b08221ff578 | |
parent | 149c12d73725c07b86cb3498290f5a6953280559 (diff) |
fix: ensure uTP peer address is IPv4 (#2125)
-rw-r--r-- | lib/torrent.js | 22 | ||||
-rw-r--r-- | test/node/conn-pool.js | 48 |
2 files changed, 67 insertions, 3 deletions
diff --git a/lib/torrent.js b/lib/torrent.js index b46cde3..8b96e14 100644 --- a/lib/torrent.js +++ b/lib/torrent.js @@ -762,8 +762,9 @@ class Torrent extends EventEmitter { if (this.destroyed) throw new Error('torrent is destroyed') if (!this.infoHash) throw new Error('addPeer() must not be called before the `infoHash` event') + let host + if (this.client.blocked) { - let host if (typeof peer === 'string') { let parts try { @@ -787,7 +788,10 @@ class Torrent extends EventEmitter { } // if the utp connection fails to connect, then it is replaced with a tcp connection to the same ip:port - const wasAdded = !!this._addPeer(peer, this.client.utp ? 'utp' : 'tcp') + + const type = (this.client.utp && this._isIPv4(host)) ? 'utp' : 'tcp' + const wasAdded = !!this._addPeer(peer, type) + if (wasAdded) { this.emit('peer', peer) } else { @@ -1800,7 +1804,9 @@ class Torrent extends EventEmitter { const reconnectTimeout = setTimeout(() => { if (this.destroyed) return - const newPeer = this._addPeer(peer.addr, this.client.utp ? 'utp' : 'tcp') + const host = addrToIPPort(peer.addr)[0] + const type = (this.client.utp && this._isIPv4(host)) ? 'utp' : 'tcp' + const newPeer = this._addPeer(peer.addr, type) if (newPeer) newPeer.retries = peer.retries + 1 }, ms) if (reconnectTimeout.unref) reconnectTimeout.unref() @@ -1824,6 +1830,16 @@ class Torrent extends EventEmitter { return port > 0 && port < 65535 && !(host === '127.0.0.1' && port === this.client.torrentPort) } + + /** + * Return `true` if string is a valid IPv4 address. + * @param {string} addr + * @return {boolean} + */ + _isIPv4 (addr) { + const IPv4Pattern = /^((?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])[.]){3}(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/ + return IPv4Pattern.test(addr) + } } function getBlockPipelineLength (wire, duration) { diff --git a/test/node/conn-pool.js b/test/node/conn-pool.js index a4850f2..b77a917 100644 --- a/test/node/conn-pool.js +++ b/test/node/conn-pool.js @@ -100,6 +100,54 @@ test('client.conn-pool: use uTP when uTP enabled', function (t) { }) }) +test('client.conn-pool: adding IPv6 peer when uTP enabled should fallback to TCP', function (t) { + t.plan(6) + + const client1 = new WebTorrent({ dht: false, tracker: false, lsd: false, utp: true }) + const client2 = new WebTorrent({ dht: false, tracker: false, lsd: false, utp: true }) + + client1.on('error', function (err) { t.fail(err) }) + client1.on('warning', function (err) { t.fail(err) }) + + client2.on('error', function (err) { t.fail(err) }) + client2.on('warning', function (err) { t.fail(err) }) + + // Start seeding + client2.seed(fixtures.leaves.content, { + name: 'Leaves of Grass by Walt Whitman.epub', + announce: [] + }) + + client2.on('listening', function () { + // Start downloading + const torrent = client1.add(fixtures.leaves.parsedTorrent.infoHash, { store: MemoryChunkStore }) + + // Manually connect peers + torrent.addPeer('[::1]:' + client2.address().port) + + let order = 0 + + torrent.on('infoHash', function () { + t.equal(++order, 1) + }) + + torrent.on('metadata', function () { + t.equal(++order, 2) + }) + + torrent.on('ready', function () { + t.equal(++order, 3) + }) + + torrent.on('done', function () { + t.equal(++order, 4) + + client1.destroy(function (err) { t.error(err, 'client 1 destroyed') }) + client2.destroy(function (err) { t.error(err, 'client 2 destroyed') }) + }) + }) +}) + // Warning: slow test as we need to rely on connection timeouts test('client.conn-pool: fallback to TCP when uTP server failed', function (t) { t.plan(6) |