Skip to content

Commit

Permalink
fix: dial self (libp2p#329)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alan Shaw authored and jacobheun committed Apr 10, 2019
1 parent 9584a4b commit 4862c48
Show file tree
Hide file tree
Showing 2 changed files with 176 additions and 11 deletions.
60 changes: 49 additions & 11 deletions src/transport.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,23 +203,61 @@ class TransportManager {
if (!transport || !transport.filter) return []

const transportAddrs = transport.filter(multiaddrs)
if (!peerInfo) {
if (!peerInfo || !transportAddrs.length) {
return transportAddrs
}

const ourAddrs = peerInfo.multiaddrs.toArray()
return transportAddrs.filter((addr) => {
const ourAddrs = ourAddresses(peerInfo)

const result = transportAddrs.filter(transportAddr => {
// If our address is in the destination address, filter it out
return !ourAddrs.find((pAddr) => {
try {
addr.decapsulate(pAddr)
} catch (err) {
return false
}
return true
})
return !ourAddrs.some(a => getDestination(transportAddr).startsWith(a))
})

return result
}
}

/**
* Expand addresses in peer info into array of addresses with and without peer
* ID suffix.
*
* @param {PeerInfo} peerInfo Our peer info object
* @returns {String[]}
*/
function ourAddresses (peerInfo) {
const ourPeerId = peerInfo.id.toB58String()
return peerInfo.multiaddrs.toArray()
.reduce((ourAddrs, addr) => {
const peerId = addr.getPeerId()
addr = addr.toString()
const otherAddr = peerId
? addr.slice(0, addr.lastIndexOf(`/ipfs/${peerId}`))
: `${addr}/ipfs/${ourPeerId}`
return ourAddrs.concat([addr, otherAddr])
}, [])
.concat(`/ipfs/${ourPeerId}`)
}

const RelayProtos = [
'p2p-circuit',
'p2p-websocket-star',
'p2p-webrtc-star',
'p2p-stardust'
]

/**
* Get the destination address of a (possibly relay) multiaddr as a string
*
* @param {Multiaddr} addr
* @returns {String}
*/
function getDestination (addr) {
const protos = addr.protoNames().reverse()
const splitProto = protos.find(p => RelayProtos.includes(p))
addr = addr.toString()
if (!splitProto) return addr
return addr.slice(addr.lastIndexOf(splitProto) + splitProto.length)
}

module.exports = TransportManager
127 changes: 127 additions & 0 deletions test/transport-manager.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
const dirtyChai = require('dirty-chai')
const expect = chai.expect
chai.use(dirtyChai)
const Multiaddr = require('multiaddr')
const PeerInfo = require('peer-info')

const TransportManager = require('../src/transport')

describe('Transport Manager', () => {
describe('dialables', () => {
let peerInfo
const dialAllTransport = { filter: addrs => addrs }

beforeEach(done => {
PeerInfo.create((err, info) => {
if (err) return done(err)
peerInfo = info
done()
})
})

it('should return all transport addresses when peer info has 0 addrs', () => {
const queryAddrs = [
'/ip4/127.0.0.1/tcp/4002',
'/ip4/192.168.0.3/tcp/4002',
'/ip6/::1/tcp/4001'
].map(a => Multiaddr(a))

const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)

expect(dialableAddrs).to.have.length(queryAddrs.length)

queryAddrs.forEach(qa => {
expect(dialableAddrs.some(da => da.equals(qa))).to.be.true()
})
})

it('should return all transport addresses when we pass no peer info', () => {
const queryAddrs = [
'/ip4/127.0.0.1/tcp/4002',
'/ip4/192.168.0.3/tcp/4002',
'/ip6/::1/tcp/4001'
].map(a => Multiaddr(a))

const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs)

expect(dialableAddrs).to.have.length(queryAddrs.length)

queryAddrs.forEach(qa => {
expect(dialableAddrs.some(da => da.equals(qa))).to.be.true()
})
})

it('should filter our addresses', () => {
const queryAddrs = [
'/ip4/127.0.0.1/tcp/4002',
'/ip4/192.168.0.3/tcp/4002',
'/ip6/::1/tcp/4001'
].map(a => Multiaddr(a))

const ourAddrs = [
'/ip4/127.0.0.1/tcp/4002',
'/ip4/192.168.0.3/tcp/4002'
]

ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))

const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)

expect(dialableAddrs).to.have.length(1)
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
})

it('should filter our addresses with peer ID suffix', () => {
const queryAddrs = [
'/ip4/127.0.0.1/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j',
'/ip4/192.168.0.3/tcp/4002',
'/ip6/::1/tcp/4001'
].map(a => Multiaddr(a))

const ourAddrs = [
`/ip4/127.0.0.1/tcp/4002`,
`/ip4/192.168.0.3/tcp/4002/ipfs/${peerInfo.id.toB58String()}`
]

ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))

const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)

expect(dialableAddrs).to.have.length(1)
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
})

it('should filter our addresses over relay/rendezvous', () => {
const peerId = peerInfo.id.toB58String()
const queryAddrs = [
`/p2p-circuit/ipfs/${peerId}`,
`/p2p-circuit/ip4/127.0.0.1/tcp/4002`,
`/p2p-circuit/ip4/192.168.0.3/tcp/4002`,
`/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/${peerId}`,
`/p2p-circuit/ip4/192.168.0.3/tcp/4002/ipfs/${peerId}`,
`/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j`,
`/p2p-circuit/ip4/192.168.0.3/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j`,
`/p2p-webrtc-star/ipfs/${peerId}`,
`/p2p-websocket-star/ipfs/${peerId}`,
`/p2p-stardust/ipfs/${peerId}`,
'/ip6/::1/tcp/4001'
].map(a => Multiaddr(a))

const ourAddrs = [
`/ip4/127.0.0.1/tcp/4002`,
`/ip4/192.168.0.3/tcp/4002/ipfs/${peerInfo.id.toB58String()}`
]

ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))

const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)

expect(dialableAddrs).to.have.length(1)
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
})
})
})

0 comments on commit 4862c48

Please sign in to comment.