Skip to content

Commit e5f8cad

Browse files
dirkmcjacobheun
authored andcommitted
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
1 parent 3fc352c commit e5f8cad

File tree

4 files changed

+96
-153
lines changed

4 files changed

+96
-153
lines changed

examples/chat/src/dialer.js

+30-62
Original file line numberDiff line numberDiff line change
@@ -4,76 +4,44 @@
44
const PeerId = require('peer-id')
55
const PeerInfo = require('peer-info')
66
const Node = require('./libp2p-bundle')
7-
const pull = require('pull-stream')
8-
const async = require('async')
9-
const Pushable = require('pull-pushable')
10-
const p = Pushable()
11-
let idListener
7+
const { stdinToStream, streamToConsole } = require('./stream')
128

13-
async.parallel([
14-
(callback) => {
15-
PeerId.createFromJSON(require('./peer-id-dialer'), (err, idDialer) => {
16-
if (err) {
17-
throw err
18-
}
19-
callback(null, idDialer)
20-
})
21-
},
22-
(callback) => {
23-
PeerId.createFromJSON(require('./peer-id-listener'), (err, idListener) => {
24-
if (err) {
25-
throw err
26-
}
27-
callback(null, idListener)
28-
})
29-
}
30-
], (err, ids) => {
31-
if (err) throw err
32-
const peerDialer = new PeerInfo(ids[0])
9+
async function run() {
10+
const [idDialer, idListener] = await Promise.all([
11+
PeerId.createFromJSON(require('./peer-id-dialer')),
12+
PeerId.createFromJSON(require('./peer-id-listener'))
13+
])
14+
15+
// Create a new libp2p node on localhost with a randomly chosen port
16+
const peerDialer = new PeerInfo(idDialer)
3317
peerDialer.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
3418
const nodeDialer = new Node({
3519
peerInfo: peerDialer
3620
})
3721

38-
const peerListener = new PeerInfo(ids[1])
39-
idListener = ids[1]
22+
// Create a PeerInfo with the listening peer's address
23+
const peerListener = new PeerInfo(idListener)
4024
peerListener.multiaddrs.add('/ip4/127.0.0.1/tcp/10333')
41-
nodeDialer.start((err) => {
42-
if (err) {
43-
throw err
44-
}
4525

46-
console.log('Dialer ready, listening on:')
26+
// Start the libp2p host
27+
await nodeDialer.start()
4728

48-
peerListener.multiaddrs.forEach((ma) => {
49-
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
50-
})
29+
// Output this node's address
30+
console.log('Dialer ready, listening on:')
31+
peerListener.multiaddrs.forEach((ma) => {
32+
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
33+
})
5134

52-
nodeDialer.dialProtocol(peerListener, '/chat/1.0.0', (err, conn) => {
53-
if (err) {
54-
throw err
55-
}
56-
console.log('nodeA dialed to nodeB on protocol: /chat/1.0.0')
57-
console.log('Type a message and see what happens')
58-
// Write operation. Data sent as a buffer
59-
pull(
60-
p,
61-
conn
62-
)
63-
// Sink, data converted from buffer to utf8 string
64-
pull(
65-
conn,
66-
pull.map((data) => {
67-
return data.toString('utf8').replace('\n', '')
68-
}),
69-
pull.drain(console.log)
70-
)
35+
// Dial to the remote peer (the "listener")
36+
const { stream } = await nodeDialer.dialProtocol(peerListener, '/chat/1.0.0')
7137

72-
process.stdin.setEncoding('utf8')
73-
process.openStdin().on('data', (chunk) => {
74-
var data = chunk.toString()
75-
p.push(data)
76-
})
77-
})
78-
})
79-
})
38+
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
39+
console.log('Type a message and see what happens')
40+
41+
// Send stdin to the stream
42+
stdinToStream(stream)
43+
// Read the stream and output to console
44+
streamToConsole(stream)
45+
}
46+
47+
run()

examples/chat/src/libp2p-bundle.js

+2-52
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,12 @@
11
'use strict'
22

33
const TCP = require('libp2p-tcp')
4-
const MulticastDNS = require('libp2p-mdns')
54
const WS = require('libp2p-websockets')
6-
const Bootstrap = require('libp2p-bootstrap')
7-
const spdy = require('libp2p-spdy')
8-
const KadDHT = require('libp2p-kad-dht')
95
const mplex = require('libp2p-mplex')
106
const secio = require('libp2p-secio')
117
const defaultsDeep = require('@nodeutils/defaults-deep')
128
const libp2p = require('../../..')
139

14-
function mapMuxers (list) {
15-
return list.map((pref) => {
16-
if (typeof pref !== 'string') {
17-
return pref
18-
}
19-
switch (pref.trim().toLowerCase()) {
20-
case 'spdy': return spdy
21-
case 'mplex': return mplex
22-
default:
23-
throw new Error(pref + ' muxer not available')
24-
}
25-
})
26-
}
27-
28-
function getMuxers (muxers) {
29-
const muxerPrefs = process.env.LIBP2P_MUXER
30-
if (muxerPrefs && !muxers) {
31-
return mapMuxers(muxerPrefs.split(','))
32-
} else if (muxers) {
33-
return mapMuxers(muxers)
34-
} else {
35-
return [mplex, spdy]
36-
}
37-
}
38-
3910
class Node extends libp2p {
4011
constructor (_options) {
4112
const defaults = {
@@ -44,29 +15,8 @@ class Node extends libp2p {
4415
TCP,
4516
WS
4617
],
47-
streamMuxer: getMuxers(_options.muxer),
48-
connEncryption: [ secio ],
49-
peerDiscovery: [
50-
MulticastDNS,
51-
Bootstrap
52-
],
53-
dht: KadDHT
54-
},
55-
config: {
56-
peerDiscovery: {
57-
mdns: {
58-
interval: 10000,
59-
enabled: false
60-
},
61-
bootstrap: {
62-
interval: 10000,
63-
enabled: false,
64-
list: _options.bootstrapList
65-
}
66-
},
67-
dht: {
68-
kBucketSize: 20
69-
}
18+
streamMuxer: [ mplex ],
19+
connEncryption: [ secio ]
7020
}
7121
}
7222

examples/chat/src/listener.js

+24-39
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,38 @@
44
const PeerId = require('peer-id')
55
const PeerInfo = require('peer-info')
66
const Node = require('./libp2p-bundle.js')
7-
const pull = require('pull-stream')
8-
const Pushable = require('pull-pushable')
9-
const p = Pushable()
7+
const { stdinToStream, streamToConsole } = require('./stream')
108

11-
PeerId.createFromJSON(require('./peer-id-listener'), (err, idListener) => {
12-
if (err) {
13-
throw err
14-
}
9+
async function run() {
10+
// Create a new libp2p node with the given multi-address
11+
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
1512
const peerListener = new PeerInfo(idListener)
1613
peerListener.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
1714
const nodeListener = new Node({
1815
peerInfo: peerListener
1916
})
2017

21-
nodeListener.start((err) => {
22-
if (err) {
23-
throw err
24-
}
25-
26-
nodeListener.on('peer:connect', (peerInfo) => {
27-
console.log(peerInfo.id.toB58String())
28-
})
29-
30-
nodeListener.handle('/chat/1.0.0', (protocol, conn) => {
31-
pull(
32-
p,
33-
conn
34-
)
18+
// Log a message when a remote peer connects to us
19+
nodeListener.on('peer:connect', (peerInfo) => {
20+
console.log(peerInfo.id.toB58String())
21+
})
3522

36-
pull(
37-
conn,
38-
pull.map((data) => {
39-
return data.toString('utf8').replace('\n', '')
40-
}),
41-
pull.drain(console.log)
42-
)
23+
// Handle messages for the protocol
24+
await nodeListener.handle('/chat/1.0.0', async ({ stream }) => {
25+
// Send stdin to the stream
26+
stdinToStream(stream)
27+
// Read the stream and output to console
28+
streamToConsole(stream)
29+
})
4330

44-
process.stdin.setEncoding('utf8')
45-
process.openStdin().on('data', (chunk) => {
46-
var data = chunk.toString()
47-
p.push(data)
48-
})
49-
})
31+
// Start listening
32+
await nodeListener.start()
5033

51-
console.log('Listener ready, listening on:')
52-
peerListener.multiaddrs.forEach((ma) => {
53-
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
54-
})
34+
// Output listen addresses to the console
35+
console.log('Listener ready, listening on:')
36+
peerListener.multiaddrs.forEach((ma) => {
37+
console.log(ma.toString() + '/p2p/' + idListener.toB58String())
5538
})
56-
})
39+
}
40+
41+
run()

examples/chat/src/stream.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
'use strict'
2+
/* eslint-disable no-console */
3+
4+
const pipe = require('it-pipe')
5+
const lp = require('it-length-prefixed')
6+
7+
function stdinToStream(stream) {
8+
// Read utf-8 from stdin
9+
process.stdin.setEncoding('utf8')
10+
pipe(
11+
// Read from stdin (the source)
12+
process.stdin,
13+
// Encode with length prefix (so receiving side knows how much data is coming)
14+
lp.encode(),
15+
// Write to the stream (the sink)
16+
stream.sink
17+
)
18+
}
19+
20+
function streamToConsole(stream) {
21+
pipe(
22+
// Read from the stream (the source)
23+
stream.source,
24+
// Decode length-prefixed data
25+
lp.decode(),
26+
// Sink function
27+
async function (source) {
28+
// For each chunk of data
29+
for await (const msg of source) {
30+
// Output the data as a utf8 string
31+
console.log('> ' + msg.toString('utf8').replace('\n', ''))
32+
}
33+
}
34+
)
35+
}
36+
37+
module.exports = {
38+
stdinToStream,
39+
streamToConsole
40+
}

0 commit comments

Comments
 (0)