Skip to content

Commit 4862c48

Browse files
Alan Shawjacobheun
Alan Shaw
authored andcommitted
fix: dial self (libp2p#329)
1 parent 9584a4b commit 4862c48

File tree

2 files changed

+176
-11
lines changed

2 files changed

+176
-11
lines changed

src/transport.js

+49-11
Original file line numberDiff line numberDiff line change
@@ -203,23 +203,61 @@ class TransportManager {
203203
if (!transport || !transport.filter) return []
204204

205205
const transportAddrs = transport.filter(multiaddrs)
206-
if (!peerInfo) {
206+
if (!peerInfo || !transportAddrs.length) {
207207
return transportAddrs
208208
}
209209

210-
const ourAddrs = peerInfo.multiaddrs.toArray()
211-
return transportAddrs.filter((addr) => {
210+
const ourAddrs = ourAddresses(peerInfo)
211+
212+
const result = transportAddrs.filter(transportAddr => {
212213
// If our address is in the destination address, filter it out
213-
return !ourAddrs.find((pAddr) => {
214-
try {
215-
addr.decapsulate(pAddr)
216-
} catch (err) {
217-
return false
218-
}
219-
return true
220-
})
214+
return !ourAddrs.some(a => getDestination(transportAddr).startsWith(a))
221215
})
216+
217+
return result
222218
}
223219
}
224220

221+
/**
222+
* Expand addresses in peer info into array of addresses with and without peer
223+
* ID suffix.
224+
*
225+
* @param {PeerInfo} peerInfo Our peer info object
226+
* @returns {String[]}
227+
*/
228+
function ourAddresses (peerInfo) {
229+
const ourPeerId = peerInfo.id.toB58String()
230+
return peerInfo.multiaddrs.toArray()
231+
.reduce((ourAddrs, addr) => {
232+
const peerId = addr.getPeerId()
233+
addr = addr.toString()
234+
const otherAddr = peerId
235+
? addr.slice(0, addr.lastIndexOf(`/ipfs/${peerId}`))
236+
: `${addr}/ipfs/${ourPeerId}`
237+
return ourAddrs.concat([addr, otherAddr])
238+
}, [])
239+
.concat(`/ipfs/${ourPeerId}`)
240+
}
241+
242+
const RelayProtos = [
243+
'p2p-circuit',
244+
'p2p-websocket-star',
245+
'p2p-webrtc-star',
246+
'p2p-stardust'
247+
]
248+
249+
/**
250+
* Get the destination address of a (possibly relay) multiaddr as a string
251+
*
252+
* @param {Multiaddr} addr
253+
* @returns {String}
254+
*/
255+
function getDestination (addr) {
256+
const protos = addr.protoNames().reverse()
257+
const splitProto = protos.find(p => RelayProtos.includes(p))
258+
addr = addr.toString()
259+
if (!splitProto) return addr
260+
return addr.slice(addr.lastIndexOf(splitProto) + splitProto.length)
261+
}
262+
225263
module.exports = TransportManager

test/transport-manager.spec.js

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const chai = require('chai')
5+
const dirtyChai = require('dirty-chai')
6+
const expect = chai.expect
7+
chai.use(dirtyChai)
8+
const Multiaddr = require('multiaddr')
9+
const PeerInfo = require('peer-info')
10+
11+
const TransportManager = require('../src/transport')
12+
13+
describe('Transport Manager', () => {
14+
describe('dialables', () => {
15+
let peerInfo
16+
const dialAllTransport = { filter: addrs => addrs }
17+
18+
beforeEach(done => {
19+
PeerInfo.create((err, info) => {
20+
if (err) return done(err)
21+
peerInfo = info
22+
done()
23+
})
24+
})
25+
26+
it('should return all transport addresses when peer info has 0 addrs', () => {
27+
const queryAddrs = [
28+
'/ip4/127.0.0.1/tcp/4002',
29+
'/ip4/192.168.0.3/tcp/4002',
30+
'/ip6/::1/tcp/4001'
31+
].map(a => Multiaddr(a))
32+
33+
const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)
34+
35+
expect(dialableAddrs).to.have.length(queryAddrs.length)
36+
37+
queryAddrs.forEach(qa => {
38+
expect(dialableAddrs.some(da => da.equals(qa))).to.be.true()
39+
})
40+
})
41+
42+
it('should return all transport addresses when we pass no peer info', () => {
43+
const queryAddrs = [
44+
'/ip4/127.0.0.1/tcp/4002',
45+
'/ip4/192.168.0.3/tcp/4002',
46+
'/ip6/::1/tcp/4001'
47+
].map(a => Multiaddr(a))
48+
49+
const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs)
50+
51+
expect(dialableAddrs).to.have.length(queryAddrs.length)
52+
53+
queryAddrs.forEach(qa => {
54+
expect(dialableAddrs.some(da => da.equals(qa))).to.be.true()
55+
})
56+
})
57+
58+
it('should filter our addresses', () => {
59+
const queryAddrs = [
60+
'/ip4/127.0.0.1/tcp/4002',
61+
'/ip4/192.168.0.3/tcp/4002',
62+
'/ip6/::1/tcp/4001'
63+
].map(a => Multiaddr(a))
64+
65+
const ourAddrs = [
66+
'/ip4/127.0.0.1/tcp/4002',
67+
'/ip4/192.168.0.3/tcp/4002'
68+
]
69+
70+
ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))
71+
72+
const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)
73+
74+
expect(dialableAddrs).to.have.length(1)
75+
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
76+
})
77+
78+
it('should filter our addresses with peer ID suffix', () => {
79+
const queryAddrs = [
80+
'/ip4/127.0.0.1/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j',
81+
'/ip4/192.168.0.3/tcp/4002',
82+
'/ip6/::1/tcp/4001'
83+
].map(a => Multiaddr(a))
84+
85+
const ourAddrs = [
86+
`/ip4/127.0.0.1/tcp/4002`,
87+
`/ip4/192.168.0.3/tcp/4002/ipfs/${peerInfo.id.toB58String()}`
88+
]
89+
90+
ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))
91+
92+
const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)
93+
94+
expect(dialableAddrs).to.have.length(1)
95+
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
96+
})
97+
98+
it('should filter our addresses over relay/rendezvous', () => {
99+
const peerId = peerInfo.id.toB58String()
100+
const queryAddrs = [
101+
`/p2p-circuit/ipfs/${peerId}`,
102+
`/p2p-circuit/ip4/127.0.0.1/tcp/4002`,
103+
`/p2p-circuit/ip4/192.168.0.3/tcp/4002`,
104+
`/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/${peerId}`,
105+
`/p2p-circuit/ip4/192.168.0.3/tcp/4002/ipfs/${peerId}`,
106+
`/p2p-circuit/ip4/127.0.0.1/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j`,
107+
`/p2p-circuit/ip4/192.168.0.3/tcp/4002/ipfs/QmebzNV1kSzLfaYpSZdShuiABNUxoKT1vJmCdxM2iWsM2j`,
108+
`/p2p-webrtc-star/ipfs/${peerId}`,
109+
`/p2p-websocket-star/ipfs/${peerId}`,
110+
`/p2p-stardust/ipfs/${peerId}`,
111+
'/ip6/::1/tcp/4001'
112+
].map(a => Multiaddr(a))
113+
114+
const ourAddrs = [
115+
`/ip4/127.0.0.1/tcp/4002`,
116+
`/ip4/192.168.0.3/tcp/4002/ipfs/${peerInfo.id.toB58String()}`
117+
]
118+
119+
ourAddrs.forEach(a => peerInfo.multiaddrs.add(a))
120+
121+
const dialableAddrs = TransportManager.dialables(dialAllTransport, queryAddrs, peerInfo)
122+
123+
expect(dialableAddrs).to.have.length(1)
124+
expect(dialableAddrs[0].toString()).to.equal('/ip6/::1/tcp/4001')
125+
})
126+
})
127+
})

0 commit comments

Comments
 (0)