mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-08 13:21:34 +00:00
Compare commits
67 Commits
Author | SHA1 | Date | |
---|---|---|---|
10a8ec3f31 | |||
41d202c4ba | |||
a5fd05875c | |||
379febb610 | |||
99873e877b | |||
4e01c094bc | |||
8fcafe2d90 | |||
947eaf166b | |||
1ebf725ac4 | |||
0c543b7180 | |||
beeb36c10c | |||
0acc7e5d72 | |||
9fd94b98a1 | |||
5c3037037a | |||
362217c8da | |||
7733ba5cd7 | |||
52bf826ec6 | |||
10619afbe6 | |||
3debabdd26 | |||
56e095983a | |||
ebdb696742 | |||
721e6ee9ce | |||
98f2903088 | |||
3dda282dfd | |||
03faf69212 | |||
0062a4b5eb | |||
f7f85dce0a | |||
59df82a675 | |||
6651401f0b | |||
cd43863db6 | |||
23e8293b75 | |||
68c170a40d | |||
bd8a35aaf9 | |||
248d86d050 | |||
8225b11082 | |||
1355af2b51 | |||
a85f041843 | |||
2c0cda2a7c | |||
b4ba267589 | |||
4c81f39ebe | |||
76922383ab | |||
3fc57ff397 | |||
13b36dcaa6 | |||
61bebd10fc | |||
97cde1ccb4 | |||
07b0cdc30e | |||
73b6d60e32 | |||
808f7495a9 | |||
ae21a6facf | |||
3aba3fd176 | |||
dc2da39a19 | |||
f8b441fff5 | |||
190ad54f9e | |||
582f8bed2e | |||
59de0da19c | |||
0caf600c9a | |||
a4943b4509 | |||
c128873a07 | |||
5e2b6df04a | |||
8d2d8c98a0 | |||
30bf5bb161 | |||
c88eaf416c | |||
c7f20383d9 | |||
a86a95c19f | |||
1b7360fcfa | |||
67ca37c356 | |||
0870068ebc |
23
.npmignore
23
.npmignore
@ -1,7 +1,16 @@
|
|||||||
|
**/node_modules/
|
||||||
|
**/*.log
|
||||||
|
test/repo-tests*
|
||||||
|
img
|
||||||
|
docs
|
||||||
|
examples
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
|
|
||||||
|
coverage
|
||||||
|
|
||||||
# Runtime data
|
# Runtime data
|
||||||
pids
|
pids
|
||||||
*.pid
|
*.pid
|
||||||
@ -16,13 +25,13 @@ coverage
|
|||||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
.grunt
|
.grunt
|
||||||
|
|
||||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
# node-waf configuration
|
||||||
build/Release
|
.lock-wscript
|
||||||
|
|
||||||
# Optional npm cache directory
|
build
|
||||||
.npm
|
|
||||||
|
|
||||||
# Optional REPL history
|
# Dependency directory
|
||||||
.node_repl_history
|
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
|
||||||
|
node_modules
|
||||||
|
|
||||||
test
|
test
|
||||||
|
13
.travis.yml
13
.travis.yml
@ -1,28 +1,19 @@
|
|||||||
|
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
sudo: false
|
sudo: false
|
||||||
language: node_js
|
language: node_js
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- node_js: 6
|
- node_js: 'stable'
|
||||||
env: CXX=g++-4.8
|
env: CXX=g++-4.8
|
||||||
- node_js: 8
|
|
||||||
env: CXX=g++-4.8
|
|
||||||
# - node_js: stable
|
|
||||||
# env: CXX=g++-4.8
|
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- npm run lint
|
|
||||||
- npm run test
|
- npm run test
|
||||||
- npm run coverage
|
|
||||||
- make test
|
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- export DISPLAY=:99.0
|
- export DISPLAY=:99.0
|
||||||
- sh -e /etc/init.d/xvfb start
|
- sh -e /etc/init.d/xvfb start
|
||||||
|
|
||||||
after_success:
|
|
||||||
- npm run coverage-publish
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
firefox: 'latest'
|
firefox: 'latest'
|
||||||
apt:
|
apt:
|
||||||
|
102
CHANGELOG.md
102
CHANGELOG.md
@ -1,3 +1,105 @@
|
|||||||
|
<a name="0.17.0"></a>
|
||||||
|
# [0.17.0](https://github.com/libp2p/js-libp2p/compare/v0.16.5...v0.17.0) (2018-02-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* use correct reference to floodSub ([947eaf1](https://github.com/libp2p/js-libp2p/commit/947eaf1))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add pubsub to libp2p ([0c543b7](https://github.com/libp2p/js-libp2p/commit/0c543b7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.5"></a>
|
||||||
|
## [0.16.5](https://github.com/libp2p/js-libp2p/compare/v0.16.4...v0.16.5) (2018-02-14)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.4"></a>
|
||||||
|
## [0.16.4](https://github.com/libp2p/js-libp2p/compare/v0.16.3...v0.16.4) (2018-02-09)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.3"></a>
|
||||||
|
## [0.16.3](https://github.com/libp2p/js-libp2p/compare/v0.16.2...v0.16.3) (2018-02-08)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.2"></a>
|
||||||
|
## [0.16.2](https://github.com/libp2p/js-libp2p/compare/v0.16.1...v0.16.2) (2018-02-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.1"></a>
|
||||||
|
## [0.16.1](https://github.com/libp2p/js-libp2p/compare/v0.16.0...v0.16.1) (2018-02-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.16.0"></a>
|
||||||
|
# [0.16.0](https://github.com/libp2p/js-libp2p/compare/v0.15.2...v0.16.0) (2018-02-07)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add explicit error for case peer id not included in multiaddr ([#155](https://github.com/libp2p/js-libp2p/issues/155)) ([bd8a35a](https://github.com/libp2p/js-libp2p/commit/bd8a35a))
|
||||||
|
* dialProtocol and small refactor ([6651401](https://github.com/libp2p/js-libp2p/commit/6651401))
|
||||||
|
* use libp2p-switch ([23e8293](https://github.com/libp2p/js-libp2p/commit/23e8293))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.15.2"></a>
|
||||||
|
## [0.15.2](https://github.com/libp2p/js-libp2p/compare/v0.15.1...v0.15.2) (2018-01-28)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.15.1"></a>
|
||||||
|
## [0.15.1](https://github.com/libp2p/js-libp2p/compare/v0.15.0...v0.15.1) (2018-01-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* typo in DHT setup ([#151](https://github.com/libp2p/js-libp2p/issues/151)) ([61bebd1](https://github.com/libp2p/js-libp2p/commit/61bebd1))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.15.0"></a>
|
||||||
|
# [0.15.0](https://github.com/libp2p/js-libp2p/compare/v0.14.3...v0.15.0) (2018-01-07)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.14.3"></a>
|
||||||
|
## [0.14.3](https://github.com/libp2p/js-libp2p/compare/v0.14.2...v0.14.3) (2017-12-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.14.2"></a>
|
||||||
|
## [0.14.2](https://github.com/libp2p/js-libp2p/compare/v0.14.1...v0.14.2) (2017-12-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.14.1"></a>
|
||||||
|
## [0.14.1](https://github.com/libp2p/js-libp2p/compare/v0.14.0...v0.14.1) (2017-12-15)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* prevent "The libp2p node is not started yet" when stopping ([#138](https://github.com/libp2p/js-libp2p/issues/138)) ([c88eaf4](https://github.com/libp2p/js-libp2p/commit/c88eaf4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.14.0"></a>
|
||||||
|
# [0.14.0](https://github.com/libp2p/js-libp2p/compare/v0.13.3...v0.14.0) (2017-12-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove innactive multiaddrs ([#131](https://github.com/libp2p/js-libp2p/issues/131)) ([1b7360f](https://github.com/libp2p/js-libp2p/commit/1b7360f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.13.3"></a>
|
<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)
|
## [0.13.3](https://github.com/libp2p/js-libp2p/compare/v0.13.2...v0.13.3) (2017-12-01)
|
||||||
|
|
||||||
|
32
README.md
32
README.md
@ -48,7 +48,7 @@ We've come a long way, but this project is still in Alpha, lots of development i
|
|||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
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, devs 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 writing 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:
|
||||||
|
|
||||||
@ -158,16 +158,26 @@ class Node extends libp2p {
|
|||||||
|
|
||||||
`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails.
|
`callback` is a function with the following `function (err) {}` signature, where `err` is an Error in case stopping the node fails.
|
||||||
|
|
||||||
#### `libp2p.dial(peer [, protocol, callback])`
|
#### `libp2p.dial(peer, callback)`
|
||||||
|
|
||||||
> Dials to another peer in the network.
|
> Dials to another peer in the network, establishes the connection.
|
||||||
|
|
||||||
- `peer`: can be an instance of [PeerInfo][], [PeerId][] or [multiaddr][]
|
- `peer`: can be an instance of [PeerInfo][], [PeerId][], [multiaddr][], or a multiaddr string
|
||||||
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
|
- `callback`: Function with signature `function (err, conn) {}` where `conn` is a [Connection](https://github.com/libp2p/interface-connection) object
|
||||||
|
|
||||||
`callback` is a function with the following `function (err, conn) {}` signature, where `err` is an Error in of failure to dial the connection and `conn` is a [Connection][] instance in case of a protocol selected, if not it is undefined.
|
`callback` is a function with the following `function (err, conn) {}` signature, where `err` is an Error in of failure to dial the connection and `conn` is a [Connection][] instance in case of a protocol selected, if not it is undefined.
|
||||||
|
|
||||||
#### `libp2p.hangUp(peer, callback)
|
#### `libp2p.dialProtocol(peer, protocol, callback)`
|
||||||
|
|
||||||
|
> Dials to another peer in the network and selects a protocol to talk with that peer.
|
||||||
|
|
||||||
|
- `peer`: can be an instance of [PeerInfo][], [PeerId][], [multiaddr][], or a multiaddr string
|
||||||
|
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
|
||||||
|
- `callback`: Function with signature `function (err, conn) {}` where `conn` is a [Connection](https://github.com/libp2p/interface-connection) object
|
||||||
|
|
||||||
|
`callback` is a function with the following `function (err, conn) {}` signature, where `err` is an Error in of failure to dial the connection and `conn` is a [Connection][] instance in case of a protocol selected, if not it is undefined.
|
||||||
|
|
||||||
|
#### `libp2p.hangUp(peer, callback)`
|
||||||
|
|
||||||
> Closes an open connection with a peer, graciously.
|
> Closes an open connection with a peer, graciously.
|
||||||
|
|
||||||
@ -196,7 +206,7 @@ class Node extends libp2p {
|
|||||||
> Handle new protocol
|
> Handle new protocol
|
||||||
|
|
||||||
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
|
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
|
||||||
- `handlerFunc`: Function with signature `function (protocol, conn) {}`
|
- `handlerFunc`: Function with signature `function (protocol, conn) {}` where `conn` is a [Connection](https://github.com/libp2p/interface-connection) object
|
||||||
- `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)`
|
||||||
@ -239,9 +249,13 @@ class Node extends libp2p {
|
|||||||
|
|
||||||
> PeerInfo instance of the node
|
> PeerInfo instance of the node
|
||||||
|
|
||||||
|
#### `libp2p.pubsub`
|
||||||
|
|
||||||
|
> Same API as IPFS PubSub, defined in the [CORE API Spec](https://github.com/ipfs/interface-ipfs-core/blob/master/SPEC/PUBSUB.md). Just replace `ipfs` by `libp2p` and you are golden.
|
||||||
|
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
`DHT methods exposed`
|
`DHT methods also exposed for the time being`
|
||||||
|
|
||||||
#### `libp2p.dht.put(key, value, callback)`
|
#### `libp2p.dht.put(key, value, callback)`
|
||||||
|
|
||||||
@ -310,6 +324,8 @@ List of packages currently in existence for libp2p
|
|||||||
| [`libp2p-utp`](//github.com/libp2p/js-libp2p-utp) | [](//github.com/libp2p/js-libp2p-utp/releases) | [](https://david-dm.org/libp2p/js-libp2p-utp) | [](https://david-dm.org/libp2p/js-libp2p-utp?type=dev) |
|
| [`libp2p-utp`](//github.com/libp2p/js-libp2p-utp) | [](//github.com/libp2p/js-libp2p-utp/releases) | [](https://david-dm.org/libp2p/js-libp2p-utp) | [](https://david-dm.org/libp2p/js-libp2p-utp?type=dev) |
|
||||||
| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [](//github.com/libp2p/js-libp2p-websockets/releases) | [](https://david-dm.org/libp2p/js-libp2p-websockets) | [](https://david-dm.org/libp2p/js-libp2p-websockets?type=dev) |
|
| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [](//github.com/libp2p/js-libp2p-websockets/releases) | [](https://david-dm.org/libp2p/js-libp2p-websockets) | [](https://david-dm.org/libp2p/js-libp2p-websockets?type=dev) |
|
||||||
| [`libp2p-webrtc-star`](//github.com/libp2p/js-libp2p-webrtc-star) | [](//github.com/libp2p/js-libp2p-webrtc-star/releases) | [](https://david-dm.org/libp2p/js-libp2p-webrtc-star) | [](https://david-dm.org/libp2p/js-libp2p-webrtc-star?type=dev) |
|
| [`libp2p-webrtc-star`](//github.com/libp2p/js-libp2p-webrtc-star) | [](//github.com/libp2p/js-libp2p-webrtc-star/releases) | [](https://david-dm.org/libp2p/js-libp2p-webrtc-star) | [](https://david-dm.org/libp2p/js-libp2p-webrtc-star?type=dev) |
|
||||||
|
| [`libp2p-websocket-star`](//github.com/libp2p/js-libp2p-websocket-star) | [](//github.com/libp2p/js-libp2p-websocket-star/releases) | [](https://david-dm.org/libp2p/js-libp2p-websocket-star) | [](https://david-dm.org/libp2p/js-libp2p-websocket-star?type=dev) |
|
||||||
|
| [`libp2p-websocket-star-rendezvous`](//github.com/libp2p/js-libp2p-websocket-star-rendezvous) | [](//github.com/libp2p/js-libp2p-websocket-star-rendezvous/releases) | [](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous) | [](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous?type=dev) |
|
||||||
| **Connection Upgrades** |
|
| **Connection Upgrades** |
|
||||||
| [`interface-connection`](//github.com/libp2p/interface-connection) | [](//github.com/libp2p/interface-connection/releases) | [](https://david-dm.org/libp2p/interface-connection) | [](https://david-dm.org/libp2p/interface-connection?type=dev) |
|
| [`interface-connection`](//github.com/libp2p/interface-connection) | [](//github.com/libp2p/interface-connection/releases) | [](https://david-dm.org/libp2p/interface-connection) | [](https://david-dm.org/libp2p/interface-connection?type=dev) |
|
||||||
| **Stream Muxers** |
|
| **Stream Muxers** |
|
||||||
|
29
appveyor.yml
Normal file
29
appveyor.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
|
version: "{build}"
|
||||||
|
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- nodejs_version: "6"
|
||||||
|
- nodejs_version: "8"
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
fast_finish: true
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Install Node.js
|
||||||
|
- ps: Install-Product node $env:nodejs_version
|
||||||
|
|
||||||
|
# Upgrade npm
|
||||||
|
- npm install -g npm
|
||||||
|
|
||||||
|
# Output our current versions for debugging
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
|
||||||
|
# Install our package dependencies
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- npm run test:node
|
||||||
|
|
||||||
|
build: off
|
2
ci/Jenkinsfile
vendored
Normal file
2
ci/Jenkinsfile
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// Warning: This file is automatically synced from https://github.com/ipfs/ci-sync so if you want to change it, please change it there and ask someone to sync all repositories.
|
||||||
|
javascript()
|
@ -2,6 +2,12 @@ machine:
|
|||||||
node:
|
node:
|
||||||
version: stable
|
version: stable
|
||||||
|
|
||||||
|
test:
|
||||||
|
pre:
|
||||||
|
- npm run lint
|
||||||
|
post:
|
||||||
|
- npm run coverage -- --upload --providers coveralls
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
pre:
|
pre:
|
||||||
- google-chrome --version
|
- google-chrome --version
|
||||||
@ -15,4 +21,4 @@ dependencies:
|
|||||||
- 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
|
||||||
|
@ -10,8 +10,8 @@ Let us know if you find any issue or if you want to contribute and add a new tut
|
|||||||
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
|
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
|
||||||
- [Encrypted Communications](./encrypted-communications)
|
- [Encrypted Communications](./encrypted-communications)
|
||||||
- [Discovery Mechanisms](./discovery-mechanisms)
|
- [Discovery Mechanisms](./discovery-mechanisms)
|
||||||
- [Peer Routing](./peer-routing)
|
- [Peer Routing](./peer-and-content-routing)
|
||||||
- [Content Routing](./content-routing)
|
- [Content Routing](./peer-and-content-routing)
|
||||||
- [PubSub](./pubsub)
|
- [PubSub](./pubsub)
|
||||||
- [NAT Traversal](./nat-traversal)
|
- [NAT Traversal](./nat-traversal)
|
||||||
- Circuit Relay (future)
|
- Circuit Relay (future)
|
||||||
|
@ -47,7 +47,7 @@ async.parallel([
|
|||||||
console.log(ma.toString() + '/ipfs/' + idListener.toB58String())
|
console.log(ma.toString() + '/ipfs/' + idListener.toB58String())
|
||||||
})
|
})
|
||||||
|
|
||||||
nodeDialer.dial(peerListener, '/chat/1.0.0', (err, conn) => {
|
nodeDialer.dialProtocol(peerListener, '/chat/1.0.0', (err, conn) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ async.parallel([
|
|||||||
'/ipfs/' + dialerId.toB58String()))
|
'/ipfs/' + dialerId.toB58String()))
|
||||||
|
|
||||||
console.log('Dialing to peer:', listenerMultiaddr.toString())
|
console.log('Dialing to peer:', listenerMultiaddr.toString())
|
||||||
dialerNode.dial(listenerPeerInfo, '/echo/1.0.0', (err, conn) => {
|
dialerNode.dialProtocol(listenerPeerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0')
|
console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0')
|
||||||
|
@ -52,7 +52,7 @@ parallel([
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
node1.dial(node2.peerInfo, '/a-protocol', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/a-protocol', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['This information is sent out encrypted to the other peer']), conn)
|
pull(pull.values(['This information is sent out encrypted to the other peer']), conn)
|
||||||
})
|
})
|
||||||
|
@ -10,7 +10,7 @@ function createNode (callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const peerIdStr = peerInfo.id.toB58String()
|
const peerIdStr = peerInfo.id.toB58String()
|
||||||
const ma = `/dns4/star-signal.cloud.ipfs.team/wss/p2p-webrtc-star/ipfs/${peerIdStr}`
|
const ma = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/ipfs/${peerIdStr}`
|
||||||
|
|
||||||
peerInfo.multiaddrs.add(ma)
|
peerInfo.multiaddrs.add(ma)
|
||||||
|
|
||||||
|
@ -75,20 +75,20 @@ parallel([
|
|||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
|
|
||||||
node1.dial(node2.peerInfo, '/your-protocol', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/your-protocol', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['my own protocol, wow!']), conn)
|
pull(pull.values(['my own protocol, wow!']), conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
node1.dial(node2.peerInfo, '/another-protocol/1.0.0', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/another-protocol/1.0.0', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['semver me please']), conn)
|
pull(pull.values(['semver me please']), conn)
|
||||||
})
|
})
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
node1.dial(node2.peerInfo, '/custom-match-func/some-query', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/custom-match-func/some-query', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['do I fall into your criteria?']), conn)
|
pull(pull.values(['do I fall into your criteria?']), conn)
|
||||||
})
|
})
|
||||||
|
@ -60,17 +60,17 @@ parallel([
|
|||||||
})
|
})
|
||||||
|
|
||||||
series([
|
series([
|
||||||
(cb) => node1.dial(node2.peerInfo, '/a', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/a', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['protocol (a)']), conn)
|
pull(pull.values(['protocol (a)']), conn)
|
||||||
cb()
|
cb()
|
||||||
}),
|
}),
|
||||||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['protocol (b)']), conn)
|
pull(pull.values(['protocol (b)']), conn)
|
||||||
cb()
|
cb()
|
||||||
}),
|
}),
|
||||||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['another conn on protocol (b)']), conn)
|
pull(pull.values(['another conn on protocol (b)']), conn)
|
||||||
cb()
|
cb()
|
||||||
|
@ -30,7 +30,7 @@ node2.handle('/your-protocol', (protocol, conn) => {
|
|||||||
After the protocol is _handled_, now we can dial to it.
|
After the protocol is _handled_, now we can dial to it.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
node1.dial(node2.peerInfo, '/your-protocol', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/your-protocol', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['my own protocol, wow!']), conn)
|
pull(pull.values(['my own protocol, wow!']), conn)
|
||||||
})
|
})
|
||||||
@ -47,7 +47,7 @@ node2.handle('/another-protocol/1.0.1', (protocol, conn) => {
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
// ...
|
// ...
|
||||||
node1.dial(node2.peerInfo, '/another-protocol/1.0.0', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/another-protocol/1.0.0', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['semver me please']), conn)
|
pull(pull.values(['semver me please']), conn)
|
||||||
})
|
})
|
||||||
@ -74,7 +74,7 @@ node2.handle('/custom-match-func', (protocol, conn) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
// ...
|
// ...
|
||||||
node1.dial(node2.peerInfo, '/custom-match-func/some-query', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/custom-match-func/some-query', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['do I fall into your criteria?']), conn)
|
pull(pull.values(['do I fall into your criteria?']), conn)
|
||||||
})
|
})
|
||||||
@ -129,17 +129,17 @@ node2.handle('/b', (protocol, conn) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
series([
|
series([
|
||||||
(cb) => node1.dial(node2.peerInfo, '/a', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/a', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['protocol (a)']), conn)
|
pull(pull.values(['protocol (a)']), conn)
|
||||||
cb()
|
cb()
|
||||||
}),
|
}),
|
||||||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['protocol (b)']), conn)
|
pull(pull.values(['protocol (b)']), conn)
|
||||||
cb()
|
cb()
|
||||||
}),
|
}),
|
||||||
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
|
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
pull(pull.values(['another conn on protocol (b)']), conn)
|
pull(pull.values(['another conn on protocol (b)']), conn)
|
||||||
cb()
|
cb()
|
||||||
@ -158,9 +158,9 @@ another protocol (b)
|
|||||||
|
|
||||||
# 3. Bidirectional connections
|
# 3. Bidirectional connections
|
||||||
|
|
||||||
There is one last trick on _protocol and stream multiplexing_ that libp2p uses to make everyone's life easier and that is _biderectional connection_.
|
There is one last trick on _protocol and stream multiplexing_ that libp2p uses to make everyone's life easier and that is _bidirectional connection_.
|
||||||
|
|
||||||
With the aid of both mechanisms, we can reuse an incomming connection to dial streams out too, this is specially useful when you are behind tricky NAT, firewalls or if you are running in a browser, where you can have listening addrs, but you can dial out. By dialing out, you enable other peers to talk with you in Protocols that they want, simply by opening a new multiplexed stream.
|
With the aid of both mechanisms, we can reuse an incomming connection to dial streams out too, this is specially useful when you are behind tricky NAT, firewalls or if you are running in a browser, where you can't have listening addrs, but you can dial out. By dialing out, you enable other peers to talk with you in Protocols that they want, simply by opening a new multiplexed stream.
|
||||||
|
|
||||||
You can see this working on example [3.js](./3.js). The result should look like the following:
|
You can see this working on example [3.js](./3.js). The result should look like the following:
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ const Multiplex = require('libp2p-multiplex')
|
|||||||
const SECIO = require('libp2p-secio')
|
const SECIO = require('libp2p-secio')
|
||||||
const PeerInfo = require('peer-info')
|
const PeerInfo = require('peer-info')
|
||||||
const MulticastDNS = require('libp2p-mdns')
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
const FloodSub = require('libp2p-floodsub')
|
|
||||||
const waterfall = require('async/waterfall')
|
const waterfall = require('async/waterfall')
|
||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const series = require('async/series')
|
const series = require('async/series')
|
||||||
@ -19,7 +18,9 @@ class MyBundle extends libp2p {
|
|||||||
muxer: [Multiplex],
|
muxer: [Multiplex],
|
||||||
crypto: [SECIO]
|
crypto: [SECIO]
|
||||||
},
|
},
|
||||||
discovery: [new MulticastDNS(peerInfo, { interval: 2000 })]
|
discovery: [
|
||||||
|
new MulticastDNS(peerInfo, { interval: 2000 })
|
||||||
|
]
|
||||||
}
|
}
|
||||||
super(modules, peerInfo)
|
super(modules, peerInfo)
|
||||||
}
|
}
|
||||||
@ -47,22 +48,19 @@ parallel([
|
|||||||
const node1 = nodes[0]
|
const node1 = nodes[0]
|
||||||
const node2 = nodes[1]
|
const node2 = nodes[1]
|
||||||
|
|
||||||
const fs1 = new FloodSub(node1)
|
|
||||||
const fs2 = new FloodSub(node2)
|
|
||||||
|
|
||||||
series([
|
series([
|
||||||
(cb) => fs1.start(cb),
|
|
||||||
(cb) => fs2.start(cb),
|
|
||||||
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
||||||
(cb) => setTimeout(cb, 500)
|
(cb) => setTimeout(cb, 500)
|
||||||
], (err) => {
|
], (err) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
fs2.on('news', (msg) => console.log(msg.from, msg.data.toString()))
|
node1.pubsub.subscribe('news',
|
||||||
fs2.subscribe('news')
|
(msg) => console.log(msg.from, msg.data.toString()),
|
||||||
|
() => {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
fs1.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
|
node2.pubsub.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
|
||||||
}, 1000)
|
}, 1000)
|
||||||
|
}
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
# Publish Subscribe
|
# Publish Subscribe
|
||||||
|
|
||||||
Publish Subscribe is something out of scope for the modular networking stack that is libp2p, however, it is something that is enabled through the primitives that libp2p offers and so it has become one of the most interesting use cases for libp2p.
|
Publish Subscribe is also included on the stack. Currently, we have on PubSub implementation which we ship by default [libp2p-floodsub](https://github.com/libp2p/js-libp2p-floodsub), with many more being researched at [research-pubsub](https://github.com/libp2p/research-pubsub).
|
||||||
|
|
||||||
Currently, we have a PubSub implementation, [libp2p-floodsub](https://github.com/libp2p/js-libp2p-floodsub) and many more being researched at [research-pubsub](https://github.com/libp2p/research-pubsub).
|
|
||||||
|
|
||||||
We've seen many interesting use cases appear with this, here are some highlights:
|
We've seen many interesting use cases appear with this, here are some highlights:
|
||||||
|
|
||||||
@ -12,29 +10,22 @@ We've seen many interesting use cases appear with this, here are some highlights
|
|||||||
|
|
||||||
## 1. Setting up a simple PubSub network on top of libp2p
|
## 1. Setting up a simple PubSub network on top of libp2p
|
||||||
|
|
||||||
For this example, we will use MulticastDNS for automatic Peer Discovery and libp2p-floodsub to give us the PubSub primitives we are looking for. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
||||||
|
|
||||||
Getting PubSub is super simple, all you have to do is require the FloodSub module and pass it in a libp2p node, once you have done that you can start subscribing and publishing in any topic.
|
Using PubSub is super simple, all you have to do is start a libp2p node, PubSub will be enabled by default.
|
||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
const FloodSub = require('libp2p-floodsub')
|
|
||||||
|
|
||||||
const fs1 = new FloodSub(node1)
|
|
||||||
const fs2 = new FloodSub(node2)
|
|
||||||
|
|
||||||
series([
|
series([
|
||||||
(cb) => fs1.start(cb),
|
|
||||||
(cb) => fs2.start(cb),
|
|
||||||
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
(cb) => node1.once('peer:discovery', (peer) => node1.dial(peer, cb)),
|
||||||
(cb) => setTimeout(cb, 500)
|
(cb) => setTimeout(cb, 500)
|
||||||
], (err) => {
|
], (err) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
fs2.on('news', (msg) => console.log(msg.from, msg.data.toString()))
|
node1.pubsub.on('news', (msg) => console.log(msg.from, msg.data.toString()))
|
||||||
fs2.subscribe('news')
|
node1.pubsub.subscribe('news')
|
||||||
|
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
fs1.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
|
node2.pubsub.publish('news', Buffer.from('Bird bird bird, bird is the word!'))
|
||||||
}, 1000)
|
}, 1000)
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
@ -54,7 +54,7 @@ parallel([
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
node1.dial(node2.peerInfo, '/print', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)
|
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)
|
||||||
|
@ -66,19 +66,19 @@ parallel([
|
|||||||
node2.handle('/print', print)
|
node2.handle('/print', print)
|
||||||
node3.handle('/print', print)
|
node3.handle('/print', print)
|
||||||
|
|
||||||
node1.dial(node2.peerInfo, '/print', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['node 1 dialed to node 2 successfully']), conn)
|
pull(pull.values(['node 1 dialed to node 2 successfully']), conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
node2.dial(node3.peerInfo, '/print', (err, conn) => {
|
node2.dialProtocol(node3.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['node 2 dialed to node 3 successfully']), conn)
|
pull(pull.values(['node 2 dialed to node 3 successfully']), conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
node3.dial(node1.peerInfo, '/print', (err, conn) => {
|
node3.dialProtocol(node1.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('node 3 failed to dial to node 1 with:', err.message)
|
console.log('node 3 failed to dial to node 1 with:', err.message)
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ parallel([
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
node1.dial(node2.peerInfo, '/print', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)
|
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)
|
||||||
@ -240,21 +240,21 @@ parallel([
|
|||||||
node3.handle('/print', print)
|
node3.handle('/print', print)
|
||||||
|
|
||||||
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
// node 1 (TCP) dials to node 2 (TCP+WebSockets)
|
||||||
node1.dial(node2.peerInfo, '/print', (err, conn) => {
|
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['node 1 dialed to node 2 successfully']), conn)
|
pull(pull.values(['node 1 dialed to node 2 successfully']), conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
// node 2 (TCP+WebSockets) dials to node 2 (WebSockets)
|
||||||
node2.dial(node3.peerInfo, '/print', (err, conn) => {
|
node2.dialProtocol(node3.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) { throw err }
|
if (err) { throw err }
|
||||||
|
|
||||||
pull(pull.values(['node 2 dialed to node 3 successfully']), conn)
|
pull(pull.values(['node 2 dialed to node 3 successfully']), conn)
|
||||||
})
|
})
|
||||||
|
|
||||||
// node 3 (WebSockets) attempts to dial to node 1 (TCP)
|
// node 3 (WebSockets) attempts to dial to node 1 (TCP)
|
||||||
node3.dial(node1.peerInfo, '/print', (err, conn) => {
|
node3.dialProtocol(node1.peerInfo, '/print', (err, conn) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log('node 3 failed to dial to node 1 with:', err.message)
|
console.log('node 3 failed to dial to node 1 with:', err.message)
|
||||||
}
|
}
|
||||||
@ -298,8 +298,8 @@ As expected, we created 3 nodes, node 1 with TCP, node 2 with TCP+WebSockets and
|
|||||||
|
|
||||||
Today there are already 3 transports available, one in the works and plenty to come, you can find these at [interface-transport implementations](https://github.com/libp2p/interface-transport#modules-that-implement-the-interface) list.
|
Today there are already 3 transports available, one in the works and plenty to come, you can find these at [interface-transport implementations](https://github.com/libp2p/interface-transport#modules-that-implement-the-interface) list.
|
||||||
|
|
||||||
Adding more transports is done through the same way as you added TCP and WebSockets. Some transports might offer extra functionalities but for what is libp2p concern, as long as it follows the interface defined at the [spec](https://github.com/libp2p/interface-transport#api), it will be able to use it.
|
Adding more transports is done through the same way as you added TCP and WebSockets. Some transports might offer extra functionalities, but as far as libp2p is concerned, if it follows the interface defined at the [spec](https://github.com/libp2p/interface-transport#api) it will be able to use it.
|
||||||
|
|
||||||
If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well.
|
If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well.
|
||||||
|
|
||||||
Hope this tutorial was useful. We are always looking to improve it, contributions are welcome!
|
Hope this tutorial was useful. We are always looking to improve it, so contributions are welcome!
|
||||||
|
46
package.json
46
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p",
|
"name": "libp2p",
|
||||||
"version": "0.13.3",
|
"version": "0.17.0",
|
||||||
"description": "JavaScript base class for libp2p bundles",
|
"description": "JavaScript base class for libp2p bundles",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -26,7 +26,7 @@
|
|||||||
"node": ">=6.0.0",
|
"node": ">=6.0.0",
|
||||||
"npm": ">=3.0.0"
|
"npm": ">=3.0.0"
|
||||||
},
|
},
|
||||||
"pre-commit": [
|
"pre-push": [
|
||||||
"lint",
|
"lint",
|
||||||
"test"
|
"test"
|
||||||
],
|
],
|
||||||
@ -38,48 +38,55 @@
|
|||||||
"homepage": "https://github.com/libp2p/js-libp2p",
|
"homepage": "https://github.com/libp2p/js-libp2p",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "^2.6.0",
|
"async": "^2.6.0",
|
||||||
"libp2p-ping": "~0.6.0",
|
"libp2p-floodsub": "^0.14.1",
|
||||||
"libp2p-swarm": "~0.33.2",
|
"libp2p-ping": "~0.6.1",
|
||||||
"mafmt": "^3.0.2",
|
"libp2p-switch": "~0.36.1",
|
||||||
"multiaddr": "^3.0.1",
|
"mafmt": "^4.0.0",
|
||||||
"peer-book": "~0.5.2",
|
"multiaddr": "^3.0.2",
|
||||||
"peer-id": "~0.10.3",
|
"peer-book": "~0.5.4",
|
||||||
"peer-info": "~0.11.3"
|
"peer-id": "~0.10.6",
|
||||||
|
"peer-info": "~0.11.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aegir": "^12.2.0",
|
"aegir": "^13.0.0",
|
||||||
"chai": "^4.1.2",
|
"chai": "^4.1.2",
|
||||||
"cids": "~0.5.2",
|
"cids": "~0.5.2",
|
||||||
"dirty-chai": "^2.0.1",
|
"dirty-chai": "^2.0.1",
|
||||||
"electron-webrtc": "~0.3.0",
|
"electron-webrtc": "~0.3.0",
|
||||||
"libp2p-circuit": "~0.1.4",
|
"libp2p-circuit": "~0.1.4",
|
||||||
"libp2p-kad-dht": "~0.6.0",
|
"libp2p-kad-dht": "~0.8.0",
|
||||||
"libp2p-mdns": "~0.9.1",
|
"libp2p-mdns": "~0.9.2",
|
||||||
"libp2p-multiplex": "~0.5.0",
|
"libp2p-multiplex": "~0.5.1",
|
||||||
"libp2p-railing": "~0.7.1",
|
"libp2p-railing": "~0.7.1",
|
||||||
"libp2p-secio": "~0.8.1",
|
"libp2p-secio": "~0.9.2",
|
||||||
"libp2p-spdy": "~0.11.0",
|
"libp2p-spdy": "~0.11.0",
|
||||||
"libp2p-tcp": "~0.11.1",
|
"libp2p-tcp": "~0.11.5",
|
||||||
"libp2p-webrtc-star": "~0.13.3",
|
"libp2p-webrtc-star": "~0.13.3",
|
||||||
"libp2p-websockets": "~0.10.4",
|
"libp2p-websockets": "~0.10.4",
|
||||||
"libp2p-websocket-star": "~0.7.1",
|
"libp2p-websocket-star": "~0.7.6",
|
||||||
"libp2p-websocket-star-rendezvous": "~0.2.1",
|
"libp2p-websocket-star-rendezvous": "~0.2.3",
|
||||||
"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.1",
|
"pull-stream": "^3.6.1",
|
||||||
"safe-buffer": "^5.1.1",
|
"safe-buffer": "^5.1.1",
|
||||||
"sinon": "^4.1.2",
|
"sinon": "^4.3.0",
|
||||||
"wrtc": "0.0.63"
|
"wrtc": "0.0.66"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
"Chris Bratlien <chrisbratlien@gmail.com>",
|
"Chris Bratlien <chrisbratlien@gmail.com>",
|
||||||
|
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
||||||
"Daijiro Wachi <daijiro.wachi@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>",
|
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||||
"Elven <mon.samuel@qq.com>",
|
"Elven <mon.samuel@qq.com>",
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
|
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||||
|
"Irakli Gozalishvili <rfobic@gmail.com>",
|
||||||
|
"Joel Gustafson <joelg@mit.edu>",
|
||||||
|
"John Rees <johnrees@users.noreply.github.com>",
|
||||||
|
"Kevin Kwok <antimatter15@gmail.com>",
|
||||||
"Lars Gierth <lgierth@users.noreply.github.com>",
|
"Lars Gierth <lgierth@users.noreply.github.com>",
|
||||||
"Maciej Krüger <mkg20001@gmail.com>",
|
"Maciej Krüger <mkg20001@gmail.com>",
|
||||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||||
@ -87,6 +94,7 @@
|
|||||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||||
"Richard Littauer <richard.littauer@gmail.com>",
|
"Richard Littauer <richard.littauer@gmail.com>",
|
||||||
"Ryan Bell <ryan@piing.net>",
|
"Ryan Bell <ryan@piing.net>",
|
||||||
|
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||||
"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>"
|
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>"
|
||||||
|
3
pdd/README.md
Normal file
3
pdd/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# PDD Test Stories Implementation
|
||||||
|
|
||||||
|
> Implementation of the Compliance tests from https://github.com/libp2p/interop
|
20
pdd/package.json
Normal file
20
pdd/package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "pdd-impl",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "PDD Test Stories implementation",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": " "
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"PDD",
|
||||||
|
"libp2p"
|
||||||
|
],
|
||||||
|
"author": "David Dias <daviddias@ipfs.io>",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"libp2p": "file:./..",
|
||||||
|
"libp2p-interop": "github:libp2p/interop#master",
|
||||||
|
"tape": "^4.8.0"
|
||||||
|
}
|
||||||
|
}
|
104
pdd/pdd-the-ipfs-bundle--story-1--peer-a.js
Normal file
104
pdd/pdd-the-ipfs-bundle--story-1--peer-a.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const SECIO = require('libp2p-secio')
|
||||||
|
const Multiplex = require('libp2p-multiplex')
|
||||||
|
const Railing = require('libp2p-railing')
|
||||||
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const series = require('async/series')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class IPFSBundle extends libp2p {
|
||||||
|
constructor (peerInfo, options) {
|
||||||
|
options = Object.assign({ bootstrap: [] }, options)
|
||||||
|
|
||||||
|
const modules = {
|
||||||
|
transport: [
|
||||||
|
new TCP(),
|
||||||
|
new WebSockets()
|
||||||
|
],
|
||||||
|
connection: {
|
||||||
|
muxer: [
|
||||||
|
Multiplex
|
||||||
|
],
|
||||||
|
crypto: [
|
||||||
|
SECIO
|
||||||
|
]
|
||||||
|
},
|
||||||
|
discovery: [
|
||||||
|
new MulticastDNS(peerInfo, 'ipfs.local'),
|
||||||
|
new Railing(options.bootstrap)
|
||||||
|
],
|
||||||
|
DHT: KadDHT
|
||||||
|
}
|
||||||
|
|
||||||
|
super(modules, peerInfo, undefined, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 1 - peerA', (t) => {
|
||||||
|
t.plan(10)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerA, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10000')
|
||||||
|
node = new IPFSBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node successfully')
|
||||||
|
t.ok(node.isStarted(), 'PeerA is Running')
|
||||||
|
|
||||||
|
const peerBAddr = `/ip4/127.0.0.1/tcp/10001/ipfs/${PeerB.id}`
|
||||||
|
|
||||||
|
node.handle('/time/1.0.0', (protocol, conn) => {
|
||||||
|
pull(
|
||||||
|
pull.values([Date.now().toString()]),
|
||||||
|
conn,
|
||||||
|
pull.onEnd((err) => {
|
||||||
|
t.ifErr(err)
|
||||||
|
t.pass('Sent time successfully')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
series([
|
||||||
|
(cb) => setTimeout(cb, 5 * 1000), // time to run both scripts
|
||||||
|
(cb) => node.ping(peerBAddr, (err, p) => {
|
||||||
|
t.ifErr(err, 'initiated Ping to PeerB')
|
||||||
|
p.once('error', (err) => t.ifErr(err, 'Ping should not fail'))
|
||||||
|
p.once('ping', (time) => {
|
||||||
|
t.pass('ping PeerB successfully')
|
||||||
|
p.stop()
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
(cb) => node.dial(peerBAddr, '/echo/1.0.0', (err, conn) => {
|
||||||
|
t.ifErr(err, 'dial successful')
|
||||||
|
|
||||||
|
const data = Buffer.from('Hey')
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([data]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, values) => {
|
||||||
|
t.ifErr(err, 'Received echo back')
|
||||||
|
t.deepEqual(values[0], data)
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
(cb) => setTimeout(cb, 2 * 1000) // time to both finish
|
||||||
|
], () => node.stop((err) => t.ifErr(err, 'PeerA has stopped')))
|
||||||
|
})
|
||||||
|
})
|
98
pdd/pdd-the-ipfs-bundle--story-1--peer-b.js
Normal file
98
pdd/pdd-the-ipfs-bundle--story-1--peer-b.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const SECIO = require('libp2p-secio')
|
||||||
|
const Multiplex = require('libp2p-multiplex')
|
||||||
|
const Railing = require('libp2p-railing')
|
||||||
|
const MulticastDNS = require('libp2p-mdns')
|
||||||
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const series = require('async/series')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class IPFSBundle extends libp2p {
|
||||||
|
constructor (peerInfo, options) {
|
||||||
|
options = Object.assign({ bootstrap: [] }, options)
|
||||||
|
|
||||||
|
const modules = {
|
||||||
|
transport: [
|
||||||
|
new TCP(),
|
||||||
|
new WebSockets()
|
||||||
|
],
|
||||||
|
connection: {
|
||||||
|
muxer: [
|
||||||
|
Multiplex
|
||||||
|
],
|
||||||
|
crypto: [
|
||||||
|
SECIO
|
||||||
|
]
|
||||||
|
},
|
||||||
|
discovery: [
|
||||||
|
new MulticastDNS(peerInfo, 'ipfs.local'),
|
||||||
|
new Railing(options.bootstrap)
|
||||||
|
],
|
||||||
|
DHT: KadDHT
|
||||||
|
}
|
||||||
|
|
||||||
|
super(modules, peerInfo, undefined, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 1 - peerA', (t) => {
|
||||||
|
t.plan(8)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerB, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10001')
|
||||||
|
node = new IPFSBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node successfully')
|
||||||
|
t.ok(node.isStarted(), 'PeerB is Running')
|
||||||
|
|
||||||
|
const peerAAddr = `/ip4/127.0.0.1/tcp/10000/ipfs/${PeerA.id}`
|
||||||
|
|
||||||
|
node.handle('/echo/1.0.0', (protocol, conn) => {
|
||||||
|
pull(
|
||||||
|
conn,
|
||||||
|
conn,
|
||||||
|
pull.onEnd((err) => t.ifErr(err, 'echo was successful'))
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
series([
|
||||||
|
(cb) => setTimeout(cb, 5 * 1000), // time to run both scripts
|
||||||
|
(cb) => node.ping(peerAAddr, (err, p) => {
|
||||||
|
t.ifErr(err, 'initiated Ping to PeerA')
|
||||||
|
p.once('error', (err) => t.ifErr(err, 'Ping should not fail'))
|
||||||
|
p.once('ping', (time) => {
|
||||||
|
t.pass('ping PeerA successfully')
|
||||||
|
p.stop()
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
(cb) => node.dial(peerAAddr, '/time/1.0.0', (err, conn) => {
|
||||||
|
t.ifErr(err, 'dial successful')
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, values) => {
|
||||||
|
t.ifErr(err, 'Received time')
|
||||||
|
cb()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
(cb) => setTimeout(cb, 2 * 1000) // time to both finish
|
||||||
|
], () => node.stop((err) => t.ifErr(err, 'PeerB has stopped')))
|
||||||
|
})
|
||||||
|
})
|
0
pdd/pdd-the-ipfs-bundle--story-2--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-2--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-2--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-2--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-3--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-d.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-d.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-e.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-4--peer-e.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-a.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-b.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-c.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-d.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-d.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-e.js
Normal file
0
pdd/pdd-the-ipfs-bundle--story-5--peer-e.js
Normal file
54
pdd/pdd-transport--story-1--peer-a.js
Normal file
54
pdd/pdd-transport--story-1--peer-a.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new TCP()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 1 - peerA', (t) => {
|
||||||
|
t.plan(6)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerA, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10000')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node')
|
||||||
|
t.ok(node.isStarted(), 'PeerA is running')
|
||||||
|
|
||||||
|
const PeerBAddr = `/ip4/127.0.0.1/tcp/10001/ipfs/${PeerB.id}`
|
||||||
|
|
||||||
|
node.dial(PeerBAddr, '/echo/1.0.0', (err, conn) => {
|
||||||
|
t.ifErr(err, 'dial successful')
|
||||||
|
|
||||||
|
const data = Buffer.from('Heey')
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([data]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, values) => {
|
||||||
|
t.ifErr(err, 'Received echo back')
|
||||||
|
t.deepEqual(values[0], data)
|
||||||
|
node.stop((err) => t.ifErr(err, 'PeerA has stopped'))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
49
pdd/pdd-transport--story-1--peer-b.js
Normal file
49
pdd/pdd-transport--story-1--peer-b.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new TCP()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 1 - peerB', (t) => {
|
||||||
|
t.plan(5)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerB, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10001')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err)
|
||||||
|
t.ok(node.isStarted(), 'PeerB is running')
|
||||||
|
|
||||||
|
node.handle('/echo/1.0.0', (protocol, conn) => {
|
||||||
|
pull(
|
||||||
|
conn,
|
||||||
|
conn,
|
||||||
|
pull.onEnd((err) => {
|
||||||
|
t.ifErr(err)
|
||||||
|
t.pass('Received End of Connection')
|
||||||
|
node.stop((err) => {
|
||||||
|
t.ifErr(err, 'PeerB has stopped')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
54
pdd/pdd-transport--story-2--peer-a.js
Normal file
54
pdd/pdd-transport--story-2--peer-a.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new WebSockets()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 2 - peerA', (t) => {
|
||||||
|
t.plan(6)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerA, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10000/ws')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node')
|
||||||
|
t.ok(node.isStarted(), 'PeerA is running')
|
||||||
|
|
||||||
|
const PeerBAddr = `/ip4/127.0.0.1/tcp/10001/ws/ipfs/${PeerB.id}`
|
||||||
|
|
||||||
|
node.dial(PeerBAddr, '/echo/1.0.0', (err, conn) => {
|
||||||
|
t.ifErr(err, 'dial successful')
|
||||||
|
|
||||||
|
const data = Buffer.from('Heey')
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values([data]),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, values) => {
|
||||||
|
t.ifErr(err, 'Received echo back')
|
||||||
|
t.deepEqual(values[0], data)
|
||||||
|
node.stop((err) => t.ifErr(err, 'PeerA has stopped'))
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
49
pdd/pdd-transport--story-2--peer-b.js
Normal file
49
pdd/pdd-transport--story-2--peer-b.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new WebSockets()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 2 - peerB', (t) => {
|
||||||
|
t.plan(5)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerB, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10001/ws')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err)
|
||||||
|
t.ok(node.isStarted(), 'PeerB is running')
|
||||||
|
|
||||||
|
node.handle('/echo/1.0.0', (protocol, conn) => {
|
||||||
|
pull(
|
||||||
|
conn,
|
||||||
|
pull.through(v => v, err => {
|
||||||
|
t.ifErr(err)
|
||||||
|
t.pass('Received End of Connection')
|
||||||
|
node.stop((err) => {
|
||||||
|
t.ifErr(err, 'PeerB has stopped')
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
conn
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
42
pdd/pdd-transport--story-3--peer-a.js
Normal file
42
pdd/pdd-transport--story-3--peer-a.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new TCP()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 3 - peerA', (t) => {
|
||||||
|
t.plan(4)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerA, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10000')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node')
|
||||||
|
t.ok(node.isStarted(), 'PeerA is running')
|
||||||
|
|
||||||
|
const PeerBAddr = `/ip4/127.0.0.1/tcp/10001/ws/ipfs/${PeerB.id}`
|
||||||
|
|
||||||
|
setTimeout(() => node.dial(PeerBAddr, '/echo/1.0.0', (err, conn) => {
|
||||||
|
t.ok(err, 'dial failed')
|
||||||
|
node.stop((err) => t.ifErr(err, 'PeerA has stopped'))
|
||||||
|
}), 1000)
|
||||||
|
})
|
||||||
|
})
|
42
pdd/pdd-transport--story-3--peer-b.js
Normal file
42
pdd/pdd-transport--story-3--peer-b.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const test = require('tape')
|
||||||
|
const libp2p = require('libp2p')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const PeerA = require('libp2p-interop/peer-a.json')
|
||||||
|
const PeerB = require('libp2p-interop/peer-b.json')
|
||||||
|
|
||||||
|
class MyBundle extends libp2p {
|
||||||
|
constructor (peerInfo) {
|
||||||
|
const modules = {
|
||||||
|
transport: [new WebSockets()]
|
||||||
|
}
|
||||||
|
super(modules, peerInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test('story 3 - peerB', (t) => {
|
||||||
|
t.plan(4)
|
||||||
|
let node
|
||||||
|
|
||||||
|
waterfall([
|
||||||
|
(cb) => PeerInfo.create(PeerB, cb),
|
||||||
|
(peerInfo, cb) => {
|
||||||
|
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/10000/ws')
|
||||||
|
node = new MyBundle(peerInfo)
|
||||||
|
node.start(cb)
|
||||||
|
}
|
||||||
|
], (err) => {
|
||||||
|
t.ifErr(err, 'created Node')
|
||||||
|
t.ok(node.isStarted(), 'PeerA is running')
|
||||||
|
|
||||||
|
const PeerAAddr = `/ip4/127.0.0.1/tcp/10000/ws/ipfs/${PeerA.id}`
|
||||||
|
|
||||||
|
setTimeout(() => node.dial(PeerAAddr, '/echo/1.0.0', (err, conn) => {
|
||||||
|
t.ok(err, 'dial failed')
|
||||||
|
node.stop((err) => t.ifErr(err, 'PeerA has stopped'))
|
||||||
|
}), 1000)
|
||||||
|
})
|
||||||
|
})
|
20
src/content-routing.js
Normal file
20
src/content-routing.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = (node) => {
|
||||||
|
return {
|
||||||
|
findProviders: (key, timeout, callback) => {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.findProviders(key, timeout, callback)
|
||||||
|
},
|
||||||
|
provide: (key, callback) => {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.provide(key, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
src/dht.js
Normal file
27
src/dht.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = (node) => {
|
||||||
|
return {
|
||||||
|
put: (key, value, callback) => {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.put(key, value, callback)
|
||||||
|
},
|
||||||
|
get: (key, callback) => {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.get(key, callback)
|
||||||
|
},
|
||||||
|
getMany (key, nVals, callback) {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.getMany(key, nVals, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
src/error-messages.js
Normal file
3
src/error-messages.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
exports.NOT_STARTED_YET = 'The libp2p node is not started yet'
|
48
src/get-peer-info.js
Normal file
48
src/get-peer-info.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const PeerId = require('peer-id')
|
||||||
|
const PeerInfo = require('peer-info')
|
||||||
|
const multiaddr = require('multiaddr')
|
||||||
|
|
||||||
|
module.exports = (node) => {
|
||||||
|
/*
|
||||||
|
* Helper method to check the data type of peer and convert it to PeerInfo
|
||||||
|
*/
|
||||||
|
return function (peer, callback) {
|
||||||
|
let p
|
||||||
|
// PeerInfo
|
||||||
|
if (PeerInfo.isPeerInfo(peer)) {
|
||||||
|
p = peer
|
||||||
|
// Multiaddr instance or Multiaddr String
|
||||||
|
} else if (multiaddr.isMultiaddr(peer) || typeof peer === 'string') {
|
||||||
|
if (typeof peer === 'string') {
|
||||||
|
peer = multiaddr(peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
const peerIdB58Str = peer.getPeerId()
|
||||||
|
if (!peerIdB58Str) {
|
||||||
|
throw new Error(`peer multiaddr instance or string must include peerId`)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
p = node.peerBook.get(peerIdB58Str)
|
||||||
|
} catch (err) {
|
||||||
|
p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str))
|
||||||
|
}
|
||||||
|
p.multiaddrs.add(peer)
|
||||||
|
|
||||||
|
// PeerId
|
||||||
|
} else if (PeerId.isPeerId(peer)) {
|
||||||
|
const peerIdB58Str = peer.toB58String()
|
||||||
|
try {
|
||||||
|
p = node.peerBook.get(peerIdB58Str)
|
||||||
|
} catch (err) {
|
||||||
|
return node.peerRouting.findPeer(peer, callback)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return setImmediate(() => callback(new Error('peer type not recognized')))
|
||||||
|
}
|
||||||
|
|
||||||
|
setImmediate(() => callback(null, p))
|
||||||
|
}
|
||||||
|
}
|
221
src/index.js
221
src/index.js
@ -7,12 +7,15 @@ const setImmediate = require('async/setImmediate')
|
|||||||
const each = require('async/each')
|
const each = require('async/each')
|
||||||
const series = require('async/series')
|
const series = require('async/series')
|
||||||
|
|
||||||
const Ping = require('libp2p-ping')
|
|
||||||
const Swarm = require('libp2p-swarm')
|
|
||||||
const PeerId = require('peer-id')
|
|
||||||
const PeerInfo = require('peer-info')
|
|
||||||
const PeerBook = require('peer-book')
|
const PeerBook = require('peer-book')
|
||||||
const multiaddr = require('multiaddr')
|
const Switch = require('libp2p-switch')
|
||||||
|
const Ping = require('libp2p-ping')
|
||||||
|
|
||||||
|
const peerRouting = require('./peer-routing')
|
||||||
|
const contentRouting = require('./content-routing')
|
||||||
|
const dht = require('./dht')
|
||||||
|
const pubsub = require('./pubsub')
|
||||||
|
const getPeerInfo = require('./get-peer-info')
|
||||||
|
|
||||||
exports = module.exports
|
exports = module.exports
|
||||||
|
|
||||||
@ -31,28 +34,28 @@ class Node extends EventEmitter {
|
|||||||
|
|
||||||
this._isStarted = false
|
this._isStarted = false
|
||||||
|
|
||||||
this.swarm = new Swarm(this.peerInfo, this.peerBook)
|
this.switch = new Switch(this.peerInfo, this.peerBook)
|
||||||
|
|
||||||
// Attach stream multiplexers
|
// Attach stream multiplexers
|
||||||
if (this.modules.connection && this.modules.connection.muxer) {
|
if (this.modules.connection && this.modules.connection.muxer) {
|
||||||
let muxers = this.modules.connection.muxer
|
let muxers = this.modules.connection.muxer
|
||||||
muxers = Array.isArray(muxers) ? muxers : [muxers]
|
muxers = Array.isArray(muxers) ? muxers : [muxers]
|
||||||
muxers.forEach((muxer) => this.swarm.connection.addStreamMuxer(muxer))
|
muxers.forEach((muxer) => this.switch.connection.addStreamMuxer(muxer))
|
||||||
|
|
||||||
// If muxer exists, we can use Identify
|
// If muxer exists, we can use Identify
|
||||||
this.swarm.connection.reuse()
|
this.switch.connection.reuse()
|
||||||
|
|
||||||
// If muxer exists, we can use Relay for listening/dialing
|
// If muxer exists, we can use Relay for listening/dialing
|
||||||
this.swarm.connection.enableCircuitRelay(_options.relay)
|
this.switch.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.switch.on('peer-mux-established', (peerInfo) => {
|
||||||
this.emit('peer:connect', peerInfo)
|
this.emit('peer:connect', peerInfo)
|
||||||
this.peerBook.put(peerInfo)
|
this.peerBook.put(peerInfo)
|
||||||
})
|
})
|
||||||
|
|
||||||
this.swarm.on('peer-mux-closed', (peerInfo) => {
|
this.switch.on('peer-mux-closed', (peerInfo) => {
|
||||||
this.emit('peer:disconnect', peerInfo)
|
this.emit('peer:disconnect', peerInfo)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -62,7 +65,7 @@ class Node extends EventEmitter {
|
|||||||
let cryptos = this.modules.connection.crypto
|
let cryptos = this.modules.connection.crypto
|
||||||
cryptos = Array.isArray(cryptos) ? cryptos : [cryptos]
|
cryptos = Array.isArray(cryptos) ? cryptos : [cryptos]
|
||||||
cryptos.forEach((crypto) => {
|
cryptos.forEach((crypto) => {
|
||||||
this.swarm.connection.crypto(crypto.tag, crypto.encrypt)
|
this.switch.connection.crypto(crypto.tag, crypto.encrypt)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,67 +79,23 @@ class Node extends EventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mount default protocols
|
|
||||||
Ping.mount(this.swarm)
|
|
||||||
|
|
||||||
// dht provided components (peerRouting, contentRouting, dht)
|
// dht provided components (peerRouting, contentRouting, dht)
|
||||||
if (_modules.DHT) {
|
if (_modules.DHT) {
|
||||||
this._dht = new this.modules.DHT(this.swarm, {
|
this._dht = new this.modules.DHT(this.switch, {
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
datastoer: _options.DHT && _options.DHT.datastore
|
datastore: _options.DHT && _options.DHT.datastore
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.peerRouting = {
|
this.peerRouting = peerRouting(this)
|
||||||
findPeer: (id, callback) => {
|
this.contentRouting = contentRouting(this)
|
||||||
if (!this._dht) {
|
this.dht = dht(this)
|
||||||
return callback(new Error('DHT is not available'))
|
this.pubsub = pubsub(this)
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.findPeer(id, callback)
|
this._getPeerInfo = getPeerInfo(this)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.contentRouting = {
|
// Mount default protocols
|
||||||
findProviders: (key, timeout, callback) => {
|
Ping.mount(this.switch)
|
||||||
if (!this._dht) {
|
|
||||||
return callback(new Error('DHT is not available'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.findProviders(key, timeout, callback)
|
|
||||||
},
|
|
||||||
provide: (key, callback) => {
|
|
||||||
if (!this._dht) {
|
|
||||||
return callback(new Error('DHT is not available'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.provide(key, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dht = {
|
|
||||||
put: (key, value, callback) => {
|
|
||||||
if (!this._dht) {
|
|
||||||
return callback(new Error('DHT is not available'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.put(key, value, callback)
|
|
||||||
},
|
|
||||||
get: (key, callback) => {
|
|
||||||
if (!this._dht) {
|
|
||||||
return callback(new Error('DHT is not available'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.get(key, callback)
|
|
||||||
},
|
|
||||||
getMany (key, nVals, callback) {
|
|
||||||
if (!this._dht) {
|
|
||||||
return callback(new Error('DHT is not available'))
|
|
||||||
}
|
|
||||||
|
|
||||||
this._dht.getMany(key, nVals, callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -156,18 +115,18 @@ class Node extends EventEmitter {
|
|||||||
// so that we can have webrtc-star addrs without adding manually the id
|
// so that we can have webrtc-star addrs without adding manually the id
|
||||||
const maOld = []
|
const maOld = []
|
||||||
const maNew = []
|
const maNew = []
|
||||||
this.peerInfo.multiaddrs.forEach((ma) => {
|
this.peerInfo.multiaddrs.toArray().forEach((ma) => {
|
||||||
if (!ma.getPeerId()) {
|
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()))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.peerInfo.multiaddrs.replace(maOld, maNew)
|
this.peerInfo.multiaddrs.replace(maOld, maNew)
|
||||||
const multiaddrs = this.peerInfo.multiaddrs.toArray()
|
|
||||||
|
|
||||||
|
const multiaddrs = this.peerInfo.multiaddrs.toArray()
|
||||||
transports.forEach((transport) => {
|
transports.forEach((transport) => {
|
||||||
if (transport.filter(multiaddrs).length > 0) {
|
if (transport.filter(multiaddrs).length > 0) {
|
||||||
this.swarm.transport.add(
|
this.switch.transport.add(
|
||||||
transport.tag || transport.constructor.name, transport)
|
transport.tag || transport.constructor.name, transport)
|
||||||
} else if (transport.constructor &&
|
} else if (transport.constructor &&
|
||||||
transport.constructor.name === 'WebSockets') {
|
transport.constructor.name === 'WebSockets') {
|
||||||
@ -178,11 +137,11 @@ class Node extends EventEmitter {
|
|||||||
})
|
})
|
||||||
|
|
||||||
series([
|
series([
|
||||||
(cb) => this.swarm.listen(cb),
|
(cb) => this.switch.start(cb),
|
||||||
(cb) => {
|
(cb) => {
|
||||||
if (ws) {
|
if (ws) {
|
||||||
// always add dialing on websockets
|
// always add dialing on websockets
|
||||||
this.swarm.transport.add(ws.tag || ws.constructor.name, ws)
|
this.switch.transport.add(ws.tag || ws.constructor.name, ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
// all transports need to be setup before discover starts
|
// all transports need to be setup before discover starts
|
||||||
@ -192,12 +151,37 @@ class Node extends EventEmitter {
|
|||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
// TODO: chicken-and-egg problem:
|
// TODO: chicken-and-egg problem #1:
|
||||||
// have to set started here because DHT requires libp2p is already started
|
// have to set started here because DHT requires libp2p is already started
|
||||||
this._isStarted = true
|
this._isStarted = true
|
||||||
if (this._dht) {
|
if (this._dht) {
|
||||||
return this._dht.start(cb)
|
this._dht.start(cb)
|
||||||
|
} else {
|
||||||
|
cb()
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
(cb) => {
|
||||||
|
// TODO: chicken-and-egg problem #2:
|
||||||
|
// have to set started here because FloodSub requires libp2p is already started
|
||||||
|
if (this._options !== false) {
|
||||||
|
this._floodSub.start(cb)
|
||||||
|
} else {
|
||||||
|
cb()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
(cb) => {
|
||||||
|
// detect which multiaddrs we don't have a transport for and remove them
|
||||||
|
const multiaddrs = this.peerInfo.multiaddrs.toArray()
|
||||||
|
|
||||||
|
transports.forEach((transport) => {
|
||||||
|
multiaddrs.forEach((multiaddr) => {
|
||||||
|
if (!multiaddr.toString().match(/\/p2p-circuit($|\/)/) &&
|
||||||
|
!transports.find((transport) => transport.filter(multiaddr).length > 0)) {
|
||||||
|
this.peerInfo.multiaddrs.delete(multiaddr)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
@ -211,8 +195,6 @@ class Node extends EventEmitter {
|
|||||||
* Stop the libp2p node by closing its listeners and open connections
|
* Stop the libp2p node by closing its listeners and open connections
|
||||||
*/
|
*/
|
||||||
stop (callback) {
|
stop (callback) {
|
||||||
this._isStarted = false
|
|
||||||
|
|
||||||
if (this.modules.discovery) {
|
if (this.modules.discovery) {
|
||||||
this.modules.discovery.forEach((discovery) => {
|
this.modules.discovery.forEach((discovery) => {
|
||||||
setImmediate(() => discovery.stop(() => {}))
|
setImmediate(() => discovery.stop(() => {}))
|
||||||
@ -220,36 +202,48 @@ class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
series([
|
series([
|
||||||
|
(cb) => {
|
||||||
|
if (this._floodSub.started) {
|
||||||
|
this._floodSub.stop(cb)
|
||||||
|
}
|
||||||
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
if (this._dht) {
|
if (this._dht) {
|
||||||
return this._dht.stop(cb)
|
return this._dht.stop(cb)
|
||||||
}
|
}
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => this.swarm.close(cb),
|
(cb) => this.switch.stop(cb),
|
||||||
(cb) => {
|
(cb) => {
|
||||||
this.emit('stop')
|
this.emit('stop')
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], callback)
|
], (err) => {
|
||||||
|
this._isStarted = false
|
||||||
|
callback(err)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
isStarted () {
|
isStarted () {
|
||||||
return this._isStarted
|
return this._isStarted
|
||||||
}
|
}
|
||||||
|
|
||||||
ping (peer, callback) {
|
dial (peer, callback) {
|
||||||
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
||||||
this._getPeerInfo(peer, (err, peerInfo) => {
|
|
||||||
if (err) {
|
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null, new Ping(this.swarm, peerInfo))
|
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||||
|
if (err) { return callback(err) }
|
||||||
|
|
||||||
|
this.switch.dial(peerInfo, (err) => {
|
||||||
|
if (err) { return callback(err) }
|
||||||
|
|
||||||
|
this.peerBook.put(peerInfo)
|
||||||
|
callback()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
dial (peer, protocol, callback) {
|
dialProtocol (peer, protocol, callback) {
|
||||||
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
||||||
|
|
||||||
if (typeof protocol === 'function') {
|
if (typeof protocol === 'function') {
|
||||||
@ -258,14 +252,10 @@ class Node extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._getPeerInfo(peer, (err, peerInfo) => {
|
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||||
if (err) {
|
if (err) { return callback(err) }
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.swarm.dial(peerInfo, protocol, (err, conn) => {
|
this.switch.dial(peerInfo, protocol, (err, conn) => {
|
||||||
if (err) {
|
if (err) { return callback(err) }
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
this.peerBook.put(peerInfo)
|
this.peerBook.put(peerInfo)
|
||||||
callback(null, conn)
|
callback(null, conn)
|
||||||
})
|
})
|
||||||
@ -276,52 +266,27 @@ class Node extends EventEmitter {
|
|||||||
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
||||||
|
|
||||||
this._getPeerInfo(peer, (err, peerInfo) => {
|
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||||
if (err) {
|
if (err) { return callback(err) }
|
||||||
return callback(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.swarm.hangUp(peerInfo, callback)
|
this.switch.hangUp(peerInfo, callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ping (peer, callback) {
|
||||||
|
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
|
||||||
|
this._getPeerInfo(peer, (err, peerInfo) => {
|
||||||
|
if (err) { return callback(err) }
|
||||||
|
|
||||||
|
callback(null, new Ping(this.switch, peerInfo))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handle (protocol, handlerFunc, matchFunc) {
|
handle (protocol, handlerFunc, matchFunc) {
|
||||||
this.swarm.handle(protocol, handlerFunc, matchFunc)
|
this.switch.handle(protocol, handlerFunc, matchFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
unhandle (protocol) {
|
unhandle (protocol) {
|
||||||
this.swarm.unhandle(protocol)
|
this.switch.unhandle(protocol)
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helper method to check the data type of peer and convert it to PeerInfo
|
|
||||||
*/
|
|
||||||
_getPeerInfo (peer, callback) {
|
|
||||||
let p
|
|
||||||
// PeerInfo
|
|
||||||
if (PeerInfo.isPeerInfo(peer)) {
|
|
||||||
p = peer
|
|
||||||
// Multiaddr instance (not string)
|
|
||||||
} else if (multiaddr.isMultiaddr(peer)) {
|
|
||||||
const peerIdB58Str = peer.getPeerId()
|
|
||||||
try {
|
|
||||||
p = this.peerBook.get(peerIdB58Str)
|
|
||||||
} catch (err) {
|
|
||||||
p = new PeerInfo(PeerId.createFromB58String(peerIdB58Str))
|
|
||||||
}
|
|
||||||
p.multiaddrs.add(peer)
|
|
||||||
// PeerId
|
|
||||||
} else if (PeerId.isPeerId(peer)) {
|
|
||||||
const peerIdB58Str = peer.toB58String()
|
|
||||||
try {
|
|
||||||
p = this.peerBook.get(peerIdB58Str)
|
|
||||||
} catch (err) {
|
|
||||||
return this.peerRouting.findPeer(peer, callback)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return setImmediate(() => callback(new Error('peer type not recognized')))
|
|
||||||
}
|
|
||||||
|
|
||||||
setImmediate(() => callback(null, p))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
13
src/peer-routing.js
Normal file
13
src/peer-routing.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
module.exports = (node) => {
|
||||||
|
return {
|
||||||
|
findPeer: (id, callback) => {
|
||||||
|
if (!node._dht) {
|
||||||
|
return callback(new Error('DHT is not available'))
|
||||||
|
}
|
||||||
|
|
||||||
|
node._dht.findPeer(id, callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
93
src/pubsub.js
Normal file
93
src/pubsub.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const setImmediate = require('async/setImmediate')
|
||||||
|
const NOT_STARTED_YET = require('./error-messages').NOT_STARTED_YET
|
||||||
|
const FloodSub = require('libp2p-floodsub')
|
||||||
|
|
||||||
|
module.exports = (node) => {
|
||||||
|
const floodSub = new FloodSub(node)
|
||||||
|
|
||||||
|
node._floodSub = floodSub
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe: (topic, options, handler, callback) => {
|
||||||
|
if (typeof options === 'function') {
|
||||||
|
callback = handler
|
||||||
|
handler = options
|
||||||
|
options = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!node.isStarted() && !floodSub.started) {
|
||||||
|
return setImmediate(() => callback(new Error(NOT_STARTED_YET)))
|
||||||
|
}
|
||||||
|
|
||||||
|
function subscribe (cb) {
|
||||||
|
if (floodSub.listenerCount(topic) === 0) {
|
||||||
|
floodSub.subscribe(topic)
|
||||||
|
}
|
||||||
|
|
||||||
|
floodSub.on(topic, handler)
|
||||||
|
setImmediate(cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(callback)
|
||||||
|
},
|
||||||
|
|
||||||
|
unsubscribe: (topic, handler) => {
|
||||||
|
if (!node.isStarted() && !floodSub.started) {
|
||||||
|
throw new Error(NOT_STARTED_YET)
|
||||||
|
}
|
||||||
|
|
||||||
|
floodSub.removeListener(topic, handler)
|
||||||
|
|
||||||
|
if (floodSub.listenerCount(topic) === 0) {
|
||||||
|
floodSub.unsubscribe(topic)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
publish: (topic, data, callback) => {
|
||||||
|
if (!node.isStarted() && !floodSub.started) {
|
||||||
|
return setImmediate(() => callback(new Error(NOT_STARTED_YET)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Buffer.isBuffer(data)) {
|
||||||
|
return setImmediate(() => callback(new Error('data must be a Buffer')))
|
||||||
|
}
|
||||||
|
|
||||||
|
floodSub.publish(topic, data)
|
||||||
|
|
||||||
|
setImmediate(() => callback())
|
||||||
|
},
|
||||||
|
|
||||||
|
ls: (callback) => {
|
||||||
|
if (!node.isStarted() && !floodSub.started) {
|
||||||
|
return setImmediate(() => callback(new Error(NOT_STARTED_YET)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const subscriptions = Array.from(floodSub.subscriptions)
|
||||||
|
|
||||||
|
setImmediate(() => callback(null, subscriptions))
|
||||||
|
},
|
||||||
|
|
||||||
|
peers: (topic, callback) => {
|
||||||
|
if (!node.isStarted() && !floodSub.started) {
|
||||||
|
return setImmediate(() => callback(new Error(NOT_STARTED_YET)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof topic === 'function') {
|
||||||
|
callback = topic
|
||||||
|
topic = null
|
||||||
|
}
|
||||||
|
|
||||||
|
const peers = Array.from(floodSub.peers.values())
|
||||||
|
.filter((peer) => topic ? peer.topics.has(topic) : true)
|
||||||
|
.map((peer) => peer.info.id.toB58String())
|
||||||
|
|
||||||
|
setImmediate(() => callback(null, peers))
|
||||||
|
},
|
||||||
|
|
||||||
|
setMaxListeners (n) {
|
||||||
|
return floodSub.setMaxListeners(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,16 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const pull = require('pull-stream')
|
|
||||||
const waterfall = require('async/waterfall')
|
const waterfall = require('async/waterfall')
|
||||||
const series = require('async/series')
|
const series = require('async/series')
|
||||||
const parallel = require('async/parallel')
|
const parallel = require('async/parallel')
|
||||||
const utils = require('./utils/node')
|
const utils = require('./utils/node')
|
||||||
const Circuit = require('libp2p-circuit')
|
const Circuit = require('libp2p-circuit')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
|
const tryEcho = require('./utils/try-echo')
|
||||||
|
|
||||||
const chai = require('chai')
|
const chai = require('chai')
|
||||||
chai.use(require('dirty-chai'))
|
chai.use(require('dirty-chai'))
|
||||||
|
|
||||||
const expect = chai.expect
|
const expect = chai.expect
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
|
|
||||||
@ -39,7 +38,7 @@ describe('circuit relay', function () {
|
|||||||
node.start((err) => {
|
node.start((err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
handlerSpies.push(sinon.spy(node.swarm.transports[Circuit.tag].listeners[0].hopHandler, 'handle'))
|
handlerSpies.push(sinon.spy(node.switch.transports[Circuit.tag].listeners[0].hopHandler, 'handle'))
|
||||||
cb(node)
|
cb(node)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -153,25 +152,16 @@ describe('circuit relay', function () {
|
|||||||
describe('any relay', function () {
|
describe('any relay', function () {
|
||||||
this.timeout(20 * 1000)
|
this.timeout(20 * 1000)
|
||||||
|
|
||||||
it('should dial from WS1 to TCP1 over any R', (done) => {
|
it('dial from WS1 to TCP1 over any R', (done) => {
|
||||||
nodeWS1.dial(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeWS1.dialProtocol(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(conn).to.exist()
|
expect(conn).to.exist()
|
||||||
|
tryEcho(conn, done)
|
||||||
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) => {
|
it('fail to dial - no R from WS2 to TCP1', (done) => {
|
||||||
nodeWS2.dial(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeWS2.dialProtocol(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(conn).to.not.exist()
|
expect(conn).to.not.exist()
|
||||||
done()
|
done()
|
||||||
@ -182,43 +172,29 @@ describe('circuit relay', function () {
|
|||||||
describe('explicit relay', function () {
|
describe('explicit relay', function () {
|
||||||
this.timeout(20 * 1000)
|
this.timeout(20 * 1000)
|
||||||
|
|
||||||
it('should dial from WS1 to TCP1 over R1', (done) => {
|
it('dial from WS1 to TCP1 over R1', (done) => {
|
||||||
nodeWS1.dial(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeWS1.dialProtocol(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(conn).to.exist()
|
expect(conn).to.exist()
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, () => {
|
||||||
pull.values(['hello']),
|
const addr = multiaddr(handlerSpies[0].args[2][0].dstPeer.addrs[0]).toString()
|
||||||
conn,
|
expect(addr).to.equal(`/ipfs/${nodeTCP1.peerInfo.id.toB58String()}`)
|
||||||
pull.collect((err, result) => {
|
done()
|
||||||
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) => {
|
it('dial from WS1 to TCP2 over R2', (done) => {
|
||||||
nodeWS1.dial(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeWS1.dialProtocol(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(conn).to.exist()
|
expect(conn).to.exist()
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, () => {
|
||||||
pull.values(['hello']),
|
const addr = multiaddr(handlerSpies[1].args[2][0].dstPeer.addrs[0]).toString()
|
||||||
conn,
|
expect(addr).to.equal(`/ipfs/${nodeTCP2.peerInfo.id.toB58String()}`)
|
||||||
pull.collect((err, result) => {
|
done()
|
||||||
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()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
40
test/multiaddr-trim.js
Normal file
40
test/multiaddr-trim.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use(require('dirty-chai'))
|
||||||
|
const expect = chai.expect
|
||||||
|
const series = require('async/series')
|
||||||
|
const createNode = require('./utils/node').createNode
|
||||||
|
|
||||||
|
describe('multiaddr trim', () => {
|
||||||
|
it('non used multiaddrs get trimmed', (done) => {
|
||||||
|
let node
|
||||||
|
|
||||||
|
series([
|
||||||
|
(cb) => createNode([
|
||||||
|
'/ip4/0.0.0.0/tcp/999/wss/p2p-webrtc-direct',
|
||||||
|
'/ip4/127.0.0.1/tcp/55555/ws',
|
||||||
|
'/ip4/0.0.0.0/tcp/0/'
|
||||||
|
], (err, _node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
node = _node
|
||||||
|
const multiaddrs = node.peerInfo.multiaddrs.toArray()
|
||||||
|
// multiaddrs.forEach((ma) => console.log(ma.toString()))
|
||||||
|
expect(multiaddrs).to.have.length(3)
|
||||||
|
cb()
|
||||||
|
}),
|
||||||
|
(cb) => node.start(cb)
|
||||||
|
], (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
const multiaddrs = node.peerInfo.multiaddrs.toArray()
|
||||||
|
// console.log('--')
|
||||||
|
// multiaddrs.forEach((ma) => console.log(ma.toString()))
|
||||||
|
|
||||||
|
expect(multiaddrs.length).to.at.least(2)
|
||||||
|
expect(multiaddrs[0].toString()).to.match(/^\/ip4\/127\.0\.0\.1\/tcp\/[0-9]+\/ws\/ipfs\/\w+$/)
|
||||||
|
node.stop(done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -4,6 +4,8 @@ require('./base')
|
|||||||
require('./transports.node')
|
require('./transports.node')
|
||||||
require('./stream-muxing.node')
|
require('./stream-muxing.node')
|
||||||
require('./peer-discovery.node')
|
require('./peer-discovery.node')
|
||||||
|
require('./pubsub.node')
|
||||||
require('./peer-routing.node')
|
require('./peer-routing.node')
|
||||||
require('./content-routing.node')
|
require('./content-routing.node')
|
||||||
require('./circuit-relay.node')
|
require('./circuit-relay.node')
|
||||||
|
require('./multiaddr-trim')
|
||||||
|
87
test/pubsub.node.js
Normal file
87
test/pubsub.node.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/* eslint-env mocha */
|
||||||
|
/* eslint max-nested-callbacks: ["error", 8] */
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const chai = require('chai')
|
||||||
|
chai.use(require('dirty-chai'))
|
||||||
|
const expect = chai.expect
|
||||||
|
const parallel = require('async/parallel')
|
||||||
|
const waterfall = require('async/waterfall')
|
||||||
|
const _times = require('lodash.times')
|
||||||
|
const utils = require('./utils/node')
|
||||||
|
const createNode = utils.createNode
|
||||||
|
|
||||||
|
function startTwo (callback) {
|
||||||
|
const tasks = _times(2, () => (cb) => {
|
||||||
|
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||||
|
mdns: false
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
node.start((err) => cb(err, node))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
parallel(tasks, (err, nodes) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
nodes[0].dial(nodes[1].peerInfo, (err) => callback(err, nodes))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopTwo (nodes, callback) {
|
||||||
|
parallel([
|
||||||
|
(cb) => nodes[0].stop(cb),
|
||||||
|
(cb) => nodes[1].stop(cb)
|
||||||
|
], callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is a vast test suite on PubSub through js-ipfs
|
||||||
|
// https://github.com/ipfs/interface-ipfs-core/blob/master/js/src/pubsub.js
|
||||||
|
// and libp2p-floodsub itself
|
||||||
|
// https://github.com/libp2p/js-libp2p-floodsub/tree/master/test
|
||||||
|
// TODO: consider if all or some of those should come here
|
||||||
|
describe('.pubsub', () => {
|
||||||
|
describe('.pubsub on (default)', (done) => {
|
||||||
|
it('start two nodes and send one message', (done) => {
|
||||||
|
waterfall([
|
||||||
|
(cb) => startTwo(cb),
|
||||||
|
(nodes, cb) => {
|
||||||
|
const data = Buffer.from('test')
|
||||||
|
nodes[0].pubsub.subscribe('pubsub',
|
||||||
|
(msg) => {
|
||||||
|
expect(msg.data).to.eql(data)
|
||||||
|
cb(null, nodes)
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
setTimeout(() => nodes[1].pubsub.publish('pubsub', data, (err) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
}), 500)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
},
|
||||||
|
(nodes, cb) => stopTwo(nodes, cb)
|
||||||
|
], done)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('.pubsub off', () => {
|
||||||
|
it('fail to use pubsub if disabled', (done) => {
|
||||||
|
createNode('/ip4/0.0.0.0/tcp/0', {
|
||||||
|
mdns: false,
|
||||||
|
pubsub: false
|
||||||
|
}, (err, node) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
|
node.pubsub.subscribe('news',
|
||||||
|
(msg) => {},
|
||||||
|
(err) => {
|
||||||
|
expect(err).to.exist()
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
@ -6,24 +6,15 @@ chai.use(require('dirty-chai'))
|
|||||||
const expect = chai.expect
|
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 utils = require('./utils/node')
|
const utils = require('./utils/node')
|
||||||
|
const tryEcho = require('./utils/try-echo')
|
||||||
const createNode = utils.createNode
|
const createNode = utils.createNode
|
||||||
const echo = utils.echo
|
const echo = utils.echo
|
||||||
|
|
||||||
function test (nodeA, nodeB, callback) {
|
function test (nodeA, nodeB, callback) {
|
||||||
nodeA.dial(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
tryEcho(conn, callback)
|
||||||
pull(
|
|
||||||
pull.values([Buffer.from('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.be.eql([Buffer.from('hey')])
|
|
||||||
callback()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +127,7 @@ describe('stream muxing', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('spdy + multiplex switched order', function (done) {
|
it('spdy + multiplex switched order', function (done) {
|
||||||
this.timeout(5000)
|
this.timeout(5 * 1000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
@ -170,7 +161,7 @@ describe('stream muxing', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('one without the other fails to establish a muxedConn', function (done) {
|
it('one without the other fails to establish a muxedConn', function (done) {
|
||||||
this.timeout(5000)
|
this.timeout(5 * 1000)
|
||||||
|
|
||||||
let nodeA
|
let nodeA
|
||||||
let nodeB
|
let nodeB
|
||||||
@ -200,12 +191,12 @@ describe('stream muxing', () => {
|
|||||||
(cb) => setup(cb),
|
(cb) => setup(cb),
|
||||||
(cb) => {
|
(cb) => {
|
||||||
// it will just 'warm up a conn'
|
// it will just 'warm up a conn'
|
||||||
expect(Object.keys(nodeA.swarm.muxers)).to.have.length(1)
|
expect(Object.keys(nodeA.switch.muxers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeB.swarm.muxers)).to.have.length(1)
|
expect(Object.keys(nodeB.switch.muxers)).to.have.length(1)
|
||||||
|
|
||||||
nodeA.dial(nodeB.peerInfo, (err) => {
|
nodeA.dial(nodeB.peerInfo, (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
@ -12,6 +12,7 @@ const parallel = require('async/parallel')
|
|||||||
const goodbye = require('pull-goodbye')
|
const goodbye = require('pull-goodbye')
|
||||||
const serializer = require('pull-serializer')
|
const serializer = require('pull-serializer')
|
||||||
const w = require('webrtcsupport')
|
const w = require('webrtcsupport')
|
||||||
|
const tryEcho = require('./utils/try-echo')
|
||||||
|
|
||||||
const Node = require('./utils/bundle.browser')
|
const Node = require('./utils/bundle.browser')
|
||||||
const rawPeer = require('./fixtures/test-peer.json')
|
const rawPeer = require('./fixtures/test-peer.json')
|
||||||
@ -63,7 +64,7 @@ describe('transports', () => {
|
|||||||
|
|
||||||
// General connectivity tests
|
// General connectivity tests
|
||||||
|
|
||||||
it('libp2p.dial using Multiaddr nodeA to nodeB', (done) => {
|
it('.dial using Multiaddr', (done) => {
|
||||||
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
|
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
@ -77,26 +78,18 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('libp2p.dial using Multiaddr on Protocol nodeA to nodeB', (done) => {
|
it('.dialProtocol using Multiaddr', (done) => {
|
||||||
nodeA.dial(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, done)
|
||||||
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) => {
|
it('.hangUp using Multiaddr', (done) => {
|
||||||
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
|
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
@ -105,13 +98,13 @@ describe('transports', () => {
|
|||||||
function check () {
|
function check () {
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('libp2p.dial using PeerInfo nodeA to nodeB', (done) => {
|
it('.dial using PeerInfo', (done) => {
|
||||||
nodeA.dial(peerB, (err) => {
|
nodeA.dial(peerB, (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
@ -125,26 +118,18 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('libp2p.dial using PeerInfo on Protocol nodeA to nodeB', (done) => {
|
it('.dialProtocol using PeerInfo', (done) => {
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, done)
|
||||||
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) => {
|
it('.hangUp using PeerInfo', (done) => {
|
||||||
nodeA.hangUp(peerB, (err) => {
|
nodeA.hangUp(peerB, (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
setTimeout(check, 500)
|
setTimeout(check, 500)
|
||||||
@ -153,7 +138,7 @@ describe('transports', () => {
|
|||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -161,7 +146,7 @@ describe('transports', () => {
|
|||||||
|
|
||||||
describe('stress', () => {
|
describe('stress', () => {
|
||||||
it('one big write', (done) => {
|
it('one big write', (done) => {
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
const rawMessage = Buffer.alloc(100000)
|
const rawMessage = Buffer.alloc(100000)
|
||||||
rawMessage.fill('a')
|
rawMessage.fill('a')
|
||||||
@ -180,7 +165,7 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('many writes', (done) => {
|
it('many writes', (done) => {
|
||||||
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
const s = serializer(goodbye({
|
const s = serializer(goodbye({
|
||||||
@ -235,39 +220,30 @@ describe('transports', () => {
|
|||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('listen on the two libp2p nodes', (done) => {
|
it('start two libp2p nodes', (done) => {
|
||||||
parallel([
|
parallel([
|
||||||
(cb) => node1.start(cb),
|
(cb) => node1.start(cb),
|
||||||
(cb) => node2.start(cb)
|
(cb) => node2.start(cb)
|
||||||
], done)
|
], done)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('handle a protocol on the first node', () => {
|
it('.handle echo on first node', () => {
|
||||||
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('dial from the second node to the first node', (done) => {
|
it('.dialProtocol from the second node to the first node', (done) => {
|
||||||
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
|
node1.dialProtocol(peer2, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
setTimeout(check, 500)
|
setTimeout(check, 500)
|
||||||
|
|
||||||
function check () {
|
function check () {
|
||||||
const text = 'hello'
|
|
||||||
const peers1 = node1.peerBook.getAll()
|
const peers1 = node1.peerBook.getAll()
|
||||||
expect(Object.keys(peers1)).to.have.length(1)
|
expect(Object.keys(peers1)).to.have.length(1)
|
||||||
|
|
||||||
const peers2 = node2.peerBook.getAll()
|
const peers2 = node2.peerBook.getAll()
|
||||||
expect(Object.keys(peers2)).to.have.length(1)
|
expect(Object.keys(peers2)).to.have.length(1)
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, done)
|
||||||
pull.values([Buffer.from(text)]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data[0].toString()).to.equal(text)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -280,7 +256,7 @@ describe('transports', () => {
|
|||||||
function check () {
|
function check () {
|
||||||
const peers = node1.peerBook.getAll()
|
const peers = node1.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(node1.switch.muxedConns)).to.have.length(0)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -291,8 +267,8 @@ describe('transports', () => {
|
|||||||
|
|
||||||
function check () {
|
function check () {
|
||||||
if (++counter === 3) {
|
if (++counter === 3) {
|
||||||
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
|
expect(Object.keys(node1.switch.muxedConns).length).to.equal(1)
|
||||||
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
|
expect(Object.keys(node2.switch.muxedConns).length).to.equal(1)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -355,28 +331,19 @@ describe('transports', () => {
|
|||||||
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('dial from the second node to the first node', (done) => {
|
it('.dialProtocol from the second node to the first node', (done) => {
|
||||||
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
|
node1.dialProtocol(peer2, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
setTimeout(check, 500)
|
setTimeout(check, 500)
|
||||||
|
|
||||||
function check () {
|
function check () {
|
||||||
const text = 'hello'
|
|
||||||
const peers1 = node1.peerBook.getAll()
|
const peers1 = node1.peerBook.getAll()
|
||||||
expect(Object.keys(peers1)).to.have.length(1)
|
expect(Object.keys(peers1)).to.have.length(1)
|
||||||
|
|
||||||
const peers2 = node2.peerBook.getAll()
|
const peers2 = node2.peerBook.getAll()
|
||||||
expect(Object.keys(peers2)).to.have.length(1)
|
expect(Object.keys(peers2)).to.have.length(1)
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, done)
|
||||||
pull.values([Buffer.from(text)]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data[0].toString()).to.equal(text)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -389,7 +356,7 @@ describe('transports', () => {
|
|||||||
function check () {
|
function check () {
|
||||||
const peers = node1.peerBook.getAll()
|
const peers = node1.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(node1.switch.muxedConns)).to.have.length(0)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -400,8 +367,8 @@ describe('transports', () => {
|
|||||||
|
|
||||||
function check () {
|
function check () {
|
||||||
if (++counter === 3) {
|
if (++counter === 3) {
|
||||||
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
|
expect(Object.keys(node1.switch.muxedConns).length).to.equal(1)
|
||||||
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
|
expect(Object.keys(node2.switch.muxedConns).length).to.equal(1)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,13 +6,13 @@ chai.use(require('dirty-chai'))
|
|||||||
const expect = chai.expect
|
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 utils = require('./utils/node.js')
|
const utils = require('./utils/node.js')
|
||||||
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
const signalling = require('libp2p-webrtc-star/src/sig-server')
|
||||||
const rendezvous = require('libp2p-websocket-star-rendezvous')
|
const rendezvous = require('libp2p-websocket-star-rendezvous')
|
||||||
const WSStar = require('libp2p-websocket-star')
|
const WSStar = require('libp2p-websocket-star')
|
||||||
const WRTCStar = require('libp2p-webrtc-star')
|
const WRTCStar = require('libp2p-webrtc-star')
|
||||||
const wrtc = require('wrtc')
|
const wrtc = require('wrtc')
|
||||||
|
const tryEcho = require('./utils/try-echo')
|
||||||
|
|
||||||
const createNode = utils.createNode
|
const createNode = utils.createNode
|
||||||
const echo = utils.echo
|
const echo = utils.echo
|
||||||
@ -73,18 +73,10 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('nodeA.dial nodeB using PeerInfo', (done) => {
|
it('nodeA.dial nodeB using PeerInfo', (done) => {
|
||||||
nodeA.dial(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
|
|
||||||
pull(
|
tryEcho(conn, done)
|
||||||
pull.values([Buffer.from('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.be.eql([Buffer.from('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -98,14 +90,14 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeB.peerBook.getAll()
|
const peers = nodeB.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -113,8 +105,8 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('nodeA.dial nodeB using multiaddr', (done) => {
|
it('nodeA.dialProtocol nodeB using multiaddr', (done) => {
|
||||||
nodeA.dial(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
|
||||||
// Some time for Identify to finish
|
// Some time for Identify to finish
|
||||||
setTimeout(check, 500)
|
setTimeout(check, 500)
|
||||||
|
|
||||||
@ -125,27 +117,17 @@ describe('transports', () => {
|
|||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeB.peerBook.getAll()
|
const peers = nodeB.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], () => {
|
], () => tryEcho(conn, done))
|
||||||
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()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -161,14 +143,14 @@ describe('transports', () => {
|
|||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeB.peerBook.getAll()
|
const peers = nodeB.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
|
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -176,8 +158,8 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('nodeA.dial nodeB using PeerId', (done) => {
|
it('nodeA.dialProtocol nodeB using PeerId', (done) => {
|
||||||
nodeA.dial(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
|
nodeA.dialProtocol(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
|
||||||
// Some time for Identify to finish
|
// Some time for Identify to finish
|
||||||
setTimeout(check, 500)
|
setTimeout(check, 500)
|
||||||
|
|
||||||
@ -187,26 +169,16 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeB.peerBook.getAll()
|
const peers = nodeB.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], () => {
|
], () => tryEcho(conn, done))
|
||||||
pull(
|
|
||||||
pull.values([Buffer.from('hey')]),
|
|
||||||
conn,
|
|
||||||
pull.collect((err, data) => {
|
|
||||||
expect(err).to.not.exist()
|
|
||||||
expect(data).to.eql([Buffer.from('hey')])
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -221,13 +193,13 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeB.peerBook.getAll()
|
const peers = nodeB.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -291,13 +263,13 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
const peers = nodeTCP.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeTCP.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -315,14 +287,14 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCP.peerBook.getAll()
|
const peers = nodeTCP.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeTCP.switch.muxedConns)).to.have.length(0)
|
||||||
|
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -342,13 +314,13 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
expect(Object.keys(peers)).to.have.length(2)
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeWS.peerBook.getAll()
|
const peers = nodeWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
|
expect(Object.keys(nodeWS.switch.muxedConns)).to.have.length(1)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -366,14 +338,14 @@ describe('transports', () => {
|
|||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeTCPnWS.peerBook.getAll()
|
const peers = nodeTCPnWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(2)
|
expect(Object.keys(peers)).to.have.length(2)
|
||||||
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(0)
|
||||||
|
|
||||||
cb()
|
cb()
|
||||||
},
|
},
|
||||||
(cb) => {
|
(cb) => {
|
||||||
const peers = nodeWS.peerBook.getAll()
|
const peers = nodeWS.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeWS.switch.muxedConns)).to.have.length(0)
|
||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
], done)
|
], done)
|
||||||
@ -465,7 +437,9 @@ describe('transports', () => {
|
|||||||
], done)
|
], done)
|
||||||
})
|
})
|
||||||
|
|
||||||
after((done) => {
|
after(function (done) {
|
||||||
|
this.timeout(10 * 1000)
|
||||||
|
|
||||||
parallel([
|
parallel([
|
||||||
(cb) => nodeAll.stop(cb),
|
(cb) => nodeAll.stop(cb),
|
||||||
(cb) => nodeTCP.stop(cb),
|
(cb) => nodeTCP.stop(cb),
|
||||||
@ -479,7 +453,7 @@ describe('transports', () => {
|
|||||||
let i = 1;
|
let i = 1;
|
||||||
[nodeAll, otherNode].forEach((node) => {
|
[nodeAll, otherNode].forEach((node) => {
|
||||||
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
||||||
expect(Object.keys(node.swarm.muxedConns)).to.have.length(muxed)
|
expect(Object.keys(node.switch.muxedConns)).to.have.length(muxed)
|
||||||
})
|
})
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
@ -517,7 +491,7 @@ describe('transports', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('nodeAll.dial nodeWStar using PeerInfo', function (done) {
|
it('nodeAll.dial nodeWStar using PeerInfo', function (done) {
|
||||||
this.timeout(10 * 1000)
|
this.timeout(40 * 1000)
|
||||||
|
|
||||||
nodeAll.dial(nodeWStar.peerInfo, (err) => {
|
nodeAll.dial(nodeWStar.peerInfo, (err) => {
|
||||||
expect(err).to.not.exist()
|
expect(err).to.not.exist()
|
||||||
@ -622,7 +596,7 @@ describe('transports', () => {
|
|||||||
let i = 1;
|
let i = 1;
|
||||||
[nodeAll, otherNode].forEach((node) => {
|
[nodeAll, otherNode].forEach((node) => {
|
||||||
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
|
||||||
expect(Object.keys(node.swarm.muxedConns)).to.have.length(muxed)
|
expect(Object.keys(node.switch.muxedConns)).to.have.length(muxed)
|
||||||
})
|
})
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ describe('Turbolence tests', () => {
|
|||||||
function check () {
|
function check () {
|
||||||
const peers = nodeA.peerBook.getAll()
|
const peers = nodeA.peerBook.getAll()
|
||||||
expect(Object.keys(peers)).to.have.length(1)
|
expect(Object.keys(peers)).to.have.length(1)
|
||||||
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
|
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
|
||||||
done()
|
done()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -22,7 +22,7 @@ function createNode (multiaddrs, options, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
waterfall([
|
waterfall([
|
||||||
(cb) => PeerId.create({ bits: 1024 }, cb),
|
(cb) => PeerId.create({ bits: 512 }, cb),
|
||||||
(peerId, cb) => PeerInfo.create(peerId, cb),
|
(peerId, cb) => PeerInfo.create(peerId, cb),
|
||||||
(peerInfo, cb) => {
|
(peerInfo, cb) => {
|
||||||
multiaddrs.map((ma) => peerInfo.multiaddrs.add(ma))
|
multiaddrs.map((ma) => peerInfo.multiaddrs.add(ma))
|
||||||
|
21
test/utils/try-echo.js
Normal file
21
test/utils/try-echo.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const pull = require('pull-stream')
|
||||||
|
const chai = require('chai')
|
||||||
|
const dirtyChai = require('dirty-chai')
|
||||||
|
const expect = chai.expect
|
||||||
|
chai.use(dirtyChai)
|
||||||
|
|
||||||
|
module.exports = (conn, callback) => {
|
||||||
|
const values = [Buffer.from('echo')]
|
||||||
|
|
||||||
|
pull(
|
||||||
|
pull.values(values),
|
||||||
|
conn,
|
||||||
|
pull.collect((err, _values) => {
|
||||||
|
expect(err).to.not.exist()
|
||||||
|
expect(_values).to.eql(values)
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
Reference in New Issue
Block a user