mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-08 13:21:34 +00:00
Compare commits
50 Commits
Author | SHA1 | Date | |
---|---|---|---|
8563395d32 | |||
ef3cae5b5a | |||
f602cd9f79 | |||
ec956c1d42 | |||
c906f698e4 | |||
95f029eb7a | |||
38a68a01b7 | |||
c08aa517a0 | |||
8eac0f806e | |||
9fd092fddf | |||
87ddc25bee | |||
efb2b67f19 | |||
7c0b4daf49 | |||
aeb3ae1301 | |||
97df76f9c5 | |||
3ad696445d | |||
30bec8d53b | |||
db2b5300b4 | |||
df4d60df88 | |||
29cc0afc64 | |||
2504cbeb26 | |||
468cc421fa | |||
0b991e19d1 | |||
2a81fc75a8 | |||
e04c249d4d | |||
4a995613ae | |||
066c4976bb | |||
429cf9c361 | |||
01c20f8ab9 | |||
c8adce3906 | |||
6e3c5427de | |||
3e140d2c47 | |||
f0858c20bd | |||
ef9c2a6296 | |||
090d75d383 | |||
04a4ffcc36 | |||
7f7278fe82 | |||
2c03222136 | |||
65857838f9 | |||
cad173e3bd | |||
19ce266f1b | |||
a2a85eb8d6 | |||
b674bccfc2 | |||
4ae8e43b8b | |||
6b059a0ba8 | |||
363259f832 | |||
56dbd9e7c2 | |||
314b45897f | |||
0a6f1faf82 | |||
5a638794c5 |
71
.aegir.js
Normal file
71
.aegir.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const PeerId = require('peer-id')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
|
||||||
|
const rawPeer = require('./test/fixtures/test-peer.json')
|
||||||
|
const Node = require('./test/utils/bundle.node.js')
|
||||||
|
const sigServer = require('libp2p-webrtc-star/src/sig-server')
|
||||||
|
const WebSocketStarRendezvous = require('libp2p-websocket-star-rendezvous')
|
||||||
|
|
||||||
|
let wrtcRendezvous
|
||||||
|
let wsRendezvous
|
||||||
|
let node
|
||||||
|
|
||||||
|
const before = (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
sigServer.start({
|
||||||
|
port: 15555
|
||||||
|
// cryptoChallenge: true TODO: needs https://github.com/libp2p/js-libp2p-webrtc-star/issues/128
|
||||||
|
}, (err, server) => {
|
||||||
|
if (err) { return cb(err) }
|
||||||
|
wrtcRendezvous = server
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
WebSocketStarRendezvous.start({
|
||||||
|
port: 14444,
|
||||||
|
refreshPeerListIntervalMS: 1000,
|
||||||
|
strictMultiaddr: false,
|
||||||
|
cryptoChallenge: true
|
||||||
|
}, (err, _server) => {
|
||||||
|
if (err) { return cb(err) }
|
||||||
|
wsRendezvous = _server
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
PeerId.createFromJSON(rawPeer, (err, peerId) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
const peer = new PeerInfo(peerId)
|
||||||
|
|
||||||
|
peer.multiaddrs.add('/ip4/127.0.0.1/tcp/9200/ws')
|
||||||
|
|
||||||
|
node = new Node(peer)
|
||||||
|
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
|
||||||
|
const after = (done) => {
|
||||||
|
setTimeout(() => parallel(
|
||||||
|
[node, wrtcRendezvous, wsRendezvous].map((s) => {
|
||||||
|
return (cb) => s.stop(cb)
|
||||||
|
})
|
||||||
|
, done), 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
hooks: {
|
||||||
|
pre: before,
|
||||||
|
post: after
|
||||||
|
}
|
||||||
|
}
|
26
.gitignore
vendored
26
.gitignore
vendored
@ -1,7 +1,14 @@
|
|||||||
|
docs
|
||||||
|
**/node_modules/
|
||||||
|
**/*.log
|
||||||
|
test/repo-tests*
|
||||||
|
**/bundle.js
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
|
||||||
|
coverage
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
pids
|
pids
|
||||||
@ -20,16 +27,17 @@ coverage
|
|||||||
# node-waf configuration
|
# node-waf configuration
|
||||||
.lock-wscript
|
.lock-wscript
|
||||||
|
|
||||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
build
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directory
|
# Dependency directory
|
||||||
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
# Optional npm cache directory
|
lib
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional REPL history
|
|
||||||
.node_repl_history
|
|
||||||
|
|
||||||
dist
|
dist
|
||||||
|
test/test-data/go-ipfs-repo/LOCK
|
||||||
|
test/test-data/go-ipfs-repo/LOG
|
||||||
|
test/test-data/go-ipfs-repo/LOG.old
|
||||||
|
|
||||||
|
# while testing npm5
|
||||||
|
package-lock.json
|
||||||
|
14
.travis.yml
14
.travis.yml
@ -1,22 +1,20 @@
|
|||||||
sudo: false
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- node_js: 4
|
|
||||||
env: CXX=g++-4.8
|
|
||||||
- node_js: 6
|
- node_js: 6
|
||||||
env: CXX=g++-4.8
|
env: CXX=g++-4.8
|
||||||
- node_js: stable
|
- node_js: 8
|
||||||
env: CXX=g++-4.8
|
env: CXX=g++-4.8
|
||||||
|
# - node_js: stable
|
||||||
# Make sure we have new NPM.
|
# env: CXX=g++-4.8
|
||||||
before_install:
|
|
||||||
- npm install -g npm@4
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run lint
|
- npm run lint
|
||||||
- npm test
|
- npm run test
|
||||||
- npm run coverage
|
- npm run coverage
|
||||||
|
- make test
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
|
65
CHANGELOG.md
65
CHANGELOG.md
@ -1,3 +1,68 @@
|
|||||||
|
<a name="0.13.3"></a>
|
||||||
|
## [0.13.3](https://github.com/libp2p/js-libp2p/compare/v0.13.2...v0.13.3) (2017-12-01)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.13.2"></a>
|
||||||
|
## [0.13.2](https://github.com/libp2p/js-libp2p/compare/v0.13.1...v0.13.2) (2017-11-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* Bring libp2p-websocket-star to the Transports family! 🌟 ([#122](https://github.com/libp2p/js-libp2p/issues/122)) ([95f029e](https://github.com/libp2p/js-libp2p/commit/95f029e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.13.1"></a>
|
||||||
|
## [0.13.1](https://github.com/libp2p/js-libp2p/compare/v0.13.0...v0.13.1) (2017-11-12)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.13.0"></a>
|
||||||
|
# [0.13.0](https://github.com/libp2p/js-libp2p/compare/v0.12.4...v0.13.0) (2017-10-26)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* enable and test Circuit Relay ([29cc0af](https://github.com/libp2p/js-libp2p/commit/29cc0af))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.4"></a>
|
||||||
|
## [0.12.4](https://github.com/libp2p/js-libp2p/compare/v0.12.3...v0.12.4) (2017-09-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.3"></a>
|
||||||
|
## [0.12.3](https://github.com/libp2p/js-libp2p/compare/v0.12.2...v0.12.3) (2017-09-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.2"></a>
|
||||||
|
## [0.12.2](https://github.com/libp2p/js-libp2p/compare/v0.12.0...v0.12.2) (2017-09-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.1"></a>
|
||||||
|
## [0.12.1](https://github.com/libp2p/js-libp2p/compare/v0.12.0...v0.12.1) (2017-09-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.12.0"></a>
|
||||||
|
# [0.12.0](https://github.com/libp2p/js-libp2p/compare/v0.11.0...v0.12.0) (2017-09-03)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* p2p addrs situation ([#119](https://github.com/libp2p/js-libp2p/issues/119)) ([cad173e](https://github.com/libp2p/js-libp2p/commit/cad173e))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.11.0"></a>
|
||||||
|
# [0.11.0](https://github.com/libp2p/js-libp2p/compare/v0.10.2...v0.11.0) (2017-07-22)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.10.2"></a>
|
<a name="0.10.2"></a>
|
||||||
## [0.10.2](https://github.com/libp2p/js-libp2p/compare/v0.10.1...v0.10.2) (2017-07-21)
|
## [0.10.2](https://github.com/libp2p/js-libp2p/compare/v0.10.1...v0.10.2) (2017-07-21)
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Contributing guidelines
|
# Contributing guidelines
|
||||||
|
|
||||||
libp2p as a project, including js-libp2p and all of its modules, follows the [standard IPFS Community contributing guidelines](https://github.com/ipfs/community/blob/master/js-project-guidelines.md).
|
libp2p as a project, including js-libp2p and all of its modules, follows the [standard IPFS Community contributing guidelines](https://github.com/ipfs/community/blob/master/contribution-guidelines.md).
|
||||||
|
|
||||||
We also adhere to the [IPFS JavaScript Community contributing guidelines](https://github.com/ipfs/community/blob/master/js-project-guidelines.md) which provide additional information of how to collaborate and contribute in the JavaScript implementation of libp2p.
|
We also adhere to the [IPFS JavaScript Community contributing guidelines](https://github.com/ipfs/community/blob/master/js-project-guidelines.md) which provide additional information of how to collaborate and contribute in the JavaScript implementation of libp2p.
|
||||||
|
|
||||||
|
43
ISSUE_TEMPLATE.md
Normal file
43
ISSUE_TEMPLATE.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<!--
|
||||||
|
Thank you for reporting an issue.
|
||||||
|
|
||||||
|
This issue tracker is for bugs and issues found within the JavaScript implementation of libp2p.
|
||||||
|
If you require more general support please file an issue on our discuss forum. https://discuss.ipfs.io/
|
||||||
|
|
||||||
|
Please fill in as much of the template below as you're able.
|
||||||
|
|
||||||
|
Version: package.json version or the commit you have installed.
|
||||||
|
Platform: output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows). If using in a Browser, please share the browser version as well.
|
||||||
|
Subsystem: if known, please specify affected core module name (e.g Transports, SECIO, etc).
|
||||||
|
|
||||||
|
If possible, please provide code that demonstrates the problem, keeping it as
|
||||||
|
simple and free of external dependencies as you are able.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- **Version**:
|
||||||
|
- **Platform**:
|
||||||
|
- **Subsystem**:
|
||||||
|
|
||||||
|
<!-- Bug, Feature, Question, Enhancement, Etc -->
|
||||||
|
#### Type:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
One of following:
|
||||||
|
Critical - System crash, application panic.
|
||||||
|
High - The main functionality of the application does not work, API breakage, repo format breakage, etc.
|
||||||
|
Medium - A non-essential functionality does not work, performance issues, etc.
|
||||||
|
Low - An optional functionality does not work.
|
||||||
|
Very Low - Translation or documentation mistake. Something that won't give anyone a bad day.
|
||||||
|
-->
|
||||||
|
#### Severity:
|
||||||
|
|
||||||
|
#### Description:
|
||||||
|
|
||||||
|
#### Steps to reproduce the error:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This is for you! Please read, and then delete this text before posting it.
|
||||||
|
The js-ipfs issues are only for bug reports and directly actionable features.
|
||||||
|
|
||||||
|
Read https://github.com/ipfs/community/blob/master/contributing.md#reporting-issues if your issue doesn't fit either of those categories.
|
||||||
|
-->
|
54
README.md
54
README.md
@ -20,10 +20,18 @@
|
|||||||
<a href="https://github.com/feross/standard"><img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"></a>
|
<a href="https://github.com/feross/standard"><img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"></a>
|
||||||
<a href="https://github.com/RichardLitt/standard-readme"><img src="https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square" /></a>
|
<a href="https://github.com/RichardLitt/standard-readme"><img src="https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square" /></a>
|
||||||
<a href=""><img src="https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square" /></a>
|
<a href=""><img src="https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square" /></a>
|
||||||
<a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D4.0.0-orange.svg?style=flat-square" /></a>
|
<a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D6.0.0-orange.svg?style=flat-square" /></a>
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
### Project status
|
||||||
|
|
||||||
|
We've come a long way, but this project is still in Alpha, lots of development is happening, API might change, beware of the Dragons 🐉..
|
||||||
|
|
||||||
|
**Want to get started?** Check our [examples folder](/examples). You can check the development status at the [Waffle Board](https://waffle.io/libp2p/js-libp2p).
|
||||||
|
|
||||||
|
[](https://waffle.io/libp2p/js-libp2p/metrics/throughput)
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Background](#background)
|
- [Background](#background)
|
||||||
@ -42,7 +50,7 @@
|
|||||||
|
|
||||||
libp2p is the product of a long and arduous quest to understand the evolution of the Internet networking stack. In order to build P2P applications, dev have long had to made custom ad-hoc solutions to fit their needs, sometimes making some hard assumptions about their runtimes and the state of the network at the time of their development. Today, looking back more than 20 years, we see a clear pattern in the types of mechanisms built around the Internet Protocol, IP, which can be found throughout many layers of the OSI layer system, libp2p distils these mechanisms into flat categories and defines clear interfaces that once exposed, enable other protocols and applications to use and swap them, enabling upgradability and adaptability for the runtime, without breaking the API.
|
libp2p is the product of a long and arduous quest to understand the evolution of the Internet networking stack. In order to build P2P applications, dev have long had to made custom ad-hoc solutions to fit their needs, sometimes making some hard assumptions about their runtimes and the state of the network at the time of their development. Today, looking back more than 20 years, we see a clear pattern in the types of mechanisms built around the Internet Protocol, IP, which can be found throughout many layers of the OSI layer system, libp2p distils these mechanisms into flat categories and defines clear interfaces that once exposed, enable other protocols and applications to use and swap them, enabling upgradability and adaptability for the runtime, without breaking the API.
|
||||||
|
|
||||||
We are in the process of writting better documentation, blog posts, tutorials and a formal specification. Today you can find:
|
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)
|
- [libp2p.io](https://libp2p.io)
|
||||||
- [Specification (WIP)](https://github.com/libp2p/specs)
|
- [Specification (WIP)](https://github.com/libp2p/specs)
|
||||||
@ -74,7 +82,7 @@ npm install --save libp2p
|
|||||||
|
|
||||||
### [Tutorials and Examples](/examples)
|
### [Tutorials and Examples](/examples)
|
||||||
|
|
||||||
You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarions.
|
You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarios.
|
||||||
|
|
||||||
### Extending libp2p skeleton
|
### Extending libp2p skeleton
|
||||||
|
|
||||||
@ -191,7 +199,7 @@ class Node extends libp2p {
|
|||||||
- `handlerFunc`: Function with signature `function (protocol, conn) {}`
|
- `handlerFunc`: Function with signature `function (protocol, conn) {}`
|
||||||
- `matchFunc`: Function for matching on protocol (exact matching, semver, etc). Default to exact match.
|
- `matchFunc`: Function for matching on protocol (exact matching, semver, etc). Default to exact match.
|
||||||
|
|
||||||
#### `libp2p.unhandle(protocol)
|
#### `libp2p.unhandle(protocol)`
|
||||||
|
|
||||||
> Stop handling protocol
|
> Stop handling protocol
|
||||||
|
|
||||||
@ -255,6 +263,42 @@ class Node extends libp2p {
|
|||||||
[multiaddr]: https://github.com/multiformats/js-multiaddr
|
[multiaddr]: https://github.com/multiformats/js-multiaddr
|
||||||
[Connection]: https://github.com/libp2p/interface-connection
|
[Connection]: https://github.com/libp2p/interface-connection
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
**Clone and install dependencies:**
|
||||||
|
|
||||||
|
```sh
|
||||||
|
> git clone https://github.com/ipfs/js-ipfs.git
|
||||||
|
> cd js-ipfs
|
||||||
|
> npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
#### Run unit tests
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# run all the unit tsts
|
||||||
|
> npm test
|
||||||
|
|
||||||
|
# run just Node.js tests
|
||||||
|
> npm run test:node
|
||||||
|
|
||||||
|
# run just Browser tests (Chrome)
|
||||||
|
> npm run test:browser
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Run interop tests
|
||||||
|
|
||||||
|
```sh
|
||||||
|
N/A
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Run benchmark tests
|
||||||
|
|
||||||
|
```sh
|
||||||
|
N/A
|
||||||
|
```
|
||||||
|
|
||||||
### Packages
|
### Packages
|
||||||
|
|
||||||
@ -296,7 +340,7 @@ List of packages currently in existence for libp2p
|
|||||||
|
|
||||||
The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out:
|
The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out:
|
||||||
|
|
||||||
- Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrasture behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
|
- Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
|
||||||
- **Perform code reviews**. Most of this has been developed by @diasdavid, which means that more eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs.
|
- **Perform code reviews**. Most of this has been developed by @diasdavid, which means that more eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs.
|
||||||
- **Add tests**. There can never be enough tests.
|
- **Add tests**. There can never be enough tests.
|
||||||
|
|
||||||
|
@ -6,9 +6,13 @@ dependencies:
|
|||||||
pre:
|
pre:
|
||||||
- google-chrome --version
|
- google-chrome --version
|
||||||
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
|
||||||
|
- for v in $(curl http://archive.ubuntu.com/ubuntu/pool/main/n/nss/ | grep "href=" | grep "libnss3.*deb\"" -o | grep -o "libnss3.*deb" | grep "3.28" | grep "14.04"); do curl -L -o $v http://archive.ubuntu.com/ubuntu/pool/main/n/nss/$v; done && rm libnss3-tools*_i386.deb libnss3-dev*_i386.deb
|
||||||
- sudo dpkg -i google-chrome.deb || true
|
- sudo dpkg -i google-chrome.deb || true
|
||||||
|
- sudo dpkg -i libnss3*.deb || true
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
|
- sudo apt-get install -f || true
|
||||||
|
- sudo dpkg -i libnss3*.deb
|
||||||
- sudo apt-get install -f
|
- sudo apt-get install -f
|
||||||
- sudo apt-get install --only-upgrade lsb-base
|
- sudo apt-get install --only-upgrade lsb-base
|
||||||
- sudo dpkg -i google-chrome.deb
|
- sudo dpkg -i google-chrome.deb
|
||||||
- google-chrome --version
|
- google-chrome --version
|
@ -32,7 +32,7 @@ class MyBundle extends libp2p {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
And that's it, from now on, all your libp2p communications are encrypted. Try running the exampme [1.js](./1.js) to see it working.
|
And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working.
|
||||||
|
|
||||||
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).
|
||||||
|
|
||||||
|
@ -10,20 +10,20 @@
|
|||||||
},
|
},
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"browserify": "^14.0.0",
|
"browserify": "^14.5.0",
|
||||||
"concat-stream": "^1.6.0",
|
"concat-stream": "^1.6.0",
|
||||||
"detect-dom-ready": "^1.0.2",
|
"detect-dom-ready": "^1.0.2",
|
||||||
"node-static": "^0.7.9"
|
"node-static": "^0.7.10"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"detect-dom-ready": "^1.0.2",
|
"detect-dom-ready": "^1.0.2",
|
||||||
"libp2p": "^0.10.0",
|
"libp2p": "^0.13.0",
|
||||||
"libp2p-multiplex": "^0.4.4",
|
"libp2p-multiplex": "^0.5.0",
|
||||||
"libp2p-railing": "^0.5.2",
|
"libp2p-railing": "^0.7.1",
|
||||||
"libp2p-secio": "^0.6.8",
|
"libp2p-secio": "^0.8.1",
|
||||||
"libp2p-spdy": "^0.10.6",
|
"libp2p-spdy": "^0.11.0",
|
||||||
"libp2p-webrtc-star": "^0.11.0",
|
"libp2p-webrtc-star": "^0.13.2",
|
||||||
"libp2p-websockets": "^0.10.0",
|
"libp2p-websockets": "^0.10.4",
|
||||||
"peer-info": "^0.9.3"
|
"peer-info": "^0.11.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ const bootstrapers = [
|
|||||||
'/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
|
'/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
|
||||||
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
|
||||||
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
|
||||||
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64'
|
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
|
||||||
|
'/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
|
||||||
|
'/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
|
||||||
]
|
]
|
||||||
|
|
||||||
class Node extends libp2p {
|
class Node extends libp2p {
|
||||||
|
@ -10,7 +10,7 @@ function createNode (callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const peerIdStr = peerInfo.id.toB58String()
|
const peerIdStr = peerInfo.id.toB58String()
|
||||||
const ma = `/libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss/ipfs/${peerIdStr}`
|
const ma = `/dns4/star-signal.cloud.ipfs.team/wss/p2p-webrtc-star/ipfs/${peerIdStr}`
|
||||||
|
|
||||||
peerInfo.multiaddrs.add(ma)
|
peerInfo.multiaddrs.add(ma)
|
||||||
|
|
||||||
|
@ -12,3 +12,5 @@ Simple go into the folder [1](./1) and execute the following
|
|||||||
> npm start
|
> npm start
|
||||||
# open your browser in port :9090
|
# open your browser in port :9090
|
||||||
```
|
```
|
||||||
|
|
||||||
|
[Version Published on IPFS](http://ipfs.io/ipfs/Qmbc1J7ehw1dNYachbkCWPto4RsnVvqCKNVzmYEod2gXcy)
|
||||||
|
@ -53,7 +53,7 @@ parallel([
|
|||||||
(cb) => node1.dial(node2.peerInfo, cb),
|
(cb) => node1.dial(node2.peerInfo, cb),
|
||||||
(cb) => node2.dial(node3.peerInfo, cb),
|
(cb) => node2.dial(node3.peerInfo, cb),
|
||||||
// Set up of the cons might take time
|
// Set up of the cons might take time
|
||||||
(cb) => setTimeout(cb, 100)
|
(cb) => setTimeout(cb, 300)
|
||||||
], (err) => {
|
], (err) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ parallel([
|
|||||||
(cb) => node1.dial(node2.peerInfo, cb),
|
(cb) => node1.dial(node2.peerInfo, cb),
|
||||||
(cb) => node2.dial(node3.peerInfo, cb),
|
(cb) => node2.dial(node3.peerInfo, cb),
|
||||||
// Set up of the cons might take time
|
// Set up of the cons might take time
|
||||||
(cb) => setTimeout(cb, 100)
|
(cb) => setTimeout(cb, 300)
|
||||||
], (err) => {
|
], (err) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
|
@ -74,10 +74,10 @@ parallel([
|
|||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
console.log('Addresses by which both peers are connected')
|
console.log('Addresses by which both peers are connected')
|
||||||
node1.peerBook
|
node1.peerBook
|
||||||
.getAllArray()
|
.getAllArray()
|
||||||
.forEach((peer) => console.log('node 1 to node 2:', peer.isConnected().toString()))
|
.forEach((peer) => console.log('node 1 to node 2:', peer.isConnected().toString()))
|
||||||
node2.peerBook
|
node2.peerBook
|
||||||
.getAllArray()
|
.getAllArray()
|
||||||
.forEach((peer) => console.log('node 2 to node 1:', peer.isConnected().toString()))
|
.forEach((peer) => console.log('node 2 to node 1:', peer.isConnected().toString()))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -26,7 +26,7 @@ waterfall([
|
|||||||
], (err) => {
|
], (err) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
console.log('node has started (true/false):', node.isOn())
|
console.log('node has started (true/false):', node.isStarted())
|
||||||
console.log('listening on:')
|
console.log('listening on:')
|
||||||
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,7 @@ A more complete definition of what is a transport can be found on the [interface
|
|||||||
|
|
||||||
## 1. Creating a libp2p Bundle with TCP
|
## 1. Creating a libp2p Bundle with TCP
|
||||||
|
|
||||||
When using libp2p, you always want to create your own libp2p Bundle, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a bundle with TCP. You can find the complete solution on the file [1.js](/1.js).
|
When using libp2p, you always want to create your own libp2p Bundle, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a bundle with TCP. You can find the complete solution on the file [1.js](./1.js).
|
||||||
|
|
||||||
You will need 4 deps total, so go ahead and install all of them with:
|
You will need 4 deps total, so go ahead and install all of them with:
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ waterfall([
|
|||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
// At this point the node has started
|
// At this point the node has started
|
||||||
console.log('node has started (true/false):', node.isOn())
|
console.log('node has started (true/false):', node.isStarted())
|
||||||
// And we can print the now listening addresses.
|
// And we can print the now listening addresses.
|
||||||
// If you are familiar with TCP, you might have noticed
|
// If you are familiar with TCP, you might have noticed
|
||||||
// that we specified the node to listen in 0.0.0.0 and port
|
// that we specified the node to listen in 0.0.0.0 and port
|
||||||
@ -90,7 +90,7 @@ That `QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ` is the PeerId that was cre
|
|||||||
|
|
||||||
## 2. Dialing from one node to another node
|
## 2. Dialing from one node to another node
|
||||||
|
|
||||||
Now that we have our bundle, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](/2.js).
|
Now that we have our bundle, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](./2.js).
|
||||||
|
|
||||||
For this step, we will need one more dependency.
|
For this step, we will need one more dependency.
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ Hello p2p world!
|
|||||||
|
|
||||||
Next, we want to be available in multiple transports to increase our chances of having common transports in the network. A simple scenario, a node running in the browser only has access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport, for this node to dial to some other node, that other node needs to share a common transport.
|
Next, we want to be available in multiple transports to increase our chances of having common transports in the network. A simple scenario, a node running in the browser only has access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport, for this node to dial to some other node, that other node needs to share a common transport.
|
||||||
|
|
||||||
What we are going to do in this step is to create 3 nodes, one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](3.js).
|
What we are going to do in this step is to create 3 nodes, one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js).
|
||||||
|
|
||||||
In this example, we will need to also install `libp2p-websockets`, go ahead and install:
|
In this example, we will need to also install `libp2p-websockets`, go ahead and install:
|
||||||
|
|
||||||
|
55
gulpfile.js
55
gulpfile.js
@ -1,55 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const gulp = require('gulp')
|
|
||||||
const Node = require('./test/nodejs-bundle/nodejs-bundle.js')
|
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const PeerId = require('peer-id')
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
|
|
||||||
const sigServer = require('libp2p-webrtc-star/src/sig-server')
|
|
||||||
let server
|
|
||||||
|
|
||||||
let node
|
|
||||||
const rawPeer = require('./test/browser-bundle/peer.json')
|
|
||||||
|
|
||||||
gulp.task('libnode:start', (done) => {
|
|
||||||
let count = 0
|
|
||||||
const ready = () => ++count === 2 ? done() : null
|
|
||||||
|
|
||||||
sigServer.start({ port: 15555 }, (err, _server) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
server = _server
|
|
||||||
ready()
|
|
||||||
})
|
|
||||||
|
|
||||||
PeerId.createFromJSON(rawPeer, (err, peerId) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
const peer = new PeerInfo(peerId)
|
|
||||||
|
|
||||||
peer.multiaddrs.add('/ip4/127.0.0.1/tcp/9200/ws')
|
|
||||||
|
|
||||||
node = new Node(peer)
|
|
||||||
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
|
||||||
node.start(() => ready())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
gulp.task('libnode:stop', (done) => {
|
|
||||||
setTimeout(() => node.stop((err) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
server.stop(done)
|
|
||||||
}), 2000)
|
|
||||||
})
|
|
||||||
|
|
||||||
gulp.task('test:browser:before', ['libnode:start'])
|
|
||||||
gulp.task('test:node:before', ['libnode:start'])
|
|
||||||
gulp.task('test:browser:after', ['libnode:stop'])
|
|
||||||
gulp.task('test:node:after', ['libnode:stop'])
|
|
||||||
|
|
||||||
require('aegir/gulp')(gulp)
|
|
89
package.json
89
package.json
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p",
|
"name": "libp2p",
|
||||||
"version": "0.10.2",
|
"version": "0.13.3",
|
||||||
"description": "JavaScript base class for libp2p bundles",
|
"description": "JavaScript base class for libp2p bundles",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "gulp test",
|
"lint": "aegir lint",
|
||||||
"test:node": "gulp test:node",
|
"build": "aegir build",
|
||||||
"test:browser": "gulp test:browser --dom",
|
"test": "aegir test -t node -t browser",
|
||||||
"release": "gulp release --dom",
|
"test:node": "aegir test -t node",
|
||||||
"release-minor": "gulp release --type minor --dom",
|
"test:browser": "aegir test -t browser",
|
||||||
"release-major": "gulp release --type major --dom",
|
"release": "aegir release -t node -t browser",
|
||||||
"build": "gulp build",
|
"release-minor": "aegir release --type minor -t node -t browser",
|
||||||
"lint": "aegir-lint",
|
"release-major": "aegir release --type major -t node -t browser",
|
||||||
"coverage": "aegir-coverage",
|
"coverage": "aegir coverage",
|
||||||
"coverage-publish": "aegir-coverage publish"
|
"coverage-publish": "aegir coverage --provider coveralls"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -23,7 +23,7 @@
|
|||||||
"IPFS"
|
"IPFS"
|
||||||
],
|
],
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0.0",
|
"node": ">=6.0.0",
|
||||||
"npm": ">=3.0.0"
|
"npm": ">=3.0.0"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-commit": [
|
||||||
@ -37,45 +37,58 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/libp2p/js-libp2p",
|
"homepage": "https://github.com/libp2p/js-libp2p",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^2.5.0",
|
"async": "^2.6.0",
|
||||||
"libp2p-ping": "~0.4.0",
|
"libp2p-ping": "~0.6.0",
|
||||||
"libp2p-swarm": "~0.30.0",
|
"libp2p-swarm": "~0.33.2",
|
||||||
"mafmt": "^2.1.8",
|
"mafmt": "^3.0.2",
|
||||||
"multiaddr": "^2.3.0",
|
"multiaddr": "^3.0.1",
|
||||||
"peer-book": "~0.4.0",
|
"peer-book": "~0.5.2",
|
||||||
"peer-id": "~0.8.8",
|
"peer-id": "~0.10.3",
|
||||||
"peer-info": "~0.9.4"
|
"peer-info": "~0.11.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aegir": "^11.0.2",
|
"aegir": "^12.2.0",
|
||||||
"chai": "^4.1.0",
|
"chai": "^4.1.2",
|
||||||
|
"cids": "~0.5.2",
|
||||||
"dirty-chai": "^2.0.1",
|
"dirty-chai": "^2.0.1",
|
||||||
"cids": "~0.5.1",
|
"electron-webrtc": "~0.3.0",
|
||||||
"libp2p-kad-dht": "~0.3.0",
|
"libp2p-circuit": "~0.1.4",
|
||||||
"libp2p-mdns": "~0.7.1",
|
"libp2p-kad-dht": "~0.6.0",
|
||||||
"libp2p-multiplex": "~0.4.4",
|
"libp2p-mdns": "~0.9.1",
|
||||||
"libp2p-railing": "~0.5.2",
|
"libp2p-multiplex": "~0.5.0",
|
||||||
"libp2p-secio": "~0.6.8",
|
"libp2p-railing": "~0.7.1",
|
||||||
"libp2p-spdy": "~0.10.6",
|
"libp2p-secio": "~0.8.1",
|
||||||
"libp2p-tcp": "~0.10.1",
|
"libp2p-spdy": "~0.11.0",
|
||||||
"libp2p-webrtc-star": "~0.11.0",
|
"libp2p-tcp": "~0.11.1",
|
||||||
"libp2p-websockets": "~0.10.0",
|
"libp2p-webrtc-star": "~0.13.3",
|
||||||
|
"libp2p-websockets": "~0.10.4",
|
||||||
|
"libp2p-websocket-star": "~0.7.1",
|
||||||
|
"libp2p-websocket-star-rendezvous": "~0.2.1",
|
||||||
"lodash.times": "^4.3.2",
|
"lodash.times": "^4.3.2",
|
||||||
"pre-commit": "^1.2.2",
|
"pre-commit": "^1.2.2",
|
||||||
"pull-goodbye": "0.0.2",
|
"pull-goodbye": "0.0.2",
|
||||||
"pull-serializer": "^0.3.2",
|
"pull-serializer": "~0.3.2",
|
||||||
"pull-stream": "^3.6.0",
|
"pull-stream": "^3.6.1",
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"electron-webrtc": "^0.3.0",
|
"sinon": "^4.1.2",
|
||||||
"wrtc": "0.0.62"
|
"wrtc": "0.0.63"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Chris Bratlien <chrisbratlien@gmail.com>",
|
"Chris Bratlien <chrisbratlien@gmail.com>",
|
||||||
|
"Daijiro Wachi <daijiro.wachi@gmail.com>",
|
||||||
"David Dias <daviddias.p@gmail.com>",
|
"David Dias <daviddias.p@gmail.com>",
|
||||||
|
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||||
|
"Elven <mon.samuel@qq.com>",
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
|
"Lars Gierth <lgierth@users.noreply.github.com>",
|
||||||
|
"Maciej Krüger <mkg20001@gmail.com>",
|
||||||
|
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||||
"Pedro Teixeira <i@pgte.me>",
|
"Pedro Teixeira <i@pgte.me>",
|
||||||
|
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||||
"Richard Littauer <richard.littauer@gmail.com>",
|
"Richard Littauer <richard.littauer@gmail.com>",
|
||||||
|
"Ryan Bell <ryan@piing.net>",
|
||||||
"greenkeeperio-bot <support@greenkeeper.io>",
|
"greenkeeperio-bot <support@greenkeeper.io>",
|
||||||
"mayerwin <mayerwin@users.noreply.github.com>"
|
"mayerwin <mayerwin@users.noreply.github.com>",
|
||||||
|
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ const Swarm = require('libp2p-swarm')
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const PeerBook = require('peer-book')
|
const PeerBook = require('peer-book')
|
||||||
const mafmt = require('mafmt')
|
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
|
|
||||||
exports = module.exports
|
exports = module.exports
|
||||||
@ -43,6 +42,9 @@ class Node extends EventEmitter {
|
|||||||
// If muxer exists, we can use Identify
|
// If muxer exists, we can use Identify
|
||||||
this.swarm.connection.reuse()
|
this.swarm.connection.reuse()
|
||||||
|
|
||||||
|
// If muxer exists, we can use Relay for listening/dialing
|
||||||
|
this.swarm.connection.enableCircuitRelay(_options.relay)
|
||||||
|
|
||||||
// Received incommind dial and muxer upgrade happened,
|
// Received incommind dial and muxer upgrade happened,
|
||||||
// reuse this muxed connection
|
// reuse this muxed connection
|
||||||
this.swarm.on('peer-mux-established', (peerInfo) => {
|
this.swarm.on('peer-mux-established', (peerInfo) => {
|
||||||
@ -155,7 +157,7 @@ class Node extends EventEmitter {
|
|||||||
const maOld = []
|
const maOld = []
|
||||||
const maNew = []
|
const maNew = []
|
||||||
this.peerInfo.multiaddrs.forEach((ma) => {
|
this.peerInfo.multiaddrs.forEach((ma) => {
|
||||||
if (!mafmt.IPFS.matches(ma)) {
|
if (!ma.getPeerId()) {
|
||||||
maOld.push(ma)
|
maOld.push(ma)
|
||||||
maNew.push(ma.encapsulate('/ipfs/' + this.peerInfo.id.toB58String()))
|
maNew.push(ma.encapsulate('/ipfs/' + this.peerInfo.id.toB58String()))
|
||||||
}
|
}
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chai = require('chai')
|
|
||||||
chai.use(require('dirty-chai'))
|
|
||||||
const expect = chai.expect
|
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const PeerId = require('peer-id')
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
|
|
||||||
const Node = require('./browser-bundle')
|
|
||||||
|
|
||||||
describe('libp2p-ipfs-browser (webrtc only)', () => {
|
|
||||||
let peer1
|
|
||||||
let peer2
|
|
||||||
let node1
|
|
||||||
let node2
|
|
||||||
|
|
||||||
it('create two peerInfo with webrtc-star addrs', (done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => PeerId.create({ bits: 1024 }, cb),
|
|
||||||
(cb) => PeerId.create({ bits: 1024 }, cb)
|
|
||||||
], (err, ids) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
peer1 = new PeerInfo(ids[0])
|
|
||||||
const ma1 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[0].toB58String()
|
|
||||||
peer1.multiaddrs.add(ma1)
|
|
||||||
|
|
||||||
peer2 = new PeerInfo(ids[1])
|
|
||||||
const ma2 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[1].toB58String()
|
|
||||||
peer2.multiaddrs.add(ma2)
|
|
||||||
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('create two libp2p nodes with those peers', (done) => {
|
|
||||||
node1 = new Node(peer1, null, { webRTCStar: true })
|
|
||||||
node2 = new Node(peer2, null, { webRTCStar: true })
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('listen on the two libp2p nodes', (done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => node1.start(cb),
|
|
||||||
(cb) => node2.start(cb)
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('handle a protocol on the first node', () => {
|
|
||||||
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('dial from the second node to the first node', (done) => {
|
|
||||||
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const text = 'hello'
|
|
||||||
const peers1 = node1.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers1)).to.have.length(1)
|
|
||||||
|
|
||||||
const peers2 = node2.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers2)).to.have.length(1)
|
|
||||||
|
|
||||||
pull(
|
|
||||||
pull.values([Buffer(text)]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data[0].toString()).to.equal(text)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('node1 hangUp node2', (done) => {
|
|
||||||
node1.hangUp(peer2, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const peers = node1.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('create a third node and check that discovery works', (done) => {
|
|
||||||
let counter = 0
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
if (++counter === 3) {
|
|
||||||
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
|
|
||||||
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PeerId.create((err, id3) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
const peer3 = new PeerInfo(id3)
|
|
||||||
const ma3 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id3.toB58String()
|
|
||||||
peer3.multiaddrs.add(ma3)
|
|
||||||
|
|
||||||
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
|
|
||||||
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
|
|
||||||
|
|
||||||
const node3 = new Node(peer3, null, { webRTCStar: true })
|
|
||||||
node3.start(check)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,201 +0,0 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 8] */
|
|
||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chai = require('chai')
|
|
||||||
chai.use(require('dirty-chai'))
|
|
||||||
const expect = chai.expect
|
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const PeerId = require('peer-id')
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
const goodbye = require('pull-goodbye')
|
|
||||||
const serializer = require('pull-serializer')
|
|
||||||
const Buffer = require('safe-buffer').Buffer
|
|
||||||
|
|
||||||
const Node = require('./browser-bundle')
|
|
||||||
const rawPeer = require('./peer.json')
|
|
||||||
|
|
||||||
describe('libp2p-ipfs-browser (websockets only)', () => {
|
|
||||||
let peerB
|
|
||||||
let nodeA
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
const ma = '/ip4/127.0.0.1/tcp/9200/ws/ipfs/' + rawPeer.id
|
|
||||||
|
|
||||||
PeerId.createFromPrivKey(rawPeer.privKey, (err, id) => {
|
|
||||||
if (err) {
|
|
||||||
return done(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
peerB = new PeerInfo(id)
|
|
||||||
peerB.multiaddrs.add(ma)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
after((done) => nodeA.stop(done))
|
|
||||||
|
|
||||||
it('create libp2pNode', (done) => {
|
|
||||||
PeerInfo.create((err, peerInfo) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
|
||||||
|
|
||||||
nodeA = new Node(peerInfo)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('create libp2pNode with multiplex only', (done) => {
|
|
||||||
PeerInfo.create((err, peerInfo) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
const b = new Node(peerInfo, null, { muxer: ['multiplex'] })
|
|
||||||
expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('start libp2pNode', (done) => {
|
|
||||||
nodeA.start(done)
|
|
||||||
})
|
|
||||||
|
|
||||||
// General connectivity tests
|
|
||||||
|
|
||||||
it('libp2p.dial using Multiaddr nodeA to nodeB', (done) => {
|
|
||||||
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
setTimeout(check, 500) // Some time for Identify to finish
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('libp2p.dial using Multiaddr on Protocol nodeA to nodeB', (done) => {
|
|
||||||
nodeA.dial(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
pull(
|
|
||||||
pull.values([Buffer.from('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.eql([Buffer.from('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('libp2p.hangUp using Multiaddr nodeA to nodeB', (done) => {
|
|
||||||
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('libp2p.dial using PeerInfo nodeA to nodeB', (done) => {
|
|
||||||
nodeA.dial(peerB, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
setTimeout(check, 500) // Some time for Identify to finish
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('libp2p.dial using PeerInfo on Protocol nodeA to nodeB', (done) => {
|
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
pull(
|
|
||||||
pull.values([Buffer.from('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.eql([Buffer.from('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('libp2p.hangUp using PeerInfo nodeA to nodeB', (done) => {
|
|
||||||
nodeA.hangUp(peerB, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
|
||||||
done()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('stress', () => {
|
|
||||||
it('one big write', (done) => {
|
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
const rawMessage = Buffer.alloc(100000)
|
|
||||||
rawMessage.fill('a')
|
|
||||||
|
|
||||||
const s = serializer(goodbye({
|
|
||||||
source: pull.values([rawMessage]),
|
|
||||||
sink: pull.collect((err, results) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(results).to.have.length(1)
|
|
||||||
expect(Buffer.from(results[0])).to.have.length(rawMessage.length)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
pull(s, conn, s)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('many writes', (done) => {
|
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
const s = serializer(goodbye({
|
|
||||||
source: pull(
|
|
||||||
pull.infinite(),
|
|
||||||
pull.take(1000),
|
|
||||||
pull.map((val) => Buffer.from(val.toString()))
|
|
||||||
),
|
|
||||||
sink: pull.collect((err, result) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(result).to.have.length(1000)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
}))
|
|
||||||
|
|
||||||
pull(s, conn, s)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,7 +1,4 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const w = require('webrtcsupport')
|
|
||||||
|
|
||||||
require('./base')
|
require('./base')
|
||||||
require('./browser-bundle/websockets-only')
|
require('./transports.browser')
|
||||||
if (w.support) { require('./browser-bundle/webrtc-star-only') }
|
|
||||||
|
225
test/circuit-relay.node.js
Normal file
225
test/circuit-relay.node.js
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const series = require('async/series')
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
const utils = require('./utils/node')
|
||||||
|
const Circuit = require('libp2p-circuit')
|
||||||
|
const multiaddr = require('multiaddr')
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use(require('dirty-chai'))
|
||||||
|
|
||||||
|
const expect = chai.expect
|
||||||
|
const sinon = require('sinon')
|
||||||
|
|
||||||
|
describe('circuit relay', function () {
|
||||||
|
let handlerSpies = []
|
||||||
|
let relayNode1
|
||||||
|
let relayNode2
|
||||||
|
let nodeWS1
|
||||||
|
let nodeWS2
|
||||||
|
let nodeTCP1
|
||||||
|
let nodeTCP2
|
||||||
|
|
||||||
|
function setupNode (addrs, options, cb) {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
cb = options
|
||||||
|
options = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {}
|
||||||
|
|
||||||
|
return utils.createNode(addrs, options, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
node.handle('/echo/1.0.0', utils.echo)
|
||||||
|
node.start((err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
handlerSpies.push(sinon.spy(node.swarm.transports[Circuit.tag].listeners[0].hopHandler, 'handle'))
|
||||||
|
cb(node)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
before(function (done) {
|
||||||
|
this.timeout(20000)
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
// set up passive relay
|
||||||
|
(cb) => setupNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0/ws',
|
||||||
|
'/ip4/0.0.0.0/tcp/0'
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true,
|
||||||
|
hop: {
|
||||||
|
enabled: true,
|
||||||
|
active: false // passive relay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
relayNode1 = node
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
// setup active relay
|
||||||
|
(cb) => setupNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0/ws',
|
||||||
|
'/ip4/0.0.0.0/tcp/0'
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true,
|
||||||
|
hop: {
|
||||||
|
enabled: true,
|
||||||
|
active: false // passive relay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
relayNode2 = node
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
// setup node with WS
|
||||||
|
(cb) => setupNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0/ws'
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
nodeWS1 = node
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
// setup node with WS
|
||||||
|
(cb) => setupNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0/ws'
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
nodeWS2 = node
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
// set up node with TCP and listening on relay1
|
||||||
|
(cb) => setupNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0',
|
||||||
|
`/ipfs/${relayNode1.peerInfo.id.toB58String()}/p2p-circuit`
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
nodeTCP1 = node
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
// 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/ipfs/${relayNode2.peerInfo.id.toB58String()}/p2p-circuit`
|
||||||
|
], {
|
||||||
|
relay: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
}, (node) => {
|
||||||
|
nodeTCP2 = node
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
series([
|
||||||
|
(cb) => nodeWS1.dial(relayNode1.peerInfo, cb),
|
||||||
|
(cb) => nodeWS1.dial(relayNode2.peerInfo, cb),
|
||||||
|
(cb) => nodeTCP1.dial(relayNode1.peerInfo, cb),
|
||||||
|
(cb) => nodeTCP2.dial(relayNode2.peerInfo, cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => relayNode1.stop(cb),
|
||||||
|
(cb) => relayNode2.stop(cb),
|
||||||
|
(cb) => nodeWS1.stop(cb),
|
||||||
|
(cb) => nodeWS2.stop(cb),
|
||||||
|
(cb) => nodeTCP1.stop(cb),
|
||||||
|
(cb) => nodeTCP2.stop(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('any relay', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
|
||||||
|
it('should dial from WS1 to TCP1 over any R', (done) => {
|
||||||
|
nodeWS1.dial(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(conn).to.exist()
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values(['hello']),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, result) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(result[0].toString()).to.equal('hello')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should not dial - no R from WS2 to TCP1', (done) => {
|
||||||
|
nodeWS2.dial(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
expect(conn).to.not.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('explicit relay', function () {
|
||||||
|
this.timeout(20 * 1000)
|
||||||
|
|
||||||
|
it('should dial from WS1 to TCP1 over R1', (done) => {
|
||||||
|
nodeWS1.dial(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(conn).to.exist()
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values(['hello']),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, result) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(result[0].toString()).to.equal('hello')
|
||||||
|
|
||||||
|
const addr = multiaddr(handlerSpies[0].args[2][0].dstPeer.addrs[0]).toString()
|
||||||
|
expect(addr).to.equal(`/ipfs/${nodeTCP1.peerInfo.id.toB58String()}`)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should dial from WS1 to TCP2 over R2', (done) => {
|
||||||
|
nodeWS1.dial(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(conn).to.exist()
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values(['hello']),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, result) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(result[0].toString()).to.equal('hello')
|
||||||
|
|
||||||
|
const addr = multiaddr(handlerSpies[1].args[2][0].dstPeer.addrs[0]).toString()
|
||||||
|
expect(addr).to.equal(`/ipfs/${nodeTCP2.peerInfo.id.toB58String()}`)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -7,10 +7,10 @@ const chai = require('chai')
|
|||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const utils = require('./utils')
|
|
||||||
const createNode = utils.createNode
|
|
||||||
const _times = require('lodash.times')
|
const _times = require('lodash.times')
|
||||||
const CID = require('cids')
|
const CID = require('cids')
|
||||||
|
const utils = require('./utils/node')
|
||||||
|
const createNode = utils.createNode
|
||||||
|
|
||||||
describe('.contentRouting', () => {
|
describe('.contentRouting', () => {
|
||||||
let nodeA
|
let nodeA
|
||||||
@ -19,7 +19,8 @@ describe('.contentRouting', () => {
|
|||||||
let nodeD
|
let nodeD
|
||||||
let nodeE
|
let nodeE
|
||||||
|
|
||||||
before((done) => {
|
before(function (done) {
|
||||||
|
this.timeout(5 * 1000)
|
||||||
const tasks = _times(5, () => (cb) => {
|
const tasks = _times(5, () => (cb) => {
|
||||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||||
mdns: false,
|
mdns: false,
|
13
test/node.js
13
test/node.js
@ -1,10 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
require('./base')
|
require('./base')
|
||||||
require('./nodejs-bundle/tcp')
|
require('./transports.node')
|
||||||
require('./nodejs-bundle/tcp+websockets')
|
require('./stream-muxing.node')
|
||||||
require('./nodejs-bundle/tcp+websockets+webrtc-star')
|
require('./peer-discovery.node')
|
||||||
require('./nodejs-bundle/stream-muxing')
|
require('./peer-routing.node')
|
||||||
require('./nodejs-bundle/discovery')
|
require('./content-routing.node')
|
||||||
require('./nodejs-bundle/peer-routing')
|
require('./circuit-relay.node')
|
||||||
require('./nodejs-bundle/content-routing')
|
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
#! /usr/bin/env node
|
|
||||||
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const Node = require('./nodejs-bundle')
|
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const PeerId = require('peer-id')
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
|
|
||||||
const idBak = require('./test-data/test-id.json')
|
|
||||||
|
|
||||||
PeerId.createFromJSON(idBak, (err, peerId) => {
|
|
||||||
if (err) {
|
|
||||||
throw err
|
|
||||||
}
|
|
||||||
|
|
||||||
const peerInfo = new PeerInfo(peerId)
|
|
||||||
|
|
||||||
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/12345')
|
|
||||||
|
|
||||||
const node = new Node(peerInfo)
|
|
||||||
|
|
||||||
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
|
||||||
|
|
||||||
node.start((err) => {
|
|
||||||
if (err) { throw err }
|
|
||||||
|
|
||||||
console.log('Spawned node started, env:', process.env.LIBP2P_MUXER)
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,246 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chai = require('chai')
|
|
||||||
chai.use(require('dirty-chai'))
|
|
||||||
const expect = chai.expect
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
|
||||||
const WStar = require('libp2p-webrtc-star')
|
|
||||||
const wrtc = require('wrtc')
|
|
||||||
const utils = require('./utils')
|
|
||||||
const createNode = utils.createNode
|
|
||||||
const echo = utils.echo
|
|
||||||
|
|
||||||
describe('TCP + WebSockets + WebRTCStar', () => {
|
|
||||||
let nodeAll
|
|
||||||
let nodeTCP
|
|
||||||
let nodeWS
|
|
||||||
let nodeWStar
|
|
||||||
|
|
||||||
let ss
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
signalling.start({ port: 24642 }, (err, server) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
ss = server
|
|
||||||
cb()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const wstar = new WStar({wrtc: wrtc})
|
|
||||||
createNode([
|
|
||||||
'/ip4/0.0.0.0/tcp/0',
|
|
||||||
'/ip4/127.0.0.1/tcp/25011/ws',
|
|
||||||
'/libp2p-webrtc-star/ip4/127.0.0.1/tcp/24642/ws'
|
|
||||||
], {
|
|
||||||
modules: {
|
|
||||||
transport: [wstar],
|
|
||||||
discovery: [wstar.discovery]
|
|
||||||
}
|
|
||||||
}, (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeAll = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
(cb) => createNode([
|
|
||||||
'/ip4/0.0.0.0/tcp/0'
|
|
||||||
], (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeTCP = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
}),
|
|
||||||
(cb) => createNode([
|
|
||||||
'/ip4/127.0.0.1/tcp/25022/ws'
|
|
||||||
], (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeWS = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
}),
|
|
||||||
|
|
||||||
(cb) => {
|
|
||||||
const wstar = new WStar({wrtc: wrtc})
|
|
||||||
|
|
||||||
createNode([
|
|
||||||
'/libp2p-webrtc-star/ip4/127.0.0.1/tcp/24642/ws'
|
|
||||||
], {
|
|
||||||
modules: {
|
|
||||||
transport: [wstar],
|
|
||||||
discovery: [wstar.discovery]
|
|
||||||
}
|
|
||||||
}, (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeWStar = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
after((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => nodeAll.stop(cb),
|
|
||||||
(cb) => nodeTCP.stop(cb),
|
|
||||||
(cb) => nodeWS.stop(cb),
|
|
||||||
(cb) => nodeWStar.stop(cb),
|
|
||||||
(cb) => ss.stop(done)
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
|
|
||||||
nodeAll.dial(nodeTCP.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
|
|
||||||
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
|
|
||||||
nodeAll.dial(nodeWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
|
|
||||||
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.dial nodeWStar using PeerInfo', (done) => {
|
|
||||||
nodeAll.dial(nodeWStar.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(3)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWStar.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
|
|
||||||
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeAll.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(3)
|
|
||||||
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWStar.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeWStar.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,167 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chai = require('chai')
|
|
||||||
chai.use(require('dirty-chai'))
|
|
||||||
const expect = chai.expect
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
// const multiaddr = require('multiaddr')
|
|
||||||
// const pull = require('pull-stream')
|
|
||||||
const utils = require('./utils')
|
|
||||||
const createNode = utils.createNode
|
|
||||||
const echo = utils.echo
|
|
||||||
|
|
||||||
describe('TCP + WebSockets', () => {
|
|
||||||
let nodeTCP
|
|
||||||
let nodeTCPnWS
|
|
||||||
let nodeWS
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => createNode([
|
|
||||||
'/ip4/0.0.0.0/tcp/0'
|
|
||||||
], (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeTCP = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
}),
|
|
||||||
(cb) => createNode([
|
|
||||||
'/ip4/0.0.0.0/tcp/0',
|
|
||||||
'/ip4/127.0.0.1/tcp/25011/ws'
|
|
||||||
], (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeTCPnWS = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
}),
|
|
||||||
(cb) => createNode([
|
|
||||||
'/ip4/127.0.0.1/tcp/25022/ws'
|
|
||||||
], (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeWS = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
})
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
after((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => nodeTCP.stop(cb),
|
|
||||||
(cb) => nodeTCPnWS.stop(cb),
|
|
||||||
(cb) => nodeWS.stop(cb)
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeTCP.dial nodeTCPnWS using PeerInfo', (done) => {
|
|
||||||
nodeTCP.dial(nodeTCPnWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeTCP.hangUp nodeTCPnWS using PeerInfo', (done) => {
|
|
||||||
nodeTCP.hangUp(nodeTCPnWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
|
|
||||||
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeTCPnWS.dial nodeWS using PeerInfo', (done) => {
|
|
||||||
nodeTCPnWS.dial(nodeWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeTCPnWS.hangUp nodeWS using PeerInfo', (done) => {
|
|
||||||
nodeTCPnWS.hangUp(nodeWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
|
||||||
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeWS.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
|
|
||||||
// Everynode will be able to dial in WebSockets
|
|
||||||
it.skip('nodeTCP.dial nodeWS using PeerInfo is unsuccesful', (done) => {
|
|
||||||
nodeTCP.dial(nodeWS.peerInfo, (err) => {
|
|
||||||
expect(err).to.exist()
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -1,234 +0,0 @@
|
|||||||
/* eslint-env mocha */
|
|
||||||
'use strict'
|
|
||||||
|
|
||||||
const chai = require('chai')
|
|
||||||
chai.use(require('dirty-chai'))
|
|
||||||
const expect = chai.expect
|
|
||||||
const parallel = require('async/parallel')
|
|
||||||
const series = require('async/series')
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
const utils = require('./utils')
|
|
||||||
const createNode = utils.createNode
|
|
||||||
const echo = utils.echo
|
|
||||||
|
|
||||||
describe('TCP only', () => {
|
|
||||||
let nodeA
|
|
||||||
let nodeB
|
|
||||||
|
|
||||||
before((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeA = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
}),
|
|
||||||
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
nodeB = node
|
|
||||||
node.handle('/echo/1.0.0', echo)
|
|
||||||
node.start(cb)
|
|
||||||
})
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
after((done) => {
|
|
||||||
parallel([
|
|
||||||
(cb) => nodeA.stop(cb),
|
|
||||||
(cb) => nodeB.stop(cb)
|
|
||||||
], done)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.dial nodeB using PeerInfo without proto (warmup)', (done) => {
|
|
||||||
nodeA.dial(nodeB.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.dial nodeB using PeerInfo', (done) => {
|
|
||||||
nodeA.dial(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
|
|
||||||
pull(
|
|
||||||
pull.values([new Buffer('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.be.eql([new Buffer('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.hangUp nodeB using PeerInfo (first)', (done) => {
|
|
||||||
nodeA.hangUp(nodeB.peerInfo, (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.dial nodeB using multiaddr', (done) => {
|
|
||||||
nodeA.dial(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
series([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], () => {
|
|
||||||
pull(
|
|
||||||
pull.values([new Buffer('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.be.eql([new Buffer('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.hangUp nodeB using multiaddr (second)', (done) => {
|
|
||||||
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.dial nodeB using PeerId', (done) => {
|
|
||||||
nodeA.dial(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
|
|
||||||
// Some time for Identify to finish
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
series([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], () => {
|
|
||||||
pull(
|
|
||||||
pull.values([new Buffer('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.be.eql([new Buffer('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('nodeA.hangUp nodeB using PeerId (third)', (done) => {
|
|
||||||
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
setTimeout(check, 500)
|
|
||||||
|
|
||||||
function check () {
|
|
||||||
parallel([
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
},
|
|
||||||
(cb) => {
|
|
||||||
const peers = nodeB.peerBook.getAll()
|
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
|
||||||
|
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
|
||||||
cb()
|
|
||||||
}
|
|
||||||
], done)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
@ -6,11 +6,11 @@ chai.use(require('dirty-chai'))
|
|||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils/node')
|
||||||
const createNode = utils.createNode
|
const createNode = utils.createNode
|
||||||
const echo = utils.echo
|
const echo = utils.echo
|
||||||
|
|
||||||
describe('discovery', () => {
|
describe('peer discovery', () => {
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
let port = 24642
|
let port = 24642
|
||||||
@ -29,7 +29,7 @@ describe('discovery', () => {
|
|||||||
},
|
},
|
||||||
(cb) => createNode([
|
(cb) => createNode([
|
||||||
'/ip4/0.0.0.0/tcp/0',
|
'/ip4/0.0.0.0/tcp/0',
|
||||||
`/libp2p-webrtc-star/ip4/127.0.0.1/tcp/${port}/ws`
|
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
|
||||||
], options, (err, node) => {
|
], options, (err, node) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
nodeA = node
|
nodeA = node
|
||||||
@ -38,7 +38,7 @@ describe('discovery', () => {
|
|||||||
}),
|
}),
|
||||||
(cb) => createNode([
|
(cb) => createNode([
|
||||||
'/ip4/0.0.0.0/tcp/0',
|
'/ip4/0.0.0.0/tcp/0',
|
||||||
`/libp2p-webrtc-star/ip4/127.0.0.1/tcp/${port}/ws`
|
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
|
||||||
], options, (err, node) => {
|
], options, (err, node) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
nodeB = node
|
nodeB = node
|
||||||
@ -60,7 +60,9 @@ describe('discovery', () => {
|
|||||||
describe('MulticastDNS', () => {
|
describe('MulticastDNS', () => {
|
||||||
setup({ mdns: true })
|
setup({ mdns: true })
|
||||||
|
|
||||||
it('find a peer', (done) => {
|
it('find a peer', function (done) {
|
||||||
|
this.timeout(15 * 1000)
|
||||||
|
|
||||||
nodeA.once('peer:discovery', (peerInfo) => {
|
nodeA.once('peer:discovery', (peerInfo) => {
|
||||||
expect(nodeB.peerInfo.id.toB58String())
|
expect(nodeB.peerInfo.id.toB58String())
|
||||||
.to.eql(peerInfo.id.toB58String())
|
.to.eql(peerInfo.id.toB58String())
|
||||||
@ -73,7 +75,8 @@ describe('discovery', () => {
|
|||||||
describe.skip('WebRTCStar', () => {
|
describe.skip('WebRTCStar', () => {
|
||||||
setup({ webRTCStar: true })
|
setup({ webRTCStar: true })
|
||||||
|
|
||||||
it('find a peer', (done) => {
|
it('find a peer', function (done) {
|
||||||
|
this.timeout(15 * 1000)
|
||||||
nodeA.once('peer:discovery', (peerInfo) => {
|
nodeA.once('peer:discovery', (peerInfo) => {
|
||||||
expect(nodeB.peerInfo.id.toB58String())
|
expect(nodeB.peerInfo.id.toB58String())
|
||||||
.to.eql(peerInfo.id.toB58String())
|
.to.eql(peerInfo.id.toB58String())
|
||||||
@ -88,7 +91,8 @@ describe('discovery', () => {
|
|||||||
mdns: true
|
mdns: true
|
||||||
})
|
})
|
||||||
|
|
||||||
it('find a peer', (done) => {
|
it('find a peer', function (done) {
|
||||||
|
this.timeout(15 * 1000)
|
||||||
nodeA.once('peer:discovery', (peerInfo) => {
|
nodeA.once('peer:discovery', (peerInfo) => {
|
||||||
expect(nodeB.peerInfo.id.toB58String())
|
expect(nodeB.peerInfo.id.toB58String())
|
||||||
.to.eql(peerInfo.id.toB58String())
|
.to.eql(peerInfo.id.toB58String())
|
@ -7,9 +7,9 @@ const chai = require('chai')
|
|||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const utils = require('./utils')
|
|
||||||
const createNode = utils.createNode
|
|
||||||
const _times = require('lodash.times')
|
const _times = require('lodash.times')
|
||||||
|
const utils = require('./utils/node')
|
||||||
|
const createNode = utils.createNode
|
||||||
|
|
||||||
describe('.peerRouting', () => {
|
describe('.peerRouting', () => {
|
||||||
let nodeA
|
let nodeA
|
||||||
@ -18,7 +18,9 @@ describe('.peerRouting', () => {
|
|||||||
let nodeD
|
let nodeD
|
||||||
let nodeE
|
let nodeE
|
||||||
|
|
||||||
before((done) => {
|
before(function (done) {
|
||||||
|
this.timeout(5 * 1000)
|
||||||
|
|
||||||
const tasks = _times(5, () => (cb) => {
|
const tasks = _times(5, () => (cb) => {
|
||||||
createNode('/ip4/0.0.0.0/tcp/0', {
|
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||||
mdns: false,
|
mdns: false,
|
@ -7,7 +7,7 @@ const expect = chai.expect
|
|||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const series = require('async/series')
|
const series = require('async/series')
|
||||||
const pull = require('pull-stream')
|
const pull = require('pull-stream')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils/node')
|
||||||
const createNode = utils.createNode
|
const createNode = utils.createNode
|
||||||
const echo = utils.echo
|
const echo = utils.echo
|
||||||
|
|
||||||
@ -16,11 +16,11 @@ function test (nodeA, nodeB, callback) {
|
|||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
pull(
|
pull(
|
||||||
pull.values([new Buffer('hey')]),
|
pull.values([Buffer.from('hey')]),
|
||||||
conn,
|
conn,
|
||||||
pull.collect((err, data) => {
|
pull.collect((err, data) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(data).to.be.eql([new Buffer('hey')])
|
expect(data).to.be.eql([Buffer.from('hey')])
|
||||||
callback()
|
callback()
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
@ -34,8 +34,10 @@ function teardown (nodeA, nodeB, callback) {
|
|||||||
], callback)
|
], callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('stream muxing', (done) => {
|
describe('stream muxing', () => {
|
||||||
it('spdy only', (done) => {
|
it('spdy only', function (done) {
|
||||||
|
this.timeout(5 * 1000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
|
|
||||||
@ -99,7 +101,9 @@ describe('stream muxing', (done) => {
|
|||||||
], done)
|
], done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('spdy + multiplex', (done) => {
|
it('spdy + multiplex', function (done) {
|
||||||
|
this.timeout(5000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
|
|
||||||
@ -131,7 +135,9 @@ describe('stream muxing', (done) => {
|
|||||||
], done)
|
], done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('spdy + multiplex switched order', (done) => {
|
it('spdy + multiplex switched order', function (done) {
|
||||||
|
this.timeout(5000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
|
|
||||||
@ -163,7 +169,9 @@ describe('stream muxing', (done) => {
|
|||||||
], done)
|
], done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('one without the other fails to establish a muxedConn', (done) => {
|
it('one without the other fails to establish a muxedConn', function (done) {
|
||||||
|
this.timeout(5000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
|
|
424
test/transports.browser.js
Normal file
424
test/transports.browser.js
Normal file
@ -0,0 +1,424 @@
|
|||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use(require('dirty-chai'))
|
||||||
|
const expect = chai.expect
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const PeerId = require('peer-id')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
const goodbye = require('pull-goodbye')
|
||||||
|
const serializer = require('pull-serializer')
|
||||||
|
const w = require('webrtcsupport')
|
||||||
|
|
||||||
|
const Node = require('./utils/bundle.browser')
|
||||||
|
const rawPeer = require('./fixtures/test-peer.json')
|
||||||
|
|
||||||
|
describe('transports', () => {
|
||||||
|
describe('websockets', () => {
|
||||||
|
let peerB
|
||||||
|
let nodeA
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
const ma = '/ip4/127.0.0.1/tcp/9200/ws/ipfs/' + rawPeer.id
|
||||||
|
|
||||||
|
PeerId.createFromPrivKey(rawPeer.privKey, (err, id) => {
|
||||||
|
if (err) {
|
||||||
|
return done(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
peerB = new PeerInfo(id)
|
||||||
|
peerB.multiaddrs.add(ma)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => nodeA.stop(done))
|
||||||
|
|
||||||
|
it('create libp2pNode', (done) => {
|
||||||
|
PeerInfo.create((err, peerInfo) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
|
||||||
|
|
||||||
|
nodeA = new Node(peerInfo)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create libp2pNode with multiplex only', (done) => {
|
||||||
|
PeerInfo.create((err, peerInfo) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const b = new Node(peerInfo, null, { muxer: ['multiplex'] })
|
||||||
|
expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('start libp2pNode', (done) => {
|
||||||
|
nodeA.start(done)
|
||||||
|
})
|
||||||
|
|
||||||
|
// General connectivity tests
|
||||||
|
|
||||||
|
it('libp2p.dial using Multiaddr nodeA to nodeB', (done) => {
|
||||||
|
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
setTimeout(check, 500) // Some time for Identify to finish
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('libp2p.dial using Multiaddr on Protocol nodeA to nodeB', (done) => {
|
||||||
|
nodeA.dial(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from('hey')]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data).to.eql([Buffer.from('hey')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('libp2p.hangUp using Multiaddr nodeA to nodeB', (done) => {
|
||||||
|
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('libp2p.dial using PeerInfo nodeA to nodeB', (done) => {
|
||||||
|
nodeA.dial(peerB, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
setTimeout(check, 500) // Some time for Identify to finish
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('libp2p.dial using PeerInfo on Protocol nodeA to nodeB', (done) => {
|
||||||
|
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from('hey')]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data).to.eql([Buffer.from('hey')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('libp2p.hangUp using PeerInfo nodeA to nodeB', (done) => {
|
||||||
|
nodeA.hangUp(peerB, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('stress', () => {
|
||||||
|
it('one big write', (done) => {
|
||||||
|
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
const rawMessage = Buffer.alloc(100000)
|
||||||
|
rawMessage.fill('a')
|
||||||
|
|
||||||
|
const s = serializer(goodbye({
|
||||||
|
source: pull.values([rawMessage]),
|
||||||
|
sink: pull.collect((err, results) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(results).to.have.length(1)
|
||||||
|
expect(Buffer.from(results[0])).to.have.length(rawMessage.length)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
pull(s, conn, s)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('many writes', (done) => {
|
||||||
|
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const s = serializer(goodbye({
|
||||||
|
source: pull(
|
||||||
|
pull.infinite(),
|
||||||
|
pull.take(1000),
|
||||||
|
pull.map((val) => Buffer.from(val.toString()))
|
||||||
|
),
|
||||||
|
sink: pull.collect((err, result) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(result).to.have.length(1000)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
|
||||||
|
pull(s, conn, s)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('webrtc-star', () => {
|
||||||
|
if (!w.support) { return console.log('NO WEBRTC SUPPORT') }
|
||||||
|
|
||||||
|
let peer1
|
||||||
|
let peer2
|
||||||
|
let node1
|
||||||
|
let node2
|
||||||
|
|
||||||
|
it('create two peerInfo with webrtc-star addrs', (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => PeerId.create({ bits: 1024 }, cb),
|
||||||
|
(cb) => PeerId.create({ bits: 1024 }, cb)
|
||||||
|
], (err, ids) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
peer1 = new PeerInfo(ids[0])
|
||||||
|
const ma1 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + ids[0].toB58String()
|
||||||
|
peer1.multiaddrs.add(ma1)
|
||||||
|
|
||||||
|
peer2 = new PeerInfo(ids[1])
|
||||||
|
const ma2 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + ids[1].toB58String()
|
||||||
|
peer2.multiaddrs.add(ma2)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create two libp2p nodes with those peers', (done) => {
|
||||||
|
node1 = new Node(peer1, null, { webRTCStar: true })
|
||||||
|
node2 = new Node(peer2, null, { webRTCStar: true })
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('listen on the two libp2p nodes', (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => node1.start(cb),
|
||||||
|
(cb) => node2.start(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handle a protocol on the first node', () => {
|
||||||
|
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dial from the second node to the first node', (done) => {
|
||||||
|
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const text = 'hello'
|
||||||
|
const peers1 = node1.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers1)).to.have.length(1)
|
||||||
|
|
||||||
|
const peers2 = node2.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers2)).to.have.length(1)
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from(text)]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data[0].toString()).to.equal(text)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('node1 hangUp node2', (done) => {
|
||||||
|
node1.hangUp(peer2, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = node1.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create a third node and check that discovery works', (done) => {
|
||||||
|
let counter = 0
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
if (++counter === 3) {
|
||||||
|
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
|
||||||
|
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerId.create((err, id3) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const peer3 = new PeerInfo(id3)
|
||||||
|
const ma3 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + id3.toB58String()
|
||||||
|
peer3.multiaddrs.add(ma3)
|
||||||
|
|
||||||
|
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
|
||||||
|
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
|
||||||
|
|
||||||
|
const node3 = new Node(peer3, null, { webRTCStar: true })
|
||||||
|
node3.start(check)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('websocket-star', () => {
|
||||||
|
let peer1
|
||||||
|
let peer2
|
||||||
|
let node1
|
||||||
|
let node2
|
||||||
|
|
||||||
|
it('create two peerInfo with websocket-star addrs', (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => PeerId.create({ bits: 1024 }, cb),
|
||||||
|
(cb) => PeerId.create({ bits: 1024 }, cb)
|
||||||
|
], (err, ids) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
peer1 = new PeerInfo(ids[0])
|
||||||
|
const ma1 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/'
|
||||||
|
peer1.multiaddrs.add(ma1)
|
||||||
|
|
||||||
|
peer2 = new PeerInfo(ids[1])
|
||||||
|
const ma2 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/'
|
||||||
|
peer2.multiaddrs.add(ma2)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create two libp2p nodes with those peers', (done) => {
|
||||||
|
node1 = new Node(peer1, null, { wsStar: true })
|
||||||
|
node2 = new Node(peer2, null, { wsStar: true })
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('listen on the two libp2p nodes', (done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => node1.start(cb),
|
||||||
|
(cb) => node2.start(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('handle a protocol on the first node', () => {
|
||||||
|
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dial from the second node to the first node', (done) => {
|
||||||
|
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const text = 'hello'
|
||||||
|
const peers1 = node1.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers1)).to.have.length(1)
|
||||||
|
|
||||||
|
const peers2 = node2.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers2)).to.have.length(1)
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from(text)]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data[0].toString()).to.equal(text)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('node1 hangUp node2', (done) => {
|
||||||
|
node1.hangUp(peer2, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
const peers = node1.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('create a third node and check that discovery works', (done) => {
|
||||||
|
let counter = 0
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
if (++counter === 3) {
|
||||||
|
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
|
||||||
|
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PeerId.create((err, id3) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const peer3 = new PeerInfo(id3)
|
||||||
|
const ma3 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/ipfs/' + id3.toB58String()
|
||||||
|
peer3.multiaddrs.add(ma3)
|
||||||
|
|
||||||
|
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
|
||||||
|
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
|
||||||
|
|
||||||
|
const node3 = new Node(peer3, null, { wsStar: true })
|
||||||
|
node3.start(check)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
678
test/transports.node.js
Normal file
678
test/transports.node.js
Normal file
@ -0,0 +1,678 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use(require('dirty-chai'))
|
||||||
|
const expect = chai.expect
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
const series = require('async/series')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const utils = require('./utils/node.js')
|
||||||
|
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
||||||
|
const rendezvous = require('libp2p-websocket-star-rendezvous')
|
||||||
|
const WSStar = require('libp2p-websocket-star')
|
||||||
|
const WRTCStar = require('libp2p-webrtc-star')
|
||||||
|
const wrtc = require('wrtc')
|
||||||
|
|
||||||
|
const createNode = utils.createNode
|
||||||
|
const echo = utils.echo
|
||||||
|
|
||||||
|
describe('transports', () => {
|
||||||
|
describe('TCP only', () => {
|
||||||
|
let nodeA
|
||||||
|
let nodeB
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeA = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeB = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodeA.stop(cb),
|
||||||
|
(cb) => nodeB.stop(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.dial nodeB using PeerInfo without proto (warmup)', (done) => {
|
||||||
|
nodeA.dial(nodeB.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.dial nodeB using PeerInfo', (done) => {
|
||||||
|
nodeA.dial(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from('hey')]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data).to.be.eql([Buffer.from('hey')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.hangUp nodeB using PeerInfo (first)', (done) => {
|
||||||
|
nodeA.hangUp(nodeB.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.dial nodeB using multiaddr', (done) => {
|
||||||
|
nodeA.dial(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
series([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], () => {
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from('hey')]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data).to.be.eql([Buffer.from('hey')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.hangUp nodeB using multiaddr (second)', (done) => {
|
||||||
|
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
|
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.dial nodeB using PeerId', (done) => {
|
||||||
|
nodeA.dial(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
series([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], () => {
|
||||||
|
pull(
|
||||||
|
pull.values([Buffer.from('hey')]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, data) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(data).to.eql([Buffer.from('hey')])
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeA.hangUp nodeB using PeerId (third)', (done) => {
|
||||||
|
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeA.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeB.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('TCP + WebSockets', () => {
|
||||||
|
let nodeTCP
|
||||||
|
let nodeTCPnWS
|
||||||
|
let nodeWS
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeTCP = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0',
|
||||||
|
'/ip4/127.0.0.1/tcp/25011/ws'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeTCPnWS = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/127.0.0.1/tcp/25022/ws'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeWS = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodeTCP.stop(cb),
|
||||||
|
(cb) => nodeTCPnWS.stop(cb),
|
||||||
|
(cb) => nodeWS.stop(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeTCP.dial nodeTCPnWS using PeerInfo', (done) => {
|
||||||
|
nodeTCP.dial(nodeTCPnWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCP.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeTCP.hangUp nodeTCPnWS using PeerInfo', (done) => {
|
||||||
|
nodeTCP.hangUp(nodeTCPnWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCP.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
|
||||||
|
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeTCPnWS.dial nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeTCPnWS.dial(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(2)
|
||||||
|
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeTCPnWS.hangUp nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeTCPnWS.hangUp(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(check, 500)
|
||||||
|
|
||||||
|
function check () {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(2)
|
||||||
|
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
||||||
|
|
||||||
|
cb()
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const peers = nodeWS.peerBook.getAll()
|
||||||
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
|
||||||
|
// Everynode will be able to dial in WebSockets
|
||||||
|
it.skip('nodeTCP.dial nodeWS using PeerInfo is unsuccesful', (done) => {
|
||||||
|
nodeTCP.dial(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('TCP + WebSockets + WebRTCStar', () => {
|
||||||
|
let nodeAll
|
||||||
|
let nodeTCP
|
||||||
|
let nodeWS
|
||||||
|
let nodeWStar
|
||||||
|
|
||||||
|
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',
|
||||||
|
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
|
||||||
|
], {
|
||||||
|
modules: {
|
||||||
|
transport: [wstar],
|
||||||
|
discovery: [wstar.discovery]
|
||||||
|
}
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeAll = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeTCP = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/127.0.0.1/tcp/25022/ws'
|
||||||
|
], (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([
|
||||||
|
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
|
||||||
|
], {
|
||||||
|
modules: {
|
||||||
|
transport: [wstar],
|
||||||
|
discovery: [wstar.discovery]
|
||||||
|
}
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeWStar = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodeAll.stop(cb),
|
||||||
|
(cb) => nodeTCP.stop(cb),
|
||||||
|
(cb) => nodeWS.stop(cb),
|
||||||
|
(cb) => nodeWStar.stop(cb),
|
||||||
|
(cb) => ss.stop(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
function check (otherNode, muxed, peers, callback) {
|
||||||
|
let i = 1;
|
||||||
|
[nodeAll, otherNode].forEach((node) => {
|
||||||
|
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
||||||
|
expect(Object.keys(node.swarm.muxedConns)).to.have.length(muxed)
|
||||||
|
})
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
|
||||||
|
nodeAll.dial(nodeTCP.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeTCP, 1, 1, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeTCP, 0, 1, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeAll.dial(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWS, 1, 2, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWS, 0, 2, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeWStar using PeerInfo', function (done) {
|
||||||
|
this.timeout(10 * 1000)
|
||||||
|
|
||||||
|
nodeAll.dial(nodeWStar.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWStar, 1, 3, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(() => check(nodeWStar, 0, 3, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('TCP + WebSockets + WebSocketStar', () => {
|
||||||
|
let nodeAll
|
||||||
|
let nodeTCP
|
||||||
|
let nodeWS
|
||||||
|
let nodeWStar
|
||||||
|
|
||||||
|
let ss
|
||||||
|
|
||||||
|
before((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => {
|
||||||
|
rendezvous.start({ port: 24642 }, (err, server) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
ss = server
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
const wstar = new WSStar()
|
||||||
|
createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0',
|
||||||
|
'/ip4/127.0.0.1/tcp/25011/ws',
|
||||||
|
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star'
|
||||||
|
], {
|
||||||
|
modules: {
|
||||||
|
transport: [wstar],
|
||||||
|
discovery: [wstar.discovery]
|
||||||
|
}
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeAll = node
|
||||||
|
wstar.lazySetId(node.peerInfo.id)
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/0'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeTCP = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/127.0.0.1/tcp/25022/ws'
|
||||||
|
], (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeWS = node
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
}),
|
||||||
|
|
||||||
|
(cb) => {
|
||||||
|
const wstar = new WSStar({})
|
||||||
|
|
||||||
|
createNode([
|
||||||
|
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star'
|
||||||
|
], {
|
||||||
|
modules: {
|
||||||
|
transport: [wstar],
|
||||||
|
discovery: [wstar.discovery]
|
||||||
|
}
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
nodeWStar = node
|
||||||
|
wstar.lazySetId(node.peerInfo.id)
|
||||||
|
node.handle('/echo/1.0.0', echo)
|
||||||
|
node.start(cb)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
after((done) => {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodeAll.stop(cb),
|
||||||
|
(cb) => nodeTCP.stop(cb),
|
||||||
|
(cb) => nodeWS.stop(cb),
|
||||||
|
(cb) => nodeWStar.stop(cb),
|
||||||
|
(cb) => ss.stop(cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
|
||||||
|
function check (otherNode, muxed, peers, done) {
|
||||||
|
let i = 1;
|
||||||
|
[nodeAll, otherNode].forEach((node) => {
|
||||||
|
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
||||||
|
expect(Object.keys(node.swarm.muxedConns)).to.have.length(muxed)
|
||||||
|
})
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
|
||||||
|
nodeAll.dial(nodeTCP.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeTCP, 1, 1, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeTCP, 0, 1, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeAll.dial(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWS, 1, 2, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWS, 0, 2, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.dial nodeWStar using PeerInfo', (done) => {
|
||||||
|
nodeAll.dial(nodeWStar.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWStar, 1, 3, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
|
||||||
|
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
// Some time for Identify to finish
|
||||||
|
setTimeout(() => check(nodeWStar, 0, 3, done), 500)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -7,9 +7,8 @@ const expect = chai.expect
|
|||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const spawn = require('child_process').spawn
|
const spawn = require('child_process').spawn
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
// const map = require('async/map')
|
|
||||||
const pull = require('pull-stream')
|
const pull = require('pull-stream')
|
||||||
const utils = require('./utils')
|
const utils = require('./utils/node')
|
||||||
const createNode = utils.createNode
|
const createNode = utils.createNode
|
||||||
const echo = utils.echo
|
const echo = utils.echo
|
||||||
|
|
||||||
@ -57,11 +56,11 @@ describe('Turbolence tests', () => {
|
|||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
pull(
|
pull(
|
||||||
pull.values([new Buffer('hey')]),
|
pull.values([Buffer.from('hey')]),
|
||||||
conn,
|
conn,
|
||||||
pull.collect((err, data) => {
|
pull.collect((err, data) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(data).to.eql([new Buffer('hey')])
|
expect(data).to.eql([Buffer.from('hey')])
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
)
|
)
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
const WS = require('libp2p-websockets')
|
const WS = require('libp2p-websockets')
|
||||||
const WebRTCStar = require('libp2p-webrtc-star')
|
const WebRTCStar = require('libp2p-webrtc-star')
|
||||||
|
const WebSocketStar = require('libp2p-websocket-star')
|
||||||
const spdy = require('libp2p-spdy')
|
const spdy = require('libp2p-spdy')
|
||||||
const multiplex = require('libp2p-multiplex')
|
const multiplex = require('libp2p-multiplex')
|
||||||
const secio = require('libp2p-secio')
|
const secio = require('libp2p-secio')
|
||||||
@ -35,12 +36,14 @@ function getMuxers (options) {
|
|||||||
class Node extends libp2p {
|
class Node extends libp2p {
|
||||||
constructor (peerInfo, peerBook, options) {
|
constructor (peerInfo, peerBook, options) {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
const webRTCStar = new WebRTCStar()
|
const wrtcStar = new WebRTCStar({ id: peerInfo.id })
|
||||||
|
const wsStar = new WebSocketStar({ id: peerInfo.id })
|
||||||
|
|
||||||
const modules = {
|
const modules = {
|
||||||
transport: [
|
transport: [
|
||||||
new WS(),
|
new WS(),
|
||||||
webRTCStar
|
wrtcStar,
|
||||||
|
wsStar
|
||||||
],
|
],
|
||||||
connection: {
|
connection: {
|
||||||
muxer: getMuxers(options.muxer),
|
muxer: getMuxers(options.muxer),
|
||||||
@ -52,7 +55,11 @@ class Node extends libp2p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.webRTCStar) {
|
if (options.webRTCStar) {
|
||||||
modules.discovery.push(webRTCStar.discovery)
|
modules.discovery.push(wrtcStar.discovery)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.wsStar) {
|
||||||
|
modules.discovery.push(wsStar.discovery)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.bootstrap) {
|
if (options.bootstrap) {
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
const chai = require('chai')
|
const chai = require('chai')
|
||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
const Node = require('./nodejs-bundle')
|
const Node = require('./bundle.node')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const waterfall = require('async/waterfall')
|
const waterfall = require('async/waterfall')
|
||||||
@ -15,6 +15,8 @@ function createNode (multiaddrs, options, callback) {
|
|||||||
options = {}
|
options = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options = options || {}
|
||||||
|
|
||||||
if (!Array.isArray(multiaddrs)) {
|
if (!Array.isArray(multiaddrs)) {
|
||||||
multiaddrs = [multiaddrs]
|
multiaddrs = [multiaddrs]
|
||||||
}
|
}
|
Reference in New Issue
Block a user