Skip to content

Commit

Permalink
fix: ensure uTP peer address is IPv4 (#2125)
Browse files Browse the repository at this point in the history
  • Loading branch information
hicom150 committed Jul 6, 2021
1 parent 149c12d commit 100a2ae
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 3 deletions.
22 changes: 19 additions & 3 deletions lib/torrent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
Expand All @@ -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) {
Expand Down
48 changes: 48 additions & 0 deletions test/node/conn-pool.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 100a2ae

Please sign in to comment.