Compare commits

...

13 Commits

25 changed files with 227 additions and 69 deletions

View File

@ -1,3 +1,13 @@
<a name="0.19.0"></a>
# [0.19.0](https://github.com/libp2p/js-libp2p/compare/v0.18.0...v0.19.0) (2018-03-15)
<a name="0.18.0"></a>
# [0.18.0](https://github.com/libp2p/js-libp2p/compare/v0.17.0...v0.18.0) (2018-02-19)
<a name="0.17.0"></a>
# [0.17.0](https://github.com/libp2p/js-libp2p/compare/v0.16.5...v0.17.0) (2018-02-16)

107
README.md
View File

@ -277,6 +277,113 @@ class Node extends libp2p {
[multiaddr]: https://github.com/multiformats/js-multiaddr
[Connection]: https://github.com/libp2p/interface-connection
-------
### Switch Stats API
##### `libp2p.stats.emit('update')`
Every time any stat value changes, this object emits an `update` event.
#### Global stats
##### `libp2p.stats.global.snapshot`
Should return a stats snapshot, which is an object containing the following keys and respective values:
- dataSent: amount of bytes sent, [Big](https://github.com/MikeMcl/big.js#readme) number
- dataReceived: amount of bytes received, [Big](https://github.com/MikeMcl/big.js#readme) number
##### `libp2p.stats.global.movingAverages`
Returns an object containing the following keys:
- dataSent
- dataReceived
Each one of them contains an object that has a key for each interval (`60000`, `300000` and `900000` miliseconds).
Each one of these values is [an exponential moving-average instance](https://github.com/pgte/moving-average#readme).
#### Per-transport stats
##### `libp2p.stats.transports()`
Returns an array containing the tags (string) for each observed transport.
##### `libp2p.stats.forTransport(transportTag).snapshot`
Should return a stats snapshot, which is an object containing the following keys and respective values:
- dataSent: amount of bytes sent, [Big](https://github.com/MikeMcl/big.js#readme) number
- dataReceived: amount of bytes received, [Big](https://github.com/MikeMcl/big.js#readme) number
##### `libp2p.stats.forTransport(transportTag).movingAverages`
Returns an object containing the following keys:
dataSent
dataReceived
Each one of them contains an object that has a key for each interval (`60000`, `300000` and `900000` miliseconds).
Each one of these values is [an exponential moving-average instance](https://github.com/pgte/moving-average#readme).
#### Per-protocol stats
##### `libp2p.stats.protocols()`
Returns an array containing the tags (string) for each observed protocol.
##### `libp2p.stats.forProtocol(protocolTag).snapshot`
Should return a stats snapshot, which is an object containing the following keys and respective values:
- dataSent: amount of bytes sent, [Big](https://github.com/MikeMcl/big.js#readme) number
- dataReceived: amount of bytes received, [Big](https://github.com/MikeMcl/big.js#readme) number
##### `libp2p.stats.forProtocol(protocolTag).movingAverages`
Returns an object containing the following keys:
- dataSent
- dataReceived
Each one of them contains an object that has a key for each interval (`60000`, `300000` and `900000` miliseconds).
Each one of these values is [an exponential moving-average instance](https://github.com/pgte/moving-average#readme).
#### Per-peer stats
##### `libp2p.stats.peers()`
Returns an array containing the peerIDs (B58-encoded string) for each observed peer.
##### `libp2p.stats.forPeer(peerId:String).snapshot`
Should return a stats snapshot, which is an object containing the following keys and respective values:
- dataSent: amount of bytes sent, [Big](https://github.com/MikeMcl/big.js#readme) number
- dataReceived: amount of bytes received, [Big](https://github.com/MikeMcl/big.js#readme) number
##### `libp2p.stats.forPeer(peerId:String).movingAverages`
Returns an object containing the following keys:
- dataSent
- dataReceived
Each one of them contains an object that has a key for each interval (`60000`, `300000` and `900000` miliseconds).
Each one of these values is [an exponential moving-average instance](https://github.com/pgte/moving-average#readme).
#### Stats update interval
Stats are not updated in real-time. Instead, measurements are buffered and stats are updated at an interval. The maximum interval can be defined through the `Switch` constructor option `stats.computeThrottleTimeout`, defined in miliseconds.
## Development
**Clone and install dependencies:**

View File

@ -6,7 +6,7 @@ const WS = require('libp2p-websockets')
const Railing = require('libp2p-railing')
const spdy = require('libp2p-spdy')
const KadDHT = require('libp2p-kad-dht')
const multiplex = require('libp2p-multiplex')
const mplex = require('libp2p-mplex')
const secio = require('libp2p-secio')
const libp2p = require('../../..')
@ -17,7 +17,7 @@ function mapMuxers (list) {
}
switch (pref.trim().toLowerCase()) {
case 'spdy': return spdy
case 'multiplex': return multiplex
case 'mplex': return mplex
default:
throw new Error(pref + ' muxer not available')
}
@ -31,7 +31,7 @@ function getMuxers (muxers) {
} else if (muxers) {
return mapMuxers(muxers)
} else {
return [multiplex, spdy]
return [mplex, spdy]
}
}

View File

@ -21,7 +21,7 @@ PeerId.createFromJSON(require('./peer-id-listener'), (err, idListener) => {
throw err
}
nodeListener.swarm.on('peer-mux-established', (peerInfo) => {
nodeListener.switch.on('peer-mux-established', (peerInfo) => {
console.log(peerInfo.id.toB58String())
})

View File

@ -2,7 +2,7 @@
const libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const Railing = require('libp2p-railing')
@ -26,7 +26,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
discovery: [new Railing(bootstrapers)]

View File

@ -2,7 +2,7 @@
const libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const MulticastDNS = require('libp2p-mdns')
@ -14,7 +14,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
discovery: [new MulticastDNS(peerInfo, { interval: 1000 })]

View File

@ -8,7 +8,7 @@ These mechanisms save configuration and enable a node to operate without any exp
## 1. Bootstrap list of Peers when booting a node
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, multiplex and SECIO. You can see the complete example at [1.js](./1.js).
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and SECIO. You can see the complete example at [1.js](./1.js).
First, we create our libp2p bundle.
@ -18,7 +18,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
discovery: [new Railing(bootstrapers)]
@ -111,7 +111,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
// We set the interval here to 1 second so that is faster to observe. The

View File

@ -6,7 +6,7 @@ const WS = require('libp2p-websockets')
const Railing = require('libp2p-railing')
const spdy = require('libp2p-spdy')
const KadDHT = require('libp2p-kad-dht')
const multiplex = require('libp2p-multiplex')
const mplex = require('libp2p-mplex')
const secio = require('libp2p-secio')
const libp2p = require('../../..')
@ -17,7 +17,7 @@ function mapMuxers (list) {
}
switch (pref.trim().toLowerCase()) {
case 'spdy': return spdy
case 'multiplex': return multiplex
case 'mplex': return mplex
default:
throw new Error(pref + ' muxer not available')
}
@ -31,7 +31,7 @@ function getMuxers (muxers) {
} else if (muxers) {
return mapMuxers(muxers)
} else {
return [multiplex, spdy]
return [mplex, spdy]
}
}

View File

@ -27,7 +27,7 @@ series([
listenerPeerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/10333')
listenerNode = new Node(listenerPeerInfo)
listenerNode.swarm.on('peer-mux-established', (peerInfo) => {
listenerNode.switch.on('peer-mux-established', (peerInfo) => {
console.log('received dial to me from:', peerInfo.id.toB58String())
})

View File

@ -18,7 +18,7 @@
"dependencies": {
"detect-dom-ready": "^1.0.2",
"libp2p": "^0.13.0",
"libp2p-multiplex": "^0.5.0",
"libp2p-mplex": "^0.6.0",
"libp2p-railing": "^0.7.1",
"libp2p-secio": "^0.8.1",
"libp2p-spdy": "^0.11.0",

View File

@ -3,7 +3,7 @@
const WebRTCStar = require('libp2p-webrtc-star')
const WebSockets = require('libp2p-websockets')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SPDY = require('libp2p-spdy')
const SECIO = require('libp2p-secio')
@ -37,7 +37,7 @@ class Node extends libp2p {
],
connection: {
muxer: [
Multiplex,
Mplex,
SPDY
],
crypto: [SECIO]

View File

@ -2,7 +2,7 @@
const libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const KadDHT = require('libp2p-kad-dht')
@ -15,7 +15,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
// we add the DHT module that will enable Peer and Content Routing

View File

@ -2,7 +2,7 @@
const libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const CID = require('cids')
@ -16,7 +16,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
// we add the DHT module that will enable Peer and Content Routing

View File

@ -18,7 +18,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
// we add the DHT module that will enable Peer and Content Routing

View File

@ -88,7 +88,7 @@ The example above would require a node to create a whole new connection for ever
Stream multiplexing is a old concept, in fact it happens in many of the layers of the [OSI System](https://en.wikipedia.org/wiki/OSI_model), in libp2p we make this feature to our avail by letting the user pick which module for stream multiplexing to use.
Currently, we have two available [libp2p-spdy](https://github.com/libp2p/js-libp2p-spdy) and [libp2p-multiplex](https://github.com/libp2p/js-libp2p-multiplex) and pluging them in is as easy as adding another transport. Let's revisit our libp2p bundle.
Currently, we have two available [libp2p-spdy](https://github.com/libp2p/js-libp2p-spdy) and [libp2p-mplex](https://github.com/libp2p/js-libp2p-mplex) and pluging them in is as easy as adding another transport. Let's revisit our libp2p bundle.
```JavaScript
const SPDY = require('libp2p-spdy')

View File

@ -2,7 +2,7 @@
const libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const Multiplex = require('libp2p-multiplex')
const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const PeerInfo = require('peer-info')
const MulticastDNS = require('libp2p-mdns')
@ -15,7 +15,7 @@ class MyBundle extends libp2p {
const modules = {
transport: [new TCP()],
connection: {
muxer: [Multiplex],
muxer: [Mplex],
crypto: [SECIO]
},
discovery: [
@ -54,11 +54,17 @@ parallel([
], (err) => {
if (err) { throw err }
// Subscribe to the topic 'news'
node1.pubsub.subscribe('news',
(msg) => console.log(msg.from, msg.data.toString()),
() => {
setInterval(() => {
node2.pubsub.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
// Publish the message on topic 'news'
node2.pubsub.publish(
'news',
Buffer.from('Bird bird bird, bird is the word!'),
() => {}
)
}, 1000)
}
)

View File

@ -21,12 +21,20 @@ series([
], (err) => {
if (err) { throw err }
node1.pubsub.on('news', (msg) => console.log(msg.from, msg.data.toString()))
node1.pubsub.subscribe('news')
setInterval(() => {
node2.pubsub.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
}, 1000)
// Subscribe to the topic 'news'
node1.pubsub.subscribe('news',
(msg) => console.log(msg.from, msg.data.toString()),
() => {
setInterval(() => {
// Publish the message on topic 'news'
node2.pubsub.publish(
'news',
Buffer.from('Bird bird bird, bird is the word!'),
() => {}
)
}, 1000)
}
)
})
```

View File

@ -1,6 +1,6 @@
{
"name": "libp2p",
"version": "0.17.0",
"version": "0.19.0",
"description": "JavaScript base class for libp2p bundles",
"main": "src/index.js",
"scripts": {
@ -40,7 +40,7 @@
"async": "^2.6.0",
"libp2p-floodsub": "^0.14.1",
"libp2p-ping": "~0.6.1",
"libp2p-switch": "~0.36.1",
"libp2p-switch": "~0.37.3",
"mafmt": "^4.0.0",
"multiaddr": "^3.0.2",
"peer-book": "~0.5.4",
@ -48,31 +48,31 @@
"peer-info": "~0.11.6"
},
"devDependencies": {
"aegir": "^13.0.0",
"aegir": "^13.0.6",
"chai": "^4.1.2",
"cids": "~0.5.2",
"cids": "~0.5.3",
"dirty-chai": "^2.0.1",
"electron-webrtc": "~0.3.0",
"libp2p-circuit": "~0.1.4",
"libp2p-kad-dht": "~0.8.0",
"libp2p-circuit": "~0.1.5",
"libp2p-kad-dht": "~0.9.0",
"libp2p-mdns": "~0.9.2",
"libp2p-multiplex": "~0.5.1",
"libp2p-mplex": "~0.6.0",
"libp2p-railing": "~0.7.1",
"libp2p-secio": "~0.9.2",
"libp2p-secio": "~0.9.3",
"libp2p-spdy": "~0.11.0",
"libp2p-tcp": "~0.11.5",
"libp2p-webrtc-star": "~0.13.3",
"libp2p-websockets": "~0.10.4",
"libp2p-websocket-star": "~0.7.6",
"libp2p-tcp": "~0.11.6",
"libp2p-webrtc-star": "~0.13.4",
"libp2p-websockets": "~0.10.5",
"libp2p-websocket-star": "~0.7.7",
"libp2p-websocket-star-rendezvous": "~0.2.3",
"lodash.times": "^4.3.2",
"pre-commit": "^1.2.2",
"pull-goodbye": "0.0.2",
"pull-serializer": "~0.3.2",
"pull-stream": "^3.6.1",
"pull-stream": "^3.6.2",
"safe-buffer": "^5.1.1",
"sinon": "^4.3.0",
"wrtc": "0.0.66"
"sinon": "^4.4.6",
"wrtc": "0.0.67"
},
"contributors": [
"Chris Bratlien <chrisbratlien@gmail.com>",
@ -95,6 +95,7 @@
"Richard Littauer <richard.littauer@gmail.com>",
"Ryan Bell <ryan@piing.net>",
"Tiago Alves <alvesjtiago@gmail.com>",
"Zane Starr <zcstarr@gmail.com>",
"greenkeeperio-bot <support@greenkeeper.io>",
"mayerwin <mayerwin@users.noreply.github.com>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>"

View File

@ -34,7 +34,8 @@ class Node extends EventEmitter {
this._isStarted = false
this.switch = new Switch(this.peerInfo, this.peerBook)
this.switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
this.stats = this.switch.stats
// Attach stream multiplexers
if (this.modules.connection && this.modules.connection.muxer) {

View File

@ -9,3 +9,4 @@ require('./peer-routing.node')
require('./content-routing.node')
require('./circuit-relay.node')
require('./multiaddr-trim')
require('./stats')

24
test/stats.js Normal file
View File

@ -0,0 +1,24 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const createNode = require('./utils/node').createNode
describe('libp2p', (done) => {
it('has stats', () => {
createNode('/ip4/127.0.0.1/tcp/0', {
mdns: false,
dht: true
}, (err, node) => {
expect(err).to.not.exist()
node.start((err) => {
expect(err).to.not.exist()
expect(node.stats).to.exist()
node.stop(done)
})
})
})
})

View File

@ -60,14 +60,14 @@ describe('stream muxing', () => {
], done)
})
it('multiplex only', (done) => {
it('mplex only', (done) => {
let nodeA
let nodeB
function setup (callback) {
parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['multiplex']
muxer: ['mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeA = node
@ -75,7 +75,7 @@ describe('stream muxing', () => {
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['multiplex']
muxer: ['mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeB = node
@ -92,7 +92,7 @@ describe('stream muxing', () => {
], done)
})
it('spdy + multiplex', function (done) {
it('spdy + mplex', function (done) {
this.timeout(5000)
let nodeA
@ -101,7 +101,7 @@ describe('stream muxing', () => {
function setup (callback) {
parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['spdy', 'multiplex']
muxer: ['spdy', 'mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeA = node
@ -109,7 +109,7 @@ describe('stream muxing', () => {
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['spdy', 'multiplex']
muxer: ['spdy', 'mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeB = node
@ -126,7 +126,7 @@ describe('stream muxing', () => {
], done)
})
it('spdy + multiplex switched order', function (done) {
it('spdy + mplex switched order', function (done) {
this.timeout(5 * 1000)
let nodeA
@ -135,7 +135,7 @@ describe('stream muxing', () => {
function setup (callback) {
parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['spdy', 'multiplex']
muxer: ['spdy', 'mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeA = node
@ -143,7 +143,7 @@ describe('stream muxing', () => {
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['multiplex', 'spdy']
muxer: ['mplex', 'spdy']
}, (err, node) => {
expect(err).to.not.exist()
nodeB = node
@ -177,7 +177,7 @@ describe('stream muxing', () => {
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
muxer: ['multiplex']
muxer: ['mplex']
}, (err, node) => {
expect(err).to.not.exist()
nodeB = node

View File

@ -48,12 +48,12 @@ describe('transports', () => {
})
})
it('create libp2pNode with multiplex only', (done) => {
it('create libp2pNode with mplex only', (done) => {
PeerInfo.create((err, peerInfo) => {
expect(err).to.not.exist()
const b = new Node(peerInfo, null, { muxer: ['multiplex'] })
expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')])
const b = new Node(peerInfo, null, { muxer: ['mplex'] })
expect(b.modules.connection.muxer).to.eql([require('libp2p-mplex')])
done()
})
})

View File

@ -4,7 +4,7 @@ const WS = require('libp2p-websockets')
const WebRTCStar = require('libp2p-webrtc-star')
const WebSocketStar = require('libp2p-websocket-star')
const spdy = require('libp2p-spdy')
const multiplex = require('libp2p-multiplex')
const mplex = require('libp2p-mplex')
const secio = require('libp2p-secio')
const Railing = require('libp2p-railing')
const libp2p = require('../..')
@ -17,8 +17,8 @@ function mapMuxers (list) {
switch (pref.trim().toLowerCase()) {
case 'spdy':
return spdy
case 'multiplex':
return multiplex
case 'mplex':
return mplex
default:
throw new Error(pref + ' muxer not available')
}
@ -29,7 +29,7 @@ function getMuxers (options) {
if (options) {
return mapMuxers(options)
} else {
return [multiplex, spdy]
return [mplex, spdy]
}
}

View File

@ -6,7 +6,7 @@ const WS = require('libp2p-websockets')
const Railing = require('libp2p-railing')
const spdy = require('libp2p-spdy')
const KadDHT = require('libp2p-kad-dht')
const multiplex = require('libp2p-multiplex')
const mplex = require('libp2p-mplex')
const secio = require('libp2p-secio')
const libp2p = require('../..')
@ -17,7 +17,7 @@ function mapMuxers (list) {
}
switch (pref.trim().toLowerCase()) {
case 'spdy': return spdy
case 'multiplex': return multiplex
case 'mplex': return mplex
default:
throw new Error(pref + ' muxer not available')
}
@ -31,7 +31,7 @@ function getMuxers (muxers) {
} else if (muxers) {
return mapMuxers(muxers)
} else {
return [multiplex, spdy]
return [mplex, spdy]
}
}