Skip to content

Commit 5333cbf

Browse files
committed
dial: fallback to peer routing when all multiaddrs fail
1 parent 851395e commit 5333cbf

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed

packages/libp2p/src/connection-manager/dial-queue.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ export class DialQueue {
218218
const peerId = options.peerId
219219
const multiaddrs = options.multiaddrs
220220
const failedMultiaddrs = new Set<string>()
221+
const hadInitialMultiaddrs = options.multiaddrs.size > 0
222+
let didPeerRoutingLookupAfterDialFailure = false
221223

222224
// if we have no multiaddrs, only a peer id, set a flag so we will look the
223225
// peer up in the peer routing to obtain multiaddrs
@@ -331,6 +333,31 @@ export class DialQueue {
331333
errors.push(err)
332334
}
333335
}
336+
337+
// If user-supplied multiaddrs for a peer all failed, try one peer routing
338+
// lookup to fetch updated addresses before giving up.
339+
if (peerId != null && hadInitialMultiaddrs && addrsToDial.length > 0 && didPeerRoutingLookupAfterDialFailure === false && signal.aborted === false) {
340+
didPeerRoutingLookupAfterDialFailure = true
341+
342+
this.log('looking up multiaddrs for %p in the peer routing after dial failures', peerId)
343+
344+
try {
345+
const peerInfo = await this.components.peerRouting.findPeer(peerId, {
346+
...options,
347+
signal
348+
})
349+
350+
for (const ma of peerInfo.multiaddrs) {
351+
multiaddrs.add(ma.toString())
352+
}
353+
} catch (err: any) {
354+
if (err.name === 'NoPeerRoutersError') {
355+
this.log('no peer routers configured', peerId)
356+
} else {
357+
this.log.error('looking up multiaddrs for %p in the peer routing failed - %e', peerId, err)
358+
}
359+
}
360+
}
334361
}
335362

336363
if (errors.length === 1) {

packages/libp2p/test/connection-manager/dial-queue.spec.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,52 @@ describe('dial queue', () => {
180180
await expect(dialer.dial(peerId)).to.eventually.equal(connection)
181181
})
182182

183+
it('should look up peer routing after user-supplied multiaddrs are exhausted', async () => {
184+
const peerId = peerIdFromPrivateKey(await generateKeyPair('Ed25519'))
185+
const connection = stubInterface<Connection>()
186+
const provided1 = multiaddr(`/ip4/127.0.0.1/tcp/1231/p2p/${peerId}`)
187+
const provided2 = multiaddr(`/ip4/127.0.0.1/tcp/1232/p2p/${peerId}`)
188+
const routed = multiaddr('/ip4/127.0.0.1/tcp/4001')
189+
const routedWithPeer = routed.encapsulate(`/p2p/${peerId}`)
190+
191+
let dialAttempts = 0
192+
193+
components.peerRouting.findPeer.callsFake(async (id) => {
194+
expect(id.equals(peerId)).to.equal(true)
195+
expect(dialAttempts).to.equal(2)
196+
197+
return {
198+
id: peerId,
199+
multiaddrs: [routed]
200+
}
201+
})
202+
203+
const actions: Record<string, () => Promise<Connection>> = {
204+
[provided1.toString()]: async () => Promise.reject(new Error('dial failure')),
205+
[provided2.toString()]: async () => Promise.reject(new Error('dial failure')),
206+
[routedWithPeer.toString()]: async () => Promise.resolve(connection)
207+
}
208+
209+
components.transportManager.dialTransportForMultiaddr.returns(stubInterface<Transport>())
210+
components.transportManager.dial.callsFake(async ma => {
211+
dialAttempts++
212+
const action = actions[ma.toString()]
213+
214+
if (action != null) {
215+
return action()
216+
}
217+
218+
throw new Error(`No action found for multiaddr ${ma.toString()}`)
219+
})
220+
221+
dialer = new DialQueue(components)
222+
223+
await expect(dialer.dial([provided1, provided2])).to.eventually.equal(connection)
224+
225+
expect(components.peerRouting.findPeer).to.have.property('callCount', 1)
226+
expect(components.transportManager.dial.getCalls().map(c => c.args[0].toString())).to.include(routedWithPeer.toString())
227+
})
228+
183229
it('should end when a single multiaddr dials succeeds even when a final dial fails', async () => {
184230
const connection = stubInterface<Connection>()
185231
const deferredConn = pDefer<Connection>()

0 commit comments

Comments
 (0)