mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-06-14 17:51:22 +00:00
docs: update examples to 0.28.x api (#625)
* chore: update examples to 0.28 api * chore: use libp2p-noise in examples * chore: examples using multiaddrs property of libp2p Co-authored-by: Jacob Heun <jacobheun@gmail.com> * docs: update language around secio in crypto example Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This commit is contained in:
@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
const multiaddr = require('multiaddr')
|
||||||
const Node = require('./libp2p-bundle')
|
const Node = require('./libp2p-bundle')
|
||||||
const { stdinToStream, streamToConsole } = require('./stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
|
|
||||||
@ -13,27 +13,25 @@ async function run() {
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Create a new libp2p node on localhost with a randomly chosen port
|
// Create a new libp2p node on localhost with a randomly chosen port
|
||||||
const peerDialer = new PeerInfo(idDialer)
|
|
||||||
peerDialer.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
const nodeDialer = new Node({
|
const nodeDialer = new Node({
|
||||||
peerInfo: peerDialer
|
peerId: idDialer,
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a PeerInfo with the listening peer's address
|
|
||||||
const peerListener = new PeerInfo(idListener)
|
|
||||||
peerListener.multiaddrs.add('/ip4/127.0.0.1/tcp/10333')
|
|
||||||
|
|
||||||
// Start the libp2p host
|
// Start the libp2p host
|
||||||
await nodeDialer.start()
|
await nodeDialer.start()
|
||||||
|
|
||||||
// Output this node's address
|
// Output this node's address
|
||||||
console.log('Dialer ready, listening on:')
|
console.log('Dialer ready, listening on:')
|
||||||
peerListener.multiaddrs.forEach((ma) => {
|
nodeDialer.multiaddrs.forEach((ma) => {
|
||||||
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
console.log(ma.toString() + '/p2p/' + idDialer.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Dial to the remote peer (the "listener")
|
// Dial to the remote peer (the "listener")
|
||||||
const { stream } = await nodeDialer.dialProtocol(peerListener, '/chat/1.0.0')
|
const listenerMa = multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toB58String()}`)
|
||||||
|
const { stream } = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0')
|
||||||
|
|
||||||
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
|
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
|
||||||
console.log('Type a message and see what happens')
|
console.log('Type a message and see what happens')
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const mplex = require('libp2p-mplex')
|
const mplex = require('libp2p-mplex')
|
||||||
const secio = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||||
const libp2p = require('../../..')
|
const libp2p = require('../../..')
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ class Node extends libp2p {
|
|||||||
WS
|
WS
|
||||||
],
|
],
|
||||||
streamMuxer: [ mplex ],
|
streamMuxer: [ mplex ],
|
||||||
connEncryption: [ secio ]
|
connEncryption: [ NOISE, SECIO ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,24 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
const multaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const Node = require('./libp2p-bundle.js')
|
const Node = require('./libp2p-bundle.js')
|
||||||
const { stdinToStream, streamToConsole } = require('./stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
// Create a new libp2p node with the given multi-address
|
// Create a new libp2p node with the given multi-address
|
||||||
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
||||||
const peerListener = new PeerInfo(idListener)
|
|
||||||
peerListener.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
|
|
||||||
const nodeListener = new Node({
|
const nodeListener = new Node({
|
||||||
peerInfo: peerListener
|
peerId: idListener,
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/10333']
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Log a message when a remote peer connects to us
|
// Log a message when a remote peer connects to us
|
||||||
nodeListener.on('peer:connect', (peerInfo) => {
|
nodeListener.connectionManager.on('peer:connect', (connection) => {
|
||||||
console.log(peerInfo.id.toB58String())
|
console.log('connected to: ', connection.remotePeer.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handle messages for the protocol
|
// Handle messages for the protocol
|
||||||
@ -33,7 +34,7 @@ async function run() {
|
|||||||
|
|
||||||
// Output listen addresses to the console
|
// Output listen addresses to the console
|
||||||
console.log('Listener ready, listening on:')
|
console.log('Listener ready, listening on:')
|
||||||
peerListener.multiaddrs.forEach((ma) => {
|
nodeListener.multiaddrs.forEach((ma) => {
|
||||||
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ 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 { NOISE } = require('libp2p-noise')
|
||||||
const Bootstrap = require('libp2p-bootstrap')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
|
|
||||||
// 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
|
||||||
@ -22,10 +23,13 @@ const bootstrapers = [
|
|||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
peerDiscovery: [Bootstrap]
|
peerDiscovery: [Bootstrap]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -39,15 +43,13 @@ const bootstrapers = [
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
node.connectionManager.on('peer:connect', (connection) => {
|
||||||
|
console.log('Connection established to:', connection.remotePeer.toB58String()) // Emitted when a peer has been found
|
||||||
node.on('peer:connect', (peer) => {
|
|
||||||
console.log('Connection established to:', peer.id.toB58String()) // Emitted when a peer has been found
|
|
||||||
})
|
})
|
||||||
|
|
||||||
node.on('peer:discovery', (peer) => {
|
node.on('peer:discovery', (peerId) => {
|
||||||
// No need to dial, autoDial is on
|
// No need to dial, autoDial is on
|
||||||
console.log('Discovered:', peer.id.toB58String())
|
console.log('Discovered:', peerId.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
await node.start()
|
await node.start()
|
||||||
|
@ -5,14 +5,18 @@ 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 { NOISE } = require('libp2p-noise')
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
peerDiscovery: [MulticastDNS]
|
peerDiscovery: [MulticastDNS]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -24,7 +28,6 @@ const createNode = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
@ -35,8 +38,8 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
node1.on('peer:discovery', (peerId) => console.log('Discovered:', peerId.toB58String()))
|
||||||
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
node2.on('peer:discovery', (peerId) => console.log('Discovered:', peerId.toB58String()))
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
node1.start(),
|
node1.start(),
|
||||||
|
@ -4,7 +4,7 @@ A Peer Discovery module enables libp2p to find peers to connect to. Think of the
|
|||||||
|
|
||||||
With these system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
|
With these system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
|
||||||
|
|
||||||
These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work.
|
These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore.
|
||||||
|
|
||||||
## 1. Bootstrap list of Peers when booting a node
|
## 1. Bootstrap list of Peers when booting a node
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ const node = Libp2p.create({
|
|||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ NOISE, SECIO ],
|
||||||
peerDiscovery: [ Bootstrap ]
|
peerDiscovery: [ Bootstrap ]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -55,11 +55,14 @@ Now, once we create and start the node, we can listen for events such as `peer:d
|
|||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
peerId,
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
}
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ NOISE, SECIO ],
|
||||||
peerDiscovery: [ Bootstrap ]
|
peerDiscovery: [ Bootstrap ]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -73,15 +76,13 @@ const node = await Libp2p.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
node.connectionManager.on('peer:connect', (connection) => {
|
||||||
|
console.log('Connection established to:', connection.remotePeer.toB58String()) // Emitted when a new connection has been created
|
||||||
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', (peerId) => {
|
||||||
node.on('peer:discovery', (peer) => {
|
// No need to dial, autoDial is on
|
||||||
console.log('Discovered:', peer.id.toB58String())
|
console.log('Discovered:', peerId.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
await node.start()
|
await node.start()
|
||||||
@ -100,6 +101,15 @@ Discovered: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
|
|||||||
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
||||||
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
||||||
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||||
|
Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
|
||||||
|
Connection established to: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z
|
||||||
|
Connection established to: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM
|
||||||
|
Connection established to: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm
|
||||||
|
Connection established to: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu
|
||||||
|
Connection established to: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
|
||||||
|
Connection established to: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
|
||||||
|
Connection established to: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
|
||||||
|
Connection established to: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. MulticastDNS to find other peers in the network
|
## 2. MulticastDNS to find other peers in the network
|
||||||
@ -114,10 +124,13 @@ const MulticastDNS = require('libp2p-mdns')
|
|||||||
|
|
||||||
const createNode = () => {
|
const createNode = () => {
|
||||||
return Libp2p.create({
|
return Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
}
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ NOISE, SECIO ],
|
||||||
peerDiscovery: [ MulticastDNS ]
|
peerDiscovery: [ MulticastDNS ]
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
* Dialer Node
|
* Dialer Node
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const multiaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const Node = require('./libp2p-bundle')
|
const Node = require('./libp2p-bundle')
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
@ -17,28 +17,26 @@ async function run() {
|
|||||||
])
|
])
|
||||||
|
|
||||||
// Dialer
|
// Dialer
|
||||||
const dialerPeerInfo = new PeerInfo(dialerId)
|
|
||||||
dialerPeerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
const dialerNode = new Node({
|
const dialerNode = new Node({
|
||||||
peerInfo: dialerPeerInfo
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
|
peerId: dialerId
|
||||||
})
|
})
|
||||||
|
|
||||||
// Peer to Dial (the listener)
|
// Add peer to Dial (the listener) into the PeerStore
|
||||||
const listenerPeerInfo = new PeerInfo(listenerId)
|
const listenerMultiaddr = '/ip4/127.0.0.1/tcp/10333/p2p/' + listenerId.toB58String()
|
||||||
const listenerMultiaddr = '/ip4/127.0.0.1/tcp/10333/p2p/' +
|
|
||||||
listenerId.toB58String()
|
|
||||||
listenerPeerInfo.multiaddrs.add(listenerMultiaddr)
|
|
||||||
|
|
||||||
// Start the dialer libp2p node
|
// Start the dialer libp2p node
|
||||||
await dialerNode.start()
|
await dialerNode.start()
|
||||||
|
|
||||||
console.log('Dialer ready, listening on:')
|
console.log('Dialer ready, listening on:')
|
||||||
dialerPeerInfo.multiaddrs.forEach((ma) => console.log(ma.toString() +
|
dialerNode.multiaddrs.forEach((ma) => console.log(ma.toString() +
|
||||||
'/p2p/' + dialerId.toB58String()))
|
'/p2p/' + dialerId.toB58String()))
|
||||||
|
|
||||||
// Dial the listener node
|
// Dial the listener node
|
||||||
console.log('Dialing to peer:', listenerMultiaddr.toString())
|
console.log('Dialing to peer:', listenerMultiaddr)
|
||||||
const { stream } = await dialerNode.dialProtocol(listenerPeerInfo, '/echo/1.0.0')
|
const { stream } = await dialerNode.dialProtocol(listenerMultiaddr, '/echo/1.0.0')
|
||||||
|
|
||||||
console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0')
|
console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0')
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const mplex = require('libp2p-mplex')
|
const mplex = require('libp2p-mplex')
|
||||||
const secio = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
|
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||||
const libp2p = require('../../..')
|
const libp2p = require('../../..')
|
||||||
|
|
||||||
@ -16,7 +18,7 @@ class Node extends libp2p {
|
|||||||
WS
|
WS
|
||||||
],
|
],
|
||||||
streamMuxer: [ mplex ],
|
streamMuxer: [ mplex ],
|
||||||
connEncryption: [ secio ]
|
connEncryption: [ NOISE, SECIO ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const Node = require('./libp2p-bundle')
|
const Node = require('./libp2p-bundle')
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
@ -14,15 +13,16 @@ async function run() {
|
|||||||
const listenerId = await PeerId.createFromJSON(require('./id-l'))
|
const listenerId = await PeerId.createFromJSON(require('./id-l'))
|
||||||
|
|
||||||
// Listener libp2p node
|
// Listener libp2p node
|
||||||
const listenerPeerInfo = new PeerInfo(listenerId)
|
|
||||||
listenerPeerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
|
|
||||||
const listenerNode = new Node({
|
const listenerNode = new Node({
|
||||||
peerInfo: listenerPeerInfo
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/10333']
|
||||||
|
},
|
||||||
|
peerId: listenerId
|
||||||
})
|
})
|
||||||
|
|
||||||
// Log a message when we receive a connection
|
// Log a message when we receive a connection
|
||||||
listenerNode.on('peer:connect', (peerInfo) => {
|
listenerNode.connectionManager.on('peer:connect', (connection) => {
|
||||||
console.log('received dial to me from:', peerInfo.id.toB58String())
|
console.log('received dial to me from:', connection.remotePeer.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handle incoming connections for the protocol by piping from the stream
|
// Handle incoming connections for the protocol by piping from the stream
|
||||||
@ -33,7 +33,7 @@ async function run() {
|
|||||||
await listenerNode.start()
|
await listenerNode.start()
|
||||||
|
|
||||||
console.log('Listener ready, listening on:')
|
console.log('Listener ready, listening on:')
|
||||||
listenerNode.peerInfo.multiaddrs.forEach((ma) => {
|
listenerNode.multiaddrs.forEach((ma) => {
|
||||||
console.log(ma.toString() + '/p2p/' + listenerId.toB58String())
|
console.log(ma.toString() + '/p2p/' + listenerId.toB58String())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -3,21 +3,20 @@
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO]
|
connEncryption: [NOISE, SECIO]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -32,6 +31,8 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
node2.handle('/a-protocol', ({ stream }) => {
|
node2.handle('/a-protocol', ({ stream }) => {
|
||||||
pipe(
|
pipe(
|
||||||
stream,
|
stream,
|
||||||
@ -43,7 +44,7 @@ const createNode = async () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/a-protocol')
|
const { stream } = await node1.dialProtocol(node2.peerId, '/a-protocol')
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['This information is sent out encrypted to the other peer'],
|
['This information is sent out encrypted to the other peer'],
|
||||||
|
@ -6,16 +6,15 @@ We call this usage a _connection upgrade_ where given a connection between peer
|
|||||||
|
|
||||||
A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/p2p/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know.
|
A byproduct of having these encrypted communications modules is that we can authenticate the peers we are dialing to. You might have noticed that every time we dial to a peer in libp2p space, we always use its PeerId at the end (e.g /ip4/127.0.0.1/tcp/89765/p2p/QmWCbVw1XZ8hiYBwwshPce2yaTDYTqTaP7GCHGpry3ykWb), this PeerId is generated by hashing the Public Key of the peer. With this, we can create a crypto challenge when dialing to another peer and prove that peer is the owner of a PrivateKey that matches the Public Key we know.
|
||||||
|
|
||||||
# 1. Set up encrypted communications with SECIO
|
# 1. Set up encrypted communications
|
||||||
|
|
||||||
We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the module `libp2p-secio` to complete it, go ahead and `npm install libp2p-secio`.
|
We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the modules `libp2p-secio`<sup>*</sup> and `libp2p-noise` to complete it, go ahead and `npm install libp2p-secio libp2p-noise`.
|
||||||
|
|
||||||
SECIO is the crypto channel developed for IPFS, it is a TLS 1.3 like crypto channel that established an encrypted communication channel between two peers.
|
To add them to your libp2p configuration, all you have to do is:
|
||||||
|
|
||||||
To add it to your libp2p configuration, all you have to do is:
|
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const Libp2p = require('libp2p')
|
const Libp2p = require('libp2p')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
|
|
||||||
const createNode = () => {
|
const createNode = () => {
|
||||||
@ -24,7 +23,7 @@ const createNode = () => {
|
|||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
// Attach secio as the crypto channel to use
|
// Attach secio as the crypto channel to use
|
||||||
connEncryption: [ SECIO ]
|
connEncryption: [ NOISE, SECIO ]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -32,6 +31,8 @@ const createNode = () => {
|
|||||||
|
|
||||||
And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working.
|
And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working.
|
||||||
|
|
||||||
|
_<sup>*</sup> SECIO is the crypto channel developed for IPFS, it is a TLS 1.3 like crypto channel that established an encrypted communication channel between two peers._
|
||||||
|
|
||||||
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
||||||
|
|
||||||
Important note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use.
|
Important note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use.
|
||||||
|
@ -2,6 +2,7 @@ import 'babel-polyfill'
|
|||||||
import Libp2p from 'libp2p'
|
import Libp2p from 'libp2p'
|
||||||
import Websockets from 'libp2p-websockets'
|
import Websockets from 'libp2p-websockets'
|
||||||
import WebRTCStar from 'libp2p-webrtc-star'
|
import WebRTCStar from 'libp2p-webrtc-star'
|
||||||
|
import { NOISE } from 'libp2p-noise'
|
||||||
import Secio from 'libp2p-secio'
|
import Secio from 'libp2p-secio'
|
||||||
import Mplex from 'libp2p-mplex'
|
import Mplex from 'libp2p-mplex'
|
||||||
import Boostrap from 'libp2p-bootstrap'
|
import Boostrap from 'libp2p-bootstrap'
|
||||||
@ -9,9 +10,15 @@ import Boostrap from 'libp2p-bootstrap'
|
|||||||
document.addEventListener('DOMContentLoaded', async () => {
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
// Create our libp2p node
|
// Create our libp2p node
|
||||||
const libp2p = await Libp2p.create({
|
const libp2p = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
// Add the signaling server address, along with our PeerId to our multiaddrs list
|
||||||
|
// libp2p will automatically attempt to dial to the signaling server so that it can
|
||||||
|
// receive inbound connections from other peers
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/9090/wss/p2p-webrtc-star']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [Websockets, WebRTCStar],
|
transport: [Websockets, WebRTCStar],
|
||||||
connEncryption: [Secio],
|
connEncryption: [NOISE, Secio],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
peerDiscovery: [Boostrap]
|
peerDiscovery: [Boostrap]
|
||||||
},
|
},
|
||||||
@ -43,30 +50,24 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
output.textContent += `${txt.trim()}\n`
|
output.textContent += `${txt.trim()}\n`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the signaling server address, along with our PeerId to our multiaddrs list
|
|
||||||
// libp2p will automatically attempt to dial to the signaling server so that it can
|
|
||||||
// receive inbound connections from other peers
|
|
||||||
const webrtcAddr = '/ip4/0.0.0.0/tcp/9090/wss/p2p-webrtc-star'
|
|
||||||
libp2p.peerInfo.multiaddrs.add(webrtcAddr)
|
|
||||||
|
|
||||||
// Listen for new peers
|
// Listen for new peers
|
||||||
libp2p.on('peer:discovery', (peerInfo) => {
|
libp2p.on('peer:discovery', (peerId) => {
|
||||||
log(`Found peer ${peerInfo.id.toB58String()}`)
|
log(`Found peer ${peerId.toB58String()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Listen for new connections to peers
|
// Listen for new connections to peers
|
||||||
libp2p.on('peer:connect', (peerInfo) => {
|
libp2p.connectionManager.on('peer:connect', (connection) => {
|
||||||
log(`Connected to ${peerInfo.id.toB58String()}`)
|
log(`Connected to ${connection.remotePeer.toB58String()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Listen for peers disconnecting
|
// Listen for peers disconnecting
|
||||||
libp2p.on('peer:disconnect', (peerInfo) => {
|
libp2p.connectionManager.on('peer:disconnect', (connection) => {
|
||||||
log(`Disconnected from ${peerInfo.id.toB58String()}`)
|
log(`Disconnected from ${connection.remotePeer.toB58String()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
await libp2p.start()
|
await libp2p.start()
|
||||||
status.innerText = 'libp2p started!'
|
status.innerText = 'libp2p started!'
|
||||||
log(`libp2p id is ${libp2p.peerInfo.id.toB58String()}`)
|
log(`libp2p id is ${libp2p.peerId.toB58String()}`)
|
||||||
|
|
||||||
// Export libp2p to the window so you can play with the API
|
// Export libp2p to the window so you can play with the API
|
||||||
window.libp2p = libp2p
|
window.libp2p = libp2p
|
||||||
|
@ -17,10 +17,11 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-env": "^7.8.3",
|
"@babel/preset-env": "^7.8.3",
|
||||||
"libp2p": "../../",
|
"libp2p": "../../",
|
||||||
"libp2p-bootstrap": "^0.10.3",
|
"libp2p-bootstrap": "^0.11",
|
||||||
"libp2p-mplex": "^0.9.3",
|
"libp2p-mplex": "^0.9.3",
|
||||||
|
"libp2p-noise": "^1.1.0",
|
||||||
"libp2p-secio": "^0.12.2",
|
"libp2p-secio": "^0.12.2",
|
||||||
"libp2p-webrtc-star": "^0.17.3",
|
"libp2p-webrtc-star": "^0.18.0",
|
||||||
"libp2p-websockets": "^0.13.2"
|
"libp2p-websockets": "^0.13.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -4,22 +4,21 @@
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
|
||||||
const delay = require('delay')
|
const delay = require('delay')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
dht: KadDHT
|
dht: KadDHT
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -40,16 +39,19 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
node2.peerStore.addressBook.set(node3.peerId, node3.multiaddrs)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
node1.dial(node2.peerInfo),
|
node1.dial(node2.peerId),
|
||||||
node2.dial(node3.peerInfo)
|
node2.dial(node3.peerId)
|
||||||
])
|
])
|
||||||
|
|
||||||
// The DHT routing tables need a moment to populate
|
// The DHT routing tables need a moment to populate
|
||||||
await delay(100)
|
await delay(100)
|
||||||
|
|
||||||
const peer = await node1.peerRouting.findPeer(node3.peerInfo.id)
|
const peer = await node1.peerRouting.findPeer(node3.peerId)
|
||||||
|
|
||||||
console.log('Found it, multiaddrs are:')
|
console.log('Found it, multiaddrs are:')
|
||||||
peer.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
peer.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${peer.id.toB58String()}`))
|
||||||
})();
|
})();
|
||||||
|
@ -5,7 +5,7 @@ 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 { NOISE } = require('libp2p-noise')
|
||||||
const CID = require('cids')
|
const CID = require('cids')
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
|
||||||
@ -13,15 +13,14 @@ const all = require('it-all')
|
|||||||
const delay = require('delay')
|
const delay = require('delay')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
dht: KadDHT
|
dht: KadDHT
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@ -42,15 +41,21 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
node2.peerStore.addressBook.set(node3.peerId, node3.multiaddrs)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
node1.dial(node2.peerInfo),
|
node1.dial(node2.peerId),
|
||||||
node2.dial(node3.peerInfo)
|
node2.dial(node3.peerId)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Wait for onConnect handlers in the DHT
|
||||||
|
await delay(100)
|
||||||
|
|
||||||
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
|
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
|
||||||
await node1.contentRouting.provide(cid)
|
await node1.contentRouting.provide(cid)
|
||||||
|
|
||||||
console.log('Node %s is providing %s', node1.peerInfo.id.toB58String(), cid.toBaseEncodedString())
|
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toBaseEncodedString())
|
||||||
|
|
||||||
// wait for propagation
|
// wait for propagation
|
||||||
await delay(300)
|
await delay(300)
|
||||||
|
@ -17,10 +17,13 @@ const Libp2p = require('libp2p')
|
|||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ NOISE, SECIO ],
|
||||||
// we add the DHT module that will enable Peer and Content Routing
|
// we add the DHT module that will enable Peer and Content Routing
|
||||||
dht: KadDHT
|
dht: KadDHT
|
||||||
},
|
},
|
||||||
@ -40,18 +43,21 @@ const node1 = nodes[0]
|
|||||||
const node2 = nodes[1]
|
const node2 = nodes[1]
|
||||||
const node3 = nodes[2]
|
const node3 = nodes[2]
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
node2.peerStore.addressBook.set(node3.peerId, node3.multiaddrs)
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
node1.dial(node2.peerInfo),
|
node1.dial(node2.peerId),
|
||||||
node2.dial(node3.peerInfo)
|
node2.dial(node3.peerId)
|
||||||
])
|
])
|
||||||
|
|
||||||
// Set up of the cons might take time
|
// Set up of the cons might take time
|
||||||
await delay(100)
|
await delay(100)
|
||||||
|
|
||||||
const peer = await node1.peerRouting.findPeer(node3.peerInfo.id)
|
const peer = await node1.peerRouting.findPeer(node3.peerId)
|
||||||
|
|
||||||
console.log('Found it, multiaddrs are:')
|
console.log('Found it, multiaddrs are:')
|
||||||
peer.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
peer.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${peer.id.toB58String()}`))
|
||||||
```
|
```
|
||||||
|
|
||||||
You should see the output being something like:
|
You should see the output being something like:
|
||||||
@ -59,8 +65,8 @@ You should see the output being something like:
|
|||||||
```Bash
|
```Bash
|
||||||
> node 1.js
|
> node 1.js
|
||||||
Found it, multiaddrs are:
|
Found it, multiaddrs are:
|
||||||
/ip4/127.0.0.1/tcp/63617/p2p/QmWrFXvZr9S4iDqycyoyc2zDdrT1jg9wpdenUTdd1LTar6
|
/ip4/127.0.0.1/tcp/63617
|
||||||
/ip4/192.168.86.41/tcp/63617/p2p/QmWrFXvZr9S4iDqycyoyc2zDdrT1jg9wpdenUTdd1LTar6
|
/ip4/192.168.86.41/tcp/63617
|
||||||
```
|
```
|
||||||
|
|
||||||
You have successfully used Peer Routing to find a peer that you were not directly connected. Now all you have to do is to dial to the multiaddrs you discovered.
|
You have successfully used Peer Routing to find a peer that you were not directly connected. Now all you have to do is to dial to the multiaddrs you discovered.
|
||||||
@ -75,7 +81,7 @@ Instead of calling `peerRouting.findPeer`, we will use `contentRouting.provide`
|
|||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
await node1.contentRouting.provide(cid)
|
await node1.contentRouting.provide(cid)
|
||||||
console.log('Node %s is providing %s', node1.peerInfo.id.toB58String(), cid.toBaseEncodedString())
|
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toBaseEncodedString())
|
||||||
|
|
||||||
const provs = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 }))
|
const provs = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 }))
|
||||||
|
|
||||||
|
@ -29,7 +29,9 @@ generate(otherSwarmKey)
|
|||||||
|
|
||||||
console.log('nodes started...')
|
console.log('nodes started...')
|
||||||
|
|
||||||
await node1.dial(node2.peerInfo)
|
// Add node 2 data to node1's PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
await node1.dial(node2.peerId)
|
||||||
|
|
||||||
node2.handle('/private', ({ stream }) => {
|
node2.handle('/private', ({ stream }) => {
|
||||||
pipe(
|
pipe(
|
||||||
@ -42,7 +44,7 @@ generate(otherSwarmKey)
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/private')
|
const { stream } = await node1.dialProtocol(node2.peerId, '/private')
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['This message is sent on a private network'],
|
['This message is sent on a private network'],
|
||||||
|
@ -4,6 +4,7 @@ const Libp2p = require('libp2p')
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const Protector = require('libp2p/src/pnet')
|
const Protector = require('libp2p/src/pnet')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,12 +16,15 @@ const Protector = require('libp2p/src/pnet')
|
|||||||
*/
|
*/
|
||||||
const privateLibp2pNode = async (swarmKey) => {
|
const privateLibp2pNode = async (swarmKey) => {
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP], // We're only using the TCP transport for this example
|
transport: [TCP], // We're only using the TCP transport for this example
|
||||||
streamMuxer: [MPLEX], // We're only using mplex muxing
|
streamMuxer: [MPLEX], // We're only using mplex muxing
|
||||||
// Let's make sure to use identifying crypto in our pnet since the protector doesn't
|
// Let's make sure to use identifying crypto in our pnet since the protector doesn't
|
||||||
// care about node identity, and only the presence of private keys
|
// care about node identity, and only the presence of private keys
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
// Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's
|
// Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's
|
||||||
// being left in for explicit readability.
|
// being left in for explicit readability.
|
||||||
// We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet
|
// We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet
|
||||||
@ -29,7 +33,6 @@ const privateLibp2pNode = async (swarmKey) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
node.peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"libp2p": "../..",
|
"libp2p": "../..",
|
||||||
"libp2p-mplex": "^0.9.3",
|
"libp2p-mplex": "^0.9.3",
|
||||||
|
"libp2p-noise": "^1.1.0",
|
||||||
"libp2p-secio": "^0.12.1",
|
"libp2p-secio": "^0.12.1",
|
||||||
"libp2p-tcp": "^0.14.2"
|
"libp2p-tcp": "^0.14.2"
|
||||||
}
|
}
|
||||||
|
@ -3,21 +3,20 @@
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [MPLEX],
|
streamMuxer: [MPLEX],
|
||||||
connEncryption: [SECIO]
|
connEncryption: [NOISE, SECIO]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -32,6 +31,9 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
// exact matching
|
// exact matching
|
||||||
node2.handle('/your-protocol', ({ stream }) => {
|
node2.handle('/your-protocol', ({ stream }) => {
|
||||||
pipe(
|
pipe(
|
||||||
@ -62,14 +64,14 @@ const createNode = async () => {
|
|||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, ['/your-protocol'])
|
const { stream } = await node1.dialProtocol(node2.peerId, ['/your-protocol'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['my own protocol, wow!'],
|
['my own protocol, wow!'],
|
||||||
stream
|
stream
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
const { stream } = node1.dialProtocol(node2.peerInfo, ['/another-protocol/1.0.0'])
|
const { stream } = node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0'])
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['my own protocol, wow!'],
|
['my own protocol, wow!'],
|
||||||
|
@ -3,21 +3,20 @@
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [MPLEX],
|
streamMuxer: [MPLEX],
|
||||||
connEncryption: [SECIO]
|
connEncryption: [NOISE, SECIO]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -32,6 +31,9 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
node2.handle(['/a', '/b'], ({ protocol, stream }) => {
|
node2.handle(['/a', '/b'], ({ protocol, stream }) => {
|
||||||
pipe(
|
pipe(
|
||||||
stream,
|
stream,
|
||||||
@ -43,19 +45,19 @@ const createNode = async () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream: stream1 } = await node1.dialProtocol(node2.peerInfo, ['/a'])
|
const { stream: stream1 } = await node1.dialProtocol(node2.peerId, ['/a'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['protocol (a)'],
|
['protocol (a)'],
|
||||||
stream1
|
stream1
|
||||||
)
|
)
|
||||||
|
|
||||||
const { stream: stream2 } = await node1.dialProtocol(node2.peerInfo, ['/b'])
|
const { stream: stream2 } = await node1.dialProtocol(node2.peerId, ['/b'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['protocol (b)'],
|
['protocol (b)'],
|
||||||
stream2
|
stream2
|
||||||
)
|
)
|
||||||
|
|
||||||
const { stream: stream3 } = await node1.dialProtocol(node2.peerInfo, ['/b'])
|
const { stream: stream3 } = await node1.dialProtocol(node2.peerId, ['/b'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['another stream on protocol (b)'],
|
['another stream on protocol (b)'],
|
||||||
stream3
|
stream3
|
||||||
|
@ -4,21 +4,20 @@
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [MPLEX],
|
streamMuxer: [MPLEX],
|
||||||
connEncryption: [SECIO]
|
connEncryption: [NOISE, SECIO]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -32,6 +31,9 @@ const createNode = async () => {
|
|||||||
createNode(),
|
createNode(),
|
||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
node1.handle('/node-1', ({ stream }) => {
|
node1.handle('/node-1', ({ stream }) => {
|
||||||
pipe(
|
pipe(
|
||||||
@ -55,13 +57,13 @@ const createNode = async () => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream: stream1 } = await node1.dialProtocol(node2.peerInfo, ['/node-2'])
|
const { stream: stream1 } = await node1.dialProtocol(node2.peerId, ['/node-2'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['from 1 to 2'],
|
['from 1 to 2'],
|
||||||
stream1
|
stream1
|
||||||
)
|
)
|
||||||
|
|
||||||
const { stream: stream2 } = await node2.dialProtocol(node1.peerInfo, ['/node-1'])
|
const { stream: stream2 } = await node2.dialProtocol(node1.peerId, ['/node-1'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['from 2 to 1'],
|
['from 2 to 1'],
|
||||||
stream2
|
stream2
|
||||||
|
@ -6,7 +6,7 @@ The feature of agreeing on a protocol over an established connection is what we
|
|||||||
|
|
||||||
# 1. Handle multiple protocols
|
# 1. Handle multiple protocols
|
||||||
|
|
||||||
Let's see _protocol multiplexing_ in action! You will need the following modules for this example: `libp2p`, `libp2p-tcp`, `peer-info`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js).
|
Let's see _protocol multiplexing_ in action! You will need the following modules for this example: `libp2p`, `libp2p-tcp`, `peer-id`, `it-pipe`, `it-buffer` and `streaming-iterables`. This example reuses the base left by the [Transports](../transports) example. You can see the complete solution at [1.js](./1.js).
|
||||||
|
|
||||||
After creating the nodes, we need to tell libp2p which protocols to handle.
|
After creating the nodes, we need to tell libp2p which protocols to handle.
|
||||||
|
|
||||||
@ -19,6 +19,9 @@ const { toBuffer } = require('it-buffer')
|
|||||||
const node1 = nodes[0]
|
const node1 = nodes[0]
|
||||||
const node2 = nodes[1]
|
const node2 = nodes[1]
|
||||||
|
|
||||||
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
// Here we are telling libp2p that if someone dials this node to talk with the `/your-protocol`
|
// Here we are telling libp2p that if someone dials this node to talk with the `/your-protocol`
|
||||||
// multicodec, the protocol identifier, please call this handler and give it the stream
|
// multicodec, the protocol identifier, please call this handler and give it the stream
|
||||||
// so that incomming data can be handled
|
// so that incomming data can be handled
|
||||||
@ -37,7 +40,7 @@ node2.handle('/your-protocol', ({ stream }) => {
|
|||||||
After the protocol is _handled_, now we can dial to it.
|
After the protocol is _handled_, now we can dial to it.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, ['/your-protocol'])
|
const { stream } = await node1.dialProtocol(node2.peerId, ['/your-protocol'])
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['my own protocol, wow!'],
|
['my own protocol, wow!'],
|
||||||
@ -59,7 +62,7 @@ node2.handle('/another-protocol/1.0.1', ({ stream }) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
// ...
|
// ...
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, ['/another-protocol/1.0.0'])
|
const { stream } = await node1.dialProtocol(node2.peerId, ['/another-protocol/1.0.0'])
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['my own protocol, wow!'],
|
['my own protocol, wow!'],
|
||||||
@ -128,19 +131,19 @@ node2.handle(['/a', '/b'], ({ protocol, stream }) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, ['/a'])
|
const { stream } = await node1.dialProtocol(node2.peerId, ['/a'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['protocol (a)'],
|
['protocol (a)'],
|
||||||
stream
|
stream
|
||||||
)
|
)
|
||||||
|
|
||||||
const { stream: stream2 } = await node1.dialProtocol(node2.peerInfo, ['/b'])
|
const { stream: stream2 } = await node1.dialProtocol(node2.peerId, ['/b'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['protocol (b)'],
|
['protocol (b)'],
|
||||||
stream2
|
stream2
|
||||||
)
|
)
|
||||||
|
|
||||||
const { stream: stream3 } = await node1.dialProtocol(node2.peerInfo, ['/b'])
|
const { stream: stream3 } = await node1.dialProtocol(node2.peerId, ['/b'])
|
||||||
await pipe(
|
await pipe(
|
||||||
['another stream on protocol (b)'],
|
['another stream on protocol (b)'],
|
||||||
stream3
|
stream3
|
||||||
|
@ -5,20 +5,19 @@ const { Buffer } = require('buffer')
|
|||||||
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 { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const Gossipsub = require('libp2p-gossipsub')
|
const Gossipsub = require('libp2p-gossipsub')
|
||||||
|
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
streamMuxer: [Mplex],
|
streamMuxer: [Mplex],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
pubsub: Gossipsub
|
pubsub: Gossipsub
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -35,7 +34,9 @@ const createNode = async () => {
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
await node1.dial(node2.peerInfo)
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
await node1.dial(node2.peerId)
|
||||||
|
|
||||||
await node1.pubsub.subscribe(topic, (msg) => {
|
await node1.pubsub.subscribe(topic, (msg) => {
|
||||||
console.log(`node1 received: ${msg.data.toString()}`)
|
console.log(`node1 received: ${msg.data.toString()}`)
|
||||||
|
@ -21,10 +21,13 @@ const Libp2p = require('libp2p')
|
|||||||
const Gossipsub = require('libp2p-gossipsub')
|
const Gossipsub = require('libp2p-gossipsub')
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
connEncryption: [ SECIO ],
|
connEncryption: [ NOISE, SECIO ],
|
||||||
// we add the Pubsub module we want
|
// we add the Pubsub module we want
|
||||||
pubsub: Gossipsub
|
pubsub: Gossipsub
|
||||||
}
|
}
|
||||||
@ -39,7 +42,10 @@ const topic = 'news'
|
|||||||
const node1 = nodes[0]
|
const node1 = nodes[0]
|
||||||
const node2 = nodes[1]
|
const node2 = nodes[1]
|
||||||
|
|
||||||
await node1.dial(node2.peerInfo)
|
// Add node's 2 data to the PeerStore
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
|
||||||
|
await node1.dial(node2.peerId)
|
||||||
|
|
||||||
await node1.pubsub.subscribe(topic, (msg) => {
|
await node1.pubsub.subscribe(topic, (msg) => {
|
||||||
console.log(`node1 received: ${msg.data.toString()}`)
|
console.log(`node1 received: ${msg.data.toString()}`)
|
||||||
|
@ -3,19 +3,19 @@
|
|||||||
|
|
||||||
const Libp2p = require('../..')
|
const Libp2p = require('../..')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const createNode = async (peerInfo) => {
|
|
||||||
// To signall the addresses we want to be available, we use
|
|
||||||
// the multiaddr format, a self describable address
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
|
const createNode = async () => {
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
// To signall the addresses we want to be available, we use
|
||||||
|
// the multiaddr format, a self describable address
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
connEncryption: [SECIO]
|
connEncryption: [NOISE, SECIO]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -24,10 +24,9 @@ const createNode = async (peerInfo) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const peerInfo = await PeerInfo.create()
|
const node = await createNode()
|
||||||
const node = await createNode(peerInfo)
|
|
||||||
|
|
||||||
console.log('node has started (true/false):', node.isStarted())
|
console.log('node has started (true/false):', node.isStarted())
|
||||||
console.log('listening on:')
|
console.log('listening on:')
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
})();
|
})();
|
||||||
|
@ -3,23 +3,23 @@
|
|||||||
|
|
||||||
const Libp2p = require('../..')
|
const Libp2p = require('../..')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const MPLEX = require('libp2p-mplex')
|
const MPLEX = require('libp2p-mplex')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
const concat = require('it-concat')
|
const concat = require('it-concat')
|
||||||
|
|
||||||
const createNode = async (peerInfo) => {
|
const createNode = async () => {
|
||||||
// To signall the addresses we want to be available, we use
|
|
||||||
// the multiaddr format, a self describable address
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
// To signall the addresses we want to be available, we use
|
||||||
|
// the multiaddr format, a self describable address
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
streamMuxer: [MPLEX]
|
streamMuxer: [MPLEX]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -30,17 +30,13 @@ const createNode = async (peerInfo) => {
|
|||||||
|
|
||||||
function printAddrs (node, number) {
|
function printAddrs (node, number) {
|
||||||
console.log('node %s is listening on:', number)
|
console.log('node %s is listening on:', number)
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const [peerInfo1, peerInfo2] = await Promise.all([
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create()
|
|
||||||
])
|
|
||||||
const [node1, node2] = await Promise.all([
|
const [node1, node2] = await Promise.all([
|
||||||
createNode(peerInfo1),
|
createNode(),
|
||||||
createNode(peerInfo2)
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
printAddrs(node1, '1')
|
printAddrs(node1, '1')
|
||||||
@ -54,7 +50,8 @@ function printAddrs (node, number) {
|
|||||||
console.log(result.toString())
|
console.log(result.toString())
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/print')
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
const { stream } = await node1.dialProtocol(node2.peerId, '/print')
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['Hello', ' ', 'p2p', ' ', 'world', '!'],
|
['Hello', ' ', 'p2p', ' ', 'world', '!'],
|
||||||
|
@ -4,24 +4,24 @@
|
|||||||
const Libp2p = require('../..')
|
const Libp2p = require('../..')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const WebSockets = require('libp2p-websockets')
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const MPLEX = require('libp2p-mplex')
|
const MPLEX = require('libp2p-mplex')
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
const createNode = async (peerInfo, transports, multiaddrs = []) => {
|
const createNode = async (transports, addresses = []) => {
|
||||||
if (!Array.isArray(multiaddrs)) {
|
if (!Array.isArray(addresses)) {
|
||||||
multiaddrs = [multiaddrs]
|
addresses = [addresses]
|
||||||
}
|
}
|
||||||
|
|
||||||
multiaddrs.forEach((addr) => peerInfo.multiaddrs.add(addr))
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: addresses.map((a) => a)
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: transports,
|
transport: transports,
|
||||||
connEncryption: [SECIO],
|
connEncryption: [NOISE, SECIO],
|
||||||
streamMuxer: [MPLEX]
|
streamMuxer: [MPLEX]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -32,7 +32,7 @@ const createNode = async (peerInfo, transports, multiaddrs = []) => {
|
|||||||
|
|
||||||
function printAddrs(node, number) {
|
function printAddrs(node, number) {
|
||||||
console.log('node %s is listening on:', number)
|
console.log('node %s is listening on:', number)
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
}
|
}
|
||||||
|
|
||||||
function print ({ stream }) {
|
function print ({ stream }) {
|
||||||
@ -47,15 +47,10 @@ function print ({ stream }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const [peerInfo1, peerInfo2, peerInfo3] = await Promise.all([
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create()
|
|
||||||
])
|
|
||||||
const [node1, node2, node3] = await Promise.all([
|
const [node1, node2, node3] = await Promise.all([
|
||||||
createNode(peerInfo1, [TCP], '/ip4/0.0.0.0/tcp/0'),
|
createNode([TCP], '/ip4/0.0.0.0/tcp/0'),
|
||||||
createNode(peerInfo2, [TCP, WebSockets], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']),
|
createNode([TCP, WebSockets], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']),
|
||||||
createNode(peerInfo3, [WebSockets], '/ip4/127.0.0.1/tcp/20000/ws')
|
createNode([WebSockets], '/ip4/127.0.0.1/tcp/20000/ws')
|
||||||
])
|
])
|
||||||
|
|
||||||
printAddrs(node1, '1')
|
printAddrs(node1, '1')
|
||||||
@ -66,15 +61,19 @@ function print ({ stream }) {
|
|||||||
node2.handle('/print', print)
|
node2.handle('/print', print)
|
||||||
node3.handle('/print', print)
|
node3.handle('/print', print)
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
node2.peerStore.addressBook.set(node3.peerId, node3.multiaddrs)
|
||||||
|
node3.peerStore.addressBook.set(node1.peerId, node1.multiaddrs)
|
||||||
|
|
||||||
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/print')
|
const { stream } = await node1.dialProtocol(node2.peerId, '/print')
|
||||||
await pipe(
|
await pipe(
|
||||||
['node 1 dialed to node 2 successfully'],
|
['node 1 dialed to node 2 successfully'],
|
||||||
stream
|
stream
|
||||||
)
|
)
|
||||||
|
|
||||||
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
||||||
const { stream: stream2 } = await node2.dialProtocol(node3.peerInfo, '/print')
|
const { stream: stream2 } = await node2.dialProtocol(node3.peerId, '/print')
|
||||||
await pipe(
|
await pipe(
|
||||||
['node 2 dialed to node 3 successfully'],
|
['node 2 dialed to node 3 successfully'],
|
||||||
stream2
|
stream2
|
||||||
@ -82,7 +81,7 @@ function print ({ stream }) {
|
|||||||
|
|
||||||
// node 3 (listening WebSockets) can dial node 1 (TCP)
|
// node 3 (listening WebSockets) can dial node 1 (TCP)
|
||||||
try {
|
try {
|
||||||
await node3.dialProtocol(node1.peerInfo, '/print')
|
await node3.dialProtocol(node1.peerId, '/print')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('node 3 failed to dial to node 1 with:', err.message)
|
console.log('node 3 failed to dial to node 1 with:', err.message)
|
||||||
}
|
}
|
||||||
|
@ -25,18 +25,19 @@ First thing is to create our own libp2p node! Insert:
|
|||||||
|
|
||||||
const Libp2p = require('libp2p')
|
const Libp2p = require('libp2p')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
|
|
||||||
const createNode = async (peerInfo) => {
|
const createNode = async () => {
|
||||||
// To signall the addresses we want to be available, we use
|
|
||||||
// the multiaddr format, a self describable address
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
// To signall the addresses we want to be available, we use
|
||||||
|
// the multiaddr format, a self describable address
|
||||||
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
connEncryption: [ SECIO ]
|
connEncryption: [ NOISE, SECIO ]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -48,8 +49,7 @@ const createNode = async (peerInfo) => {
|
|||||||
Now that we have a function to create our own libp2p node, let's create a node with it.
|
Now that we have a function to create our own libp2p node, let's create a node with it.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const peerInfo = await PeerInfo.create()
|
const node = await createNode()
|
||||||
const node = await createNode(peerInfo)
|
|
||||||
|
|
||||||
// At this point the node has started
|
// At this point the node has started
|
||||||
console.log('node has started (true/false):', node.isStarted())
|
console.log('node has started (true/false):', node.isStarted())
|
||||||
@ -59,7 +59,7 @@ console.log('node has started (true/false):', node.isStarted())
|
|||||||
// 0, which means "listen in any network interface and pick
|
// 0, which means "listen in any network interface and pick
|
||||||
// a port for me
|
// a port for me
|
||||||
console.log('listening on:')
|
console.log('listening on:')
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
```
|
```
|
||||||
|
|
||||||
Running this should result in something like:
|
Running this should result in something like:
|
||||||
@ -96,7 +96,7 @@ We are going to reuse the `createNode` function from step 1, but this time to ma
|
|||||||
```JavaScript
|
```JavaScript
|
||||||
function printAddrs (node, number) {
|
function printAddrs (node, number) {
|
||||||
console.log('node %s is listening on:', number)
|
console.log('node %s is listening on:', number)
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -104,10 +104,6 @@ Then,
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
;(async () => {
|
;(async () => {
|
||||||
const [peerInfo1, peerInfo2] = await Promise.all([
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create()
|
|
||||||
])
|
|
||||||
const [node1, node2] = await Promise.all([
|
const [node1, node2] = await Promise.all([
|
||||||
createNode(),
|
createNode(),
|
||||||
createNode()
|
createNode()
|
||||||
@ -127,7 +123,8 @@ Then,
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/print')
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
const { stream } = await node1.dialProtocol(node2.peerId, '/print')
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
['Hello', ' ', 'p2p', ' ', 'world', '!'],
|
['Hello', ' ', 'p2p', ' ', 'world', '!'],
|
||||||
@ -166,18 +163,19 @@ We want to create 3 nodes, one with TCP, one with TCP+WebSockets and one with ju
|
|||||||
```JavaScript
|
```JavaScript
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
const createNode = async (peerInfo, transports, multiaddrs = []) => {
|
const createNode = async (transports, multiaddrs = []) => {
|
||||||
if (!Array.isArray(multiaddrs)) {
|
if (!Array.isArray(multiaddrs)) {
|
||||||
multiaddrs = [multiaddrs]
|
multiaddrs = [multiaddrs]
|
||||||
}
|
}
|
||||||
|
|
||||||
multiaddrs.forEach((addr) => peerInfo.multiaddrs.add(addr))
|
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
peerInfo,
|
addresses: {
|
||||||
|
listen: multiaddrs.map((a) => multiaddr(a))
|
||||||
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: transports,
|
transport: transports,
|
||||||
connEncryption: [ SECIO ]
|
connEncryption: [SECIO],
|
||||||
|
streamMuxer: [MPLEX]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -194,15 +192,10 @@ Let's update our flow to create nodes and see how they behave when dialing to ea
|
|||||||
const WebSockets = require('libp2p-websockets')
|
const WebSockets = require('libp2p-websockets')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
|
|
||||||
const [peerInfo1, peerInfo2, peerInfo3] = await Promise.all([
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create(),
|
|
||||||
PeerInfo.create()
|
|
||||||
])
|
|
||||||
const [node1, node2, node3] = await Promise.all([
|
const [node1, node2, node3] = await Promise.all([
|
||||||
createNode(peerInfo1, [TCP], '/ip4/0.0.0.0/tcp/0'),
|
createNode([TCP], '/ip4/0.0.0.0/tcp/0'),
|
||||||
createNode(peerInfo2, [TCP, WebSockets], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']),
|
createNode([TCP, WebSockets], ['/ip4/0.0.0.0/tcp/0', '/ip4/127.0.0.1/tcp/10000/ws']),
|
||||||
createNode(peerInfo3, [WebSockets], '/ip4/127.0.0.1/tcp/20000/ws')
|
createNode([WebSockets], '/ip4/127.0.0.1/tcp/20000/ws')
|
||||||
])
|
])
|
||||||
|
|
||||||
printAddrs(node1, '1')
|
printAddrs(node1, '1')
|
||||||
@ -213,15 +206,19 @@ node1.handle('/print', print)
|
|||||||
node2.handle('/print', print)
|
node2.handle('/print', print)
|
||||||
node3.handle('/print', print)
|
node3.handle('/print', print)
|
||||||
|
|
||||||
|
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||||
|
node2.peerStore.addressBook.set(node3.peerId, node3.multiaddrs)
|
||||||
|
node3.peerStore.addressBook.set(node1.peerId, node1.multiaddrs)
|
||||||
|
|
||||||
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
||||||
const { stream } = await node1.dialProtocol(node2.peerInfo, '/print')
|
const { stream } = await node1.dialProtocol(node2.peerId, '/print')
|
||||||
await pipe(
|
await pipe(
|
||||||
['node 1 dialed to node 2 successfully'],
|
['node 1 dialed to node 2 successfully'],
|
||||||
stream
|
stream
|
||||||
)
|
)
|
||||||
|
|
||||||
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
||||||
const { stream: stream2 } = await node2.dialProtocol(node3.peerInfo, '/print')
|
const { stream: stream2 } = await node2.dialProtocol(node3.peerId, '/print')
|
||||||
await pipe(
|
await pipe(
|
||||||
['node 2 dialed to node 3 successfully'],
|
['node 2 dialed to node 3 successfully'],
|
||||||
stream2
|
stream2
|
||||||
@ -229,7 +226,7 @@ await pipe(
|
|||||||
|
|
||||||
// node 3 (WebSockets) attempts to dial to node 1 (TCP)
|
// node 3 (WebSockets) attempts to dial to node 1 (TCP)
|
||||||
try {
|
try {
|
||||||
await node3.dialProtocol(node1.peerInfo, '/print')
|
await node3.dialProtocol(node1.peerId, '/print')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log('node 3 failed to dial to node 1 with:', err.message)
|
console.log('node 3 failed to dial to node 1 with:', err.message)
|
||||||
}
|
}
|
||||||
|
12
src/index.js
12
src/index.js
@ -293,7 +293,7 @@ class Libp2p extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dials to the provided peer. If successful, the known `Peer` data of the
|
* Dials to the provided peer. If successful, the known metadata of the
|
||||||
* peer will be added to the nodes `peerStore`
|
* peer will be added to the nodes `peerStore`
|
||||||
* @param {PeerId|Multiaddr|string} peer The peer to dial
|
* @param {PeerId|Multiaddr|string} peer The peer to dial
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
@ -306,7 +306,7 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Dials to the provided peer and handshakes with the given protocol.
|
* Dials to the provided peer and handshakes with the given protocol.
|
||||||
* If successful, the known `Peer` data of the peer will be added to the nodes `peerStore`,
|
* If successful, the known metadata of the peer will be added to the nodes `peerStore`,
|
||||||
* and the `Connection` will be returned
|
* and the `Connection` will be returned
|
||||||
* @async
|
* @async
|
||||||
* @param {PeerId|Multiaddr|string} peer The peer to dial
|
* @param {PeerId|Multiaddr|string} peer The peer to dial
|
||||||
@ -465,21 +465,21 @@ class Libp2p extends EventEmitter {
|
|||||||
this._maybeConnect(peerId)
|
this._maybeConnect(peerId)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Peer discovery
|
|
||||||
await this._setupPeerDiscovery()
|
|
||||||
|
|
||||||
// Once we start, emit and dial any peers we may have already discovered
|
// Once we start, emit and dial any peers we may have already discovered
|
||||||
for (const peer of this.peerStore.peers.values()) {
|
for (const peer of this.peerStore.peers.values()) {
|
||||||
this.emit('peer:discovery', peer.id)
|
this.emit('peer:discovery', peer.id)
|
||||||
this._maybeConnect(peer.id)
|
this._maybeConnect(peer.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Peer discovery
|
||||||
|
await this._setupPeerDiscovery()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called whenever peer discovery services emit `peer` events.
|
* Called whenever peer discovery services emit `peer` events.
|
||||||
* Known peers may be emitted.
|
* Known peers may be emitted.
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerDara} peer
|
* @param {{ id: PeerId, multiaddrs: Array<Multiaddr>, protocols: Array<string> }} peer
|
||||||
*/
|
*/
|
||||||
_onDiscoveryPeer (peer) {
|
_onDiscoveryPeer (peer) {
|
||||||
if (peer.id.toB58String() === this.peerId.toB58String()) {
|
if (peer.id.toB58String() === this.peerId.toB58String()) {
|
||||||
|
Reference in New Issue
Block a user