mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-06-25 23:11:35 +00:00
refactor(docs): async await version of examples/chat (#482)
* fix: performance bottleneck in stat.js (#463) Array.shift seems to be very slow, perhaps linear, on some engines, resulting in _update consuming a lot of CPU. * docs(fix): correct docs and example for pnet (#464) * docs(fix): correct docs and example for pnet * docs(fix): correct pnet docs * docs(fix): update README.md language (#468) * docs: reciprocate (#474) * docs(example): fix ipfs cat (#475) `ipfs.files.cat` is incorrect. the correct function is `ipfs.cat` * fix: async-await example chat * fix: move handler before start * fix: examples readme typos (#481) * fix: simplify libp2p bundle for echo example * chore: remove unused vars
This commit is contained in:
@ -4,76 +4,44 @@
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const Node = require('./libp2p-bundle')
|
const Node = require('./libp2p-bundle')
|
||||||
const pull = require('pull-stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
const async = require('async')
|
|
||||||
const Pushable = require('pull-pushable')
|
|
||||||
const p = Pushable()
|
|
||||||
let idListener
|
|
||||||
|
|
||||||
async.parallel([
|
async function run() {
|
||||||
(callback) => {
|
const [idDialer, idListener] = await Promise.all([
|
||||||
PeerId.createFromJSON(require('./peer-id-dialer'), (err, idDialer) => {
|
PeerId.createFromJSON(require('./peer-id-dialer')),
|
||||||
if (err) {
|
PeerId.createFromJSON(require('./peer-id-listener'))
|
||||||
throw err
|
])
|
||||||
}
|
|
||||||
callback(null, idDialer)
|
// Create a new libp2p node on localhost with a randomly chosen port
|
||||||
})
|
const peerDialer = new PeerInfo(idDialer)
|
||||||
},
|
|
||||||
(callback) => {
|
|
||||||
PeerId.createFromJSON(require('./peer-id-listener'), (err, idListener) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
callback(null, idListener)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
], (err, ids) => {
|
|
||||||
if (err) throw err
|
|
||||||
const peerDialer = new PeerInfo(ids[0])
|
|
||||||
peerDialer.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
peerDialer.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
||||||
const nodeDialer = new Node({
|
const nodeDialer = new Node({
|
||||||
peerInfo: peerDialer
|
peerInfo: peerDialer
|
||||||
})
|
})
|
||||||
|
|
||||||
const peerListener = new PeerInfo(ids[1])
|
// Create a PeerInfo with the listening peer's address
|
||||||
idListener = ids[1]
|
const peerListener = new PeerInfo(idListener)
|
||||||
peerListener.multiaddrs.add('/ip4/127.0.0.1/tcp/10333')
|
peerListener.multiaddrs.add('/ip4/127.0.0.1/tcp/10333')
|
||||||
nodeDialer.start((err) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Dialer ready, listening on:')
|
// Start the libp2p host
|
||||||
|
await nodeDialer.start()
|
||||||
|
|
||||||
peerListener.multiaddrs.forEach((ma) => {
|
// Output this node's address
|
||||||
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
console.log('Dialer ready, listening on:')
|
||||||
})
|
peerListener.multiaddrs.forEach((ma) => {
|
||||||
|
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
||||||
nodeDialer.dialProtocol(peerListener, '/chat/1.0.0', (err, conn) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
console.log('nodeA dialed to nodeB on protocol: /chat/1.0.0')
|
|
||||||
console.log('Type a message and see what happens')
|
|
||||||
// Write operation. Data sent as a buffer
|
|
||||||
pull(
|
|
||||||
p,
|
|
||||||
conn
|
|
||||||
)
|
|
||||||
// Sink, data converted from buffer to utf8 string
|
|
||||||
pull(
|
|
||||||
conn,
|
|
||||||
pull.map((data) => {
|
|
||||||
return data.toString('utf8').replace('\n', '')
|
|
||||||
}),
|
|
||||||
pull.drain(console.log)
|
|
||||||
)
|
|
||||||
|
|
||||||
process.stdin.setEncoding('utf8')
|
|
||||||
process.openStdin().on('data', (chunk) => {
|
|
||||||
var data = chunk.toString()
|
|
||||||
p.push(data)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
// Dial to the remote peer (the "listener")
|
||||||
|
const { stream } = await nodeDialer.dialProtocol(peerListener, '/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')
|
||||||
|
|
||||||
|
// Send stdin to the stream
|
||||||
|
stdinToStream(stream)
|
||||||
|
// Read the stream and output to console
|
||||||
|
streamToConsole(stream)
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
@ -1,41 +1,12 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const Bootstrap = require('libp2p-bootstrap')
|
|
||||||
const spdy = require('libp2p-spdy')
|
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
|
||||||
const mplex = require('libp2p-mplex')
|
const mplex = require('libp2p-mplex')
|
||||||
const secio = require('libp2p-secio')
|
const secio = require('libp2p-secio')
|
||||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||||
const libp2p = require('../../..')
|
const libp2p = require('../../..')
|
||||||
|
|
||||||
function mapMuxers (list) {
|
|
||||||
return list.map((pref) => {
|
|
||||||
if (typeof pref !== 'string') {
|
|
||||||
return pref
|
|
||||||
}
|
|
||||||
switch (pref.trim().toLowerCase()) {
|
|
||||||
case 'spdy': return spdy
|
|
||||||
case 'mplex': return mplex
|
|
||||||
default:
|
|
||||||
throw new Error(pref + ' muxer not available')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMuxers (muxers) {
|
|
||||||
const muxerPrefs = process.env.LIBP2P_MUXER
|
|
||||||
if (muxerPrefs && !muxers) {
|
|
||||||
return mapMuxers(muxerPrefs.split(','))
|
|
||||||
} else if (muxers) {
|
|
||||||
return mapMuxers(muxers)
|
|
||||||
} else {
|
|
||||||
return [mplex, spdy]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Node extends libp2p {
|
class Node extends libp2p {
|
||||||
constructor (_options) {
|
constructor (_options) {
|
||||||
const defaults = {
|
const defaults = {
|
||||||
@ -44,29 +15,8 @@ class Node extends libp2p {
|
|||||||
TCP,
|
TCP,
|
||||||
WS
|
WS
|
||||||
],
|
],
|
||||||
streamMuxer: getMuxers(_options.muxer),
|
streamMuxer: [ mplex ],
|
||||||
connEncryption: [ secio ],
|
connEncryption: [ secio ]
|
||||||
peerDiscovery: [
|
|
||||||
MulticastDNS,
|
|
||||||
Bootstrap
|
|
||||||
],
|
|
||||||
dht: KadDHT
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
peerDiscovery: {
|
|
||||||
mdns: {
|
|
||||||
interval: 10000,
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
bootstrap: {
|
|
||||||
interval: 10000,
|
|
||||||
enabled: false,
|
|
||||||
list: _options.bootstrapList
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dht: {
|
|
||||||
kBucketSize: 20
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,53 +4,38 @@
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const Node = require('./libp2p-bundle.js')
|
const Node = require('./libp2p-bundle.js')
|
||||||
const pull = require('pull-stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
const Pushable = require('pull-pushable')
|
|
||||||
const p = Pushable()
|
|
||||||
|
|
||||||
PeerId.createFromJSON(require('./peer-id-listener'), (err, idListener) => {
|
async function run() {
|
||||||
if (err) {
|
// Create a new libp2p node with the given multi-address
|
||||||
throw err
|
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
||||||
}
|
|
||||||
const peerListener = new PeerInfo(idListener)
|
const peerListener = new PeerInfo(idListener)
|
||||||
peerListener.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
|
peerListener.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
|
||||||
const nodeListener = new Node({
|
const nodeListener = new Node({
|
||||||
peerInfo: peerListener
|
peerInfo: peerListener
|
||||||
})
|
})
|
||||||
|
|
||||||
nodeListener.start((err) => {
|
// Log a message when a remote peer connects to us
|
||||||
if (err) {
|
nodeListener.on('peer:connect', (peerInfo) => {
|
||||||
throw err
|
console.log(peerInfo.id.toB58String())
|
||||||
}
|
|
||||||
|
|
||||||
nodeListener.on('peer:connect', (peerInfo) => {
|
|
||||||
console.log(peerInfo.id.toB58String())
|
|
||||||
})
|
|
||||||
|
|
||||||
nodeListener.handle('/chat/1.0.0', (protocol, conn) => {
|
|
||||||
pull(
|
|
||||||
p,
|
|
||||||
conn
|
|
||||||
)
|
|
||||||
|
|
||||||
pull(
|
|
||||||
conn,
|
|
||||||
pull.map((data) => {
|
|
||||||
return data.toString('utf8').replace('\n', '')
|
|
||||||
}),
|
|
||||||
pull.drain(console.log)
|
|
||||||
)
|
|
||||||
|
|
||||||
process.stdin.setEncoding('utf8')
|
|
||||||
process.openStdin().on('data', (chunk) => {
|
|
||||||
var data = chunk.toString()
|
|
||||||
p.push(data)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
console.log('Listener ready, listening on:')
|
|
||||||
peerListener.multiaddrs.forEach((ma) => {
|
|
||||||
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
// Handle messages for the protocol
|
||||||
|
await nodeListener.handle('/chat/1.0.0', async ({ stream }) => {
|
||||||
|
// Send stdin to the stream
|
||||||
|
stdinToStream(stream)
|
||||||
|
// Read the stream and output to console
|
||||||
|
streamToConsole(stream)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Start listening
|
||||||
|
await nodeListener.start()
|
||||||
|
|
||||||
|
// Output listen addresses to the console
|
||||||
|
console.log('Listener ready, listening on:')
|
||||||
|
peerListener.multiaddrs.forEach((ma) => {
|
||||||
|
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
run()
|
||||||
|
40
examples/chat/src/stream.js
Normal file
40
examples/chat/src/stream.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
'use strict'
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
|
const pipe = require('it-pipe')
|
||||||
|
const lp = require('it-length-prefixed')
|
||||||
|
|
||||||
|
function stdinToStream(stream) {
|
||||||
|
// Read utf-8 from stdin
|
||||||
|
process.stdin.setEncoding('utf8')
|
||||||
|
pipe(
|
||||||
|
// Read from stdin (the source)
|
||||||
|
process.stdin,
|
||||||
|
// Encode with length prefix (so receiving side knows how much data is coming)
|
||||||
|
lp.encode(),
|
||||||
|
// Write to the stream (the sink)
|
||||||
|
stream.sink
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function streamToConsole(stream) {
|
||||||
|
pipe(
|
||||||
|
// Read from the stream (the source)
|
||||||
|
stream.source,
|
||||||
|
// Decode length-prefixed data
|
||||||
|
lp.decode(),
|
||||||
|
// Sink function
|
||||||
|
async function (source) {
|
||||||
|
// For each chunk of data
|
||||||
|
for await (const msg of source) {
|
||||||
|
// Output the data as a utf8 string
|
||||||
|
console.log('> ' + msg.toString('utf8').replace('\n', ''))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
stdinToStream,
|
||||||
|
streamToConsole
|
||||||
|
}
|
Reference in New Issue
Block a user