mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-24 04:51:56 +00:00
Compare commits
1 Commits
v0.26.0-rc
...
feat/instr
Author | SHA1 | Date | |
---|---|---|---|
|
5b0a909145 |
19
.aegir.js
19
.aegir.js
@@ -22,12 +22,13 @@ const before = (done) => {
|
||||
sigServer.start({
|
||||
port: WRTC_RENDEZVOUS_MULTIADDR.nodeAddress().port
|
||||
// cryptoChallenge: true TODO: needs https://github.com/libp2p/js-libp2p-webrtc-star/issues/128
|
||||
})
|
||||
.then(server => {
|
||||
}, (err, server) => {
|
||||
if (err) {
|
||||
return cb(err)
|
||||
}
|
||||
wrtcRendezvous = server
|
||||
cb()
|
||||
})
|
||||
.catch(cb)
|
||||
},
|
||||
(cb) => {
|
||||
WebSocketStarRendezvous.start({
|
||||
@@ -71,16 +72,14 @@ const before = (done) => {
|
||||
|
||||
const after = (done) => {
|
||||
setTimeout(() =>
|
||||
parallel([
|
||||
(cb) => wrtcRendezvous.stop().then(cb).catch(cb),
|
||||
...[node, wsRendezvous].map((s) => (cb) => s.stop(cb)),
|
||||
], done),
|
||||
2000
|
||||
)
|
||||
parallel(
|
||||
[node, wrtcRendezvous, wsRendezvous].map((s) => (cb) => s.stop(cb)),
|
||||
done),
|
||||
2000)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bundlesize: { maxSize: '220kB' },
|
||||
bundlesize: { maxSize: '215kB' },
|
||||
hooks: {
|
||||
pre: before,
|
||||
post: after
|
||||
|
@@ -7,12 +7,11 @@ stages:
|
||||
|
||||
node_js:
|
||||
- '10'
|
||||
- '12'
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
|
||||
script: npx nyc -s npm run test:node -- --bail
|
||||
after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov
|
||||
|
||||
@@ -21,6 +20,7 @@ jobs:
|
||||
- stage: check
|
||||
script:
|
||||
- npx aegir build --bundlesize
|
||||
- npx aegir commitlint --travis
|
||||
- npx aegir dep-check -- -i wrtc -i electron-webrtc
|
||||
- npm run lint
|
||||
|
||||
|
110
CHANGELOG.md
110
CHANGELOG.md
@@ -1,113 +1,3 @@
|
||||
<a name="0.26.0-rc.1"></a>
|
||||
# [0.26.0-rc.1](https://github.com/libp2p/js-libp2p/compare/v0.26.0-rc.0...v0.26.0-rc.1) (2019-07-31)
|
||||
|
||||
|
||||
|
||||
<a name="0.26.0-rc.0"></a>
|
||||
# [0.26.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.25.5...v0.26.0-rc.0) (2019-07-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* make subscribe comply with ipfs interface ([#389](https://github.com/libp2p/js-libp2p/issues/389)) ([9554b05](https://github.com/libp2p/js-libp2p/commit/9554b05))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* integrate gossipsub by default ([#365](https://github.com/libp2p/js-libp2p/issues/365)) ([791f39a](https://github.com/libp2p/js-libp2p/commit/791f39a))
|
||||
* promisify all api methods that accept callbacks ([#381](https://github.com/libp2p/js-libp2p/issues/381)) ([df6ef45](https://github.com/libp2p/js-libp2p/commit/df6ef45))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* new configuration for deciding the implementation of pubsub to be used.
|
||||
In this context, the experimental flags were also removed. See the README for the latest usage.
|
||||
* The ipfs interface specified that options
|
||||
should be provided after the handler, not before.
|
||||
https://github.com/ipfs/interface-js-ipfs-core/blob/v0.109.0/SPEC/PUBSUB.md#pubsubsubscribe
|
||||
|
||||
This corrects the order of parameters. See the jsdocs examples
|
||||
for subscribe to see how it should be used.
|
||||
|
||||
|
||||
|
||||
<a name="0.25.5"></a>
|
||||
## [0.25.5](https://github.com/libp2p/js-libp2p/compare/v0.25.4...v0.25.5) (2019-07-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* peer routing for delegate router ([#377](https://github.com/libp2p/js-libp2p/issues/377)) ([905c911](https://github.com/libp2p/js-libp2p/commit/905c911)), closes [/github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go#L15-L24](https://github.com//github.com/libp2p/go-libp2p-core/blob/6e566d10f4a5447317a66d64c7459954b969bdab/routing/query.go/issues/L15-L24)
|
||||
|
||||
|
||||
|
||||
<a name="0.25.4"></a>
|
||||
## [0.25.4](https://github.com/libp2p/js-libp2p/compare/v0.25.3...v0.25.4) (2019-06-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add createLibp2p to generate a PeerInfo instance ([#367](https://github.com/libp2p/js-libp2p/issues/367)) ([04faf18](https://github.com/libp2p/js-libp2p/commit/04faf18))
|
||||
* pass libp2p as option to transport creation ([#363](https://github.com/libp2p/js-libp2p/issues/363)) ([b06ca1b](https://github.com/libp2p/js-libp2p/commit/b06ca1b))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.3"></a>
|
||||
## [0.25.3](https://github.com/libp2p/js-libp2p/compare/v0.25.2...v0.25.3) (2019-05-07)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* sign pubsub messages ([#362](https://github.com/libp2p/js-libp2p/issues/362)) ([40978a1](https://github.com/libp2p/js-libp2p/commit/40978a1))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.2"></a>
|
||||
## [0.25.2](https://github.com/libp2p/js-libp2p/compare/v0.25.1...v0.25.2) (2019-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* dht config ([#359](https://github.com/libp2p/js-libp2p/issues/359)) ([f3801f0](https://github.com/libp2p/js-libp2p/commit/f3801f0))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.1"></a>
|
||||
## [0.25.1](https://github.com/libp2p/js-libp2p/compare/v0.25.0...v0.25.1) (2019-04-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bail when discovering self ([#357](https://github.com/libp2p/js-libp2p/issues/357)) ([f28dffb](https://github.com/libp2p/js-libp2p/commit/f28dffb))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.0"></a>
|
||||
# [0.25.0](https://github.com/libp2p/js-libp2p/compare/v0.25.0-rc.6...v0.25.0) (2019-04-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow switch to be configured ([#354](https://github.com/libp2p/js-libp2p/issues/354)) ([eb5aa03](https://github.com/libp2p/js-libp2p/commit/eb5aa03))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.0-rc.6"></a>
|
||||
# [0.25.0-rc.6](https://github.com/libp2p/js-libp2p/compare/v0.25.0-rc.5...v0.25.0-rc.6) (2019-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* connection emits ([#352](https://github.com/libp2p/js-libp2p/issues/352)) ([313b1ea](https://github.com/libp2p/js-libp2p/commit/313b1ea))
|
||||
* remove unneeded peerbook puts ([#348](https://github.com/libp2p/js-libp2p/issues/348)) ([e5f19e8](https://github.com/libp2p/js-libp2p/commit/e5f19e8))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* auto dial discovered peers ([#349](https://github.com/libp2p/js-libp2p/issues/349)) ([01aa447](https://github.com/libp2p/js-libp2p/commit/01aa447))
|
||||
|
||||
|
||||
|
||||
<a name="0.25.0-rc.5"></a>
|
||||
# [0.25.0-rc.5](https://github.com/libp2p/js-libp2p/compare/v0.25.0-rc.4...v0.25.0-rc.5) (2019-03-21)
|
||||
|
||||
|
@@ -1,60 +0,0 @@
|
||||
# Peer Discovery and Auto Dial
|
||||
|
||||
**Synopsis**:
|
||||
* All peers discovered are emitted via `peer:discovery` so applications can take any desired action.
|
||||
* Libp2p defaults to automatically connecting to new peers, when under the [ConnectionManager](https://github.com/libp2p/js-libp2p-connection-manager) low watermark (minimum peers).
|
||||
* Applications can disable this via the `peerDiscovery.autoDial` config property, and handle connections themselves.
|
||||
* Applications who have not disabled this should **never** connect on peer discovery. Applications should use the `peer:connect` event if they wish to take a specific action on new peers.
|
||||
|
||||
## Scenarios
|
||||
In any scenario, if a peer is discovered it should be added to the PeerBook. This ensures that even if we don't dial to a node when we discover it, we know about it in the event that it becomes known as a provider for something we need. The scenarios listed below detail what actions the auto dialer will take when peers are discovered.
|
||||
|
||||
### 1. Joining the network
|
||||
The node is new and needs to join the network. It currently has 0 peers.
|
||||
**Discovery Mechanisms**: [Ambient Discovery](#ambient-discovery)
|
||||
|
||||
### Action to take
|
||||
Connect to discovered peers. This should have some degree of concurrency limiting. While the case should be low, if we immediately discover more peers than our high watermark we should avoid dialing them all.
|
||||
|
||||
### 2. Connected to some
|
||||
The node is connected to other nodes. The current number of connections is less than the desired low watermark.
|
||||
**Discovery Mechanisms**: [Ambient Discovery](#ambient-discovery) and [Active Discovery](#active-discovery)
|
||||
|
||||
### Action to take
|
||||
Connect to discovered peers. This should have some degree of concurrency limiting. The concurrency may need to be modified to reflect the current number of peers connected. The more peers we have, the lower the concurrency may need to be.
|
||||
|
||||
### 3. Connected to enough
|
||||
**Discovery Mechanisms**: [Ambient Discovery](#ambient-discovery) and [Active Discovery](#active-discovery)
|
||||
|
||||
### Action to take
|
||||
None. If we are connected to enough peers, the low watermark, we should not connect to discovered peers. As other peers discover us, they may connect to us based on their current scenario.
|
||||
|
||||
For example, a long running node with adequate peers is on an MDNS network. A new peer joins the network and both become aware of each other. The new peer should be the peer that dials, as it has too few peers. The existing node has no reason to dial the new peer, but should keep a record of it in case it later becomes an important node due to its contents/capabilities.
|
||||
|
||||
Avoiding dials above the low watermark also allows for a pool of connections to be reserved for application specific actions, such as connecting to a specific content provider via a DHT query to find that content (ipfs-bitswap).
|
||||
|
||||
### 4. Connected to too many
|
||||
The node has more connections than it wants. The current number of connections is greater than the high watermark.
|
||||
|
||||
[WIP Connection Manager v2 spec](https://github.com/libp2p/specs/pull/161)
|
||||
**Discovery Mechanisms**: [Ambient Discovery](#ambient-discovery) and [Active Discovery](#active-discovery)
|
||||
|
||||
### Action to take
|
||||
None, the `ConnectionManager` will automatically prune connections.
|
||||
|
||||
## Discovery Mechanisms
|
||||
Means of which a libp2p node discovers other peers.
|
||||
|
||||
### Active Discovery
|
||||
Through active use of the libp2p network, a node may discovery peers.
|
||||
|
||||
* Content/Peer routing (DHT, delegated, etc) provider and peer queries
|
||||
* DHT random walk
|
||||
* Rendezvous servers
|
||||
|
||||
### Ambient Discovery
|
||||
Leveraging known addresses, or network discovery mechanisms, a node may discover peers outside of the bounds of the libp2p network.
|
||||
|
||||
* Bootstrap
|
||||
* MDNS
|
||||
* proximity based (bluetooth, sound, etc)
|
78
README.md
78
README.md
@@ -8,7 +8,6 @@
|
||||
<a href="http://ipn.io"><img src="https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square" /></a>
|
||||
<a href="http://libp2p.io/"><img src="https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square" /></a>
|
||||
<a href="http://webchat.freenode.net/?channels=%23libp2p"><img src="https://img.shields.io/badge/freenode-%23libp2p-yellow.svg?style=flat-square" /></a>
|
||||
<a href="https://discuss.libp2p.io"><img src="https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg" /></a>
|
||||
<a href="https://waffle.io/libp2p/libp2p"><img src="https://img.shields.io/badge/pm-waffle-yellow.svg?style=flat-square" /></a>
|
||||
</p>
|
||||
|
||||
@@ -65,9 +64,7 @@ libp2p is the product of a long and arduous quest to understand the evolution of
|
||||
We are in the process of writing better documentation, blog posts, tutorials and a formal specification. Today you can find:
|
||||
|
||||
- [libp2p.io](https://libp2p.io)
|
||||
- [docs.libp2p.io](https://docs.libp2p.io)
|
||||
- [Specification (WIP)](https://github.com/libp2p/specs)
|
||||
- [Discussion Forums](https://discuss.libp2p.io)
|
||||
- Talks
|
||||
- [`libp2p <3 ethereum` at DEVCON2](https://ethereumfoundation.org/devcon/?session=libp2p) [📼 video](https://www.youtube.com/watch?v=HxueJbeMVG4) [slides](https://ethereumfoundation.org/devcon/wp-content/uploads/2016/10/libp2p-HEART-devp2p-IPFS-PLUS-Ethereum-networking.pdf) [📼 demo-1](https://ethereumfoundation.org/devcon/wp-content/uploads/2016/10/libp2p_demo1-1.mp4) [📼 demo-2](https://ethereumfoundation.org/devcon/wp-content/uploads/2016/10/libp2p_demo2-1.mp4)
|
||||
- Articles
|
||||
@@ -111,7 +108,7 @@ The libp2p module acts as a glue for every libp2p module that you can use to cre
|
||||
// crypto-channel: secio
|
||||
// discovery: multicast-dns
|
||||
|
||||
const Libp2p = require('libp2p')
|
||||
const libp2p = require('libp2p')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const WS = require('libp2p-websockets')
|
||||
const SPDY = require('libp2p-spdy')
|
||||
@@ -119,13 +116,12 @@ const MPLEX = require('libp2p-mplex')
|
||||
const SECIO = require('libp2p-secio')
|
||||
const MulticastDNS = require('libp2p-mdns')
|
||||
const DHT = require('libp2p-kad-dht')
|
||||
const GossipSub = require('libp2p-gossipsub')
|
||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||
const Protector = require('libp2p-pnet')
|
||||
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
|
||||
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
|
||||
|
||||
class Node extends Libp2p {
|
||||
class Node extends libp2p {
|
||||
constructor (_options) {
|
||||
const peerInfo = _options.peerInfo
|
||||
const defaults = {
|
||||
@@ -155,14 +151,12 @@ class Node extends Libp2p {
|
||||
peerDiscovery: [
|
||||
MulticastDNS
|
||||
],
|
||||
dht: DHT, // DHT enables PeerRouting, ContentRouting and DHT itself components
|
||||
pubsub: GossipSub
|
||||
dht: DHT // DHT enables PeerRouting, ContentRouting and DHT itself components
|
||||
},
|
||||
|
||||
// libp2p config options (typically found on a config.json)
|
||||
config: { // The config object is the part of the config that can go into a file, config.json.
|
||||
peerDiscovery: {
|
||||
autoDial: true, // Auto connect to discovered peers (limited by ConnectionManager minPeers)
|
||||
mdns: { // mdns options
|
||||
interval: 1000, // ms
|
||||
enabled: true
|
||||
@@ -183,14 +177,11 @@ class Node extends Libp2p {
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
enabled: true,
|
||||
randomWalk: {
|
||||
enabled: true, // Allows to disable discovery (enabled by default)
|
||||
interval: 300e3,
|
||||
timeout: 10e3
|
||||
}
|
||||
enabledDiscovery: true // Allows to disable discovery (enabled by default)
|
||||
},
|
||||
pubsub: {
|
||||
enabled: true
|
||||
// Enable/Disable Experimental features
|
||||
EXPERIMENTAL: { // Experimental features ("behind a flag")
|
||||
pubsub: false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -205,33 +196,13 @@ class Node extends Libp2p {
|
||||
|
||||
### API
|
||||
|
||||
**IMPORTANT NOTE**: All the methods listed in the API section that take a callback are also now Promisified. Libp2p is migrating away from callbacks to async/await, and in a future release (that will be announced in advance), callback support will be removed entirely. You can follow progress of the async/await endeavor at https://github.com/ipfs/js-ipfs/issues/1670.
|
||||
#### Create a Node - `new libp2p.Node(options)`
|
||||
|
||||
#### Create a Node - `Libp2p.createLibp2p(options, callback)`
|
||||
|
||||
> Behaves exactly like `new Libp2p(options)`, but doesn't require a PeerInfo. One will be generated instead
|
||||
|
||||
```js
|
||||
const { createLibp2p } = require('libp2p')
|
||||
createLibp2p(options, (err, libp2p) => {
|
||||
if (err) throw err
|
||||
libp2p.start((err) => {
|
||||
if (err) throw err
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
- `options`: Object of libp2p configuration options
|
||||
- `callback`: Function with signature `function (Error, Libp2p) {}`
|
||||
|
||||
#### Create a Node alternative - `new Libp2p(options)`
|
||||
|
||||
> Creates an instance of Libp2p with a custom `PeerInfo` provided via `options.peerInfo`.
|
||||
> Creates an instance of the libp2p.Node.
|
||||
|
||||
Required keys in the `options` object:
|
||||
|
||||
- `peerInfo`: instance of [PeerInfo][] that contains the [PeerId][], Keys and [multiaddrs][multiaddr] of the libp2p Node.
|
||||
- `modules.transport`: An array that must include at least 1 transport, such as `libp2p-tcp`.
|
||||
|
||||
#### `libp2p.start(callback)`
|
||||
|
||||
@@ -331,32 +302,17 @@ Required keys in the `options` object:
|
||||
|
||||
> Peer has been discovered.
|
||||
|
||||
If `autoDial` is `true`, applications should **not** attempt to connect to the peer
|
||||
unless they are performing a specific action. See [peer discovery and auto dial](./PEER_DISCOVERY.md) for more information.
|
||||
|
||||
- `peer`: instance of [PeerInfo][]
|
||||
|
||||
##### `libp2p.on('peer:connect', (peer) => {})`
|
||||
|
||||
> We have a new muxed connection to a peer
|
||||
> We connected to a new peer
|
||||
|
||||
- `peer`: instance of [PeerInfo][]
|
||||
|
||||
##### `libp2p.on('peer:disconnect', (peer) => {})`
|
||||
|
||||
> We have closed a connection to a peer
|
||||
|
||||
- `peer`: instance of [PeerInfo][]
|
||||
|
||||
##### `libp2p.on('connection:start', (peer) => {})`
|
||||
|
||||
> We created a new connection to a peer
|
||||
|
||||
- `peer`: instance of [PeerInfo][]
|
||||
|
||||
##### `libp2p.on('connection:end', (peer) => {})`
|
||||
|
||||
> We closed a connection to a peer
|
||||
> We disconnected from Peer
|
||||
|
||||
- `peer`: instance of [PeerInfo][]
|
||||
|
||||
@@ -550,6 +506,18 @@ Some available network protectors:
|
||||
> npm run test:browser
|
||||
```
|
||||
|
||||
#### Run interop tests
|
||||
|
||||
```sh
|
||||
N/A
|
||||
```
|
||||
|
||||
#### Run benchmark tests
|
||||
|
||||
```sh
|
||||
N/A
|
||||
```
|
||||
|
||||
### Packages
|
||||
|
||||
List of packages currently in existence for libp2p
|
||||
|
@@ -33,7 +33,7 @@
|
||||
- [ ] Twitter
|
||||
- [ ] IRC
|
||||
- [ ] Reddit
|
||||
- [ ] [discuss.libp2p.io](https://discuss.libp2p.io/c/news)
|
||||
- [ ] [discuss.ipfs.io](https://discuss.ipfs.io/c/announcements)
|
||||
- [ ] Blog post
|
||||
- [ ] Copy release notes to the [GitHub Release description](https://github.com/libp2p/js-libp2p/releases)
|
||||
|
||||
@@ -47,7 +47,7 @@ In alphabetical order, here are all the humans that contributed to the release:
|
||||
|
||||
Would you like to contribute to the libp2p project and don't know how? Well, there are a few places you can get started:
|
||||
|
||||
- Check the issues with the `help wanted` label in the [libp2p repo](https://github.com/libp2p/js-libp2p/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
- Check the issues with the `help wanted` label at the Ready column in our waffle board - https://waffle.io/libp2p/js-libp2p?label=help%20wanted
|
||||
- Join an IPFS All Hands, introduce yourself and let us know where you would like to contribute - https://github.com/ipfs/team-mgmt#all-hands-call
|
||||
- Hack with IPFS and show us what you made! The All Hands call is also the perfect venue for demos, join in and show us what you built
|
||||
- Join the discussion at http://discuss.ipfs.io/ and help users finding their answers.
|
||||
@@ -55,4 +55,4 @@ Would you like to contribute to the libp2p project and don't know how? Well, the
|
||||
|
||||
# ⁉️ Do you have questions?
|
||||
|
||||
The best place to ask your questions about libp2p, how it works and what you can do with it is at [discuss.libp2p.io](https://discuss.libp2p.io). We are also available at the #libp2p channel on Freenode.
|
||||
The best place to ask your questions about libp2p, how it works and what you can do with it is at [discuss.ipfs.io](http://discuss.ipfs.io). We are also available at the #libp2p channel on Freenode.
|
||||
|
@@ -3,8 +3,8 @@
|
||||
This example creates a simple chat app in your terminal.
|
||||
|
||||
## Setup
|
||||
1. Install the modules in the libp2p root directory, `npm install`.
|
||||
2. Open 2 terminal windows in the `./examples/chat/src` directory.
|
||||
1. Install the modules, `npm install`.
|
||||
2. Open 2 terminal windows in the `./src` directory.
|
||||
|
||||
## Running
|
||||
1. Run the listener in window 1, `node listener.js`
|
||||
|
@@ -3,27 +3,21 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"ipfs": "~0.34.4",
|
||||
"libp2p": "github:libp2p/js-libp2p#master",
|
||||
"ipfs": "~0.32.2",
|
||||
"libp2p": "../../",
|
||||
"libp2p-delegated-content-routing": "~0.2.2",
|
||||
"libp2p-delegated-peer-routing": "~0.2.2",
|
||||
"libp2p-kad-dht": "~0.14.12",
|
||||
"libp2p-mplex": "~0.8.5",
|
||||
"libp2p-secio": "~0.11.1",
|
||||
"libp2p-webrtc-star": "~0.15.8",
|
||||
"libp2p-websocket-star": "~0.10.2",
|
||||
"libp2p-websockets": "~0.12.2",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"react-scripts": "2.1.8"
|
||||
"libp2p-kad-dht": "~0.10.4",
|
||||
"libp2p-mplex": "~0.8.0",
|
||||
"libp2p-secio": "~0.10.0",
|
||||
"libp2p-webrtc-star": "~0.15.5",
|
||||
"libp2p-websocket-star": "~0.8.1",
|
||||
"libp2p-websockets": "~0.12.0",
|
||||
"react": "^16.5.2",
|
||||
"react-dom": "^16.5.2",
|
||||
"react-scripts": "1.1.5"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,11 @@
|
||||
// eslint-disable-next-line
|
||||
'use strict'
|
||||
|
||||
import React from 'react'
|
||||
import Ipfs from 'ipfs'
|
||||
import libp2pBundle from './libp2p-bundle'
|
||||
const React = require('react')
|
||||
const Component = React.Component
|
||||
const Ipfs = require('ipfs')
|
||||
const libp2pBundle = require('./libp2p-bundle')
|
||||
// require('./App.css')
|
||||
|
||||
const BootstrapNode = '/ip4/127.0.0.1/tcp/8081/ws/p2p/QmdoG8DpzYUZMVP5dGmgmigZwR1RE8Cf6SxMPg1SBXJAQ8'
|
||||
|
||||
@@ -149,4 +150,4 @@ class App extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default App
|
||||
module.exports = App
|
||||
|
@@ -1,8 +1,9 @@
|
||||
// eslint-disable-next-line
|
||||
'use strict'
|
||||
|
||||
import React from 'react' // eslint-disable-line no-unused-vars
|
||||
import ReactDOM from 'react-dom'
|
||||
import App from './App' // eslint-disable-line no-unused-vars
|
||||
const React = require('react') // eslint-disable-line no-unused-vars
|
||||
const ReactDOM = require('react-dom')
|
||||
const App = require('./App') // eslint-disable-line no-unused-vars
|
||||
// require('index.css')
|
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root'))
|
||||
|
@@ -11,7 +11,7 @@ const KadDHT = require('libp2p-kad-dht')
|
||||
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
|
||||
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
|
||||
|
||||
export default function Libp2pBundle ({peerInfo, peerBook}) {
|
||||
module.exports = ({peerInfo, peerBook}) => {
|
||||
const wrtcstar = new WebRTCStar({id: peerInfo.id})
|
||||
const wsstar = new WebSocketStar({id: peerInfo.id})
|
||||
const delegatedApiOptions = {
|
||||
@@ -54,7 +54,6 @@ export default function Libp2pBundle ({peerInfo, peerBook}) {
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: false,
|
||||
webrtcStar: {
|
||||
enabled: false
|
||||
},
|
||||
@@ -63,13 +62,16 @@ export default function Libp2pBundle ({peerInfo, peerBook}) {
|
||||
}
|
||||
},
|
||||
dht: {
|
||||
enabled: false
|
||||
kBucketSize: 20
|
||||
},
|
||||
relay: {
|
||||
enabled: true,
|
||||
hop: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
dht: false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -34,9 +34,8 @@ class MyBundle extends libp2p {
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
bootstrap: {
|
||||
interval: 20e3,
|
||||
interval: 2000,
|
||||
enabled: true,
|
||||
list: bootstrapers
|
||||
}
|
||||
@@ -63,8 +62,8 @@ waterfall([
|
||||
if (err) { throw err }
|
||||
|
||||
node.on('peer:discovery', (peer) => {
|
||||
// No need to dial, autoDial is on
|
||||
console.log('Discovered:', peer.id.toB58String())
|
||||
node.dial(peer, () => {})
|
||||
})
|
||||
|
||||
node.on('peer:connect', (peer) => {
|
||||
|
@@ -23,7 +23,7 @@ class MyBundle extends libp2p {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mdns: {
|
||||
interval: 20e3,
|
||||
interval: 1000,
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
This example performs a simple echo from the listener to the dialer.
|
||||
|
||||
## Setup
|
||||
1. Install the modules from libp2p root, `npm install`.
|
||||
1. Install the modules, `npm install`.
|
||||
2. Open 2 terminal windows in the `./src` directory.
|
||||
|
||||
## Running
|
||||
|
@@ -17,15 +17,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"detect-dom-ready": "^1.0.2",
|
||||
"libp2p": "../../../",
|
||||
"libp2p-bootstrap": "~0.9.7",
|
||||
"libp2p-kad-dht": "^0.15.3",
|
||||
"libp2p-mplex": "~0.8.5",
|
||||
"libp2p-secio": "~0.11.1",
|
||||
"libp2p-spdy": "~0.13.3",
|
||||
"libp2p-webrtc-star": "~0.15.8",
|
||||
"libp2p-websocket-star": "~0.10.2",
|
||||
"libp2p-websockets": "~0.12.2",
|
||||
"libp2p-bootstrap": "~0.9.3",
|
||||
"libp2p-mplex": "~0.8.0",
|
||||
"libp2p-secio": "~0.10.0",
|
||||
"libp2p-spdy": "~0.12.1",
|
||||
"libp2p-webrtc-star": "~0.15.3",
|
||||
"libp2p-websocket-star": "~0.8.1",
|
||||
"libp2p-websockets": "~0.12.0",
|
||||
"peer-info": "~0.15.1"
|
||||
}
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@ const Mplex = require('libp2p-mplex')
|
||||
const SPDY = require('libp2p-spdy')
|
||||
const SECIO = require('libp2p-secio')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
const DHT = require('libp2p-kad-dht')
|
||||
const libp2p = require('libp2p')
|
||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||
const libp2p = require('../../../../')
|
||||
|
||||
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-browser.json
|
||||
const bootstrapList = [
|
||||
@@ -25,9 +25,9 @@ const bootstrapList = [
|
||||
]
|
||||
|
||||
class Node extends libp2p {
|
||||
constructor ({ peerInfo }) {
|
||||
const wrtcStar = new WebRTCStar({ id: peerInfo.id })
|
||||
const wsstar = new WebSocketStar({ id: peerInfo.id })
|
||||
constructor (_options) {
|
||||
const wrtcStar = new WebRTCStar({ id: _options.peerInfo.id })
|
||||
const wsstar = new WebSocketStar({ id: _options.peerInfo.id })
|
||||
|
||||
const defaults = {
|
||||
modules: {
|
||||
@@ -47,12 +47,10 @@ class Node extends libp2p {
|
||||
wrtcStar.discovery,
|
||||
wsstar.discovery,
|
||||
Bootstrap
|
||||
],
|
||||
dht: DHT
|
||||
]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
webRTCStar: {
|
||||
enabled: true
|
||||
},
|
||||
@@ -60,7 +58,7 @@ class Node extends libp2p {
|
||||
enabled: true
|
||||
},
|
||||
bootstrap: {
|
||||
interval: 20e3,
|
||||
interval: 10000,
|
||||
enabled: true,
|
||||
list: bootstrapList
|
||||
}
|
||||
@@ -68,24 +66,21 @@ class Node extends libp2p {
|
||||
relay: {
|
||||
enabled: true,
|
||||
hop: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
active: false
|
||||
}
|
||||
},
|
||||
dht: {
|
||||
enabled: false
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
dht: false,
|
||||
pubsub: false
|
||||
}
|
||||
},
|
||||
connectionManager: {
|
||||
minPeers: 10,
|
||||
maxPeers: 50
|
||||
}
|
||||
}
|
||||
|
||||
super({ ...defaults, peerInfo })
|
||||
super(defaultsDeep(_options, defaults))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -10,11 +10,9 @@ function createNode (callback) {
|
||||
}
|
||||
|
||||
const peerIdStr = peerInfo.id.toB58String()
|
||||
const webrtcAddr = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/p2p/${peerIdStr}`
|
||||
const wsAddr = `/dns4/ws-star.discovery.libp2p.io/tcp/443/wss/p2p-websocket-star`
|
||||
const ma = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/p2p/${peerIdStr}`
|
||||
|
||||
peerInfo.multiaddrs.add(webrtcAddr)
|
||||
peerInfo.multiaddrs.add(wsAddr)
|
||||
peerInfo.multiaddrs.add(ma)
|
||||
|
||||
const node = new Node({
|
||||
peerInfo
|
||||
|
@@ -14,8 +14,26 @@ domReady(() => {
|
||||
return console.log('Could not create the Node, check if your browser has WebRTC Support', err)
|
||||
}
|
||||
|
||||
let connections = {}
|
||||
|
||||
node.on('peer:discovery', (peerInfo) => {
|
||||
console.log('Discovered a peer:', peerInfo.id.toB58String())
|
||||
const idStr = peerInfo.id.toB58String()
|
||||
if (connections[idStr]) {
|
||||
// If we're already trying to connect to this peer, dont dial again
|
||||
return
|
||||
}
|
||||
console.log('Discovered a peer:', idStr)
|
||||
|
||||
connections[idStr] = true
|
||||
node.dial(peerInfo, (err, conn) => {
|
||||
if (err) {
|
||||
// Prevent immediate connection retries from happening
|
||||
// and include a 10s jitter
|
||||
const timeToNextDial = 25 * 1000 + (Math.random(0) * 10000).toFixed(0)
|
||||
console.log('Failed to dial:', idStr)
|
||||
setTimeout(() => delete connections[idStr], timeToNextDial)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
node.on('peer:connect', (peerInfo) => {
|
||||
@@ -29,13 +47,15 @@ domReady(() => {
|
||||
|
||||
node.on('peer:disconnect', (peerInfo) => {
|
||||
const idStr = peerInfo.id.toB58String()
|
||||
delete connections[idStr]
|
||||
console.log('Lost connection to: ' + idStr)
|
||||
const el = document.getElementById(idStr)
|
||||
el && el.remove()
|
||||
})
|
||||
|
||||
node.start((err) => {
|
||||
if (err) {
|
||||
return console.log(err)
|
||||
return console.log('WebRTC not supported')
|
||||
}
|
||||
|
||||
const idStr = node.peerInfo.id.toB58String()
|
||||
@@ -46,9 +66,6 @@ domReady(() => {
|
||||
myPeerDiv.append(idDiv)
|
||||
|
||||
console.log('Node is listening o/')
|
||||
node.peerInfo.multiaddrs.toArray().forEach(ma => {
|
||||
console.log(ma.toString())
|
||||
})
|
||||
|
||||
// NOTE: to stop the node
|
||||
// node.stop((err) => {})
|
||||
|
@@ -20,3 +20,5 @@ Then simply go into the folder [1](./1) and execute the following
|
||||
> npm start
|
||||
# open your browser in port :9090
|
||||
```
|
||||
|
||||
[Version Published on IPFS](http://ipfs.io/ipfs/Qmbc1J7ehw1dNYachbkCWPto4RsnVvqCKNVzmYEod2gXcy)
|
||||
|
@@ -23,8 +23,10 @@ class MyBundle extends libp2p {
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
enabled: true,
|
||||
kBucketSize: 20
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
dht: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -24,8 +24,10 @@ class MyBundle extends libp2p {
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
enabled: true,
|
||||
kBucketSize: 20
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
dht: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,9 +25,11 @@ class MyBundle extends libp2p {
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
// dht must be enabled
|
||||
enabled: true,
|
||||
kBucketSize: 20
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
// dht must be enabled
|
||||
dht: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -62,8 +62,11 @@ parallel([
|
||||
const node1 = nodes[0]
|
||||
const node2 = nodes[1]
|
||||
|
||||
node1.once('peer:connect', (peer) => {
|
||||
console.log('connected to %s', peer.id.toB58String())
|
||||
series([
|
||||
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
||||
(cb) => setTimeout(cb, 500)
|
||||
], (err) => {
|
||||
if (err) { throw err }
|
||||
|
||||
// Subscribe to the topic 'news'
|
||||
node1.pubsub.subscribe('news',
|
||||
|
@@ -12,11 +12,14 @@ We've seen many interesting use cases appear with this, here are some highlights
|
||||
|
||||
For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
||||
|
||||
Using PubSub is super simple, all you have to do is start a libp2p node with `EXPERIMENTAL.pubsub` set to true.
|
||||
Using PubSub is super simple, all you have to do is start a libp2p node, PubSub will be enabled by default.
|
||||
|
||||
```JavaScript
|
||||
node1.once('peer:connect', (peer) => {
|
||||
console.log('connected to %s', peer.id.toB58String())
|
||||
series([
|
||||
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
||||
(cb) => setTimeout(cb, 500)
|
||||
], (err) => {
|
||||
if (err) { throw err }
|
||||
|
||||
// Subscribe to the topic 'news'
|
||||
node1.pubsub.subscribe('news',
|
||||
@@ -39,7 +42,6 @@ The output of the program should look like:
|
||||
|
||||
```
|
||||
> node 1.js
|
||||
connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82
|
||||
QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 Bird bird bird, bird is the word!
|
||||
QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 Bird bird bird, bird is the word!
|
||||
QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82 Bird bird bird, bird is the word!
|
||||
|
112
introspection/test.js
Normal file
112
introspection/test.js
Normal file
@@ -0,0 +1,112 @@
|
||||
'use strict'
|
||||
|
||||
const createNode = require('../test/utils/create-node')
|
||||
|
||||
const introspection = async () => {
|
||||
let libp2pNode
|
||||
|
||||
// Start node
|
||||
await new Promise((resolve, reject) => {
|
||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
bootstrap: {
|
||||
interval: 100,
|
||||
enabled: true,
|
||||
list: [
|
||||
'/ip4/104.236.176.52/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z',
|
||||
'/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
|
||||
'/ip4/104.236.179.241/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
|
||||
'/ip4/162.243.248.213/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
||||
'/ip4/128.199.219.111/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
||||
'/ip4/104.236.76.40/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
|
||||
'/ip4/178.62.158.247/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
|
||||
'/ip4/178.62.61.185/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
|
||||
'/ip4/104.236.151.122/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx',
|
||||
'/ip6/2604:a880:1:20::1f9:9001/tcp/4001/ipfs/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z',
|
||||
'/ip6/2604:a880:1:20::203:d001/tcp/4001/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
|
||||
'/ip6/2604:a880:0:1010::23:d001/tcp/4001/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
||||
'/ip6/2400:6180:0:d0::151:6001/tcp/4001/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
||||
'/ip6/2604:a880:800:10::4a:5001/tcp/4001/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
|
||||
'/ip6/2a03:b0c0:0:1010::23:1001/tcp/4001/ipfs/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
|
||||
'/ip6/2a03:b0c0:1:d0::e7:1/tcp/4001/ipfs/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
|
||||
'/ip6/2604:a880:1:20::1d9:6001/tcp/4001/ipfs/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx',
|
||||
'/dns4/node0.preload.ipfs.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
|
||||
'/dns4/node1.preload.ipfs.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
|
||||
]
|
||||
},
|
||||
mdns: {
|
||||
interval: 100,
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
}
|
||||
|
||||
libp2pNode = node
|
||||
|
||||
libp2pNode.start((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
libp2pNode.on('peer:discovery', (peerInfo) => {
|
||||
const noop = () => { }
|
||||
|
||||
peerInfo = libp2pNode.peerBook.put(peerInfo)
|
||||
if (!peerInfo.isConnected()) {
|
||||
libp2pNode.dial(peerInfo, noop)
|
||||
}
|
||||
})
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 15000))
|
||||
|
||||
// Intropsection
|
||||
const data = libp2pNode.introspection.host()
|
||||
|
||||
// console.log('conns', data.subsystems.swarm.conns)
|
||||
|
||||
const conns = libp2pNode._switch.connection.connections
|
||||
const connsPeers = Object.keys(conns)
|
||||
|
||||
connsPeers.forEach((key) => {
|
||||
const conn = conns[key][0]
|
||||
|
||||
console.log(conn.muxer.multiplex._list.filter((m) => !!m))
|
||||
})
|
||||
|
||||
const encodedData = libp2pNode.introspection.marshal(data)
|
||||
const decodedData = libp2pNode.introspection.unmarshal(encodedData)
|
||||
|
||||
console.log('dec', decodedData)
|
||||
|
||||
// Stop node
|
||||
await new Promise((resolve, reject) => {
|
||||
libp2pNode.stop((err) => {
|
||||
if (err) {
|
||||
reject(err)
|
||||
} else {
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
console.log('all done')
|
||||
process.exit()
|
||||
}
|
||||
|
||||
introspection()
|
||||
|
||||
/*
|
||||
TODO:
|
||||
|
||||
- WebSockets transports with empty listen_multiaddrs
|
||||
*/
|
89
package.json
89
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "libp2p",
|
||||
"version": "0.26.0-rc.1",
|
||||
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
||||
"version": "0.25.0-rc.5",
|
||||
"description": "JavaScript base class for libp2p bundles",
|
||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||
"main": "src/index.js",
|
||||
"files": [
|
||||
@@ -23,82 +23,75 @@
|
||||
"url": "https://github.com/libp2p/js-libp2p.git"
|
||||
},
|
||||
"keywords": [
|
||||
"libp2p",
|
||||
"network",
|
||||
"p2p",
|
||||
"peer",
|
||||
"peer-to-peer",
|
||||
"IPFS"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=6.0.0",
|
||||
"npm": ">=3.0.0"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/libp2p/js-libp2p/issues"
|
||||
},
|
||||
"homepage": "https://libp2p.io",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/libp2p/js-libp2p",
|
||||
"browser": {
|
||||
"./test/utils/bundle-nodejs": "./test/utils/bundle-browser"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.0.0",
|
||||
"npm": ">=6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "^2.6.2",
|
||||
"debug": "^4.1.1",
|
||||
"err-code": "^1.1.2",
|
||||
"fsm-event": "^2.1.0",
|
||||
"libp2p-connection-manager": "^0.1.0",
|
||||
"libp2p-ping": "^0.8.5",
|
||||
"libp2p-switch": "^0.42.12",
|
||||
"libp2p-websockets": "^0.12.2",
|
||||
"libp2p-connection-manager": "~0.0.2",
|
||||
"libp2p-introspection": "vasco-santos/js-libp2p-introspection#feat/instrumentation",
|
||||
"libp2p-floodsub": "~0.15.8",
|
||||
"libp2p-ping": "~0.8.5",
|
||||
"libp2p-switch": "libp2p/js-libp2p-switch#feat/instrumentation",
|
||||
"libp2p-websockets": "~0.12.2",
|
||||
"mafmt": "^6.0.7",
|
||||
"multiaddr": "^6.1.0",
|
||||
"multiaddr": "^6.0.6",
|
||||
"once": "^1.4.0",
|
||||
"peer-book": "^0.9.1",
|
||||
"peer-id": "^0.12.2",
|
||||
"peer-info": "^0.15.1",
|
||||
"promisify-es6": "^1.0.3",
|
||||
"superstruct": "^0.6.0"
|
||||
"peer-book": "~0.9.1",
|
||||
"peer-id": "~0.12.2",
|
||||
"peer-info": "~0.15.1",
|
||||
"superstruct": "~0.6.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nodeutils/defaults-deep": "^1.1.0",
|
||||
"aegir": "^20.0.0",
|
||||
"aegir": "^18.2.1",
|
||||
"chai": "^4.2.0",
|
||||
"chai-checkmark": "^1.0.1",
|
||||
"cids": "^0.7.1",
|
||||
"cids": "~0.5.8",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"electron-webrtc": "^0.3.0",
|
||||
"interface-datastore": "^0.6.0",
|
||||
"libp2p-bootstrap": "^0.9.7",
|
||||
"libp2p-circuit": "^0.3.7",
|
||||
"libp2p-delegated-content-routing": "^0.2.2",
|
||||
"libp2p-delegated-peer-routing": "^0.2.2",
|
||||
"libp2p-floodsub": "~0.17.0",
|
||||
"libp2p-gossipsub": "~0.0.4",
|
||||
"libp2p-kad-dht": "^0.15.3",
|
||||
"libp2p-mdns": "^0.12.3",
|
||||
"libp2p-mplex": "^0.8.4",
|
||||
"libp2p-secio": "^0.11.1",
|
||||
"libp2p-spdy": "^0.13.2",
|
||||
"libp2p-tcp": "^0.13.0",
|
||||
"libp2p-webrtc-star": "^0.16.1",
|
||||
"electron-webrtc": "~0.3.0",
|
||||
"interface-datastore": "~0.6.0",
|
||||
"libp2p-bootstrap": "~0.9.7",
|
||||
"libp2p-circuit": "~0.3.6",
|
||||
"libp2p-delegated-content-routing": "~0.2.2",
|
||||
"libp2p-delegated-peer-routing": "~0.2.2",
|
||||
"libp2p-kad-dht": "~0.14.8",
|
||||
"libp2p-mdns": "~0.12.2",
|
||||
"libp2p-mplex": "~0.8.4",
|
||||
"libp2p-secio": "~0.11.1",
|
||||
"libp2p-spdy": "~0.13.2",
|
||||
"libp2p-tcp": "~0.13.0",
|
||||
"libp2p-webrtc-star": "~0.15.8",
|
||||
"libp2p-websocket-star": "~0.10.2",
|
||||
"libp2p-websocket-star-rendezvous": "~0.3.0",
|
||||
"lodash.times": "^4.3.2",
|
||||
"merge-options": "^1.0.1",
|
||||
"nock": "^10.0.6",
|
||||
"protons": "^1.0.1",
|
||||
"pull-goodbye": "0.0.2",
|
||||
"pull-mplex": "^0.1.2",
|
||||
"pull-serializer": "^0.3.2",
|
||||
"pull-stream": "^3.6.12",
|
||||
"pull-mplex": "~0.1.2",
|
||||
"pull-serializer": "~0.3.2",
|
||||
"pull-stream": "^3.6.9",
|
||||
"sinon": "^7.2.7",
|
||||
"wrtc": "^0.4.1"
|
||||
"wrtc": "~0.3.5"
|
||||
},
|
||||
"contributors": [
|
||||
"Aditya Bose <13054902+adbose@users.noreply.github.com>",
|
||||
"Alan Shaw <alan.shaw@protocol.ai>",
|
||||
"Alan Shaw <alan@tableflip.io>",
|
||||
"Alex Potsides <alex@achingbrain.net>",
|
||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||
"Chris Bratlien <chrisbratlien@gmail.com>",
|
||||
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
||||
@@ -110,7 +103,6 @@
|
||||
"Florian-Merle <florian.david.merle@gmail.com>",
|
||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||
"Guy Sviry <32539816+guysv@users.noreply.github.com>",
|
||||
"Henrique Dias <hacdias@gmail.com>",
|
||||
"Hugo Dias <mail@hugodias.me>",
|
||||
"Hugo Dias <hugomrdias@gmail.com>",
|
||||
@@ -133,10 +125,9 @@
|
||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||
"Thomas Eizinger <thomas@eizinger.io>",
|
||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||
"Vasco Santos <vasco.santos@ua.pt>",
|
||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||
"Volker Mische <volker.mische@gmail.com>",
|
||||
"Yusef Napora <yusef@napora.org>",
|
||||
"Zane Starr <zcstarr@gmail.com>",
|
||||
"ebinks <elizabethjbinks@gmail.com>",
|
||||
"greenkeeperio-bot <support@greenkeeper.io>",
|
||||
|
120
src/config.js
120
src/config.js
@@ -12,72 +12,58 @@ const transport = s.union([
|
||||
}),
|
||||
'function'
|
||||
])
|
||||
const modulesSchema = s({
|
||||
connEncryption: optional(list([s('object|function')])),
|
||||
// this is hacky to simulate optional because interface doesnt work correctly with it
|
||||
// change to optional when fixed upstream
|
||||
connProtector: s.union(['undefined', s.interface({ protect: 'function' })]),
|
||||
contentRouting: optional(list(['object'])),
|
||||
dht: optional(s('null|function|object')),
|
||||
pubsub: optional(s('null|function|object')),
|
||||
peerDiscovery: optional(list([s('object|function')])),
|
||||
peerRouting: optional(list(['object'])),
|
||||
streamMuxer: optional(list([s('object|function')])),
|
||||
transport: s.intersection([[transport], s.interface({
|
||||
length (v) {
|
||||
return v > 0 ? true : 'ERROR_EMPTY'
|
||||
}
|
||||
})])
|
||||
})
|
||||
|
||||
const configSchema = s({
|
||||
peerDiscovery: s('object', {
|
||||
autoDial: true
|
||||
}),
|
||||
relay: s({
|
||||
enabled: 'boolean',
|
||||
hop: optional(s({
|
||||
enabled: 'boolean',
|
||||
active: 'boolean'
|
||||
}, {
|
||||
// HOP defaults
|
||||
enabled: false,
|
||||
active: false
|
||||
}))
|
||||
}, {
|
||||
// Relay defaults
|
||||
enabled: true
|
||||
}),
|
||||
// DHT config
|
||||
dht: s('object?', {
|
||||
// DHT defaults
|
||||
enabled: false,
|
||||
kBucketSize: 20,
|
||||
randomWalk: {
|
||||
enabled: false, // disabled waiting for https://github.com/libp2p/js-libp2p-kad-dht/issues/86
|
||||
queriesPerPeriod: 1,
|
||||
interval: 300e3,
|
||||
timeout: 10e3
|
||||
}
|
||||
}),
|
||||
// Pubsub config
|
||||
pubsub: s('object?', {
|
||||
// DHT defaults
|
||||
enabled: false
|
||||
})
|
||||
}, {})
|
||||
|
||||
const optionsSchema = s({
|
||||
switch: 'object?',
|
||||
connectionManager: s('object', {
|
||||
minPeers: 25
|
||||
}),
|
||||
datastore: 'object?',
|
||||
peerInfo: 'object',
|
||||
peerBook: 'object?',
|
||||
modules: modulesSchema,
|
||||
config: configSchema
|
||||
})
|
||||
const optionsSchema = s(
|
||||
{
|
||||
connectionManager: 'object?',
|
||||
datastore: 'object?',
|
||||
peerInfo: 'object',
|
||||
peerBook: 'object?',
|
||||
modules: s({
|
||||
connEncryption: optional(list([s('object|function')])),
|
||||
// this is hacky to simulate optional because interface doesnt work correctly with it
|
||||
// change to optional when fixed upstream
|
||||
connProtector: s.union(['undefined', s.interface({ protect: 'function' })]),
|
||||
contentRouting: optional(list(['object'])),
|
||||
dht: optional(s('null|function|object')),
|
||||
peerDiscovery: optional(list([s('object|function')])),
|
||||
peerRouting: optional(list(['object'])),
|
||||
streamMuxer: optional(list([s('object|function')])),
|
||||
transport: s.intersection([[transport], s.interface({
|
||||
length (v) {
|
||||
return v > 0 ? true : 'ERROR_EMPTY'
|
||||
}
|
||||
})])
|
||||
}),
|
||||
config: s({
|
||||
peerDiscovery: 'object?',
|
||||
relay: s({
|
||||
enabled: 'boolean',
|
||||
hop: optional(s({
|
||||
enabled: 'boolean',
|
||||
active: 'boolean'
|
||||
},
|
||||
{ enabled: false, active: false }))
|
||||
}, { enabled: true, hop: {} }),
|
||||
dht: s({
|
||||
kBucketSize: 'number',
|
||||
enabled: 'boolean?',
|
||||
randomWalk: optional(s({
|
||||
enabled: 'boolean?', // disabled waiting for https://github.com/libp2p/js-libp2p-kad-dht/issues/86
|
||||
queriesPerPeriod: 'number?',
|
||||
interval: 'number?',
|
||||
timeout: 'number?'
|
||||
}, { enabled: false, queriesPerPeriod: 1, interval: 30000, timeout: 10000 })),
|
||||
validators: 'object?',
|
||||
selectors: 'object?'
|
||||
}, { enabled: false, kBucketSize: 20, enabledDiscovery: false }),
|
||||
EXPERIMENTAL: s({
|
||||
pubsub: 'boolean'
|
||||
}, { pubsub: false })
|
||||
}, { relay: {}, dht: {}, EXPERIMENTAL: {} })
|
||||
},
|
||||
{ config: {}, modules: {} }
|
||||
)
|
||||
|
||||
module.exports.validate = (opts) => {
|
||||
const [error, options] = optionsSchema.validate(opts)
|
||||
@@ -92,9 +78,5 @@ module.exports.validate = (opts) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (options.config.peerDiscovery.autoDial === undefined) {
|
||||
options.config.peerDiscovery.autoDial = true
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
const tryEach = require('async/tryEach')
|
||||
const parallel = require('async/parallel')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
|
||||
module.exports = (node) => {
|
||||
const routers = node._modules.contentRouting || []
|
||||
@@ -25,7 +24,7 @@ module.exports = (node) => {
|
||||
* @param {function(Error, Result<Array>)} callback
|
||||
* @returns {void}
|
||||
*/
|
||||
findProviders: promisify((key, options, callback) => {
|
||||
findProviders: (key, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
@@ -61,7 +60,7 @@ module.exports = (node) => {
|
||||
results = results || []
|
||||
callback(null, results)
|
||||
})
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Iterates over all content routers in parallel to notify it is
|
||||
@@ -71,7 +70,7 @@ module.exports = (node) => {
|
||||
* @param {function(Error)} callback
|
||||
* @returns {void}
|
||||
*/
|
||||
provide: promisify((key, callback) => {
|
||||
provide: (key, callback) => {
|
||||
if (!routers.length) {
|
||||
return callback(errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE'))
|
||||
}
|
||||
@@ -79,6 +78,6 @@ module.exports = (node) => {
|
||||
parallel(routers.map((router) => {
|
||||
return (cb) => router.provide(key, cb)
|
||||
}), callback)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
src/dht.js
13
src/dht.js
@@ -2,20 +2,19 @@
|
||||
|
||||
const nextTick = require('async/nextTick')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
|
||||
const { messages, codes } = require('./errors')
|
||||
|
||||
module.exports = (node) => {
|
||||
return {
|
||||
put: promisify((key, value, callback) => {
|
||||
put: (key, value, callback) => {
|
||||
if (!node._dht) {
|
||||
return nextTick(callback, errCode(new Error(messages.DHT_DISABLED), codes.DHT_DISABLED))
|
||||
}
|
||||
|
||||
node._dht.put(key, value, callback)
|
||||
}),
|
||||
get: promisify((key, options, callback) => {
|
||||
},
|
||||
get: (key, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
@@ -26,8 +25,8 @@ module.exports = (node) => {
|
||||
}
|
||||
|
||||
node._dht.get(key, options, callback)
|
||||
}),
|
||||
getMany: promisify((key, nVals, options, callback) => {
|
||||
},
|
||||
getMany: (key, nVals, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
@@ -38,6 +37,6 @@ module.exports = (node) => {
|
||||
}
|
||||
|
||||
node._dht.getMany(key, nVals, options, callback)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,5 @@ exports.messages = {
|
||||
|
||||
exports.codes = {
|
||||
DHT_DISABLED: 'ERR_DHT_DISABLED',
|
||||
PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED',
|
||||
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
|
||||
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF'
|
||||
PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED'
|
||||
}
|
||||
|
@@ -4,13 +4,12 @@ const PeerId = require('peer-id')
|
||||
const PeerInfo = require('peer-info')
|
||||
const multiaddr = require('multiaddr')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
|
||||
module.exports = (node) => {
|
||||
/*
|
||||
* Helper method to check the data type of peer and convert it to PeerInfo
|
||||
*/
|
||||
return promisify(function (peer, callback) {
|
||||
return function (peer, callback) {
|
||||
let p
|
||||
// PeerInfo
|
||||
if (PeerInfo.isPeerInfo(peer)) {
|
||||
@@ -63,5 +62,5 @@ module.exports = (node) => {
|
||||
}
|
||||
|
||||
callback(null, p)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
296
src/index.js
296
src/index.js
@@ -6,15 +6,12 @@ const debug = require('debug')
|
||||
const log = debug('libp2p')
|
||||
log.error = debug('libp2p:error')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
|
||||
const each = require('async/each')
|
||||
const series = require('async/series')
|
||||
const parallel = require('async/parallel')
|
||||
const nextTick = require('async/nextTick')
|
||||
|
||||
const PeerBook = require('peer-book')
|
||||
const PeerInfo = require('peer-info')
|
||||
const Switch = require('libp2p-switch')
|
||||
const Ping = require('libp2p-ping')
|
||||
const WebSockets = require('libp2p-websockets')
|
||||
@@ -25,51 +22,52 @@ const peerRouting = require('./peer-routing')
|
||||
const contentRouting = require('./content-routing')
|
||||
const dht = require('./dht')
|
||||
const pubsub = require('./pubsub')
|
||||
const introspection = require('libp2p-introspection')
|
||||
const getPeerInfo = require('./get-peer-info')
|
||||
const validateConfig = require('./config').validate
|
||||
const { codes } = require('./errors')
|
||||
|
||||
const notStarted = (action, state) => {
|
||||
return errCode(
|
||||
new Error(`libp2p cannot ${action} when not started; state is ${state}`),
|
||||
codes.ERR_NODE_NOT_STARTED
|
||||
'ERR_NODE_NOT_STARTED'
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* @fires Libp2p#error Emitted when an error occurs
|
||||
* @fires Libp2p#peer:connect Emitted when a peer is connected to this node
|
||||
* @fires Libp2p#peer:disconnect Emitted when a peer disconnects from this node
|
||||
* @fires Libp2p#peer:discovery Emitted when a peer is discovered
|
||||
* @fires Libp2p#start Emitted when the node and its services has started
|
||||
* @fires Libp2p#stop Emitted when the node and its services has stopped
|
||||
* @fires Node#error Emitted when an error occurs
|
||||
* @fires Node#peer:connect Emitted when a peer is connected to this node
|
||||
* @fires Node#peer:disconnect Emitted when a peer disconnects from this node
|
||||
* @fires Node#peer:discovery Emitted when a peer is discovered
|
||||
* @fires Node#start Emitted when the node and its services has started
|
||||
* @fires Node#stop Emitted when the node and its services has stopped
|
||||
*/
|
||||
class Libp2p extends EventEmitter {
|
||||
class Node extends EventEmitter {
|
||||
constructor (_options) {
|
||||
super()
|
||||
// validateConfig will ensure the config is correct,
|
||||
// and add default values where appropriate
|
||||
this._options = validateConfig(_options)
|
||||
_options = validateConfig(_options)
|
||||
|
||||
this.datastore = this._options.datastore
|
||||
this.peerInfo = this._options.peerInfo
|
||||
this.peerBook = this._options.peerBook || new PeerBook()
|
||||
this.datastore = _options.datastore
|
||||
this.peerInfo = _options.peerInfo
|
||||
this.peerBook = _options.peerBook || new PeerBook()
|
||||
this.introspection = introspection(this)
|
||||
|
||||
this._modules = this._options.modules
|
||||
this._config = this._options.config
|
||||
this._modules = _options.modules
|
||||
this._config = _options.config
|
||||
this._transport = [] // Transport instances/references
|
||||
this._discovery = [] // Discovery service instances/references
|
||||
|
||||
// create the switch, and listen for errors
|
||||
this._switch = new Switch(this.peerInfo, this.peerBook, this._options.switch)
|
||||
this._switch = new Switch(this.peerInfo, this.peerBook, _options.switch)
|
||||
this._switch.on('error', (...args) => this.emit('error', ...args))
|
||||
|
||||
this.stats = this._switch.stats
|
||||
this.connectionManager = new ConnectionManager(this, this._options.connectionManager)
|
||||
this.connectionManager = new ConnectionManager(this, _options.connectionManager)
|
||||
|
||||
// Attach stream multiplexers
|
||||
if (this._modules.streamMuxer) {
|
||||
const muxers = this._modules.streamMuxer
|
||||
let muxers = this._modules.streamMuxer
|
||||
muxers.forEach((muxer) => this._switch.connection.addStreamMuxer(muxer))
|
||||
|
||||
// If muxer exists
|
||||
@@ -82,6 +80,7 @@ class Libp2p extends EventEmitter {
|
||||
// reuse this muxed connection
|
||||
this._switch.on('peer-mux-established', (peerInfo) => {
|
||||
this.emit('peer:connect', peerInfo)
|
||||
this.peerBook.put(peerInfo)
|
||||
})
|
||||
|
||||
this._switch.on('peer-mux-closed', (peerInfo) => {
|
||||
@@ -89,17 +88,9 @@ class Libp2p extends EventEmitter {
|
||||
})
|
||||
}
|
||||
|
||||
// Events for anytime connections are created/removed
|
||||
this._switch.on('connection:start', (peerInfo) => {
|
||||
this.emit('connection:start', peerInfo)
|
||||
})
|
||||
this._switch.on('connection:end', (peerInfo) => {
|
||||
this.emit('connection:end', peerInfo)
|
||||
})
|
||||
|
||||
// Attach crypto channels
|
||||
if (this._modules.connEncryption) {
|
||||
const cryptos = this._modules.connEncryption
|
||||
let cryptos = this._modules.connEncryption
|
||||
cryptos.forEach((crypto) => {
|
||||
this._switch.connection.crypto(crypto.tag, crypto.encrypt)
|
||||
})
|
||||
@@ -122,9 +113,9 @@ class Libp2p extends EventEmitter {
|
||||
})
|
||||
}
|
||||
|
||||
// start pubsub
|
||||
if (this._modules.pubsub && this._config.pubsub.enabled !== false) {
|
||||
this.pubsub = pubsub(this, this._modules.pubsub)
|
||||
// enable/disable pubsub
|
||||
if (this._config.EXPERIMENTAL.pubsub) {
|
||||
this.pubsub = pubsub(this)
|
||||
}
|
||||
|
||||
// Attach remaining APIs
|
||||
@@ -177,23 +168,6 @@ class Libp2p extends EventEmitter {
|
||||
log.error(err)
|
||||
this.emit('error', err)
|
||||
})
|
||||
|
||||
// Once we start, emit and dial any peers we may have already discovered
|
||||
this.state.on('STARTED', () => {
|
||||
this.peerBook.getAllArray().forEach((peerInfo) => {
|
||||
this.emit('peer:discovery', peerInfo)
|
||||
this._maybeConnect(peerInfo)
|
||||
})
|
||||
})
|
||||
|
||||
this._peerDiscovered = this._peerDiscovered.bind(this)
|
||||
|
||||
// promisify all instance methods
|
||||
;['start', 'stop', 'dial', 'dialProtocol', 'dialFSM', 'hangUp', 'ping'].forEach(method => {
|
||||
this[method] = promisify(this[method], {
|
||||
context: this
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -272,7 +246,11 @@ class Libp2p extends EventEmitter {
|
||||
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
this._switch.dial(peerInfo, protocol, callback)
|
||||
this._switch.dial(peerInfo, protocol, (err, conn) => {
|
||||
if (err) { return callback(err) }
|
||||
this.peerBook.put(peerInfo)
|
||||
callback(null, conn)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -298,7 +276,12 @@ class Libp2p extends EventEmitter {
|
||||
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||
if (err) { return callback(err) }
|
||||
|
||||
this._switch.dialFSM(peerInfo, protocol, callback)
|
||||
this._switch.dialFSM(peerInfo, protocol, (err, connFSM) => {
|
||||
if (!err) {
|
||||
this.peerBook.put(peerInfo)
|
||||
}
|
||||
callback(err, connFSM)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -355,7 +338,7 @@ class Libp2p extends EventEmitter {
|
||||
let t
|
||||
|
||||
if (typeof Transport === 'function') {
|
||||
t = new Transport({ libp2p: this })
|
||||
t = new Transport()
|
||||
} else {
|
||||
t = Transport
|
||||
}
|
||||
@@ -381,6 +364,60 @@ class Libp2p extends EventEmitter {
|
||||
this._switch.transport.add(ws.tag || ws.constructor.name, ws)
|
||||
}
|
||||
|
||||
// all transports need to be setup before discover starts
|
||||
if (this._modules.peerDiscovery) {
|
||||
each(this._modules.peerDiscovery, (D, _cb) => {
|
||||
let config = {}
|
||||
|
||||
if (D.tag &&
|
||||
this._config.peerDiscovery &&
|
||||
this._config.peerDiscovery[D.tag]) {
|
||||
config = this._config.peerDiscovery[D.tag]
|
||||
}
|
||||
|
||||
// If not configured to be enabled/disabled then enable by default
|
||||
const enabled = config.enabled == null ? true : config.enabled
|
||||
|
||||
// If enabled then start it
|
||||
if (enabled) {
|
||||
let d
|
||||
|
||||
if (typeof D === 'function') {
|
||||
d = new D(Object.assign({}, config, { peerInfo: this.peerInfo }))
|
||||
} else {
|
||||
d = D
|
||||
}
|
||||
|
||||
d.on('peer', (peerInfo) => {
|
||||
this.emit('peer:discovery', peerInfo)
|
||||
})
|
||||
this._discovery.push(d)
|
||||
d.start(_cb)
|
||||
} else {
|
||||
_cb()
|
||||
}
|
||||
}, cb)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
(cb) => {
|
||||
if (this._dht) {
|
||||
this._dht.start(() => {
|
||||
this._dht.on('peer', (peerInfo) => this.emit('peer:discovery', peerInfo))
|
||||
cb()
|
||||
})
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
(cb) => {
|
||||
if (this._floodSub) {
|
||||
return this._floodSub.start(cb)
|
||||
}
|
||||
cb()
|
||||
},
|
||||
(cb) => {
|
||||
// detect which multiaddrs we don't have a transport for and remove them
|
||||
const multiaddrs = this.peerInfo.multiaddrs.toArray()
|
||||
|
||||
@@ -391,30 +428,6 @@ class Libp2p extends EventEmitter {
|
||||
}
|
||||
})
|
||||
cb()
|
||||
},
|
||||
(cb) => {
|
||||
if (this._dht) {
|
||||
this._dht.start(() => {
|
||||
this._dht.on('peer', this._peerDiscovered)
|
||||
cb()
|
||||
})
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
},
|
||||
(cb) => {
|
||||
if (this.pubsub) {
|
||||
return this.pubsub.start(cb)
|
||||
}
|
||||
cb()
|
||||
},
|
||||
// Peer Discovery
|
||||
(cb) => {
|
||||
if (this._modules.peerDiscovery) {
|
||||
this._setupPeerDiscovery(cb)
|
||||
} else {
|
||||
cb()
|
||||
}
|
||||
}
|
||||
], (err) => {
|
||||
if (err) {
|
||||
@@ -429,27 +442,25 @@ class Libp2p extends EventEmitter {
|
||||
_onStopping () {
|
||||
series([
|
||||
(cb) => {
|
||||
// stop all discoveries before continuing with shutdown
|
||||
parallel(
|
||||
this._discovery.map((d) => {
|
||||
d.removeListener('peer', this._peerDiscovered)
|
||||
return (_cb) => d.stop((err) => {
|
||||
log.error('an error occurred stopping the discovery service', err)
|
||||
_cb()
|
||||
})
|
||||
}),
|
||||
cb
|
||||
)
|
||||
if (this._modules.peerDiscovery) {
|
||||
// stop all discoveries before continuing with shutdown
|
||||
return parallel(
|
||||
this._discovery.map((d) => {
|
||||
return (_cb) => d.stop(() => { _cb() })
|
||||
}),
|
||||
cb
|
||||
)
|
||||
}
|
||||
cb()
|
||||
},
|
||||
(cb) => {
|
||||
if (this.pubsub) {
|
||||
return this.pubsub.stop(cb)
|
||||
if (this._floodSub) {
|
||||
return this._floodSub.stop(cb)
|
||||
}
|
||||
cb()
|
||||
},
|
||||
(cb) => {
|
||||
if (this._dht) {
|
||||
this._dht.removeListener('peer', this._peerDiscovered)
|
||||
return this._dht.stop(cb)
|
||||
}
|
||||
cb()
|
||||
@@ -471,107 +482,6 @@ class Libp2p extends EventEmitter {
|
||||
this.state('done')
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles discovered peers. Each discovered peer will be emitted via
|
||||
* the `peer:discovery` event. If auto dial is enabled for libp2p
|
||||
* and the current connection count is under the low watermark, the
|
||||
* peer will be dialed.
|
||||
*
|
||||
* TODO: If `peerBook.put` becomes centralized, https://github.com/libp2p/js-libp2p/issues/345,
|
||||
* it would be ideal if only new peers were emitted. Currently, with
|
||||
* other modules adding peers to the `PeerBook` we have no way of knowing
|
||||
* if a peer is new or not, so it has to be emitted.
|
||||
*
|
||||
* @private
|
||||
* @param {PeerInfo} peerInfo
|
||||
*/
|
||||
_peerDiscovered (peerInfo) {
|
||||
if (peerInfo.id.toB58String() === this.peerInfo.id.toB58String()) {
|
||||
log.error(new Error(codes.ERR_DISCOVERED_SELF))
|
||||
return
|
||||
}
|
||||
peerInfo = this.peerBook.put(peerInfo)
|
||||
|
||||
if (!this.isStarted()) return
|
||||
|
||||
this.emit('peer:discovery', peerInfo)
|
||||
this._maybeConnect(peerInfo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Will dial to the given `peerInfo` if the current number of
|
||||
* connected peers is less than the configured `ConnectionManager`
|
||||
* minPeers.
|
||||
* @private
|
||||
* @param {PeerInfo} peerInfo
|
||||
*/
|
||||
_maybeConnect (peerInfo) {
|
||||
// If auto dialing is on, check if we should dial
|
||||
if (this._config.peerDiscovery.autoDial === true && !peerInfo.isConnected()) {
|
||||
const minPeers = this._options.connectionManager.minPeers || 0
|
||||
if (minPeers > Object.keys(this._switch.connection.connections).length) {
|
||||
log('connecting to discovered peer')
|
||||
this._switch.dialer.connect(peerInfo, (err) => {
|
||||
err && log.error('could not connect to discovered peer', err)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and starts peer discovery services
|
||||
*
|
||||
* @private
|
||||
* @param {function(Error)} callback
|
||||
*/
|
||||
_setupPeerDiscovery (callback) {
|
||||
for (const DiscoveryService of this._modules.peerDiscovery) {
|
||||
let config = {
|
||||
enabled: true // on by default
|
||||
}
|
||||
|
||||
if (DiscoveryService.tag &&
|
||||
this._config.peerDiscovery &&
|
||||
this._config.peerDiscovery[DiscoveryService.tag]) {
|
||||
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
|
||||
}
|
||||
|
||||
if (config.enabled) {
|
||||
let discoveryService
|
||||
|
||||
if (typeof DiscoveryService === 'function') {
|
||||
discoveryService = new DiscoveryService(Object.assign({}, config, { peerInfo: this.peerInfo }))
|
||||
} else {
|
||||
discoveryService = DiscoveryService
|
||||
}
|
||||
|
||||
discoveryService.on('peer', this._peerDiscovered)
|
||||
this._discovery.push(discoveryService)
|
||||
}
|
||||
}
|
||||
|
||||
each(this._discovery, (d, cb) => {
|
||||
d.start(cb)
|
||||
}, callback)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Libp2p
|
||||
/**
|
||||
* Like `new Libp2p(options)` except it will create a `PeerInfo`
|
||||
* instance if one is not provided in options.
|
||||
* @param {object} options Libp2p configuration options
|
||||
* @param {function(Error, Libp2p)} callback
|
||||
* @returns {void}
|
||||
*/
|
||||
module.exports.createLibp2p = promisify((options, callback) => {
|
||||
if (options.peerInfo) {
|
||||
return nextTick(callback, null, new Libp2p(options))
|
||||
}
|
||||
PeerInfo.create((err, peerInfo) => {
|
||||
if (err) return callback(err)
|
||||
options.peerInfo = peerInfo
|
||||
callback(null, new Libp2p(options))
|
||||
})
|
||||
})
|
||||
module.exports = Node
|
||||
|
@@ -2,7 +2,6 @@
|
||||
|
||||
const tryEach = require('async/tryEach')
|
||||
const errCode = require('err-code')
|
||||
const promisify = require('promisify-es6')
|
||||
|
||||
module.exports = (node) => {
|
||||
const routers = node._modules.peerRouting || []
|
||||
@@ -22,7 +21,7 @@ module.exports = (node) => {
|
||||
* @param {function(Error, Result<Array>)} callback
|
||||
* @returns {void}
|
||||
*/
|
||||
findPeer: promisify((id, options, callback) => {
|
||||
findPeer: (id, options, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
@@ -48,12 +47,12 @@ module.exports = (node) => {
|
||||
})
|
||||
|
||||
tryEach(tasks, (err, results) => {
|
||||
if (err) {
|
||||
if (err && err.code !== 'NOT_FOUND') {
|
||||
return callback(err)
|
||||
}
|
||||
results = results || []
|
||||
callback(null, results)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
128
src/pubsub.js
128
src/pubsub.js
@@ -2,128 +2,84 @@
|
||||
|
||||
const nextTick = require('async/nextTick')
|
||||
const { messages, codes } = require('./errors')
|
||||
const promisify = require('promisify-es6')
|
||||
const FloodSub = require('libp2p-floodsub')
|
||||
|
||||
const errCode = require('err-code')
|
||||
|
||||
module.exports = (node, Pubsub) => {
|
||||
const pubsub = new Pubsub(node, { emitSelf: true })
|
||||
module.exports = (node) => {
|
||||
const floodSub = new FloodSub(node)
|
||||
|
||||
node._floodSub = floodSub
|
||||
|
||||
return {
|
||||
/**
|
||||
* Subscribe the given handler to a pubsub topic
|
||||
*
|
||||
* @param {string} topic
|
||||
* @param {function} handler The handler to subscribe
|
||||
* @param {object|null} [options]
|
||||
* @param {function} [callback] An optional callback
|
||||
*
|
||||
* @returns {Promise|void} A promise is returned if no callback is provided
|
||||
*
|
||||
* @example <caption>Subscribe a handler to a topic</caption>
|
||||
*
|
||||
* // `null` must be passed for options until subscribe is no longer using promisify
|
||||
* const handler = (message) => { }
|
||||
* await libp2p.subscribe(topic, handler, null)
|
||||
*
|
||||
* @example <caption>Use a callback instead of the Promise api</caption>
|
||||
*
|
||||
* // `options` may be passed or omitted when supplying a callback
|
||||
* const handler = (message) => { }
|
||||
* libp2p.subscribe(topic, handler, callback)
|
||||
*/
|
||||
subscribe: promisify((topic, handler, options, callback) => {
|
||||
subscribe: (topic, options, handler, callback) => {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
callback = handler
|
||||
handler = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
if (!node.isStarted() && !floodSub.started) {
|
||||
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
|
||||
}
|
||||
|
||||
function subscribe (cb) {
|
||||
if (pubsub.listenerCount(topic) === 0) {
|
||||
pubsub.subscribe(topic)
|
||||
if (floodSub.listenerCount(topic) === 0) {
|
||||
floodSub.subscribe(topic)
|
||||
}
|
||||
|
||||
pubsub.on(topic, handler)
|
||||
floodSub.on(topic, handler)
|
||||
nextTick(cb)
|
||||
}
|
||||
|
||||
subscribe(callback)
|
||||
}),
|
||||
},
|
||||
|
||||
/**
|
||||
* Unsubscribes from a pubsub topic
|
||||
*
|
||||
* @param {string} topic
|
||||
* @param {function|null} handler The handler to unsubscribe from
|
||||
* @param {function} [callback] An optional callback
|
||||
*
|
||||
* @returns {Promise|void} A promise is returned if no callback is provided
|
||||
*
|
||||
* @example <caption>Unsubscribe a topic for all handlers</caption>
|
||||
*
|
||||
* // `null` must be passed until unsubscribe is no longer using promisify
|
||||
* await libp2p.unsubscribe(topic, null)
|
||||
*
|
||||
* @example <caption>Unsubscribe a topic for 1 handler</caption>
|
||||
*
|
||||
* await libp2p.unsubscribe(topic, handler)
|
||||
*
|
||||
* @example <caption>Use a callback instead of the Promise api</caption>
|
||||
*
|
||||
* libp2p.unsubscribe(topic, handler, callback)
|
||||
*/
|
||||
unsubscribe: promisify((topic, handler, callback) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
unsubscribe: (topic, handler, callback) => {
|
||||
if (!node.isStarted() && !floodSub.started) {
|
||||
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
pubsub.removeAllListeners(topic)
|
||||
if (!handler && !callback) {
|
||||
floodSub.removeAllListeners(topic)
|
||||
} else {
|
||||
pubsub.removeListener(topic, handler)
|
||||
floodSub.removeListener(topic, handler)
|
||||
}
|
||||
|
||||
if (pubsub.listenerCount(topic) === 0) {
|
||||
pubsub.unsubscribe(topic)
|
||||
if (floodSub.listenerCount(topic) === 0) {
|
||||
floodSub.unsubscribe(topic)
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
return nextTick(() => callback())
|
||||
nextTick(() => callback())
|
||||
}
|
||||
},
|
||||
|
||||
return Promise.resolve()
|
||||
}),
|
||||
|
||||
publish: promisify((topic, data, callback) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
publish: (topic, data, callback) => {
|
||||
if (!node.isStarted() && !floodSub.started) {
|
||||
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
|
||||
}
|
||||
|
||||
try {
|
||||
data = Buffer.from(data)
|
||||
} catch (err) {
|
||||
return nextTick(callback, errCode(new Error('data must be convertible to a Buffer'), 'ERR_DATA_IS_NOT_VALID'))
|
||||
if (!Buffer.isBuffer(data)) {
|
||||
return nextTick(callback, errCode(new Error('data must be a Buffer'), 'ERR_DATA_IS_NOT_A_BUFFER'))
|
||||
}
|
||||
|
||||
pubsub.publish(topic, data, callback)
|
||||
}),
|
||||
floodSub.publish(topic, data)
|
||||
|
||||
ls: promisify((callback) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
nextTick(() => callback())
|
||||
},
|
||||
|
||||
ls: (callback) => {
|
||||
if (!node.isStarted() && !floodSub.started) {
|
||||
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
|
||||
}
|
||||
|
||||
const subscriptions = Array.from(pubsub.subscriptions)
|
||||
const subscriptions = Array.from(floodSub.subscriptions)
|
||||
|
||||
nextTick(() => callback(null, subscriptions))
|
||||
}),
|
||||
},
|
||||
|
||||
peers: promisify((topic, callback) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
peers: (topic, callback) => {
|
||||
if (!node.isStarted() && !floodSub.started) {
|
||||
return nextTick(callback, errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED))
|
||||
}
|
||||
|
||||
@@ -132,19 +88,15 @@ module.exports = (node, Pubsub) => {
|
||||
topic = null
|
||||
}
|
||||
|
||||
const peers = Array.from(pubsub.peers.values())
|
||||
const peers = Array.from(floodSub.peers.values())
|
||||
.filter((peer) => topic ? peer.topics.has(topic) : true)
|
||||
.map((peer) => peer.info.id.toB58String())
|
||||
|
||||
nextTick(() => callback(null, peers))
|
||||
}),
|
||||
|
||||
setMaxListeners (n) {
|
||||
return pubsub.setMaxListeners(n)
|
||||
},
|
||||
|
||||
start: promisify((cb) => pubsub.start(cb)),
|
||||
|
||||
stop: promisify((cb) => pubsub.stop(cb))
|
||||
setMaxListeners (n) {
|
||||
return floodSub.setMaxListeners(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ const tryEcho = require('./utils/try-echo')
|
||||
const echo = require('./utils/echo')
|
||||
|
||||
describe('circuit relay', () => {
|
||||
const handlerSpies = []
|
||||
let handlerSpies = []
|
||||
let relayNode1
|
||||
let relayNode2
|
||||
let nodeWS1
|
||||
@@ -114,9 +114,10 @@ describe('circuit relay', () => {
|
||||
nodeWS2 = node
|
||||
cb()
|
||||
}),
|
||||
// set up node with TCP
|
||||
// set up node with TCP and listening on relay1
|
||||
(cb) => setupNode([
|
||||
'/ip4/0.0.0.0/tcp/0'
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
`/p2p/${relayNode1.peerInfo.id.toB58String()}/p2p-circuit`
|
||||
], {
|
||||
config: {
|
||||
relay: {
|
||||
@@ -127,9 +128,10 @@ describe('circuit relay', () => {
|
||||
nodeTCP1 = node
|
||||
cb()
|
||||
}),
|
||||
// set up node with TCP
|
||||
// set up node with TCP and listening on relay2 over TCP transport
|
||||
(cb) => setupNode([
|
||||
'/ip4/0.0.0.0/tcp/0'
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
`/ip4/0.0.0.0/tcp/0/p2p/${relayNode2.peerInfo.id.toB58String()}/p2p-circuit`
|
||||
], {
|
||||
config: {
|
||||
relay: {
|
||||
|
@@ -33,7 +33,7 @@ describe('configuration', () => {
|
||||
expect(() => {
|
||||
validateConfig({
|
||||
modules: {
|
||||
transport: [WS]
|
||||
transport: [ WS ]
|
||||
}
|
||||
})
|
||||
}).to.throw()
|
||||
@@ -52,68 +52,18 @@ describe('configuration', () => {
|
||||
validateConfig({
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: []
|
||||
transport: [ ]
|
||||
}
|
||||
})
|
||||
}).to.throw('ERROR_EMPTY')
|
||||
})
|
||||
|
||||
it('should add defaults to config', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: [Bootstrap],
|
||||
dht: DHT
|
||||
}
|
||||
}
|
||||
|
||||
const expected = {
|
||||
peerInfo,
|
||||
connectionManager: {
|
||||
minPeers: 25
|
||||
},
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: [Bootstrap],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true
|
||||
},
|
||||
pubsub: {
|
||||
enabled: false
|
||||
},
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
enabled: false,
|
||||
randomWalk: {
|
||||
enabled: false,
|
||||
queriesPerPeriod: 1,
|
||||
interval: 300000,
|
||||
timeout: 10000
|
||||
}
|
||||
},
|
||||
relay: {
|
||||
enabled: true,
|
||||
hop: {
|
||||
active: false,
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
expect(validateConfig(options)).to.deep.equal(expected)
|
||||
})
|
||||
|
||||
it('should add defaults to missing items', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: [Bootstrap],
|
||||
transport: [ WS ],
|
||||
peerDiscovery: [ Bootstrap ],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
@@ -128,24 +78,20 @@ describe('configuration', () => {
|
||||
|
||||
const expected = {
|
||||
peerInfo,
|
||||
connectionManager: {
|
||||
minPeers: 25
|
||||
},
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: [Bootstrap],
|
||||
transport: [ WS ],
|
||||
peerDiscovery: [ Bootstrap ],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
bootstrap: {
|
||||
interval: 1000,
|
||||
enabled: true
|
||||
}
|
||||
},
|
||||
pubsub: {
|
||||
enabled: false
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
},
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
@@ -153,7 +99,7 @@ describe('configuration', () => {
|
||||
randomWalk: {
|
||||
enabled: false,
|
||||
queriesPerPeriod: 1,
|
||||
interval: 300000,
|
||||
interval: 30000,
|
||||
timeout: 10000
|
||||
}
|
||||
},
|
||||
@@ -170,33 +116,6 @@ describe('configuration', () => {
|
||||
expect(validateConfig(options)).to.deep.equal(expected)
|
||||
})
|
||||
|
||||
it('should allow for configuring the switch', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
switch: {
|
||||
blacklistTTL: 60e3,
|
||||
blackListAttempts: 5,
|
||||
maxParallelDials: 100,
|
||||
maxColdCalls: 50,
|
||||
dialTimeout: 30e3
|
||||
},
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: []
|
||||
}
|
||||
}
|
||||
|
||||
expect(validateConfig(options)).to.deep.include({
|
||||
switch: {
|
||||
blacklistTTL: 60e3,
|
||||
blackListAttempts: 5,
|
||||
maxParallelDials: 100,
|
||||
maxColdCalls: 50,
|
||||
dialTimeout: 30e3
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('should allow for delegated content and peer routing', () => {
|
||||
const peerRouter = new DelegatedPeerRouter()
|
||||
const contentRouter = new DelegatedContentRouter(peerInfo)
|
||||
@@ -204,10 +123,10 @@ describe('configuration', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS],
|
||||
peerDiscovery: [Bootstrap],
|
||||
peerRouting: [peerRouter],
|
||||
contentRouting: [contentRouter],
|
||||
transport: [ WS ],
|
||||
peerDiscovery: [ Bootstrap ],
|
||||
peerRouting: [ peerRouter ],
|
||||
contentRouting: [ contentRouter ],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
@@ -221,8 +140,8 @@ describe('configuration', () => {
|
||||
}
|
||||
|
||||
expect(validateConfig(options).modules).to.deep.include({
|
||||
peerRouting: [peerRouter],
|
||||
contentRouting: [contentRouter]
|
||||
peerRouting: [ peerRouter ],
|
||||
contentRouting: [ contentRouter ]
|
||||
})
|
||||
})
|
||||
|
||||
@@ -230,7 +149,7 @@ describe('configuration', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS]
|
||||
transport: [ WS ]
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
@@ -242,7 +161,7 @@ describe('configuration', () => {
|
||||
expect(() => validateConfig(options)).to.throw()
|
||||
})
|
||||
|
||||
it('should be able to add validators and selectors for dht', () => {
|
||||
it('should add defaults, validators and selectors for dht', () => {
|
||||
const selectors = {}
|
||||
const validators = {}
|
||||
|
||||
@@ -261,19 +180,13 @@ describe('configuration', () => {
|
||||
}
|
||||
const expected = {
|
||||
peerInfo,
|
||||
connectionManager: {
|
||||
minPeers: 25
|
||||
},
|
||||
modules: {
|
||||
transport: [WS],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: false
|
||||
},
|
||||
peerDiscovery: {
|
||||
autoDial: true
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
},
|
||||
relay: {
|
||||
enabled: true,
|
||||
@@ -283,6 +196,14 @@ describe('configuration', () => {
|
||||
}
|
||||
},
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
enabled: false,
|
||||
randomWalk: {
|
||||
enabled: false,
|
||||
queriesPerPeriod: 1,
|
||||
interval: 30000,
|
||||
timeout: 10000
|
||||
},
|
||||
selectors,
|
||||
validators
|
||||
}
|
||||
@@ -290,43 +211,4 @@ describe('configuration', () => {
|
||||
}
|
||||
expect(validateConfig(options)).to.deep.equal(expected)
|
||||
})
|
||||
|
||||
it('should support new properties for the dht config', () => {
|
||||
const options = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS],
|
||||
dht: DHT
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
kBucketSize: 20,
|
||||
enabled: false,
|
||||
myNewDHTConfigProperty: true,
|
||||
randomWalk: {
|
||||
enabled: false,
|
||||
queriesPerPeriod: 1,
|
||||
interval: 300000,
|
||||
timeout: 10000
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const expected = {
|
||||
kBucketSize: 20,
|
||||
enabled: false,
|
||||
myNewDHTConfigProperty: true,
|
||||
randomWalk: {
|
||||
enabled: false,
|
||||
queriesPerPeriod: 1,
|
||||
interval: 300000,
|
||||
timeout: 10000
|
||||
}
|
||||
}
|
||||
|
||||
const actual = validateConfig(options).config.dht
|
||||
|
||||
expect(actual).to.deep.equal(expected)
|
||||
})
|
||||
})
|
||||
|
@@ -121,9 +121,8 @@ describe('.contentRouting', () => {
|
||||
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSnnnn')
|
||||
|
||||
nodeE.contentRouting.findProviders(cid, { maxTimeout: 5000 }, (err, providers) => {
|
||||
expect(err).to.exist()
|
||||
expect(err.code).to.eql('ERR_NOT_FOUND')
|
||||
expect(providers).to.not.exist()
|
||||
expect(err).to.not.exist()
|
||||
expect(providers).to.have.length(0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -151,7 +150,7 @@ describe('.contentRouting', () => {
|
||||
nodeA = new Node({
|
||||
peerInfo,
|
||||
modules: {
|
||||
contentRouting: [delegate]
|
||||
contentRouting: [ delegate ]
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
@@ -186,10 +185,19 @@ describe('.contentRouting', () => {
|
||||
it('should be able to register as a provider', (done) => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
// mock the swarm connect
|
||||
.post('/api/v0/swarm/connect')
|
||||
.query({
|
||||
arg: `/ip4/0.0.0.0/tcp/60194/p2p-circuit/ipfs/${nodeA.peerInfo.id.toB58String()}`,
|
||||
'stream-channels': true
|
||||
})
|
||||
.reply(200, {
|
||||
Strings: [`connect ${nodeA.peerInfo.id.toB58String()} success`]
|
||||
}, ['Content-Type', 'application/json'])
|
||||
// mock the refs call
|
||||
.post('/api/v0/refs')
|
||||
.query({
|
||||
recursive: false,
|
||||
recursive: true,
|
||||
arg: cid.toBaseEncodedString(),
|
||||
'stream-channels': true
|
||||
})
|
||||
@@ -208,11 +216,10 @@ describe('.contentRouting', () => {
|
||||
it('should handle errors when registering as a provider', (done) => {
|
||||
const cid = new CID('QmU621oD8AhHw6t25vVyfYKmL9VV3PTgc52FngEhTGACFB')
|
||||
const mockApi = nock('http://0.0.0.0:60197')
|
||||
// mock the refs call
|
||||
.post('/api/v0/refs')
|
||||
// mock the swarm connect
|
||||
.post('/api/v0/swarm/connect')
|
||||
.query({
|
||||
recursive: false,
|
||||
arg: cid.toBaseEncodedString(),
|
||||
arg: `/ip4/0.0.0.0/tcp/60194/p2p-circuit/ipfs/${nodeA.peerInfo.id.toB58String()}`,
|
||||
'stream-channels': true
|
||||
})
|
||||
.reply(502, 'Bad Gateway', ['Content-Type', 'application/json'])
|
||||
@@ -244,7 +251,7 @@ describe('.contentRouting', () => {
|
||||
timeout: '1000ms',
|
||||
'stream-channels': true
|
||||
})
|
||||
.reply(200, `{"Extra":"","ID":"QmWKqWXCtRXEeCQTo3FoZ7g4AfnGiauYYiczvNxFCHicbB","Responses":[{"Addrs":["/ip4/0.0.0.0/tcp/0"],"ID":"${provider}"}],"Type":4}\n`, [
|
||||
.reply(200, `{"Extra":"","ID":"QmWKqWXCtRXEeCQTo3FoZ7g4AfnGiauYYiczvNxFCHicbB","Responses":[{"Addrs":["/ip4/0.0.0.0/tcp/0"],"ID":"${provider}"}],"Type":1}\n`, [
|
||||
'Content-Type', 'application/json',
|
||||
'X-Chunked-Output', '1'
|
||||
])
|
||||
@@ -301,7 +308,7 @@ describe('.contentRouting', () => {
|
||||
nodeA = new Node({
|
||||
peerInfo,
|
||||
modules: {
|
||||
contentRouting: [delegate]
|
||||
contentRouting: [ delegate ]
|
||||
},
|
||||
config: {
|
||||
relay: {
|
||||
|
@@ -7,20 +7,13 @@ const expect = chai.expect
|
||||
const series = require('async/series')
|
||||
const createNode = require('./utils/create-node')
|
||||
const sinon = require('sinon')
|
||||
const { createLibp2p } = require('../src')
|
||||
const WS = require('libp2p-websockets')
|
||||
const PeerInfo = require('peer-info')
|
||||
|
||||
describe('libp2p creation', () => {
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('should be able to start and stop successfully', (done) => {
|
||||
createNode([], {
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: true
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
},
|
||||
dht: {
|
||||
enabled: true
|
||||
@@ -29,10 +22,10 @@ describe('libp2p creation', () => {
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
|
||||
const sw = node._switch
|
||||
const cm = node.connectionManager
|
||||
const dht = node._dht
|
||||
const pub = node.pubsub
|
||||
let sw = node._switch
|
||||
let cm = node.connectionManager
|
||||
let dht = node._dht
|
||||
let pub = node._floodSub
|
||||
|
||||
sinon.spy(sw, 'start')
|
||||
sinon.spy(cm, 'start')
|
||||
@@ -77,13 +70,13 @@ describe('libp2p creation', () => {
|
||||
it('should not create disabled modules', (done) => {
|
||||
createNode([], {
|
||||
config: {
|
||||
pubsub: {
|
||||
enabled: false
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
expect(node._pubsub).to.not.exist()
|
||||
expect(node._floodSub).to.not.exist()
|
||||
done()
|
||||
})
|
||||
})
|
||||
@@ -108,36 +101,4 @@ describe('libp2p creation', () => {
|
||||
node._switch.emit('error', error)
|
||||
})
|
||||
})
|
||||
|
||||
it('createLibp2p should create a peerInfo instance', function (done) {
|
||||
this.timeout(10e3)
|
||||
createLibp2p({
|
||||
modules: {
|
||||
transport: [WS]
|
||||
}
|
||||
}, (err, libp2p) => {
|
||||
expect(err).to.not.exist()
|
||||
expect(libp2p).to.exist()
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
it('createLibp2p should allow for a provided peerInfo instance', function (done) {
|
||||
this.timeout(10e3)
|
||||
PeerInfo.create((err, peerInfo) => {
|
||||
expect(err).to.not.exist()
|
||||
sinon.spy(PeerInfo, 'create')
|
||||
createLibp2p({
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS]
|
||||
}
|
||||
}, (err, libp2p) => {
|
||||
expect(err).to.not.exist()
|
||||
expect(libp2p).to.exist()
|
||||
expect(PeerInfo.create.callCount).to.eql(0)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -60,9 +60,9 @@ describe('libp2p state machine (fsm)', () => {
|
||||
node.once('stop', done)
|
||||
|
||||
// stop the stopped node
|
||||
node.stop(() => {})
|
||||
node.stop()
|
||||
})
|
||||
node.start(() => {})
|
||||
node.start()
|
||||
})
|
||||
|
||||
it('should callback with an error when it occurs on stop', (done) => {
|
||||
@@ -79,7 +79,7 @@ describe('libp2p state machine (fsm)', () => {
|
||||
expect(2).checks(done)
|
||||
|
||||
sinon.stub(node._switch, 'stop').callsArgWith(0, error)
|
||||
node.start(() => {})
|
||||
node.start()
|
||||
})
|
||||
|
||||
it('should noop when starting a started node', (done) => {
|
||||
@@ -89,17 +89,17 @@ describe('libp2p state machine (fsm)', () => {
|
||||
})
|
||||
node.once('start', () => {
|
||||
node.once('stop', done)
|
||||
node.stop(() => {})
|
||||
node.stop()
|
||||
})
|
||||
|
||||
// start the started node
|
||||
node.start(() => {})
|
||||
node.start()
|
||||
})
|
||||
node.start(() => {})
|
||||
node.start()
|
||||
})
|
||||
|
||||
it('should error on start with no transports', (done) => {
|
||||
const transports = node._modules.transport
|
||||
let transports = node._modules.transport
|
||||
node._modules.transport = null
|
||||
|
||||
node.on('stop', () => {
|
||||
@@ -115,7 +115,7 @@ describe('libp2p state machine (fsm)', () => {
|
||||
|
||||
expect(2).checks(done)
|
||||
|
||||
node.start(() => {})
|
||||
node.start()
|
||||
})
|
||||
|
||||
it('should not start if the switch fails to start', (done) => {
|
||||
@@ -150,7 +150,7 @@ describe('libp2p state machine (fsm)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
node.stop(() => {})
|
||||
node.stop()
|
||||
})
|
||||
|
||||
it('should not dial (fsm) when the node is stopped', (done) => {
|
||||
@@ -162,7 +162,7 @@ describe('libp2p state machine (fsm)', () => {
|
||||
})
|
||||
})
|
||||
|
||||
node.stop(() => {})
|
||||
node.stop()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -5,24 +5,36 @@ const chai = require('chai')
|
||||
chai.use(require('dirty-chai'))
|
||||
const expect = chai.expect
|
||||
const sinon = require('sinon')
|
||||
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
||||
const parallel = require('async/parallel')
|
||||
const crypto = require('crypto')
|
||||
|
||||
const PeerId = require('peer-id')
|
||||
const PeerInfo = require('peer-info')
|
||||
|
||||
const createNode = require('./utils/create-node')
|
||||
const echo = require('./utils/echo')
|
||||
const { WRTC_RENDEZVOUS_MULTIADDR } = require('./utils/constants')
|
||||
|
||||
describe('peer discovery', () => {
|
||||
let nodeA
|
||||
let nodeB
|
||||
let nodeC
|
||||
let port = 24642
|
||||
let ss
|
||||
|
||||
function setup (options) {
|
||||
before((done) => {
|
||||
port++
|
||||
parallel([
|
||||
(cb) => {
|
||||
signalling.start({ port: port }, (err, server) => {
|
||||
expect(err).to.not.exist()
|
||||
ss = server
|
||||
cb()
|
||||
})
|
||||
},
|
||||
(cb) => createNode([
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
`${WRTC_RENDEZVOUS_MULTIADDR.toString()}/p2p-webrtc-star`
|
||||
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
|
||||
], options, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
nodeA = node
|
||||
@@ -31,21 +43,12 @@ describe('peer discovery', () => {
|
||||
}),
|
||||
(cb) => createNode([
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
`${WRTC_RENDEZVOUS_MULTIADDR.toString()}/p2p-webrtc-star`
|
||||
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
|
||||
], options, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
nodeB = node
|
||||
node.handle('/echo/1.0.0', echo)
|
||||
node.start(cb)
|
||||
}),
|
||||
(cb) => createNode([
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
`${WRTC_RENDEZVOUS_MULTIADDR.toString()}/p2p-webrtc-star`
|
||||
], options, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
nodeC = node
|
||||
node.handle('/echo/1.0.0', echo)
|
||||
node.start(cb)
|
||||
})
|
||||
], done)
|
||||
})
|
||||
@@ -54,25 +57,20 @@ describe('peer discovery', () => {
|
||||
parallel([
|
||||
(cb) => nodeA.stop(cb),
|
||||
(cb) => nodeB.stop(cb),
|
||||
(cb) => nodeC.stop(cb)
|
||||
(cb) => ss.stop(cb)
|
||||
], done)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
}
|
||||
|
||||
describe('module registration', () => {
|
||||
it('should enable by default a module passed as an object', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0)
|
||||
}
|
||||
|
||||
const options = { modules: { peerDiscovery: [mockDiscovery] } }
|
||||
const options = { modules: { peerDiscovery: [ mockDiscovery ] } }
|
||||
|
||||
createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -88,14 +86,13 @@ describe('peer discovery', () => {
|
||||
it('should enable by default a module passed as a function', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0)
|
||||
}
|
||||
|
||||
const MockDiscovery = sinon.stub().returns(mockDiscovery)
|
||||
|
||||
const options = { modules: { peerDiscovery: [MockDiscovery] } }
|
||||
const options = { modules: { peerDiscovery: [ MockDiscovery ] } }
|
||||
|
||||
createNode(['/ip4/0.0.0.0/tcp/0'], options, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -111,7 +108,6 @@ describe('peer discovery', () => {
|
||||
it('should enable module by configutation', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0),
|
||||
tag: 'mockDiscovery'
|
||||
@@ -120,7 +116,7 @@ describe('peer discovery', () => {
|
||||
const enabled = sinon.stub().returns(true)
|
||||
|
||||
const options = {
|
||||
modules: { peerDiscovery: [mockDiscovery] },
|
||||
modules: { peerDiscovery: [ mockDiscovery ] },
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mockDiscovery: {
|
||||
@@ -147,7 +143,6 @@ describe('peer discovery', () => {
|
||||
it('should disable module by configutation', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0),
|
||||
tag: 'mockDiscovery'
|
||||
@@ -156,7 +151,7 @@ describe('peer discovery', () => {
|
||||
const disabled = sinon.stub().returns(false)
|
||||
|
||||
const options = {
|
||||
modules: { peerDiscovery: [mockDiscovery] },
|
||||
modules: { peerDiscovery: [ mockDiscovery ] },
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mockDiscovery: {
|
||||
@@ -183,7 +178,6 @@ describe('peer discovery', () => {
|
||||
it('should register module passed as function', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0)
|
||||
}
|
||||
@@ -192,7 +186,7 @@ describe('peer discovery', () => {
|
||||
MockDiscovery.tag = 'mockDiscovery'
|
||||
|
||||
const options = {
|
||||
modules: { peerDiscovery: [MockDiscovery] },
|
||||
modules: { peerDiscovery: [ MockDiscovery ] },
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mockDiscovery: {
|
||||
@@ -221,14 +215,13 @@ describe('peer discovery', () => {
|
||||
it('should register module passed as object', (done) => {
|
||||
const mockDiscovery = {
|
||||
on: sinon.stub(),
|
||||
removeListener: sinon.stub(),
|
||||
start: sinon.stub().callsArg(0),
|
||||
stop: sinon.stub().callsArg(0),
|
||||
tag: 'mockDiscovery'
|
||||
}
|
||||
|
||||
const options = {
|
||||
modules: { peerDiscovery: [mockDiscovery] },
|
||||
modules: { peerDiscovery: [ mockDiscovery ] },
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mockDiscovery: { enabled: true }
|
||||
@@ -248,33 +241,6 @@ describe('peer discovery', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('discovery scenarios', () => {
|
||||
setup({
|
||||
config: {
|
||||
dht: {
|
||||
enabled: false
|
||||
},
|
||||
peerDiscovery: {
|
||||
autoDial: false,
|
||||
bootstrap: {
|
||||
enabled: true,
|
||||
list: []
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('should ignore self on discovery', function () {
|
||||
const discoverySpy = sinon.spy()
|
||||
nodeA.on('peer:discovery', discoverySpy)
|
||||
nodeA._discovery[0].emit('peer', nodeA.peerInfo)
|
||||
|
||||
expect(discoverySpy.called).to.eql(false)
|
||||
expect(nodeA.peerBook.getAllArray()).to.have.length(0)
|
||||
expect()
|
||||
})
|
||||
})
|
||||
|
||||
describe('MulticastDNS', () => {
|
||||
setup({
|
||||
config: {
|
||||
@@ -282,10 +248,8 @@ describe('peer discovery', () => {
|
||||
enabled: false
|
||||
},
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
mdns: {
|
||||
enabled: true,
|
||||
interval: 200, // discover quickly
|
||||
// use a random tag to prevent CI collision
|
||||
serviceTag: crypto.randomBytes(10).toString('hex')
|
||||
}
|
||||
@@ -293,23 +257,13 @@ describe('peer discovery', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('find peers', function (done) {
|
||||
const expectedPeers = new Set([
|
||||
nodeB.peerInfo.id.toB58String(),
|
||||
nodeC.peerInfo.id.toB58String()
|
||||
])
|
||||
it('find a peer', function (done) {
|
||||
this.timeout(15 * 1000)
|
||||
|
||||
function finish () {
|
||||
nodeA.removeAllListeners('peer:discovery')
|
||||
expect(expectedPeers.size).to.eql(0)
|
||||
nodeA.once('peer:discovery', (peerInfo) => {
|
||||
expect(nodeB.peerInfo.id.toB58String())
|
||||
.to.eql(peerInfo.id.toB58String())
|
||||
done()
|
||||
}
|
||||
|
||||
nodeA.on('peer:discovery', (peerInfo) => {
|
||||
expectedPeers.delete(peerInfo.id.toB58String())
|
||||
if (expectedPeers.size === 0) {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -322,7 +276,6 @@ describe('peer discovery', () => {
|
||||
enabled: false
|
||||
},
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
webRTCStar: {
|
||||
enabled: true
|
||||
}
|
||||
@@ -330,24 +283,12 @@ describe('peer discovery', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('find peers', function (done) {
|
||||
this.timeout(20e3)
|
||||
const expectedPeers = new Set([
|
||||
nodeB.peerInfo.id.toB58String(),
|
||||
nodeC.peerInfo.id.toB58String()
|
||||
])
|
||||
|
||||
function finish () {
|
||||
nodeA.removeAllListeners('peer:discovery')
|
||||
expect(expectedPeers.size).to.eql(0)
|
||||
it('find a peer', function (done) {
|
||||
this.timeout(15 * 1000)
|
||||
nodeA.once('peer:discovery', (peerInfo) => {
|
||||
expect(nodeB.peerInfo.id.toB58String())
|
||||
.to.eql(peerInfo.id.toB58String())
|
||||
done()
|
||||
}
|
||||
|
||||
nodeA.on('peer:discovery', (peerInfo) => {
|
||||
expectedPeers.delete(peerInfo.id.toB58String())
|
||||
if (expectedPeers.size === 0) {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -359,10 +300,8 @@ describe('peer discovery', () => {
|
||||
enabled: false
|
||||
},
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
mdns: {
|
||||
enabled: true,
|
||||
interval: 200, // discovery quickly
|
||||
// use a random tag to prevent CI collision
|
||||
serviceTag: crypto.randomBytes(10).toString('hex')
|
||||
},
|
||||
@@ -373,23 +312,12 @@ describe('peer discovery', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('find peers', function (done) {
|
||||
const expectedPeers = new Set([
|
||||
nodeB.peerInfo.id.toB58String(),
|
||||
nodeC.peerInfo.id.toB58String()
|
||||
])
|
||||
|
||||
function finish () {
|
||||
nodeA.removeAllListeners('peer:discovery')
|
||||
expect(expectedPeers.size).to.eql(0)
|
||||
it('find a peer', function (done) {
|
||||
this.timeout(15 * 1000)
|
||||
nodeA.once('peer:discovery', (peerInfo) => {
|
||||
expect(nodeB.peerInfo.id.toB58String())
|
||||
.to.eql(peerInfo.id.toB58String())
|
||||
done()
|
||||
}
|
||||
|
||||
nodeA.on('peer:discovery', (peerInfo) => {
|
||||
expectedPeers.delete(peerInfo.id.toB58String())
|
||||
if (expectedPeers.size === 0) {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -398,97 +326,32 @@ describe('peer discovery', () => {
|
||||
setup({
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
mdns: {
|
||||
enabled: false
|
||||
},
|
||||
webRTCStar: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
dht: {
|
||||
enabled: true,
|
||||
kBucketSize: 20,
|
||||
randomWalk: {
|
||||
enabled: true,
|
||||
queriesPerPeriod: 1,
|
||||
delay: 100,
|
||||
interval: 200, // start the query sooner
|
||||
timeout: 3000
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('find peers through the dht', function (done) {
|
||||
const expectedPeers = new Set([
|
||||
nodeB.peerInfo.id.toB58String(),
|
||||
nodeC.peerInfo.id.toB58String()
|
||||
])
|
||||
it('find a peer', function (done) {
|
||||
this.timeout(15 * 1000)
|
||||
|
||||
function finish () {
|
||||
nodeA.removeAllListeners('peer:discovery')
|
||||
expect(expectedPeers.size).to.eql(0)
|
||||
nodeA.once('peer:discovery', (peerInfo) => {
|
||||
expect(nodeB.peerInfo.id.toB58String())
|
||||
.to.eql(peerInfo.id.toB58String())
|
||||
done()
|
||||
}
|
||||
|
||||
nodeA.on('peer:discovery', (peerInfo) => {
|
||||
expectedPeers.delete(peerInfo.id.toB58String())
|
||||
if (expectedPeers.size === 0) {
|
||||
finish()
|
||||
}
|
||||
})
|
||||
|
||||
// Topology:
|
||||
// A -> B
|
||||
// C -> B
|
||||
nodeA.dial(nodeB.peerInfo, (err) => {
|
||||
// connect two dhts
|
||||
const publicPeerId = new PeerId(nodeB._dht.peerInfo.id.id, null, nodeB._dht.peerInfo.id.pubKey)
|
||||
const target = new PeerInfo(publicPeerId)
|
||||
target.multiaddrs = nodeB._dht.peerInfo.multiaddrs
|
||||
nodeA._dht.switch.dial(target, (err) => {
|
||||
expect(err).to.not.exist()
|
||||
})
|
||||
nodeC.dial(nodeB.peerInfo, (err) => {
|
||||
expect(err).to.not.exist()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('auto dial', () => {
|
||||
setup({
|
||||
connectionManager: {
|
||||
minPeers: 1
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
mdns: {
|
||||
enabled: false
|
||||
},
|
||||
webRTCStar: {
|
||||
enabled: false
|
||||
},
|
||||
bootstrap: {
|
||||
enabled: true,
|
||||
list: []
|
||||
}
|
||||
},
|
||||
dht: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
it('should only dial when the peer count is below the low watermark', (done) => {
|
||||
const bootstrap = nodeA._discovery[0]
|
||||
sinon.stub(nodeA._switch.dialer, 'connect').callsFake((peerInfo) => {
|
||||
nodeA._switch.connection.connections[peerInfo.id.toB58String()] = []
|
||||
})
|
||||
|
||||
bootstrap.emit('peer', nodeB.peerInfo)
|
||||
bootstrap.emit('peer', nodeC.peerInfo)
|
||||
|
||||
// Only nodeB should get dialed
|
||||
expect(nodeA._switch.dialer.connect.callCount).to.eql(1)
|
||||
expect(nodeA._switch.dialer.connect.getCall(0).args[0]).to.eql(nodeB.peerInfo)
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -105,7 +105,7 @@ describe('.peerRouting', () => {
|
||||
})
|
||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
peerRouting: [delegate]
|
||||
peerRouting: [ delegate ]
|
||||
},
|
||||
config: {
|
||||
dht: {
|
||||
@@ -211,7 +211,7 @@ describe('.peerRouting', () => {
|
||||
})
|
||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
peerRouting: [delegate]
|
||||
peerRouting: [ delegate ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
|
@@ -24,7 +24,7 @@ describe('private network', () => {
|
||||
config = {
|
||||
peerInfo,
|
||||
modules: {
|
||||
transport: [WS],
|
||||
transport: [ WS ],
|
||||
dht: DHT
|
||||
}
|
||||
}
|
||||
@@ -50,14 +50,14 @@ describe('private network', () => {
|
||||
|
||||
it('should create a libp2p node with a provided protector', () => {
|
||||
let node
|
||||
const protector = {
|
||||
let protector = {
|
||||
psk: '123',
|
||||
tag: '/psk/1.0.0',
|
||||
protect: () => { }
|
||||
}
|
||||
|
||||
expect(() => {
|
||||
const options = defaultsDeep(config, {
|
||||
let options = defaultsDeep(config, {
|
||||
modules: {
|
||||
connProtector: protector
|
||||
}
|
||||
@@ -71,7 +71,7 @@ describe('private network', () => {
|
||||
|
||||
it('should throw an error if the protector does not have a protect method', () => {
|
||||
expect(() => {
|
||||
const options = defaultsDeep(config, {
|
||||
let options = defaultsDeep(config, {
|
||||
modules: {
|
||||
connProtector: { }
|
||||
}
|
||||
|
@@ -11,31 +11,23 @@ const parallel = require('async/parallel')
|
||||
const series = require('async/series')
|
||||
const _times = require('lodash.times')
|
||||
|
||||
const Floodsub = require('libp2p-floodsub')
|
||||
const mergeOptions = require('merge-options')
|
||||
|
||||
const { codes } = require('../src/errors')
|
||||
const createNode = require('./utils/create-node')
|
||||
|
||||
function startTwo (options, callback) {
|
||||
if (typeof options === 'function') {
|
||||
callback = options
|
||||
options = {}
|
||||
}
|
||||
|
||||
function startTwo (callback) {
|
||||
const tasks = _times(2, () => (cb) => {
|
||||
createNode('/ip4/0.0.0.0/tcp/0', mergeOptions({
|
||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mdns: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
pubsub: {
|
||||
enabled: true
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
}
|
||||
}
|
||||
}, options), (err, node) => {
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
node.start((err) => cb(err, node))
|
||||
})
|
||||
@@ -55,46 +47,17 @@ function stopTwo (nodes, callback) {
|
||||
], callback)
|
||||
}
|
||||
|
||||
// There is a vast test suite on PubSub through js-ipfs
|
||||
// https://github.com/ipfs/interface-ipfs-core/blob/master/js/src/pubsub.js
|
||||
// and libp2p-floodsub itself
|
||||
// https://github.com/libp2p/js-libp2p-floodsub/tree/master/test
|
||||
// TODO: consider if all or some of those should come here
|
||||
describe('.pubsub', () => {
|
||||
describe('.pubsub on (default)', () => {
|
||||
describe('.pubsub on (default)', (done) => {
|
||||
it('start two nodes and send one message, then unsubscribe', (done) => {
|
||||
// Check the final series error, and the publish handler
|
||||
expect(2).checks(done)
|
||||
|
||||
let nodes
|
||||
const data = 'test'
|
||||
const handler = (msg) => {
|
||||
// verify the data is correct and mark the expect
|
||||
expect(msg.data.toString()).to.eql(data).mark()
|
||||
}
|
||||
|
||||
series([
|
||||
// Start the nodes
|
||||
(cb) => startTwo((err, _nodes) => {
|
||||
nodes = _nodes
|
||||
cb(err)
|
||||
}),
|
||||
// subscribe on the first
|
||||
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, null, cb),
|
||||
// Wait a moment before publishing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// publish on the second
|
||||
(cb) => nodes[1].pubsub.publish('pubsub', data, cb),
|
||||
// Wait a moment before unsubscribing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// unsubscribe on the first
|
||||
(cb) => nodes[0].pubsub.unsubscribe('pubsub', handler, cb),
|
||||
// Stop both nodes
|
||||
(cb) => stopTwo(nodes, cb)
|
||||
], (err) => {
|
||||
// Verify there was no error, and mark the expect
|
||||
expect(err).to.not.exist().mark()
|
||||
})
|
||||
})
|
||||
it('start two nodes and send one message, then unsubscribe without handler', (done) => {
|
||||
// Check the final series error, and the publish handler
|
||||
expect(3).checks(done)
|
||||
|
||||
let nodes
|
||||
const data = Buffer.from('test')
|
||||
const handler = (msg) => {
|
||||
@@ -109,7 +72,7 @@ describe('.pubsub', () => {
|
||||
cb(err)
|
||||
}),
|
||||
// subscribe on the first
|
||||
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, {}, cb),
|
||||
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb),
|
||||
// Wait a moment before publishing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// publish on the second
|
||||
@@ -120,81 +83,6 @@ describe('.pubsub', () => {
|
||||
(cb) => nodes[1].pubsub.peers('pubsub', cb),
|
||||
// Wait a moment before unsubscribing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// unsubscribe from all
|
||||
(cb) => nodes[0].pubsub.unsubscribe('pubsub', null, cb),
|
||||
// Verify unsubscribed
|
||||
(cb) => {
|
||||
nodes[0].pubsub.ls((err, topics) => {
|
||||
expect(topics.length).to.eql(0).mark()
|
||||
cb(err)
|
||||
})
|
||||
},
|
||||
// Stop both nodes
|
||||
(cb) => stopTwo(nodes, cb)
|
||||
], (err) => {
|
||||
// Verify there was no error, and mark the expect
|
||||
expect(err).to.not.exist().mark()
|
||||
})
|
||||
})
|
||||
it('publish should fail if data is not a buffer nor a string', (done) => {
|
||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
mdns: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
pubsub: {
|
||||
enabled: true
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
|
||||
node.start((err) => {
|
||||
expect(err).to.not.exist()
|
||||
|
||||
node.pubsub.publish('pubsub', 10, (err) => {
|
||||
expect(err).to.exist()
|
||||
expect(err.code).to.equal('ERR_DATA_IS_NOT_VALID')
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.pubsub on using floodsub', () => {
|
||||
it('start two nodes and send one message, then unsubscribe', (done) => {
|
||||
// Check the final series error, and the publish handler
|
||||
expect(2).checks(done)
|
||||
|
||||
let nodes
|
||||
const data = Buffer.from('test')
|
||||
const handler = (msg) => {
|
||||
// verify the data is correct and mark the expect
|
||||
expect(msg.data).to.eql(data).mark()
|
||||
}
|
||||
|
||||
series([
|
||||
// Start the nodes
|
||||
(cb) => startTwo({
|
||||
modules: {
|
||||
pubsub: Floodsub
|
||||
}
|
||||
}, (err, _nodes) => {
|
||||
nodes = _nodes
|
||||
cb(err)
|
||||
}),
|
||||
// subscribe on the first
|
||||
(cb) => nodes[0].pubsub.subscribe('pubsub', handler, cb),
|
||||
// Wait a moment before publishing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// publish on the second
|
||||
(cb) => nodes[1].pubsub.publish('pubsub', data, cb),
|
||||
// Wait a moment before unsubscribing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// unsubscribe on the first
|
||||
(cb) => nodes[0].pubsub.unsubscribe('pubsub', handler, cb),
|
||||
// Stop both nodes
|
||||
@@ -217,11 +105,7 @@ describe('.pubsub', () => {
|
||||
|
||||
series([
|
||||
// Start the nodes
|
||||
(cb) => startTwo({
|
||||
modules: {
|
||||
pubsub: Floodsub
|
||||
}
|
||||
}, (err, _nodes) => {
|
||||
(cb) => startTwo((err, _nodes) => {
|
||||
nodes = _nodes
|
||||
cb(err)
|
||||
}),
|
||||
@@ -233,8 +117,12 @@ describe('.pubsub', () => {
|
||||
(cb) => nodes[1].pubsub.publish('pubsub', data, cb),
|
||||
// Wait a moment before unsubscribing
|
||||
(cb) => setTimeout(cb, 500),
|
||||
// unsubscribe from all
|
||||
(cb) => nodes[0].pubsub.unsubscribe('pubsub', null, cb),
|
||||
// unsubscribe on the first
|
||||
(cb) => {
|
||||
nodes[0].pubsub.unsubscribe('pubsub')
|
||||
// Wait a moment to make sure the ubsubscribe-from-all worked
|
||||
setTimeout(cb, 500)
|
||||
},
|
||||
// Verify unsubscribed
|
||||
(cb) => {
|
||||
nodes[0].pubsub.ls((err, topics) => {
|
||||
@@ -257,12 +145,9 @@ describe('.pubsub', () => {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
pubsub: {
|
||||
enabled: true
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
}
|
||||
},
|
||||
modules: {
|
||||
pubsub: Floodsub
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -270,9 +155,9 @@ describe('.pubsub', () => {
|
||||
node.start((err) => {
|
||||
expect(err).to.not.exist()
|
||||
|
||||
node.pubsub.publish('pubsub', 10, (err) => {
|
||||
node.pubsub.publish('pubsub', 'datastr', (err) => {
|
||||
expect(err).to.exist()
|
||||
expect(err.code).to.equal('ERR_DATA_IS_NOT_VALID')
|
||||
expect(err.code).to.equal('ERR_DATA_IS_NOT_A_BUFFER')
|
||||
|
||||
done()
|
||||
})
|
||||
@@ -289,6 +174,9 @@ describe('.pubsub', () => {
|
||||
mdns: {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
@@ -310,8 +198,8 @@ describe('.pubsub', () => {
|
||||
enabled: false
|
||||
}
|
||||
},
|
||||
pubsub: {
|
||||
enabled: true
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
|
@@ -36,7 +36,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY]
|
||||
streamMuxer: [ SPDY ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -46,7 +46,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY]
|
||||
streamMuxer: [ SPDY ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -72,7 +72,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -82,7 +82,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -108,7 +108,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [pMplex]
|
||||
streamMuxer: [ pMplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -118,7 +118,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [pMplex]
|
||||
streamMuxer: [ pMplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -146,7 +146,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -156,7 +156,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY, Mplex]
|
||||
streamMuxer: [ SPDY, Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -184,7 +184,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -194,7 +194,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [pMplex]
|
||||
streamMuxer: [ pMplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -222,7 +222,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY, Mplex]
|
||||
streamMuxer: [ SPDY, Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -232,7 +232,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex, SPDY]
|
||||
streamMuxer: [ Mplex, SPDY ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -260,7 +260,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY, pMplex]
|
||||
streamMuxer: [ SPDY, pMplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -270,7 +270,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [pMplex, SPDY]
|
||||
streamMuxer: [ pMplex, SPDY ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -298,7 +298,7 @@ describe('stream muxing', () => {
|
||||
parallel([
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [SPDY]
|
||||
streamMuxer: [ SPDY ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -308,7 +308,7 @@ describe('stream muxing', () => {
|
||||
}),
|
||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', {
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
}, (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
|
@@ -4,7 +4,6 @@
|
||||
|
||||
const chai = require('chai')
|
||||
chai.use(require('dirty-chai'))
|
||||
chai.use(require('chai-checkmark'))
|
||||
const expect = chai.expect
|
||||
const PeerInfo = require('peer-info')
|
||||
const PeerId = require('peer-id')
|
||||
@@ -55,7 +54,7 @@ describe('transports', () => {
|
||||
const b = new Node({
|
||||
peerInfo: peerInfo,
|
||||
modules: {
|
||||
streamMuxer: [Mplex]
|
||||
streamMuxer: [ Mplex ]
|
||||
}
|
||||
})
|
||||
expect(b._modules.streamMuxer).to.eql([require('pull-mplex')])
|
||||
@@ -414,19 +413,29 @@ describe('transports', () => {
|
||||
it('node1 hangUp node2', (done) => {
|
||||
node1.hangUp(peer2, (err) => {
|
||||
expect(err).to.not.exist()
|
||||
const peers = node1.peerBook.getAll()
|
||||
expect(Object.keys(peers)).to.have.length(1)
|
||||
expect(node1._switch.connection.getAll()).to.have.length(0)
|
||||
done()
|
||||
setTimeout(check, 500)
|
||||
|
||||
function check () {
|
||||
const peers = node1.peerBook.getAll()
|
||||
expect(Object.keys(peers)).to.have.length(1)
|
||||
expect(node1._switch.connection.getAll()).to.have.length(0)
|
||||
done()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('create a third node and check that discovery works', function (done) {
|
||||
this.timeout(10 * 1000)
|
||||
const expectedPeers = [
|
||||
node1.peerInfo.id.toB58String(),
|
||||
node2.peerInfo.id.toB58String()
|
||||
]
|
||||
|
||||
let counter = 0
|
||||
|
||||
function check () {
|
||||
if (++counter === 3) {
|
||||
expect(node1._switch.connection.getAll()).to.have.length(1)
|
||||
expect(node2._switch.connection.getAll()).to.have.length(1)
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
PeerId.create((err, id3) => {
|
||||
expect(err).to.not.exist()
|
||||
@@ -435,18 +444,13 @@ describe('transports', () => {
|
||||
const ma3 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/p2p/' + id3.toB58String()
|
||||
peer3.multiaddrs.add(ma3)
|
||||
|
||||
// 2 connects and 1 start
|
||||
expect(3).checks(done)
|
||||
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
|
||||
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
|
||||
|
||||
const node3 = new Node({
|
||||
peerInfo: peer3
|
||||
})
|
||||
node3.on('peer:connect', (peerInfo) => {
|
||||
expect(expectedPeers).to.include(peerInfo.id.toB58String()).mark()
|
||||
})
|
||||
node3.start((err) => {
|
||||
expect(err).to.not.exist().mark()
|
||||
})
|
||||
node3.start(check)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@@ -6,6 +6,7 @@ chai.use(require('dirty-chai'))
|
||||
const expect = chai.expect
|
||||
const parallel = require('async/parallel')
|
||||
const series = require('async/series')
|
||||
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
||||
const rendezvous = require('libp2p-websocket-star-rendezvous')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const WS = require('libp2p-websockets')
|
||||
@@ -17,8 +18,6 @@ const createNode = require('./utils/create-node.js')
|
||||
const tryEcho = require('./utils/try-echo')
|
||||
const echo = require('./utils/echo')
|
||||
|
||||
const { WRTC_RENDEZVOUS_MULTIADDR } = require('./utils/constants')
|
||||
|
||||
describe('transports', () => {
|
||||
describe('TCP only', () => {
|
||||
let nodeA
|
||||
@@ -410,17 +409,24 @@ describe('transports', () => {
|
||||
let nodeWS
|
||||
let nodeWebRTCStar
|
||||
|
||||
let ss
|
||||
|
||||
before(function (done) {
|
||||
this.timeout(5 * 1000)
|
||||
|
||||
parallel([
|
||||
(cb) => signalling.start({ port: 24642 }, (err, server) => {
|
||||
expect(err).to.not.exist()
|
||||
ss = server
|
||||
cb()
|
||||
}),
|
||||
(cb) => {
|
||||
const wstar = new WRTCStar({ wrtc: wrtc })
|
||||
|
||||
createNode([
|
||||
'/ip4/0.0.0.0/tcp/0',
|
||||
'/ip4/127.0.0.1/tcp/25011/ws',
|
||||
`${WRTC_RENDEZVOUS_MULTIADDR.toString()}/p2p-webrtc-star`
|
||||
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
|
||||
], {
|
||||
modules: {
|
||||
transport: [
|
||||
@@ -432,7 +438,6 @@ describe('transports', () => {
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: false,
|
||||
[wstar.discovery.tag]: {
|
||||
enabled: true
|
||||
}
|
||||
@@ -447,13 +452,7 @@ describe('transports', () => {
|
||||
},
|
||||
(cb) => createNode([
|
||||
'/ip4/0.0.0.0/tcp/0'
|
||||
], {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: false
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
], (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
nodeTCP = node
|
||||
node.handle('/echo/1.0.0', echo)
|
||||
@@ -461,23 +460,18 @@ describe('transports', () => {
|
||||
}),
|
||||
(cb) => createNode([
|
||||
'/ip4/127.0.0.1/tcp/25022/ws'
|
||||
], {
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: false
|
||||
}
|
||||
}
|
||||
}, (err, node) => {
|
||||
], (err, node) => {
|
||||
expect(err).to.not.exist()
|
||||
nodeWS = node
|
||||
node.handle('/echo/1.0.0', echo)
|
||||
node.start(cb)
|
||||
}),
|
||||
|
||||
(cb) => {
|
||||
const wstar = new WRTCStar({ wrtc: wrtc })
|
||||
|
||||
createNode([
|
||||
`${WRTC_RENDEZVOUS_MULTIADDR.toString()}/p2p-webrtc-star`
|
||||
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
|
||||
], {
|
||||
modules: {
|
||||
transport: [wstar],
|
||||
@@ -485,7 +479,6 @@ describe('transports', () => {
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: false,
|
||||
[wstar.discovery.tag]: {
|
||||
enabled: true
|
||||
}
|
||||
@@ -508,7 +501,8 @@ describe('transports', () => {
|
||||
(cb) => nodeAll.stop(cb),
|
||||
(cb) => nodeTCP.stop(cb),
|
||||
(cb) => nodeWS.stop(cb),
|
||||
(cb) => nodeWebRTCStar.stop(cb)
|
||||
(cb) => nodeWebRTCStar.stop(cb),
|
||||
(cb) => ss.stop(cb)
|
||||
], done)
|
||||
})
|
||||
|
||||
|
@@ -8,7 +8,6 @@ const SPDY = require('libp2p-spdy')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
const PULLMPLEX = require('pull-mplex')
|
||||
const KadDHT = require('libp2p-kad-dht')
|
||||
const GossipSub = require('libp2p-gossipsub')
|
||||
const SECIO = require('libp2p-secio')
|
||||
const defaultsDeep = require('@nodeutils/defaults-deep')
|
||||
const libp2p = require('../..')
|
||||
@@ -58,12 +57,10 @@ class Node extends libp2p {
|
||||
wsStar.discovery,
|
||||
Bootstrap
|
||||
],
|
||||
dht: KadDHT,
|
||||
pubsub: GossipSub
|
||||
dht: KadDHT
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
webRTCStar: {
|
||||
enabled: true
|
||||
},
|
||||
@@ -90,8 +87,8 @@ class Node extends libp2p {
|
||||
},
|
||||
enabled: false
|
||||
},
|
||||
pubsub: {
|
||||
enabled: false
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,7 +6,6 @@ const WS = require('libp2p-websockets')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
const SPDY = require('libp2p-spdy')
|
||||
const KadDHT = require('libp2p-kad-dht')
|
||||
const GossipSub = require('libp2p-gossipsub')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
const PULLMPLEX = require('pull-mplex')
|
||||
const SECIO = require('libp2p-secio')
|
||||
@@ -53,12 +52,10 @@ class Node extends libp2p {
|
||||
MulticastDNS,
|
||||
Bootstrap
|
||||
],
|
||||
dht: KadDHT,
|
||||
pubsub: GossipSub
|
||||
dht: KadDHT
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
autoDial: true,
|
||||
mdns: {
|
||||
interval: 10000,
|
||||
enabled: false
|
||||
@@ -83,8 +80,8 @@ class Node extends libp2p {
|
||||
},
|
||||
enabled: true
|
||||
},
|
||||
pubsub: {
|
||||
enabled: false
|
||||
EXPERIMENTAL: {
|
||||
pubsub: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user