Skip to content

Commit 9fd58c8

Browse files
authored
fix: dialling duplicated addresses (#1489)
resolves #1409
1 parent 8f4cfa1 commit 9fd58c8

File tree

2 files changed

+37
-19
lines changed

2 files changed

+37
-19
lines changed

src/connection-manager/dialer/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ export class DefaultDialer implements Startable, Dialer {
235235
async _createDialTarget (peer: PeerId, options: AbortOptions): Promise<DialTarget> {
236236
const _resolve = this._resolve.bind(this)
237237

238-
const addrs = await pipe(
238+
let addrs = await pipe(
239239
await this.components.peerStore.addressBook.get(peer),
240240
(source) => filter(source, async (address) => {
241241
return !(await this.components.connectionGater.denyDialMultiaddr(peer, address.multiaddr))
@@ -259,6 +259,8 @@ export class DefaultDialer implements Startable, Dialer {
259259
async (source) => await all(source)
260260
)
261261

262+
addrs = [...new Set(addrs)]
263+
262264
if (addrs.length > this.maxAddrsToDial) {
263265
await this.components.peerStore.delete(peer)
264266
throw errCode(new Error('dial with more addresses than allowed'), codes.ERR_TOO_MANY_ADDRESSES)

test/dialing/direct.node.ts

+34-18
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,38 @@
11
/* eslint-env mocha */
22

3-
import { expect } from 'aegir/chai'
4-
import sinon from 'sinon'
5-
import { tcp } from '@libp2p/tcp'
63
import { mplex } from '@libp2p/mplex'
7-
import { plaintext } from '../../src/insecure/index.js'
4+
import { tcp } from '@libp2p/tcp'
85
import type { Multiaddr } from '@multiformats/multiaddr'
96
import { multiaddr } from '@multiformats/multiaddr'
7+
import { expect } from 'aegir/chai'
8+
import sinon from 'sinon'
9+
import { plaintext } from '../../src/insecure/index.js'
1010

11+
import { Connection, isConnection } from '@libp2p/interface-connection'
12+
import { mockConnection, mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader } from '@libp2p/interface-mocks'
13+
import type { PeerId } from '@libp2p/interface-peer-id'
14+
import { AbortError } from '@libp2p/interfaces/errors'
15+
import { createFromJSON } from '@libp2p/peer-id-factory'
16+
import { PersistentPeerStore } from '@libp2p/peer-store'
17+
import { MemoryDatastore } from 'datastore-core/memory'
1118
import delay from 'delay'
19+
import { pipe } from 'it-pipe'
20+
import { pushable } from 'it-pushable'
1221
import pDefer from 'p-defer'
1322
import pSettle, { PromiseResult } from 'p-settle'
1423
import pWaitFor from 'p-wait-for'
15-
import { pipe } from 'it-pipe'
16-
import { pushable } from 'it-pushable'
17-
import { Connection, isConnection } from '@libp2p/interface-connection'
18-
import { AbortError } from '@libp2p/interfaces/errors'
1924
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
20-
import { MemoryDatastore } from 'datastore-core/memory'
21-
import { DefaultDialer } from '../../src/connection-manager/dialer/index.js'
2225
import { DefaultAddressManager } from '../../src/address-manager/index.js'
23-
import { PersistentPeerStore } from '@libp2p/peer-store'
24-
import { DefaultTransportManager } from '../../src/transport-manager.js'
26+
import { DefaultComponents } from '../../src/components.js'
27+
import { DefaultDialer } from '../../src/connection-manager/dialer/index.js'
28+
import { DefaultConnectionManager } from '../../src/connection-manager/index.js'
2529
import { codes as ErrorCodes } from '../../src/errors.js'
26-
import { mockConnectionGater, mockDuplex, mockMultiaddrConnection, mockUpgrader, mockConnection } from '@libp2p/interface-mocks'
27-
import Peers from '../fixtures/peers.js'
28-
import { createFromJSON } from '@libp2p/peer-id-factory'
29-
import type { PeerId } from '@libp2p/interface-peer-id'
3030
import { createLibp2pNode, Libp2pNode } from '../../src/libp2p.js'
3131
import { preSharedKey } from '../../src/pnet/index.js'
32+
import { DefaultTransportManager } from '../../src/transport-manager.js'
33+
import Peers from '../fixtures/peers.js'
3234
import swarmKey from '../fixtures/swarm.key.js'
33-
import { DefaultConnectionManager } from '../../src/connection-manager/index.js'
34-
import { DefaultComponents } from '../../src/components.js'
35+
import { getPeer } from '../../src/get-peer.js'
3536

3637
const swarmKeyBuffer = uint8ArrayFromString(swarmKey)
3738
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
@@ -43,8 +44,10 @@ describe('Dialing (direct, TCP)', () => {
4344
let remoteAddr: Multiaddr
4445
let remoteComponents: DefaultComponents
4546
let localComponents: DefaultComponents
47+
let resolver: sinon.SinonStub<[Multiaddr], Promise<string[]>>
4648

4749
beforeEach(async () => {
50+
resolver = sinon.stub<[Multiaddr], Promise<string[]>>()
4851
const [localPeerId, remotePeerId] = await Promise.all([
4952
createFromJSON(Peers[0]),
5053
createFromJSON(Peers[1])
@@ -103,6 +106,19 @@ describe('Dialing (direct, TCP)', () => {
103106
await connection.close()
104107
})
105108

109+
it('should be able to connect to remote node with duplicated addresses', async () => {
110+
const dnsaddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteAddr.getPeerId() ?? ''}`)
111+
await localComponents.peerStore.addressBook.add(getPeer(remoteAddr).id, [dnsaddr])
112+
const dialer = new DefaultDialer(localComponents, { resolvers: { dnsaddr: resolver }, maxAddrsToDial: 1 })
113+
114+
// Resolver stub
115+
resolver.onCall(1).resolves([remoteAddr.toString()])
116+
117+
const connection = await dialer.dial(remoteAddr)
118+
expect(connection).to.exist()
119+
await connection.close()
120+
})
121+
106122
it('should fail to connect to an unsupported multiaddr', async () => {
107123
const dialer = new DefaultDialer(localComponents)
108124

0 commit comments

Comments
 (0)