Skip to content

Commit f1eb373

Browse files
feat: discovery modules from transports should be added (#510)
* feat: discovery modules from transports should be added * chore: apply suggestions from code review Co-Authored-By: Jacob Heun <jacobheun@gmail.com> * chore: address review * chore: apply suggestions from code review Co-Authored-By: Jacob Heun <jacobheun@gmail.com>
1 parent dabee00 commit f1eb373

File tree

5 files changed

+147
-42
lines changed

5 files changed

+147
-42
lines changed

doc/CONFIGURATION.md

+31
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ Some available peer discovery modules are:
110110
- [js-libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht)
111111
- [js-libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star)
112112

113+
**Note**: `peer-discovery` services within transports (such as `js-libp2p-webrtc-star`) are automatically gathered from the `transport`, via it's `discovery` property. As such, they do not need to be added in the discovery modules. However, these transports can also be configured and disabled as the other ones.
114+
113115
If none of the available peer discovery protocols fulfills your needs, you can create a libp2p compatible one. A libp2p peer discovery protocol just needs to be compliant with the [Peer Discovery Interface](https://github.com/libp2p/js-interfaces/tree/master/src/peer-discovery).
114116

115117
If you want to know more about libp2p peer discovery, you should read the following content:
@@ -268,6 +270,35 @@ const node = await Libp2p.create({
268270
})
269271
```
270272

273+
#### Setup webrtc transport and discovery
274+
275+
```js
276+
277+
const Libp2p = require('libp2p')
278+
const WS = require('libp2p-websockets')
279+
const WebRTCStar = require('libp2p-webrtc-star')
280+
const MPLEX = require('libp2p-mplex')
281+
const SECIO = require('libp2p-secio')
282+
283+
const node = await Libp2p.create({
284+
modules: {
285+
transport: [
286+
WS,
287+
WebRTCStar
288+
],
289+
streamMuxer: [MPLEX],
290+
connEncryption: [SECIO],
291+
},
292+
config: {
293+
peerDiscovery: {
294+
webRTCStar: {
295+
enabled: true
296+
}
297+
}
298+
}
299+
})
300+
```
301+
271302
#### Customizing Pubsub
272303

273304
```js

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
"libp2p-mplex": "^0.9.1",
9797
"libp2p-secio": "^0.12.1",
9898
"libp2p-tcp": "^0.14.1",
99+
"libp2p-webrtc-star": "^0.17.0",
99100
"libp2p-websockets": "^0.13.1",
100101
"nock": "^10.0.6",
101102
"p-defer": "^3.0.0",

src/index.js

+18-5
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class Libp2p extends EventEmitter {
4848
this._modules = this._options.modules
4949
this._config = this._options.config
5050
this._transport = [] // Transport instances/references
51-
this._discovery = [] // Discovery service instances/references
51+
this._discovery = new Map() // Discovery service instances/references
5252

5353
this.peerStore = new PeerStore()
5454

@@ -437,7 +437,7 @@ class Libp2p extends EventEmitter {
437437
* @returns {Promise<void>}
438438
*/
439439
_setupPeerDiscovery () {
440-
for (const DiscoveryService of this._modules.peerDiscovery || []) {
440+
const setupService = (DiscoveryService) => {
441441
let config = {
442442
enabled: true // on by default
443443
}
@@ -448,7 +448,8 @@ class Libp2p extends EventEmitter {
448448
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
449449
}
450450

451-
if (config.enabled) {
451+
if (config.enabled &&
452+
!this._discovery.has(DiscoveryService.tag)) { // not already added
452453
let discoveryService
453454

454455
if (typeof DiscoveryService === 'function') {
@@ -458,11 +459,23 @@ class Libp2p extends EventEmitter {
458459
}
459460

460461
discoveryService.on('peer', this._onDiscoveryPeer)
461-
this._discovery.push(discoveryService)
462+
this._discovery.set(DiscoveryService.tag, discoveryService)
463+
}
464+
}
465+
466+
// Discovery modules
467+
for (const DiscoveryService of this._modules.peerDiscovery || []) {
468+
setupService(DiscoveryService)
469+
}
470+
471+
// Transport modules with discovery
472+
for (const Transport of this.transportManager.getTransports()) {
473+
if (Transport.discovery) {
474+
setupService(Transport.discovery)
462475
}
463476
}
464477

465-
return this._discovery.map(d => d.start())
478+
return Promise.all(Array.from(this._discovery.values(), d => d.start()))
466479
}
467480
}
468481

src/transport-manager.js

+8
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ class TransportManager {
103103
return addrs
104104
}
105105

106+
/**
107+
* Returns all the transports instances.
108+
* @returns {Iterator<Transport>}
109+
*/
110+
getTransports () {
111+
return this._transports.values()
112+
}
113+
106114
/**
107115
* Finds a transport that matches the given Multiaddr
108116
* @param {Multiaddr} ma

test/peer-discovery/index.spec.js

+89-37
Original file line numberDiff line numberDiff line change
@@ -10,57 +10,109 @@ const defer = require('p-defer')
1010
const mergeOptions = require('merge-options')
1111

1212
const MulticastDNS = require('libp2p-mdns')
13+
const WebRTCStar = require('libp2p-webrtc-star')
1314

1415
const Libp2p = require('../../src')
1516
const baseOptions = require('../utils/base-options.browser')
1617
const { createPeerInfo } = require('../utils/creators/peer')
1718

1819
describe('peer discovery', () => {
19-
let peerInfo
20-
let remotePeerInfo
21-
let libp2p
20+
describe('basic functions', () => {
21+
let peerInfo
22+
let remotePeerInfo
23+
let libp2p
2224

23-
before(async () => {
24-
[peerInfo, remotePeerInfo] = await createPeerInfo({ number: 2 })
25-
})
26-
27-
afterEach(async () => {
28-
libp2p && await libp2p.stop()
29-
sinon.reset()
30-
})
25+
before(async () => {
26+
[peerInfo, remotePeerInfo] = await createPeerInfo({ number: 2 })
27+
})
3128

32-
it('should dial know peers on startup', async () => {
33-
libp2p = new Libp2p({
34-
...baseOptions,
35-
peerInfo
29+
afterEach(async () => {
30+
libp2p && await libp2p.stop()
31+
sinon.reset()
3632
})
37-
libp2p.peerStore.add(remotePeerInfo)
38-
const deferred = defer()
39-
sinon.stub(libp2p.dialer, 'connectToPeer').callsFake((remotePeerInfo) => {
40-
expect(remotePeerInfo).to.equal(remotePeerInfo)
41-
deferred.resolve()
33+
34+
it('should dial know peers on startup', async () => {
35+
libp2p = new Libp2p({
36+
...baseOptions,
37+
peerInfo
38+
})
39+
libp2p.peerStore.add(remotePeerInfo)
40+
const deferred = defer()
41+
sinon.stub(libp2p.dialer, 'connectToPeer').callsFake((remotePeerInfo) => {
42+
expect(remotePeerInfo).to.equal(remotePeerInfo)
43+
deferred.resolve()
44+
})
45+
const spy = sinon.spy()
46+
libp2p.on('peer:discovery', spy)
47+
48+
libp2p.start()
49+
await deferred.promise
50+
expect(spy.getCall(0).args).to.eql([remotePeerInfo])
4251
})
43-
const spy = sinon.spy()
44-
libp2p.on('peer:discovery', spy)
4552

46-
libp2p.start()
47-
await deferred.promise
48-
expect(spy.getCall(0).args).to.eql([remotePeerInfo])
53+
it('should ignore self on discovery', async () => {
54+
libp2p = new Libp2p(mergeOptions(baseOptions, {
55+
peerInfo,
56+
modules: {
57+
peerDiscovery: [MulticastDNS]
58+
}
59+
}))
60+
61+
await libp2p.start()
62+
const discoverySpy = sinon.spy()
63+
libp2p.on('peer:discovery', discoverySpy)
64+
libp2p._discovery.get('mdns').emit('peer', libp2p.peerInfo)
65+
66+
expect(discoverySpy.called).to.eql(false)
67+
})
4968
})
5069

51-
it('should ignore self on discovery', async () => {
52-
libp2p = new Libp2p(mergeOptions(baseOptions, {
53-
peerInfo,
54-
modules: {
55-
peerDiscovery: [MulticastDNS]
56-
}
57-
}))
70+
describe('discovery modules from transports', () => {
71+
let peerInfo, libp2p
5872

59-
await libp2p.start()
60-
const discoverySpy = sinon.spy()
61-
libp2p.on('peer:discovery', discoverySpy)
62-
libp2p._discovery[0].emit('peer', libp2p.peerInfo)
73+
before(async () => {
74+
[peerInfo] = await createPeerInfo()
75+
})
76+
77+
it('should add discovery module if present in transports and enabled', async () => {
78+
libp2p = new Libp2p(mergeOptions(baseOptions, {
79+
peerInfo,
80+
modules: {
81+
transport: [WebRTCStar]
82+
},
83+
config: {
84+
peerDiscovery: {
85+
webRTCStar: {
86+
enabled: true
87+
}
88+
}
89+
}
90+
}))
91+
92+
await libp2p.start()
93+
94+
expect(libp2p._discovery.size).to.eql(1)
95+
expect(libp2p._discovery.has('webRTCStar')).to.eql(true)
96+
})
97+
98+
it('should not add discovery module if present in transports but disabled', async () => {
99+
libp2p = new Libp2p(mergeOptions(baseOptions, {
100+
peerInfo,
101+
modules: {
102+
transport: [WebRTCStar]
103+
},
104+
config: {
105+
peerDiscovery: {
106+
webRTCStar: {
107+
enabled: false
108+
}
109+
}
110+
}
111+
}))
63112

64-
expect(discoverySpy.called).to.eql(false)
113+
await libp2p.start()
114+
115+
expect(libp2p._discovery.size).to.eql(0)
116+
})
65117
})
66118
})

0 commit comments

Comments
 (0)