mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-04-22 17:12:14 +00:00
refactor: examples/discovery-mechanisms (#498)
* refactor: examples-discovery-mechanisms * chore: apply suggestions from code review Co-Authored-By: Jacob Heun <jacobheun@gmail.com> * chore: suggestion interval Co-Authored-By: Jacob Heun <jacobheun@gmail.com> * chore: add peer connected event Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This commit is contained in:
parent
ba4681b312
commit
efc96c2f19
@ -1,14 +1,11 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const libp2p = require('../../')
|
const Libp2p = require('../../')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const Mplex = require('libp2p-mplex')
|
const Mplex = require('libp2p-mplex')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const Bootstrap = require('libp2p-bootstrap')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
const waterfall = require('async/waterfall')
|
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
|
||||||
|
|
||||||
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json
|
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json
|
||||||
const bootstrapers = [
|
const bootstrapers = [
|
||||||
@ -23,51 +20,35 @@ const bootstrapers = [
|
|||||||
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
|
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
|
||||||
]
|
]
|
||||||
|
|
||||||
class MyBundle extends libp2p {
|
;(async () => {
|
||||||
constructor (_options) {
|
const node = await Libp2p.create({
|
||||||
const defaults = {
|
modules: {
|
||||||
modules: {
|
transport: [TCP],
|
||||||
transport: [ TCP ],
|
streamMuxer: [Mplex],
|
||||||
streamMuxer: [ Mplex ],
|
connEncryption: [SECIO],
|
||||||
connEncryption: [ SECIO ],
|
peerDiscovery: [Bootstrap]
|
||||||
peerDiscovery: [ Bootstrap ]
|
},
|
||||||
},
|
config: {
|
||||||
config: {
|
peerDiscovery: {
|
||||||
peerDiscovery: {
|
bootstrap: {
|
||||||
autoDial: true,
|
interval: 60e3,
|
||||||
bootstrap: {
|
enabled: true,
|
||||||
interval: 20e3,
|
list: bootstrapers
|
||||||
enabled: true,
|
|
||||||
list: bootstrapers
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
super(defaultsDeep(_options, defaults))
|
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let node
|
node.on('peer:connect', (peer) => {
|
||||||
|
console.log('Connection established to:', peer.id.toB58String()) // Emitted when a peer has been found
|
||||||
waterfall([
|
})
|
||||||
(cb) => PeerInfo.create(cb),
|
|
||||||
(peerInfo, cb) => {
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
node = new MyBundle({
|
|
||||||
peerInfo
|
|
||||||
})
|
|
||||||
node.start(cb)
|
|
||||||
}
|
|
||||||
], (err) => {
|
|
||||||
if (err) { throw err }
|
|
||||||
|
|
||||||
node.on('peer:discovery', (peer) => {
|
node.on('peer:discovery', (peer) => {
|
||||||
// No need to dial, autoDial is on
|
// No need to dial, autoDial is on
|
||||||
console.log('Discovered:', peer.id.toB58String())
|
console.log('Discovered:', peer.id.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
node.on('peer:connect', (peer) => {
|
await node.start()
|
||||||
console.log('Connection established to:', peer.id.toB58String())
|
})();
|
||||||
})
|
|
||||||
})
|
|
||||||
|
@ -1,63 +1,45 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const libp2p = require('../../')
|
const Libp2p = require('../../')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const Mplex = require('libp2p-mplex')
|
const Mplex = require('libp2p-mplex')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
const waterfall = require('async/waterfall')
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
|
||||||
|
|
||||||
class MyBundle extends libp2p {
|
const createNode = async () => {
|
||||||
constructor (_options) {
|
const node = await Libp2p.create({
|
||||||
const defaults = {
|
modules: {
|
||||||
modules: {
|
transport: [TCP],
|
||||||
transport: [ TCP ],
|
streamMuxer: [Mplex],
|
||||||
streamMuxer: [ Mplex ],
|
connEncryption: [SECIO],
|
||||||
connEncryption: [ SECIO ],
|
peerDiscovery: [MulticastDNS]
|
||||||
peerDiscovery: [ MulticastDNS ]
|
},
|
||||||
},
|
config: {
|
||||||
config: {
|
peerDiscovery: {
|
||||||
peerDiscovery: {
|
mdns: {
|
||||||
mdns: {
|
interval: 20e3,
|
||||||
interval: 20e3,
|
enabled: true
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
||||||
|
|
||||||
super(defaultsDeep(_options, defaults))
|
return node
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNode (callback) {
|
;(async () => {
|
||||||
let node
|
const [node1, node2] = await Promise.all([
|
||||||
|
createNode(),
|
||||||
waterfall([
|
createNode()
|
||||||
(cb) => PeerInfo.create(cb),
|
])
|
||||||
(peerInfo, cb) => {
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
node = new MyBundle({
|
|
||||||
peerInfo
|
|
||||||
})
|
|
||||||
node.start(cb)
|
|
||||||
}
|
|
||||||
], (err) => callback(err, node))
|
|
||||||
}
|
|
||||||
|
|
||||||
parallel([
|
|
||||||
(cb) => createNode(cb),
|
|
||||||
(cb) => createNode(cb)
|
|
||||||
], (err, nodes) => {
|
|
||||||
if (err) { throw err }
|
|
||||||
|
|
||||||
const node1 = nodes[0]
|
|
||||||
const node2 = nodes[1]
|
|
||||||
|
|
||||||
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
})
|
|
||||||
|
await Promise.all([
|
||||||
|
node1.start(),
|
||||||
|
node2.start()
|
||||||
|
])
|
||||||
|
})();
|
||||||
|
@ -10,36 +10,32 @@ These mechanisms save configuration and enable a node to operate without any exp
|
|||||||
|
|
||||||
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and SECIO. You can see the complete example at [1.js](./1.js).
|
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and SECIO. You can see the complete example at [1.js](./1.js).
|
||||||
|
|
||||||
First, we create our libp2p bundle.
|
First, we create our libp2p node.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const Bootstrap = require('libp2p-railing')
|
const Libp2p = require('libp2p')
|
||||||
class MyBundle extends libp2p {
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
constructor (peerInfo) {
|
|
||||||
const defaults = {
|
const node = Libp2p.create({
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ SECIO ],
|
||||||
peerDiscovery: [ Bootstrap ]
|
peerDiscovery: [ Bootstrap ]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
peerDiscovery: {
|
peerDiscovery: {
|
||||||
bootstrap: {
|
bootstrap: {
|
||||||
interval: 2000,
|
interval: 60e3,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
list: bootstrapers
|
list: bootstrapers
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
super(defaultsDeep(_options, defaults))
|
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
In this bundle, we use a `bootstrappers` array listing peers to connect _on boot_. Here is the list used by js-ipfs and go-ipfs.
|
In this configuration, we use a `bootstrappers` array listing peers to connect _on boot_. Here is the list used by js-ipfs and go-ipfs.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const bootstrapers = [
|
const bootstrapers = [
|
||||||
@ -58,34 +54,37 @@ const bootstrapers = [
|
|||||||
Now, once we create and start the node, we can listen for events such as `peer:discovery` and `peer:connect`, these events tell us when we found a peer, independently of the discovery mechanism used and when we actually dialed to that peer.
|
Now, once we create and start the node, we can listen for events such as `peer:discovery` and `peer:connect`, these events tell us when we found a peer, independently of the discovery mechanism used and when we actually dialed to that peer.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
let node
|
const node = await Libp2p.create({
|
||||||
|
peerInfo,
|
||||||
waterfall([
|
modules: {
|
||||||
(cb) => PeerInfo.create(cb),
|
transport: [ TCP ],
|
||||||
(peerInfo, cb) => {
|
streamMuxer: [ Mplex ],
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
connEncryption: [ SECIO ],
|
||||||
node = new MyBundle({
|
peerDiscovery: [ Bootstrap ]
|
||||||
peerInfo
|
},
|
||||||
})
|
config: {
|
||||||
node.start(cb)
|
peerDiscovery: {
|
||||||
|
bootstrap: {
|
||||||
|
interval: 60e3,
|
||||||
|
enabled: true,
|
||||||
|
list: bootstrapers
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
], (err) => {
|
|
||||||
if (err) { throw err }
|
|
||||||
|
|
||||||
// Emitted when a peer has been found
|
|
||||||
node.on('peer:discovery', (peer) => {
|
|
||||||
console.log('Discovered:', peer.id.toB58String())
|
|
||||||
// Note how we need to dial, even if just to warm up the Connection (by not
|
|
||||||
// picking any protocol) in order to get a full Connection. The Peer Discovery
|
|
||||||
// doesn't make any decisions for you.
|
|
||||||
node.dial(peer, () => {})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Once the dial is complete, this event is emitted.
|
|
||||||
node.on('peer:connect', (peer) => {
|
|
||||||
console.log('Connection established to:', peer.id.toB58String())
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
||||||
|
|
||||||
|
node.on('peer:connect', (peer) => {
|
||||||
|
console.log('Connection established to:', peer.id.toB58String()) // Emitted when a peer has been found
|
||||||
|
})
|
||||||
|
|
||||||
|
// Emitted when a peer has been found
|
||||||
|
node.on('peer:discovery', (peer) => {
|
||||||
|
console.log('Discovered:', peer.id.toB58String())
|
||||||
|
})
|
||||||
|
|
||||||
|
await node.start()
|
||||||
```
|
```
|
||||||
|
|
||||||
From running [1.js](./1.js), you should see the following:
|
From running [1.js](./1.js), you should see the following:
|
||||||
@ -101,76 +100,56 @@ Discovered: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
|
|||||||
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
||||||
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
||||||
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||||
Connection established to: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
|
||||||
Connection established to: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
|
||||||
Connection established to: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
|
|
||||||
Connection established to: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm
|
|
||||||
Connection established to: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM
|
|
||||||
Connection established to: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
|
||||||
Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
|
|
||||||
Connection established to: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z
|
|
||||||
Connection established to: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. MulticastDNS to find other peers in the network
|
## 2. MulticastDNS to find other peers in the network
|
||||||
|
|
||||||
For this example, we need `libp2p-mdns`, go ahead and `npm install` it. You can find the complete solution at [2.js](./2.js).
|
For this example, we need `libp2p-mdns`, go ahead and `npm install` it. You can find the complete solution at [2.js](./2.js).
|
||||||
|
|
||||||
Update your libp2p bundle to include MulticastDNS.
|
Update your libp2p configuration to include MulticastDNS.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
class MyBundle extends libp2p {
|
const Libp2p = require('libp2p')
|
||||||
constructor (peerInfo) {
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
const defaults = {
|
|
||||||
modules: {
|
const createNode = () => {
|
||||||
transport: [ TCP ],
|
return Libp2p.create({
|
||||||
streamMuxer: [ Mplex ],
|
modules: {
|
||||||
connEncryption: [ SECIO ],
|
transport: [ TCP ],
|
||||||
peerDiscovery: [ MulticastDNS ]
|
streamMuxer: [ Mplex ],
|
||||||
},
|
connEncryption: [ SECIO ],
|
||||||
config: {
|
peerDiscovery: [ MulticastDNS ]
|
||||||
peerDiscovery: {
|
},
|
||||||
mdns: {
|
config: {
|
||||||
// Run at 1s so we can observe more quickly, default is 10s
|
peerDiscovery: {
|
||||||
interval: 1000,
|
mdns: {
|
||||||
enabled: true
|
interval: 20e3,
|
||||||
}
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
super(defaultsDeep(_options, defaults))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
To observe it working, spawn two nodes.
|
To observe it working, spawn two nodes.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
parallel([
|
const [node1, node2] = await Promise.all([
|
||||||
(cb) => createNode(cb),
|
createNode(),
|
||||||
(cb) => createNode(cb)
|
createNode()
|
||||||
], (err, nodes) => {
|
])
|
||||||
if (err) { throw err }
|
|
||||||
|
|
||||||
const node1 = nodes[0]
|
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
const node2 = nodes[1]
|
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
|
|
||||||
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
|
||||||
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
|
||||||
})
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you run this example, you will see a continuous stream of each peer discovering each other.
|
If you run this example, you will see the other peers being discovered.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
> node 2.js
|
> node 2.js
|
||||||
Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
|
Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
|
||||||
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
|
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
|
||||||
Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
|
|
||||||
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
|
|
||||||
Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
|
|
||||||
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. Where to find other Peer Discovery Mechanisms
|
## 3. Where to find other Peer Discovery Mechanisms
|
||||||
|
Loading…
x
Reference in New Issue
Block a user