Compare commits

..

97 Commits

Author SHA1 Message Date
ebdb696742 chore: release version v0.16.1 2018-02-07 09:45:01 +00:00
721e6ee9ce chore: update contributors 2018-02-07 09:45:01 +00:00
98f2903088 chore: release version v0.16.0 2018-02-07 08:39:08 +00:00
3dda282dfd chore: update contributors 2018-02-07 08:39:08 +00:00
03faf69212 test: fix linting 2018-02-07 08:37:03 +00:00
0062a4b5eb docs: update examples 2018-02-07 08:37:03 +00:00
f7f85dce0a test: update tests to new API 2018-02-07 08:37:03 +00:00
59df82a675 docs: dialProtocol 2018-02-07 08:37:03 +00:00
6651401f0b feat: dialProtocol and small refactor 2018-02-07 08:37:03 +00:00
cd43863db6 chore: use pre-push 2018-02-07 07:31:10 +00:00
23e8293b75 feat: use libp2p-switch 2018-02-07 07:31:10 +00:00
68c170a40d docs: Add ws-star and ws-star-rendezvous (#158) 2018-02-07 07:07:53 +00:00
bd8a35aaf9 feat: add explicit error for case peer id not included in multiaddr (#155) 2018-02-05 12:36:20 +01:00
248d86d050 fix typo (#152) 2018-01-27 23:26:57 -08:00
8225b11082 fix typo (#153) 2018-01-27 23:26:52 -08:00
1355af2b51 docs: fix typos (#154) 2018-01-27 23:26:46 -08:00
a85f041843 chore: release version v0.15.2 2018-01-27 18:51:45 -08:00
2c0cda2a7c chore: update contributors 2018-01-27 18:51:45 -08:00
b4ba267589 chore: update deps 2018-01-27 18:48:44 -08:00
4c81f39ebe chore: release version v0.15.1 2018-01-16 06:16:15 -08:00
76922383ab chore: update contributors 2018-01-16 06:16:15 -08:00
3fc57ff397 chore: bump timeout on after 2018-01-16 06:13:42 -08:00
13b36dcaa6 chore: update deps 2018-01-16 06:03:04 -08:00
61bebd10fc fix: typo in DHT setup (#151)
I think there was a typo that would have ignored passed options and fallback to defaults for DHT datastore.
2018-01-16 05:58:12 -08:00
97cde1ccb4 test: Various pdd fixes (#150)
* fix(pdd): url for interop pkg was pointing to non-existing branch

* fix(pdd): case-sensitive names

peer-B.json does not _actually_ exist

* fix(pdd): story 2 peer b
2018-01-10 14:53:24 +00:00
07b0cdc30e docs: note the Connection type on .handle and .dial docs (#149) 2018-01-07 18:47:02 +00:00
73b6d60e32 docs: update to new URL format on the browser example 2018-01-07 17:17:22 +00:00
808f7495a9 chore: release version v0.15.0 2018-01-07 17:09:57 +00:00
ae21a6facf chore: update contributors 2018-01-07 17:09:56 +00:00
3aba3fd176 chore: update deps (#148) 2018-01-07 17:00:24 +00:00
dc2da39a19 docs: tcp/443 on webrtc-star example. (#147)
according to https://github.com/libp2p/js-libp2p-webrtc-star/issues/134 and my own fiddling with this example.
2018-01-06 14:28:20 +00:00
f8b441fff5 docs: Update README.md (#143)
added missing backtick
2018-01-02 07:18:41 +00:00
190ad54f9e PDD Compliance Tests (#137)
* transport story 1 done

* c

* transport series 2

* transports story 3

* the ipfs-bundle story 1
2017-12-18 10:23:34 +00:00
582f8bed2e docs: fix links on examples peer and content routing (#141) 2017-12-18 09:53:30 +00:00
59de0da19c chore: release version v0.14.3 2017-12-15 08:25:08 +00:00
0caf600c9a chore: update contributors 2017-12-15 08:25:08 +00:00
a4943b4509 chore: update npm ignore 2017-12-15 08:24:49 +00:00
c128873a07 chore: release version v0.14.2 2017-12-15 07:15:05 +00:00
5e2b6df04a chore: update contributors 2017-12-15 07:15:05 +00:00
8d2d8c98a0 chore: release version v0.14.1 2017-12-15 07:10:42 +00:00
30bf5bb161 chore: update contributors 2017-12-15 07:10:42 +00:00
c88eaf416c fix: prevent "The libp2p node is not started yet" when stopping (#138) 2017-12-15 07:08:44 +00:00
c7f20383d9 chore: release version v0.14.0 2017-12-14 07:39:37 +00:00
a86a95c19f chore: update contributors 2017-12-14 07:39:37 +00:00
1b7360fcfa fix: remove innactive multiaddrs (#131) 2017-12-14 07:27:13 +00:00
67ca37c356 chore: updating CI files (#132)
* Updating CI files

This commit updates all CI scripts to the latest version

* chore: update deps

* bump timout

* fix circle
2017-12-14 07:14:36 +00:00
0870068ebc docs: fix typo (#136) 2017-12-11 12:16:05 +00:00
8563395d32 chore: release version v0.13.3 2017-12-01 09:32:49 +00:00
ef3cae5b5a chore: update contributors 2017-12-01 09:32:49 +00:00
f602cd9f79 test: use that crypto puzzle! (#135) 2017-12-01 09:19:44 +00:00
ec956c1d42 chore: release version v0.13.2 2017-11-27 09:13:13 +00:00
c906f698e4 chore: update contributors 2017-11-27 09:13:12 +00:00
95f029eb7a feat: Bring libp2p-websocket-star to the Transports family! 🌟 (#122)
* test: add libp2p-websocket-star tests

* refactor: websocket-star-{signal => rendezvous}

* misc: Apply requested changes

* chore: update deps

* refactor: considerable amount of refactor, clean up test structure

* use right flag

* test: refactor transport tests
2017-11-27 09:10:36 +00:00
38a68a01b7 chore: Upgrade wrtc to 0.0.63 (#133)
For testing on CIs
2017-11-22 16:19:27 +00:00
c08aa517a0 chore: release version v0.13.1 2017-11-12 10:53:37 +00:00
8eac0f806e chore: update contributors 2017-11-12 10:53:37 +00:00
9fd092fddf chore: update deps 2017-11-12 10:51:13 +00:00
87ddc25bee chore: update example 2017-11-04 16:44:09 +00:00
efb2b67f19 chore: update example 2017-11-04 16:25:58 +00:00
7c0b4daf49 chore: update deps on browser example 2017-11-04 16:21:11 +00:00
aeb3ae1301 chore: update deps 2017-11-04 16:20:28 +00:00
97df76f9c5 chore: gitignore 2017-10-26 13:03:40 +01:00
3ad696445d chore: release version v0.13.0 2017-10-26 13:02:16 +01:00
30bec8d53b chore: update contributors 2017-10-26 13:02:16 +01:00
db2b5300b4 chore: update deps 2017-10-26 12:57:33 +01:00
df4d60df88 docs(examples): update browser /wss bootstrap list (#129) 2017-10-26 12:52:01 +01:00
29cc0afc64 feat: enable and test Circuit Relay
* feat: new super simplified API

* feat: append peer id to multiaddr if not there

* [WIP] Awesome DHT (#86)

* feat: integrate dht

* better interfaces

* docs: add documentation for peerRouting, contentRouting, dht

* fix: take in passed datastore

* fix: update usage of _getPeerInfo

* fix: getPeerInfo

* docs: update docs

* moar

feat: correctly handle p2p-circuit addrs when creating a peer info object

refactor: rework config options

* feat: adding circuit relaying

* feat: rework circuit relay for protobufs

* feat: circuit loading and tests

* fix: clean up _getPeerInfo to work with /p2p-circuit

* wip: tests cleaup

* test: clean up

* wip

* fix: bringing back test reworks and new aegir

* test: group tests

* test: clean up

* test: adjust test

* fix: use getPeerId to determine if the ipfs fragment is missing

* feat: adding circuit relaying

* feat: circuit loading and tests

* test: clean up

* wip

* feat: upgrade to latest aegir

* fix: removing unused tests

* feat: cleanup tests

* fix: create node defautl options

* chore: upgrade swarm to latest version

* fix: updated aegir and adjust timeouts

* feat: more timeouts

* chore: updating deps

* fix: circle ci builds

* test: timeouts
2017-10-26 12:51:36 +01:00
2504cbeb26 docs: add missing sections to the README (#128) 2017-10-22 10:27:36 +01:00
468cc421fa docs: update README.md (#124) 2017-10-22 10:19:50 +01:00
0b991e19d1 docs(examples): fix peer-content routing example scripts (#126). (#127) 2017-10-22 10:19:16 +01:00
2a81fc75a8 chore: update deps 2017-09-10 05:20:56 +01:00
e04c249d4d chore: update deps 2017-09-10 04:52:07 +01:00
4a995613ae chore: release version v0.12.4 2017-09-07 17:17:38 +01:00
066c4976bb chore: update contributors 2017-09-07 17:17:38 +01:00
429cf9c361 chore: update deps 2017-09-07 17:15:08 +01:00
01c20f8ab9 chore: release version v0.12.3 2017-09-07 11:18:58 +01:00
c8adce3906 chore: update contributors 2017-09-07 11:18:57 +01:00
6e3c5427de chore: update deps 2017-09-07 11:17:39 +01:00
3e140d2c47 chore: release version v0.12.2 2017-09-07 10:54:49 +01:00
f0858c20bd chore: update contributors 2017-09-07 10:54:48 +01:00
ef9c2a6296 chore: release version v0.12.1 2017-09-07 10:53:25 +01:00
090d75d383 chore: update contributors 2017-09-07 10:53:25 +01:00
04a4ffcc36 chore: update deps 2017-09-07 10:53:25 +01:00
7f7278fe82 docs: fix typo in readme (#121) 2017-09-06 09:55:12 +01:00
2c03222136 chore: release version v0.12.0 2017-09-03 14:43:35 +01:00
65857838f9 chore: update contributors 2017-09-03 14:43:34 +01:00
cad173e3bd feat: p2p addrs situation (#119)
* chore: update gitignore and CI

* chore: update deps

* test: update tests to use p2p-webrtc-star
2017-09-03 14:39:55 +01:00
19ce266f1b chore: update deps and readme of browser example 2017-08-24 10:58:06 +01:00
a2a85eb8d6 chore: update deps 2017-08-24 10:53:05 +01:00
b674bccfc2 chane three links~😉 (#115) 2017-07-31 02:35:21 -07:00
4ae8e43b8b Fix transport example (#114)
* fix the readme of transport-example-1

* change wrong node.isOn to node.isStarted()
2017-07-31 02:35:08 -07:00
6b059a0ba8 docs: fix link to contribution guidelines (#112) 2017-07-24 01:53:06 -07:00
363259f832 docs: add project status and throughput graph 2017-07-23 11:20:18 -07:00
56dbd9e7c2 docs: add issue template 2017-07-23 11:18:44 -07:00
314b45897f chore: release version v0.11.0 2017-07-22 15:21:07 -07:00
0a6f1faf82 chore: update contributors 2017-07-22 15:21:07 -07:00
5a638794c5 chore: update deps - no moar webcrypto-ossl 2017-07-22 15:17:41 -07:00
85 changed files with 2571 additions and 1365 deletions

71
.aegir.js Normal file
View File

@ -0,0 +1,71 @@
'use strict'
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream')
const parallel = require('async/parallel')
const rawPeer = require('./test/fixtures/test-peer.json')
const Node = require('./test/utils/bundle.node.js')
const sigServer = require('libp2p-webrtc-star/src/sig-server')
const WebSocketStarRendezvous = require('libp2p-websocket-star-rendezvous')
let wrtcRendezvous
let wsRendezvous
let node
const before = (done) => {
parallel([
(cb) => {
sigServer.start({
port: 15555
// cryptoChallenge: true TODO: needs https://github.com/libp2p/js-libp2p-webrtc-star/issues/128
}, (err, server) => {
if (err) { return cb(err) }
wrtcRendezvous = server
cb()
})
},
(cb) => {
WebSocketStarRendezvous.start({
port: 14444,
refreshPeerListIntervalMS: 1000,
strictMultiaddr: false,
cryptoChallenge: true
}, (err, _server) => {
if (err) { return cb(err) }
wsRendezvous = _server
cb()
})
},
(cb) => {
PeerId.createFromJSON(rawPeer, (err, peerId) => {
if (err) {
return done(err)
}
const peer = new PeerInfo(peerId)
peer.multiaddrs.add('/ip4/127.0.0.1/tcp/9200/ws')
node = new Node(peer)
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
node.start(cb)
})
}
], done)
}
const after = (done) => {
setTimeout(() => parallel(
[node, wrtcRendezvous, wsRendezvous].map((s) => {
return (cb) => s.stop(cb)
})
, done), 2000)
}
module.exports = {
hooks: {
pre: before,
post: after
}
}

26
.gitignore vendored
View File

@ -1,7 +1,14 @@
docs
**/node_modules/
**/*.log
test/repo-tests*
**/bundle.js
# Logs
logs
*.log
npm-debug.log*
coverage
# Runtime data
pids
@ -20,16 +27,17 @@ coverage
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
build
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
# Optional npm cache directory
.npm
# Optional REPL history
.node_repl_history
lib
dist
test/test-data/go-ipfs-repo/LOCK
test/test-data/go-ipfs-repo/LOG
test/test-data/go-ipfs-repo/LOG.old
# while testing npm5
package-lock.json

View File

@ -1,7 +1,13 @@
**/node_modules/
**/*.log
test/repo-tests*
# Logs
logs
*.log
coverage
# Runtime data
pids
*.pid
@ -16,13 +22,13 @@ coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# node-waf configuration
.lock-wscript
# Optional npm cache directory
.npm
build
# Optional REPL history
.node_repl_history
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
test
test

View File

@ -1,21 +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
language: node_js
matrix:
include:
- node_js: 4
env: CXX=g++-4.8
- node_js: 6
env: CXX=g++-4.8
- node_js: stable
- node_js: 8
env: CXX=g++-4.8
# Make sure we have new NPM.
before_install:
- npm install -g npm@4
# - node_js: stable
# env: CXX=g++-4.8
script:
- npm run lint
- npm test
- npm run test
- npm run coverage
before_script:

View File

@ -1,3 +1,135 @@
<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>
## [0.13.3](https://github.com/libp2p/js-libp2p/compare/v0.13.2...v0.13.3) (2017-12-01)
<a name="0.13.2"></a>
## [0.13.2](https://github.com/libp2p/js-libp2p/compare/v0.13.1...v0.13.2) (2017-11-27)
### Features
* Bring libp2p-websocket-star to the Transports family! 🌟 ([#122](https://github.com/libp2p/js-libp2p/issues/122)) ([95f029e](https://github.com/libp2p/js-libp2p/commit/95f029e))
<a name="0.13.1"></a>
## [0.13.1](https://github.com/libp2p/js-libp2p/compare/v0.13.0...v0.13.1) (2017-11-12)
<a name="0.13.0"></a>
# [0.13.0](https://github.com/libp2p/js-libp2p/compare/v0.12.4...v0.13.0) (2017-10-26)
### Features
* enable and test Circuit Relay ([29cc0af](https://github.com/libp2p/js-libp2p/commit/29cc0af))
<a name="0.12.4"></a>
## [0.12.4](https://github.com/libp2p/js-libp2p/compare/v0.12.3...v0.12.4) (2017-09-07)
<a name="0.12.3"></a>
## [0.12.3](https://github.com/libp2p/js-libp2p/compare/v0.12.2...v0.12.3) (2017-09-07)
<a name="0.12.2"></a>
## [0.12.2](https://github.com/libp2p/js-libp2p/compare/v0.12.0...v0.12.2) (2017-09-07)
<a name="0.12.1"></a>
## [0.12.1](https://github.com/libp2p/js-libp2p/compare/v0.12.0...v0.12.1) (2017-09-07)
<a name="0.12.0"></a>
# [0.12.0](https://github.com/libp2p/js-libp2p/compare/v0.11.0...v0.12.0) (2017-09-03)
### Features
* p2p addrs situation ([#119](https://github.com/libp2p/js-libp2p/issues/119)) ([cad173e](https://github.com/libp2p/js-libp2p/commit/cad173e))
<a name="0.11.0"></a>
# [0.11.0](https://github.com/libp2p/js-libp2p/compare/v0.10.2...v0.11.0) (2017-07-22)
<a name="0.10.2"></a>
## [0.10.2](https://github.com/libp2p/js-libp2p/compare/v0.10.1...v0.10.2) (2017-07-21)

View File

@ -1,6 +1,6 @@
# Contributing guidelines
libp2p as a project, including js-libp2p and all of its modules, follows the [standard IPFS Community contributing guidelines](https://github.com/ipfs/community/blob/master/js-project-guidelines.md).
libp2p as a project, including js-libp2p and all of its modules, follows the [standard IPFS Community contributing guidelines](https://github.com/ipfs/community/blob/master/contribution-guidelines.md).
We also adhere to the [IPFS JavaScript Community contributing guidelines](https://github.com/ipfs/community/blob/master/js-project-guidelines.md) which provide additional information of how to collaborate and contribute in the JavaScript implementation of libp2p.

43
ISSUE_TEMPLATE.md Normal file
View File

@ -0,0 +1,43 @@
<!--
Thank you for reporting an issue.
This issue tracker is for bugs and issues found within the JavaScript implementation of libp2p.
If you require more general support please file an issue on our discuss forum. https://discuss.ipfs.io/
Please fill in as much of the template below as you're able.
Version: package.json version or the commit you have installed.
Platform: output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows). If using in a Browser, please share the browser version as well.
Subsystem: if known, please specify affected core module name (e.g Transports, SECIO, etc).
If possible, please provide code that demonstrates the problem, keeping it as
simple and free of external dependencies as you are able.
-->
- **Version**:
- **Platform**:
- **Subsystem**:
<!-- Bug, Feature, Question, Enhancement, Etc -->
#### Type:
<!--
One of following:
Critical - System crash, application panic.
High - The main functionality of the application does not work, API breakage, repo format breakage, etc.
Medium - A non-essential functionality does not work, performance issues, etc.
Low - An optional functionality does not work.
Very Low - Translation or documentation mistake. Something that won't give anyone a bad day.
-->
#### Severity:
#### Description:
#### Steps to reproduce the error:
<!--
This is for you! Please read, and then delete this text before posting it.
The js-ipfs issues are only for bug reports and directly actionable features.
Read https://github.com/ipfs/community/blob/master/contributing.md#reporting-issues if your issue doesn't fit either of those categories.
-->

View File

@ -20,10 +20,18 @@
<a href="https://github.com/feross/standard"><img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/RichardLitt/standard-readme"><img src="https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square" /></a>
<a href=""><img src="https://img.shields.io/badge/npm-%3E%3D3.0.0-orange.svg?style=flat-square" /></a>
<a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D4.0.0-orange.svg?style=flat-square" /></a>
<a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D6.0.0-orange.svg?style=flat-square" /></a>
<br>
</p>
### Project status
We've come a long way, but this project is still in Alpha, lots of development is happening, API might change, beware of the Dragons 🐉..
**Want to get started?** Check our [examples folder](/examples). You can check the development status at the [Waffle Board](https://waffle.io/libp2p/js-libp2p).
[![Throughput Graph](https://graphs.waffle.io/libp2p/js-libp2p/throughput.svg)](https://waffle.io/libp2p/js-libp2p/metrics/throughput)
## Table of Contents
- [Background](#background)
@ -40,9 +48,9 @@
## 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 writting better documentation, blog posts, tutorials and a formal specification. Today you can find:
We are in the process of writing better documentation, blog posts, tutorials and a formal specification. Today you can find:
- [libp2p.io](https://libp2p.io)
- [Specification (WIP)](https://github.com/libp2p/specs)
@ -74,7 +82,7 @@ npm install --save libp2p
### [Tutorials and Examples](/examples)
You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarions.
You can find multiple examples on the [examples folder](/examples) that will guide you through using libp2p for several scenarios.
### Extending libp2p skeleton
@ -150,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.
#### `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][]
- `protocol`: String that defines the protocol (e.g '/ipfs/bitswap/1.1.0')
- `peer`: can be an instance of [PeerInfo][], [PeerId][], [multiaddr][], or a multiaddr string
- `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)
#### `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.
@ -188,10 +206,10 @@ class Node extends libp2p {
> Handle new protocol
- `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.
#### `libp2p.unhandle(protocol)
#### `libp2p.unhandle(protocol)`
> Stop handling protocol
@ -255,6 +273,42 @@ class Node extends libp2p {
[multiaddr]: https://github.com/multiformats/js-multiaddr
[Connection]: https://github.com/libp2p/interface-connection
## Development
**Clone and install dependencies:**
```sh
> git clone https://github.com/ipfs/js-ipfs.git
> cd js-ipfs
> npm install
```
### Tests
#### Run unit tests
```sh
# run all the unit tsts
> npm test
# run just Node.js tests
> npm run test:node
# run just Browser tests (Chrome)
> npm run test:browser
```
#### Run interop tests
```sh
N/A
```
#### Run benchmark tests
```sh
N/A
```
### Packages
@ -266,6 +320,8 @@ List of packages currently in existence for libp2p
| [`libp2p-utp`](//github.com/libp2p/js-libp2p-utp) | [![npm](https://img.shields.io/npm/v/libp2p-utp.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-utp/releases) | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-utp.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-utp) | [![devDependency Status](https://david-dm.org/libp2p/js-libp2p-utp/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-utp?type=dev) |
| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [![npm](https://img.shields.io/npm/v/libp2p-websockets.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-websockets/releases) | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets) | [![devDependency Status](https://david-dm.org/libp2p/js-libp2p-websockets/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets?type=dev) |
| [`libp2p-webrtc-star`](//github.com/libp2p/js-libp2p-webrtc-star) | [![npm](https://img.shields.io/npm/v/libp2p-webrtc-star.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-webrtc-star/releases) | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-webrtc-star.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-webrtc-star) | [![devDependency Status](https://david-dm.org/libp2p/js-libp2p-webrtc-star/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-webrtc-star?type=dev) |
| [`libp2p-websocket-star`](//github.com/libp2p/js-libp2p-websocket-star) | [![npm](https://img.shields.io/npm/v/libp2p-websocket-star.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-websocket-star/releases) | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-websocket-star.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websocket-star) | [![devDependency Status](https://david-dm.org/libp2p/js-libp2p-websocket-star/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websocket-star?type=dev) |
| [`libp2p-websocket-star-rendezvous`](//github.com/libp2p/js-libp2p-websocket-star-rendezvous) | [![npm](https://img.shields.io/npm/v/libp2p-websocket-star-rendezvous.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-websocket-star-rendezvous/releases) | [![Dependency Status](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous) | [![devDependency Status](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websocket-star-rendezvous?type=dev) |
| **Connection Upgrades** |
| [`interface-connection`](//github.com/libp2p/interface-connection) | [![npm](https://img.shields.io/npm/v/interface-connection.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/interface-connection/releases) | [![Dependency Status](https://david-dm.org/libp2p/interface-connection.svg?style=flat-square)](https://david-dm.org/libp2p/interface-connection) | [![devDependency Status](https://david-dm.org/libp2p/interface-connection/dev-status.svg?style=flat-square)](https://david-dm.org/libp2p/interface-connection?type=dev) |
| **Stream Muxers** |
@ -296,7 +352,7 @@ List of packages currently in existence for libp2p
The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out:
- Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrasture behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
- Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically.
- **Perform code reviews**. Most of this has been developed by @diasdavid, which means that more eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs.
- **Add tests**. There can never be enough tests.

29
appveyor.yml Normal file
View 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
View 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()

View File

@ -6,9 +6,13 @@ dependencies:
pre:
- google-chrome --version
- curl -L -o google-chrome.deb https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- for v in $(curl http://archive.ubuntu.com/ubuntu/pool/main/n/nss/ | grep "href=" | grep "libnss3.*deb\"" -o | grep -o "libnss3.*deb" | grep "3.28" | grep "14.04"); do curl -L -o $v http://archive.ubuntu.com/ubuntu/pool/main/n/nss/$v; done && rm libnss3-tools*_i386.deb libnss3-dev*_i386.deb
- sudo dpkg -i google-chrome.deb || true
- sudo dpkg -i libnss3*.deb || true
- sudo apt-get update
- sudo apt-get install -f || true
- sudo dpkg -i libnss3*.deb
- sudo apt-get install -f
- sudo apt-get install --only-upgrade lsb-base
- sudo dpkg -i google-chrome.deb
- google-chrome --version
- google-chrome --version

View File

@ -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)
- [Encrypted Communications](./encrypted-communications)
- [Discovery Mechanisms](./discovery-mechanisms)
- [Peer Routing](./peer-routing)
- [Content Routing](./content-routing)
- [Peer Routing](./peer-and-content-routing)
- [Content Routing](./peer-and-content-routing)
- [PubSub](./pubsub)
- [NAT Traversal](./nat-traversal)
- Circuit Relay (future)

View File

@ -47,7 +47,7 @@ async.parallel([
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) {
throw err
}

View File

@ -38,7 +38,7 @@ async.parallel([
'/ipfs/' + dialerId.toB58String()))
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 }
console.log('nodeA dialed to nodeB on protocol: /echo/1.0.0')

View File

@ -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 }
pull(pull.values(['This information is sent out encrypted to the other peer']), conn)
})

View File

@ -32,7 +32,7 @@ class MyBundle extends libp2p {
}
```
And that's it, from now on, all your libp2p communications are encrypted. Try running the exampme [1.js](./1.js) to see it working.
And that's it, from now on, all your libp2p communications are encrypted. Try running the example [1.js](./1.js) to see it working.
If you want to want to learn more about how SECIO works, you can read the [great write up done by Dominic Tarr](https://github.com/auditdrivencrypto/secure-channel/blob/master/prior-art.md#ipfss-secure-channel).

View File

@ -10,20 +10,20 @@
},
"license": "MIT",
"devDependencies": {
"browserify": "^14.0.0",
"browserify": "^14.5.0",
"concat-stream": "^1.6.0",
"detect-dom-ready": "^1.0.2",
"node-static": "^0.7.9"
"node-static": "^0.7.10"
},
"dependencies": {
"detect-dom-ready": "^1.0.2",
"libp2p": "^0.10.0",
"libp2p-multiplex": "^0.4.4",
"libp2p-railing": "^0.5.2",
"libp2p-secio": "^0.6.8",
"libp2p-spdy": "^0.10.6",
"libp2p-webrtc-star": "^0.11.0",
"libp2p-websockets": "^0.10.0",
"peer-info": "^0.9.3"
"libp2p": "^0.13.0",
"libp2p-multiplex": "^0.5.0",
"libp2p-railing": "^0.7.1",
"libp2p-secio": "^0.8.1",
"libp2p-spdy": "^0.11.0",
"libp2p-webrtc-star": "^0.13.2",
"libp2p-websockets": "^0.10.4",
"peer-info": "^0.11.0"
}
}

View File

@ -19,7 +19,9 @@ const bootstrapers = [
'/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64'
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
'/dns4/wss0.bootstrap.libp2p.io/tcp/443/wss/ipfs/QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic',
'/dns4/wss1.bootstrap.libp2p.io/tcp/443/wss/ipfs/Qmbut9Ywz9YEDrz8ySBSgWyJk41Uvm2QJPhwDJzJyGFsD6'
]
class Node extends libp2p {

View File

@ -10,7 +10,7 @@ function createNode (callback) {
}
const peerIdStr = peerInfo.id.toB58String()
const ma = `/libp2p-webrtc-star/dns4/star-signal.cloud.ipfs.team/wss/ipfs/${peerIdStr}`
const ma = `/dns4/star-signal.cloud.ipfs.team/tcp/443/wss/p2p-webrtc-star/ipfs/${peerIdStr}`
peerInfo.multiaddrs.add(ma)

View File

@ -12,3 +12,5 @@ Simple go into the folder [1](./1) and execute the following
> npm start
# open your browser in port :9090
```
[Version Published on IPFS](http://ipfs.io/ipfs/Qmbc1J7ehw1dNYachbkCWPto4RsnVvqCKNVzmYEod2gXcy)

View File

@ -53,7 +53,7 @@ parallel([
(cb) => node1.dial(node2.peerInfo, cb),
(cb) => node2.dial(node3.peerInfo, cb),
// Set up of the cons might take time
(cb) => setTimeout(cb, 100)
(cb) => setTimeout(cb, 300)
], (err) => {
if (err) { throw err }

View File

@ -54,7 +54,7 @@ parallel([
(cb) => node1.dial(node2.peerInfo, cb),
(cb) => node2.dial(node3.peerInfo, cb),
// Set up of the cons might take time
(cb) => setTimeout(cb, 100)
(cb) => setTimeout(cb, 300)
], (err) => {
if (err) { throw err }

View File

@ -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 }
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 }
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 }
pull(pull.values(['do I fall into your criteria?']), conn)
})

View File

@ -60,17 +60,17 @@ parallel([
})
series([
(cb) => node1.dial(node2.peerInfo, '/a', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/a', (err, conn) => {
if (err) { throw err }
pull(pull.values(['protocol (a)']), conn)
cb()
}),
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
if (err) { throw err }
pull(pull.values(['protocol (b)']), conn)
cb()
}),
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
if (err) { throw err }
pull(pull.values(['another conn on protocol (b)']), conn)
cb()

View File

@ -74,10 +74,10 @@ parallel([
if (err) { throw err }
console.log('Addresses by which both peers are connected')
node1.peerBook
.getAllArray()
.forEach((peer) => console.log('node 1 to node 2:', peer.isConnected().toString()))
.getAllArray()
.forEach((peer) => console.log('node 1 to node 2:', peer.isConnected().toString()))
node2.peerBook
.getAllArray()
.forEach((peer) => console.log('node 2 to node 1:', peer.isConnected().toString()))
.getAllArray()
.forEach((peer) => console.log('node 2 to node 1:', peer.isConnected().toString()))
})
})

View File

@ -30,7 +30,7 @@ node2.handle('/your-protocol', (protocol, conn) => {
After the protocol is _handled_, now we can dial to it.
```JavaScript
node1.dial(node2.peerInfo, '/your-protocol', (err, conn) => {
node1.dialProtocol(node2.peerInfo, '/your-protocol', (err, conn) => {
if (err) { throw err }
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 }
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 }
pull(pull.values(['do I fall into your criteria?']), conn)
})
@ -129,17 +129,17 @@ node2.handle('/b', (protocol, conn) => {
})
series([
(cb) => node1.dial(node2.peerInfo, '/a', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/a', (err, conn) => {
if (err) { throw err }
pull(pull.values(['protocol (a)']), conn)
cb()
}),
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
if (err) { throw err }
pull(pull.values(['protocol (b)']), conn)
cb()
}),
(cb) => node1.dial(node2.peerInfo, '/b', (err, conn) => {
(cb) => node1.dialProtocol(node2.peerInfo, '/b', (err, conn) => {
if (err) { throw err }
pull(pull.values(['another conn on protocol (b)']), conn)
cb()
@ -158,9 +158,9 @@ another protocol (b)
# 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:

View File

@ -26,7 +26,7 @@ waterfall([
], (err) => {
if (err) { throw err }
console.log('node has started (true/false):', node.isOn())
console.log('node has started (true/false):', node.isStarted())
console.log('listening on:')
node.peerInfo.multiaddrs.forEach((ma) => console.log(ma.toString()))
})

View File

@ -54,7 +54,7 @@ parallel([
)
})
node1.dial(node2.peerInfo, '/print', (err, conn) => {
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
if (err) { throw err }
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)

View File

@ -66,19 +66,19 @@ parallel([
node2.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 }
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 }
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) {
console.log('node 3 failed to dial to node 1 with:', err.message)
}

View File

@ -8,7 +8,7 @@ A more complete definition of what is a transport can be found on the [interface
## 1. Creating a libp2p Bundle with TCP
When using libp2p, you always want to create your own libp2p Bundle, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a bundle with TCP. You can find the complete solution on the file [1.js](/1.js).
When using libp2p, you always want to create your own libp2p Bundle, that is, pick your set of modules and create your network stack with the properties you need. In this example, we will create a bundle with TCP. You can find the complete solution on the file [1.js](./1.js).
You will need 4 deps total, so go ahead and install all of them with:
@ -65,7 +65,7 @@ waterfall([
if (err) { throw err }
// At this point the node has started
console.log('node has started (true/false):', node.isOn())
console.log('node has started (true/false):', node.isStarted())
// And we can print the now listening addresses.
// If you are familiar with TCP, you might have noticed
// that we specified the node to listen in 0.0.0.0 and port
@ -90,7 +90,7 @@ That `QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ` is the PeerId that was cre
## 2. Dialing from one node to another node
Now that we have our bundle, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](/2.js).
Now that we have our bundle, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](./2.js).
For this step, we will need one more dependency.
@ -143,7 +143,7 @@ parallel([
)
})
node1.dial(node2.peerInfo, '/print', (err, conn) => {
node1.dialProtocol(node2.peerInfo, '/print', (err, conn) => {
if (err) { throw err }
pull(pull.values(['Hello', ' ', 'p2p', ' ', 'world', '!']), conn)
@ -168,7 +168,7 @@ Hello p2p world!
Next, we want to be available in multiple transports to increase our chances of having common transports in the network. A simple scenario, a node running in the browser only has access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport, for this node to dial to some other node, that other node needs to share a common transport.
What we are going to do in this step is to create 3 nodes, one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](3.js).
What we are going to do in this step is to create 3 nodes, one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js).
In this example, we will need to also install `libp2p-websockets`, go ahead and install:
@ -240,21 +240,21 @@ parallel([
node3.handle('/print', print)
// 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 }
pull(pull.values(['node 1 dialed to node 2 successfully']), conn)
})
// 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 }
pull(pull.values(['node 2 dialed to node 3 successfully']), conn)
})
// 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) {
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.
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.
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!

View File

@ -1,55 +0,0 @@
'use strict'
const gulp = require('gulp')
const Node = require('./test/nodejs-bundle/nodejs-bundle.js')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream')
const sigServer = require('libp2p-webrtc-star/src/sig-server')
let server
let node
const rawPeer = require('./test/browser-bundle/peer.json')
gulp.task('libnode:start', (done) => {
let count = 0
const ready = () => ++count === 2 ? done() : null
sigServer.start({ port: 15555 }, (err, _server) => {
if (err) {
throw err
}
server = _server
ready()
})
PeerId.createFromJSON(rawPeer, (err, peerId) => {
if (err) {
return done(err)
}
const peer = new PeerInfo(peerId)
peer.multiaddrs.add('/ip4/127.0.0.1/tcp/9200/ws')
node = new Node(peer)
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
node.start(() => ready())
})
})
gulp.task('libnode:stop', (done) => {
setTimeout(() => node.stop((err) => {
if (err) {
return done(err)
}
server.stop(done)
}), 2000)
})
gulp.task('test:browser:before', ['libnode:start'])
gulp.task('test:node:before', ['libnode:start'])
gulp.task('test:browser:after', ['libnode:stop'])
gulp.task('test:node:after', ['libnode:stop'])
require('aegir/gulp')(gulp)

View File

@ -1,19 +1,19 @@
{
"name": "libp2p",
"version": "0.10.2",
"version": "0.16.1",
"description": "JavaScript base class for libp2p bundles",
"main": "src/index.js",
"scripts": {
"test": "gulp test",
"test:node": "gulp test:node",
"test:browser": "gulp test:browser --dom",
"release": "gulp release --dom",
"release-minor": "gulp release --type minor --dom",
"release-major": "gulp release --type major --dom",
"build": "gulp build",
"lint": "aegir-lint",
"coverage": "aegir-coverage",
"coverage-publish": "aegir-coverage publish"
"lint": "aegir lint",
"build": "aegir build",
"test": "aegir test -t node -t browser",
"test:node": "aegir test -t node",
"test:browser": "aegir test -t browser",
"release": "aegir release -t node -t browser",
"release-minor": "aegir release --type minor -t node -t browser",
"release-major": "aegir release --type major -t node -t browser",
"coverage": "aegir coverage",
"coverage-publish": "aegir coverage --provider coveralls"
},
"repository": {
"type": "git",
@ -23,10 +23,10 @@
"IPFS"
],
"engines": {
"node": ">=4.0.0",
"node": ">=6.0.0",
"npm": ">=3.0.0"
},
"pre-commit": [
"pre-push": [
"lint",
"test"
],
@ -37,45 +37,65 @@
},
"homepage": "https://github.com/libp2p/js-libp2p",
"dependencies": {
"async": "^2.5.0",
"libp2p-ping": "~0.4.0",
"libp2p-swarm": "~0.30.0",
"mafmt": "^2.1.8",
"multiaddr": "^2.3.0",
"peer-book": "~0.4.0",
"peer-id": "~0.8.8",
"peer-info": "~0.9.4"
"async": "^2.6.0",
"libp2p-ping": "~0.6.0",
"libp2p-switch": "~0.36.0",
"mafmt": "^3.0.2",
"multiaddr": "^3.0.2",
"peer-book": "~0.5.4",
"peer-id": "~0.10.5",
"peer-info": "~0.11.6"
},
"devDependencies": {
"aegir": "^11.0.2",
"chai": "^4.1.0",
"aegir": "^12.4.0",
"chai": "^4.1.2",
"cids": "~0.5.2",
"dirty-chai": "^2.0.1",
"cids": "~0.5.1",
"libp2p-kad-dht": "~0.3.0",
"libp2p-mdns": "~0.7.1",
"libp2p-multiplex": "~0.4.4",
"libp2p-railing": "~0.5.2",
"libp2p-secio": "~0.6.8",
"libp2p-spdy": "~0.10.6",
"libp2p-tcp": "~0.10.1",
"libp2p-webrtc-star": "~0.11.0",
"libp2p-websockets": "~0.10.0",
"electron-webrtc": "~0.3.0",
"libp2p-circuit": "~0.1.4",
"libp2p-kad-dht": "~0.6.3",
"libp2p-mdns": "~0.9.2",
"libp2p-multiplex": "~0.5.1",
"libp2p-railing": "~0.7.1",
"libp2p-secio": "~0.9.1",
"libp2p-spdy": "~0.11.0",
"libp2p-tcp": "~0.11.5",
"libp2p-webrtc-star": "~0.13.3",
"libp2p-websockets": "~0.10.4",
"libp2p-websocket-star": "~0.7.2",
"libp2p-websocket-star-rendezvous": "~0.2.2",
"lodash.times": "^4.3.2",
"pre-commit": "^1.2.2",
"pull-goodbye": "0.0.2",
"pull-serializer": "^0.3.2",
"pull-stream": "^3.6.0",
"pull-serializer": "~0.3.2",
"pull-stream": "^3.6.1",
"safe-buffer": "^5.1.1",
"electron-webrtc": "^0.3.0",
"wrtc": "0.0.62"
"sinon": "^4.2.2",
"wrtc": "0.0.65"
},
"contributors": [
"Chris Bratlien <chrisbratlien@gmail.com>",
"Chris Dostert <chrisdostert@users.noreply.github.com>",
"Daijiro Wachi <daijiro.wachi@gmail.com>",
"David Dias <daviddias.p@gmail.com>",
"Dmitriy Ryajov <dryajov@gmail.com>",
"Elven <mon.samuel@qq.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>",
"Maciej Krüger <mkg20001@gmail.com>",
"Nuno Nogueira <nunofmn@gmail.com>",
"Pedro Teixeira <i@pgte.me>",
"RasmusErik Voel Jensen <github@solsort.com>",
"Richard Littauer <richard.littauer@gmail.com>",
"Ryan Bell <ryan@piing.net>",
"Tiago Alves <alvesjtiago@gmail.com>",
"greenkeeperio-bot <support@greenkeeper.io>",
"mayerwin <mayerwin@users.noreply.github.com>"
"mayerwin <mayerwin@users.noreply.github.com>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>"
]
}
}

3
pdd/README.md Normal file
View 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
View 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"
}
}

View 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')))
})
})

View 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')))
})
})

View 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'))
})
)
})
})
})

View 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')
})
})
)
})
})
})

View 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'))
})
)
})
})
})

View 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
)
})
})
})

View 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)
})
})

View 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
View 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
View 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)
}
}
}

48
src/get-peer-info.js Normal file
View 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))
}
}

View File

@ -7,13 +7,14 @@ const setImmediate = require('async/setImmediate')
const each = require('async/each')
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 mafmt = require('mafmt')
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 getPeerInfo = require('./get-peer-info')
exports = module.exports
@ -32,25 +33,28 @@ class Node extends EventEmitter {
this._isStarted = false
this.swarm = new Swarm(this.peerInfo, this.peerBook)
this.switch = new Switch(this.peerInfo, this.peerBook)
// Attach stream multiplexers
if (this.modules.connection && this.modules.connection.muxer) {
let muxers = this.modules.connection.muxer
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
this.swarm.connection.reuse()
this.switch.connection.reuse()
// If muxer exists, we can use Relay for listening/dialing
this.switch.connection.enableCircuitRelay(_options.relay)
// Received incommind dial and muxer upgrade happened,
// reuse this muxed connection
this.swarm.on('peer-mux-established', (peerInfo) => {
this.switch.on('peer-mux-established', (peerInfo) => {
this.emit('peer:connect', peerInfo)
this.peerBook.put(peerInfo)
})
this.swarm.on('peer-mux-closed', (peerInfo) => {
this.switch.on('peer-mux-closed', (peerInfo) => {
this.emit('peer:disconnect', peerInfo)
})
}
@ -60,7 +64,7 @@ class Node extends EventEmitter {
let cryptos = this.modules.connection.crypto
cryptos = Array.isArray(cryptos) ? cryptos : [cryptos]
cryptos.forEach((crypto) => {
this.swarm.connection.crypto(crypto.tag, crypto.encrypt)
this.switch.connection.crypto(crypto.tag, crypto.encrypt)
})
}
@ -74,67 +78,22 @@ class Node extends EventEmitter {
})
}
// Mount default protocols
Ping.mount(this.swarm)
// dht provided components (peerRouting, contentRouting, dht)
if (_modules.DHT) {
this._dht = new this.modules.DHT(this.swarm, {
this._dht = new this.modules.DHT(this.switch, {
kBucketSize: 20,
datastoer: _options.DHT && _options.DHT.datastore
datastore: _options.DHT && _options.DHT.datastore
})
}
this.peerRouting = {
findPeer: (id, callback) => {
if (!this._dht) {
return callback(new Error('DHT is not available'))
}
this.peerRouting = peerRouting(this)
this.contentRouting = contentRouting(this)
this.dht = dht(this)
this._dht.findPeer(id, callback)
}
}
this._getPeerInfo = getPeerInfo(this)
this.contentRouting = {
findProviders: (key, timeout, callback) => {
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)
}
}
// Mount default protocols
Ping.mount(this.switch)
}
/*
@ -154,18 +113,18 @@ class Node extends EventEmitter {
// so that we can have webrtc-star addrs without adding manually the id
const maOld = []
const maNew = []
this.peerInfo.multiaddrs.forEach((ma) => {
if (!mafmt.IPFS.matches(ma)) {
this.peerInfo.multiaddrs.toArray().forEach((ma) => {
if (!ma.getPeerId()) {
maOld.push(ma)
maNew.push(ma.encapsulate('/ipfs/' + this.peerInfo.id.toB58String()))
}
})
this.peerInfo.multiaddrs.replace(maOld, maNew)
const multiaddrs = this.peerInfo.multiaddrs.toArray()
const multiaddrs = this.peerInfo.multiaddrs.toArray()
transports.forEach((transport) => {
if (transport.filter(multiaddrs).length > 0) {
this.swarm.transport.add(
this.switch.transport.add(
transport.tag || transport.constructor.name, transport)
} else if (transport.constructor &&
transport.constructor.name === 'WebSockets') {
@ -176,11 +135,11 @@ class Node extends EventEmitter {
})
series([
(cb) => this.swarm.listen(cb),
(cb) => this.switch.start(cb),
(cb) => {
if (ws) {
// 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
@ -198,6 +157,19 @@ class Node extends EventEmitter {
}
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) => {
this.emit('start')
cb()
@ -209,8 +181,6 @@ class Node extends EventEmitter {
* Stop the libp2p node by closing its listeners and open connections
*/
stop (callback) {
this._isStarted = false
if (this.modules.discovery) {
this.modules.discovery.forEach((discovery) => {
setImmediate(() => discovery.stop(() => {}))
@ -224,30 +194,37 @@ class Node extends EventEmitter {
}
cb()
},
(cb) => this.swarm.close(cb),
(cb) => this.switch.stop(cb),
(cb) => {
this.emit('stop')
cb()
}
], callback)
], (err) => {
this._isStarted = false
callback(err)
})
}
isStarted () {
return this._isStarted
}
ping (peer, callback) {
dial (peer, callback) {
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)
if (typeof protocol === 'function') {
@ -256,14 +233,10 @@ class Node extends EventEmitter {
}
this._getPeerInfo(peer, (err, peerInfo) => {
if (err) {
return callback(err)
}
if (err) { return callback(err) }
this.swarm.dial(peerInfo, protocol, (err, conn) => {
if (err) {
return callback(err)
}
this.switch.dial(peerInfo, protocol, (err, conn) => {
if (err) { return callback(err) }
this.peerBook.put(peerInfo)
callback(null, conn)
})
@ -274,52 +247,27 @@ class Node extends EventEmitter {
assert(this.isStarted(), NOT_STARTED_ERROR_MESSAGE)
this._getPeerInfo(peer, (err, peerInfo) => {
if (err) {
return callback(err)
}
if (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) {
this.swarm.handle(protocol, handlerFunc, matchFunc)
this.switch.handle(protocol, handlerFunc, matchFunc)
}
unhandle (protocol) {
this.swarm.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))
this.switch.unhandle(protocol)
}
}

13
src/peer-routing.js Normal file
View 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)
}
}
}

View File

@ -1,121 +0,0 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const parallel = require('async/parallel')
const pull = require('pull-stream')
const Node = require('./browser-bundle')
describe('libp2p-ipfs-browser (webrtc only)', () => {
let peer1
let peer2
let node1
let node2
it('create two peerInfo with webrtc-star addrs', (done) => {
parallel([
(cb) => PeerId.create({ bits: 1024 }, cb),
(cb) => PeerId.create({ bits: 1024 }, cb)
], (err, ids) => {
expect(err).to.not.exist()
peer1 = new PeerInfo(ids[0])
const ma1 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[0].toB58String()
peer1.multiaddrs.add(ma1)
peer2 = new PeerInfo(ids[1])
const ma2 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + ids[1].toB58String()
peer2.multiaddrs.add(ma2)
done()
})
})
it('create two libp2p nodes with those peers', (done) => {
node1 = new Node(peer1, null, { webRTCStar: true })
node2 = new Node(peer2, null, { webRTCStar: true })
done()
})
it('listen on the two libp2p nodes', (done) => {
parallel([
(cb) => node1.start(cb),
(cb) => node2.start(cb)
], done)
})
it('handle a protocol on the first node', () => {
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
})
it('dial from the second node to the first node', (done) => {
node1.dial(peer2, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const text = 'hello'
const peers1 = node1.peerBook.getAll()
expect(Object.keys(peers1)).to.have.length(1)
const peers2 = node2.peerBook.getAll()
expect(Object.keys(peers2)).to.have.length(1)
pull(
pull.values([Buffer(text)]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data[0].toString()).to.equal(text)
done()
})
)
}
})
})
it('node1 hangUp node2', (done) => {
node1.hangUp(peer2, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = node1.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(node1.swarm.muxedConns)).to.have.length(0)
done()
}
})
})
it('create a third node and check that discovery works', (done) => {
let counter = 0
function check () {
if (++counter === 3) {
expect(Object.keys(node1.swarm.muxedConns).length).to.equal(1)
expect(Object.keys(node2.swarm.muxedConns).length).to.equal(1)
done()
}
}
PeerId.create((err, id3) => {
expect(err).to.not.exist()
const peer3 = new PeerInfo(id3)
const ma3 = '/libp2p-webrtc-star/ip4/127.0.0.1/tcp/15555/ws/ipfs/' + id3.toB58String()
peer3.multiaddrs.add(ma3)
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
const node3 = new Node(peer3, null, { webRTCStar: true })
node3.start(check)
})
})
})

View File

@ -1,201 +0,0 @@
/* eslint max-nested-callbacks: ["error", 8] */
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream')
const goodbye = require('pull-goodbye')
const serializer = require('pull-serializer')
const Buffer = require('safe-buffer').Buffer
const Node = require('./browser-bundle')
const rawPeer = require('./peer.json')
describe('libp2p-ipfs-browser (websockets only)', () => {
let peerB
let nodeA
before((done) => {
const ma = '/ip4/127.0.0.1/tcp/9200/ws/ipfs/' + rawPeer.id
PeerId.createFromPrivKey(rawPeer.privKey, (err, id) => {
if (err) {
return done(err)
}
peerB = new PeerInfo(id)
peerB.multiaddrs.add(ma)
done()
})
})
after((done) => nodeA.stop(done))
it('create libp2pNode', (done) => {
PeerInfo.create((err, peerInfo) => {
expect(err).to.not.exist()
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
nodeA = new Node(peerInfo)
done()
})
})
it('create libp2pNode with multiplex only', (done) => {
PeerInfo.create((err, peerInfo) => {
expect(err).to.not.exist()
const b = new Node(peerInfo, null, { muxer: ['multiplex'] })
expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')])
done()
})
})
it('start libp2pNode', (done) => {
nodeA.start(done)
})
// General connectivity tests
it('libp2p.dial using Multiaddr nodeA to nodeB', (done) => {
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500) // Some time for Identify to finish
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
done()
}
})
})
it('libp2p.dial using Multiaddr on Protocol nodeA to nodeB', (done) => {
nodeA.dial(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
pull(
pull.values([Buffer.from('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.eql([Buffer.from('hey')])
done()
})
)
})
})
it('libp2p.hangUp using Multiaddr nodeA to nodeB', (done) => {
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
done()
}
})
})
it('libp2p.dial using PeerInfo nodeA to nodeB', (done) => {
nodeA.dial(peerB, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500) // Some time for Identify to finish
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
done()
}
})
})
it('libp2p.dial using PeerInfo on Protocol nodeA to nodeB', (done) => {
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
pull(
pull.values([Buffer.from('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.eql([Buffer.from('hey')])
done()
})
)
})
})
it('libp2p.hangUp using PeerInfo nodeA to nodeB', (done) => {
nodeA.hangUp(peerB, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
done()
}
})
})
describe('stress', () => {
it('one big write', (done) => {
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const rawMessage = Buffer.alloc(100000)
rawMessage.fill('a')
const s = serializer(goodbye({
source: pull.values([rawMessage]),
sink: pull.collect((err, results) => {
expect(err).to.not.exist()
expect(results).to.have.length(1)
expect(Buffer.from(results[0])).to.have.length(rawMessage.length)
done()
})
}))
pull(s, conn, s)
})
})
it('many writes', (done) => {
nodeA.dial(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const s = serializer(goodbye({
source: pull(
pull.infinite(),
pull.take(1000),
pull.map((val) => Buffer.from(val.toString()))
),
sink: pull.collect((err, result) => {
expect(err).to.not.exist()
expect(result).to.have.length(1000)
done()
})
}))
pull(s, conn, s)
})
})
})
})

View File

@ -1,7 +1,4 @@
'use strict'
const w = require('webrtcsupport')
require('./base')
require('./browser-bundle/websockets-only')
if (w.support) { require('./browser-bundle/webrtc-star-only') }
require('./transports.browser')

201
test/circuit-relay.node.js Normal file
View File

@ -0,0 +1,201 @@
/* eslint-env mocha */
'use strict'
const waterfall = require('async/waterfall')
const series = require('async/series')
const parallel = require('async/parallel')
const utils = require('./utils/node')
const Circuit = require('libp2p-circuit')
const multiaddr = require('multiaddr')
const tryEcho = require('./utils/try-echo')
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const sinon = require('sinon')
describe('circuit relay', function () {
let handlerSpies = []
let relayNode1
let relayNode2
let nodeWS1
let nodeWS2
let nodeTCP1
let nodeTCP2
function setupNode (addrs, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
}
options = options || {}
return utils.createNode(addrs, options, (err, node) => {
expect(err).to.not.exist()
node.handle('/echo/1.0.0', utils.echo)
node.start((err) => {
expect(err).to.not.exist()
handlerSpies.push(sinon.spy(node.switch.transports[Circuit.tag].listeners[0].hopHandler, 'handle'))
cb(node)
})
})
}
before(function (done) {
this.timeout(20000)
waterfall([
// set up passive relay
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0/ws',
'/ip4/0.0.0.0/tcp/0'
], {
relay: {
enabled: true,
hop: {
enabled: true,
active: false // passive relay
}
}
}, (node) => {
relayNode1 = node
cb()
}),
// setup active relay
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0/ws',
'/ip4/0.0.0.0/tcp/0'
], {
relay: {
enabled: true,
hop: {
enabled: true,
active: false // passive relay
}
}
}, (node) => {
relayNode2 = node
cb()
}),
// setup node with WS
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0/ws'
], {
relay: {
enabled: true
}
}, (node) => {
nodeWS1 = node
cb()
}),
// setup node with WS
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0/ws'
], {
relay: {
enabled: true
}
}, (node) => {
nodeWS2 = node
cb()
}),
// set up node with TCP and listening on relay1
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0',
`/ipfs/${relayNode1.peerInfo.id.toB58String()}/p2p-circuit`
], {
relay: {
enabled: true
}
}, (node) => {
nodeTCP1 = node
cb()
}),
// set up node with TCP and listening on relay2 over TCP transport
(cb) => setupNode([
'/ip4/0.0.0.0/tcp/0',
`/ip4/0.0.0.0/tcp/0/ipfs/${relayNode2.peerInfo.id.toB58String()}/p2p-circuit`
], {
relay: {
enabled: true
}
}, (node) => {
nodeTCP2 = node
cb()
})
], (err) => {
expect(err).to.not.exist()
series([
(cb) => nodeWS1.dial(relayNode1.peerInfo, cb),
(cb) => nodeWS1.dial(relayNode2.peerInfo, cb),
(cb) => nodeTCP1.dial(relayNode1.peerInfo, cb),
(cb) => nodeTCP2.dial(relayNode2.peerInfo, cb)
], done)
})
})
after((done) => {
parallel([
(cb) => relayNode1.stop(cb),
(cb) => relayNode2.stop(cb),
(cb) => nodeWS1.stop(cb),
(cb) => nodeWS2.stop(cb),
(cb) => nodeTCP1.stop(cb),
(cb) => nodeTCP2.stop(cb)
], done)
})
describe('any relay', function () {
this.timeout(20 * 1000)
it('dial from WS1 to TCP1 over any R', (done) => {
nodeWS1.dialProtocol(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.exist()
tryEcho(conn, done)
})
})
it('fail to dial - no R from WS2 to TCP1', (done) => {
nodeWS2.dialProtocol(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.exist()
expect(conn).to.not.exist()
done()
})
})
})
describe('explicit relay', function () {
this.timeout(20 * 1000)
it('dial from WS1 to TCP1 over R1', (done) => {
nodeWS1.dialProtocol(nodeTCP1.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.exist()
tryEcho(conn, () => {
const addr = multiaddr(handlerSpies[0].args[2][0].dstPeer.addrs[0]).toString()
expect(addr).to.equal(`/ipfs/${nodeTCP1.peerInfo.id.toB58String()}`)
done()
})
})
})
it('dial from WS1 to TCP2 over R2', (done) => {
nodeWS1.dialProtocol(nodeTCP2.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
expect(conn).to.exist()
tryEcho(conn, () => {
const addr = multiaddr(handlerSpies[1].args[2][0].dstPeer.addrs[0]).toString()
expect(addr).to.equal(`/ipfs/${nodeTCP2.peerInfo.id.toB58String()}`)
done()
})
})
})
})
})

View File

@ -7,10 +7,10 @@ const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const utils = require('./utils')
const createNode = utils.createNode
const _times = require('lodash.times')
const CID = require('cids')
const utils = require('./utils/node')
const createNode = utils.createNode
describe('.contentRouting', () => {
let nodeA
@ -19,7 +19,8 @@ describe('.contentRouting', () => {
let nodeD
let nodeE
before((done) => {
before(function (done) {
this.timeout(5 * 1000)
const tasks = _times(5, () => (cb) => {
createNode('/ip4/0.0.0.0/tcp/0', {
mdns: false,

40
test/multiaddr-trim.js Normal file
View 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)
})
})
})

View File

@ -1,10 +1,10 @@
'use strict'
require('./base')
require('./nodejs-bundle/tcp')
require('./nodejs-bundle/tcp+websockets')
require('./nodejs-bundle/tcp+websockets+webrtc-star')
require('./nodejs-bundle/stream-muxing')
require('./nodejs-bundle/discovery')
require('./nodejs-bundle/peer-routing')
require('./nodejs-bundle/content-routing')
require('./transports.node')
require('./stream-muxing.node')
require('./peer-discovery.node')
require('./peer-routing.node')
require('./content-routing.node')
require('./circuit-relay.node')
require('./multiaddr-trim')

View File

@ -1,30 +0,0 @@
#! /usr/bin/env node
'use strict'
const Node = require('./nodejs-bundle')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream')
const idBak = require('./test-data/test-id.json')
PeerId.createFromJSON(idBak, (err, peerId) => {
if (err) {
throw err
}
const peerInfo = new PeerInfo(peerId)
peerInfo.multiaddrs.add('/ip4/127.0.0.1/tcp/12345')
const node = new Node(peerInfo)
node.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
node.start((err) => {
if (err) { throw err }
console.log('Spawned node started, env:', process.env.LIBP2P_MUXER)
})
})

View File

@ -1,246 +0,0 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const signalling = require('libp2p-webrtc-star/src/sig-server')
const WStar = require('libp2p-webrtc-star')
const wrtc = require('wrtc')
const utils = require('./utils')
const createNode = utils.createNode
const echo = utils.echo
describe('TCP + WebSockets + WebRTCStar', () => {
let nodeAll
let nodeTCP
let nodeWS
let nodeWStar
let ss
before((done) => {
parallel([
(cb) => {
signalling.start({ port: 24642 }, (err, server) => {
expect(err).to.not.exist()
ss = server
cb()
})
},
(cb) => {
const wstar = new WStar({wrtc: wrtc})
createNode([
'/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws',
'/libp2p-webrtc-star/ip4/127.0.0.1/tcp/24642/ws'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeAll = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
},
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0'
], (err, node) => {
expect(err).to.not.exist()
nodeTCP = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/127.0.0.1/tcp/25022/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => {
const wstar = new WStar({wrtc: wrtc})
createNode([
'/libp2p-webrtc-star/ip4/127.0.0.1/tcp/24642/ws'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeWStar = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
}
], done)
})
after((done) => {
parallel([
(cb) => nodeAll.stop(cb),
(cb) => nodeTCP.stop(cb),
(cb) => nodeWS.stop(cb),
(cb) => nodeWStar.stop(cb),
(cb) => ss.stop(done)
], done)
})
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
nodeAll.dial(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
nodeAll.dial(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeAll.dial nodeWStar using PeerInfo', (done) => {
nodeAll.dial(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(3)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeWStar.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeAll.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(3)
expect(Object.keys(nodeAll.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeWStar.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWStar.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
})

View File

@ -1,167 +0,0 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
// const multiaddr = require('multiaddr')
// const pull = require('pull-stream')
const utils = require('./utils')
const createNode = utils.createNode
const echo = utils.echo
describe('TCP + WebSockets', () => {
let nodeTCP
let nodeTCPnWS
let nodeWS
before((done) => {
parallel([
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0'
], (err, node) => {
expect(err).to.not.exist()
nodeTCP = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeTCPnWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/127.0.0.1/tcp/25022/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
], done)
})
after((done) => {
parallel([
(cb) => nodeTCP.stop(cb),
(cb) => nodeTCPnWS.stop(cb),
(cb) => nodeWS.stop(cb)
], done)
})
it('nodeTCP.dial nodeTCPnWS using PeerInfo', (done) => {
nodeTCP.dial(nodeTCPnWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeTCP.hangUp nodeTCPnWS using PeerInfo', (done) => {
nodeTCP.hangUp(nodeTCPnWS.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeTCPnWS.dial nodeWS using PeerInfo', (done) => {
nodeTCPnWS.dial(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeTCPnWS.hangUp nodeWS using PeerInfo', (done) => {
nodeTCPnWS.hangUp(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeTCPnWS.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
// Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
// Everynode will be able to dial in WebSockets
it.skip('nodeTCP.dial nodeWS using PeerInfo is unsuccesful', (done) => {
nodeTCP.dial(nodeWS.peerInfo, (err) => {
expect(err).to.exist()
done()
})
})
})

View File

@ -1,234 +0,0 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const series = require('async/series')
const pull = require('pull-stream')
const utils = require('./utils')
const createNode = utils.createNode
const echo = utils.echo
describe('TCP only', () => {
let nodeA
let nodeB
before((done) => {
parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
expect(err).to.not.exist()
nodeA = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
expect(err).to.not.exist()
nodeB = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
], done)
})
after((done) => {
parallel([
(cb) => nodeA.stop(cb),
(cb) => nodeB.stop(cb)
], done)
})
it('nodeA.dial nodeB using PeerInfo without proto (warmup)', (done) => {
nodeA.dial(nodeB.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeA.dial nodeB using PeerInfo', (done) => {
nodeA.dial(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
pull(
pull.values([new Buffer('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.be.eql([new Buffer('hey')])
done()
})
)
})
})
it('nodeA.hangUp nodeB using PeerInfo (first)', (done) => {
nodeA.hangUp(nodeB.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeA.dial nodeB using multiaddr', (done) => {
nodeA.dial(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
expect(err).to.not.exist()
series([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
cb()
}
], () => {
pull(
pull.values([new Buffer('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.be.eql([new Buffer('hey')])
done()
})
)
})
}
})
})
it('nodeA.hangUp nodeB using multiaddr (second)', (done) => {
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeA.dial nodeB using PeerId', (done) => {
nodeA.dial(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
expect(err).to.not.exist()
series([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(1)
cb()
}
], () => {
pull(
pull.values([new Buffer('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.be.eql([new Buffer('hey')])
done()
})
)
})
}
})
})
it('nodeA.hangUp nodeB using PeerId (third)', (done) => {
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.swarm.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
})

View File

@ -6,11 +6,11 @@ chai.use(require('dirty-chai'))
const expect = chai.expect
const signalling = require('libp2p-webrtc-star/src/sig-server')
const parallel = require('async/parallel')
const utils = require('./utils')
const utils = require('./utils/node')
const createNode = utils.createNode
const echo = utils.echo
describe('discovery', () => {
describe('peer discovery', () => {
let nodeA
let nodeB
let port = 24642
@ -29,7 +29,7 @@ describe('discovery', () => {
},
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0',
`/libp2p-webrtc-star/ip4/127.0.0.1/tcp/${port}/ws`
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
], options, (err, node) => {
expect(err).to.not.exist()
nodeA = node
@ -38,7 +38,7 @@ describe('discovery', () => {
}),
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0',
`/libp2p-webrtc-star/ip4/127.0.0.1/tcp/${port}/ws`
`/ip4/127.0.0.1/tcp/${port}/ws/p2p-webrtc-star`
], options, (err, node) => {
expect(err).to.not.exist()
nodeB = node
@ -60,7 +60,9 @@ describe('discovery', () => {
describe('MulticastDNS', () => {
setup({ mdns: true })
it('find a peer', (done) => {
it('find a peer', function (done) {
this.timeout(15 * 1000)
nodeA.once('peer:discovery', (peerInfo) => {
expect(nodeB.peerInfo.id.toB58String())
.to.eql(peerInfo.id.toB58String())
@ -73,7 +75,8 @@ describe('discovery', () => {
describe.skip('WebRTCStar', () => {
setup({ webRTCStar: true })
it('find a peer', (done) => {
it('find a peer', function (done) {
this.timeout(15 * 1000)
nodeA.once('peer:discovery', (peerInfo) => {
expect(nodeB.peerInfo.id.toB58String())
.to.eql(peerInfo.id.toB58String())
@ -88,7 +91,8 @@ describe('discovery', () => {
mdns: true
})
it('find a peer', (done) => {
it('find a peer', function (done) {
this.timeout(15 * 1000)
nodeA.once('peer:discovery', (peerInfo) => {
expect(nodeB.peerInfo.id.toB58String())
.to.eql(peerInfo.id.toB58String())

View File

@ -7,9 +7,9 @@ const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const utils = require('./utils')
const createNode = utils.createNode
const _times = require('lodash.times')
const utils = require('./utils/node')
const createNode = utils.createNode
describe('.peerRouting', () => {
let nodeA
@ -18,7 +18,9 @@ describe('.peerRouting', () => {
let nodeD
let nodeE
before((done) => {
before(function (done) {
this.timeout(5 * 1000)
const tasks = _times(5, () => (cb) => {
createNode('/ip4/0.0.0.0/tcp/0', {
mdns: false,

View File

@ -6,24 +6,15 @@ chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const series = require('async/series')
const pull = require('pull-stream')
const utils = require('./utils')
const utils = require('./utils/node')
const tryEcho = require('./utils/try-echo')
const createNode = utils.createNode
const echo = utils.echo
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()
pull(
pull.values([new Buffer('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.be.eql([new Buffer('hey')])
callback()
})
)
tryEcho(conn, callback)
})
}
@ -34,8 +25,10 @@ function teardown (nodeA, nodeB, callback) {
], callback)
}
describe('stream muxing', (done) => {
it('spdy only', (done) => {
describe('stream muxing', () => {
it('spdy only', function (done) {
this.timeout(5 * 1000)
let nodeA
let nodeB
@ -99,7 +92,9 @@ describe('stream muxing', (done) => {
], done)
})
it('spdy + multiplex', (done) => {
it('spdy + multiplex', function (done) {
this.timeout(5000)
let nodeA
let nodeB
@ -131,7 +126,9 @@ describe('stream muxing', (done) => {
], done)
})
it('spdy + multiplex switched order', (done) => {
it('spdy + multiplex switched order', function (done) {
this.timeout(5 * 1000)
let nodeA
let nodeB
@ -163,7 +160,9 @@ describe('stream muxing', (done) => {
], done)
})
it('one without the other fails to establish a muxedConn', (done) => {
it('one without the other fails to establish a muxedConn', function (done) {
this.timeout(5 * 1000)
let nodeA
let nodeB
@ -192,12 +191,12 @@ describe('stream muxing', (done) => {
(cb) => setup(cb),
(cb) => {
// it will just 'warm up a conn'
expect(Object.keys(nodeA.swarm.muxers)).to.have.length(1)
expect(Object.keys(nodeB.swarm.muxers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxers)).to.have.length(1)
expect(Object.keys(nodeB.switch.muxers)).to.have.length(1)
nodeA.dial(nodeB.peerInfo, (err) => {
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()
})
},

391
test/transports.browser.js Normal file
View File

@ -0,0 +1,391 @@
/* eslint max-nested-callbacks: ["error", 8] */
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const pull = require('pull-stream')
const parallel = require('async/parallel')
const goodbye = require('pull-goodbye')
const serializer = require('pull-serializer')
const w = require('webrtcsupport')
const tryEcho = require('./utils/try-echo')
const Node = require('./utils/bundle.browser')
const rawPeer = require('./fixtures/test-peer.json')
describe('transports', () => {
describe('websockets', () => {
let peerB
let nodeA
before((done) => {
const ma = '/ip4/127.0.0.1/tcp/9200/ws/ipfs/' + rawPeer.id
PeerId.createFromPrivKey(rawPeer.privKey, (err, id) => {
if (err) {
return done(err)
}
peerB = new PeerInfo(id)
peerB.multiaddrs.add(ma)
done()
})
})
after((done) => nodeA.stop(done))
it('create libp2pNode', (done) => {
PeerInfo.create((err, peerInfo) => {
expect(err).to.not.exist()
peerInfo.multiaddrs.add('/ip4/0.0.0.0/tcp/0')
nodeA = new Node(peerInfo)
done()
})
})
it('create libp2pNode with multiplex only', (done) => {
PeerInfo.create((err, peerInfo) => {
expect(err).to.not.exist()
const b = new Node(peerInfo, null, { muxer: ['multiplex'] })
expect(b.modules.connection.muxer).to.eql([require('libp2p-multiplex')])
done()
})
})
it('start libp2pNode', (done) => {
nodeA.start(done)
})
// General connectivity tests
it('.dial using Multiaddr', (done) => {
nodeA.dial(peerB.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500) // Some time for Identify to finish
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
done()
}
})
})
it('.dialProtocol using Multiaddr', (done) => {
nodeA.dialProtocol(peerB.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
tryEcho(conn, done)
})
})
it('.hangUp using Multiaddr', (done) => {
nodeA.hangUp(peerB.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
done()
}
})
})
it('.dial using PeerInfo', (done) => {
nodeA.dial(peerB, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500) // Some time for Identify to finish
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
done()
}
})
})
it('.dialProtocol using PeerInfo', (done) => {
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
tryEcho(conn, done)
})
})
it('.hangUp using PeerInfo', (done) => {
nodeA.hangUp(peerB, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
done()
}
})
})
describe('stress', () => {
it('one big write', (done) => {
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const rawMessage = Buffer.alloc(100000)
rawMessage.fill('a')
const s = serializer(goodbye({
source: pull.values([rawMessage]),
sink: pull.collect((err, results) => {
expect(err).to.not.exist()
expect(results).to.have.length(1)
expect(Buffer.from(results[0])).to.have.length(rawMessage.length)
done()
})
}))
pull(s, conn, s)
})
})
it('many writes', (done) => {
nodeA.dialProtocol(peerB, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
const s = serializer(goodbye({
source: pull(
pull.infinite(),
pull.take(1000),
pull.map((val) => Buffer.from(val.toString()))
),
sink: pull.collect((err, result) => {
expect(err).to.not.exist()
expect(result).to.have.length(1000)
done()
})
}))
pull(s, conn, s)
})
})
})
})
describe('webrtc-star', () => {
if (!w.support) { return console.log('NO WEBRTC SUPPORT') }
let peer1
let peer2
let node1
let node2
it('create two peerInfo with webrtc-star addrs', (done) => {
parallel([
(cb) => PeerId.create({ bits: 1024 }, cb),
(cb) => PeerId.create({ bits: 1024 }, cb)
], (err, ids) => {
expect(err).to.not.exist()
peer1 = new PeerInfo(ids[0])
const ma1 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + ids[0].toB58String()
peer1.multiaddrs.add(ma1)
peer2 = new PeerInfo(ids[1])
const ma2 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + ids[1].toB58String()
peer2.multiaddrs.add(ma2)
done()
})
})
it('create two libp2p nodes with those peers', (done) => {
node1 = new Node(peer1, null, { webRTCStar: true })
node2 = new Node(peer2, null, { webRTCStar: true })
done()
})
it('start two libp2p nodes', (done) => {
parallel([
(cb) => node1.start(cb),
(cb) => node2.start(cb)
], done)
})
it('.handle echo on first node', () => {
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
})
it('.dialProtocol from the second node to the first node', (done) => {
node1.dialProtocol(peer2, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers1 = node1.peerBook.getAll()
expect(Object.keys(peers1)).to.have.length(1)
const peers2 = node2.peerBook.getAll()
expect(Object.keys(peers2)).to.have.length(1)
tryEcho(conn, done)
}
})
})
it('node1 hangUp node2', (done) => {
node1.hangUp(peer2, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = node1.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(node1.switch.muxedConns)).to.have.length(0)
done()
}
})
})
it('create a third node and check that discovery works', (done) => {
let counter = 0
function check () {
if (++counter === 3) {
expect(Object.keys(node1.switch.muxedConns).length).to.equal(1)
expect(Object.keys(node2.switch.muxedConns).length).to.equal(1)
done()
}
}
PeerId.create((err, id3) => {
expect(err).to.not.exist()
const peer3 = new PeerInfo(id3)
const ma3 = '/ip4/127.0.0.1/tcp/15555/ws/p2p-webrtc-star/ipfs/' + id3.toB58String()
peer3.multiaddrs.add(ma3)
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
const node3 = new Node(peer3, null, { webRTCStar: true })
node3.start(check)
})
})
})
describe('websocket-star', () => {
let peer1
let peer2
let node1
let node2
it('create two peerInfo with websocket-star addrs', (done) => {
parallel([
(cb) => PeerId.create({ bits: 1024 }, cb),
(cb) => PeerId.create({ bits: 1024 }, cb)
], (err, ids) => {
expect(err).to.not.exist()
peer1 = new PeerInfo(ids[0])
const ma1 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/'
peer1.multiaddrs.add(ma1)
peer2 = new PeerInfo(ids[1])
const ma2 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/'
peer2.multiaddrs.add(ma2)
done()
})
})
it('create two libp2p nodes with those peers', (done) => {
node1 = new Node(peer1, null, { wsStar: true })
node2 = new Node(peer2, null, { wsStar: true })
done()
})
it('listen on the two libp2p nodes', (done) => {
parallel([
(cb) => node1.start(cb),
(cb) => node2.start(cb)
], done)
})
it('handle a protocol on the first node', () => {
node2.handle('/echo/1.0.0', (protocol, conn) => pull(conn, conn))
})
it('.dialProtocol from the second node to the first node', (done) => {
node1.dialProtocol(peer2, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers1 = node1.peerBook.getAll()
expect(Object.keys(peers1)).to.have.length(1)
const peers2 = node2.peerBook.getAll()
expect(Object.keys(peers2)).to.have.length(1)
tryEcho(conn, done)
}
})
})
it('node1 hangUp node2', (done) => {
node1.hangUp(peer2, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
const peers = node1.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(node1.switch.muxedConns)).to.have.length(0)
done()
}
})
})
it('create a third node and check that discovery works', (done) => {
let counter = 0
function check () {
if (++counter === 3) {
expect(Object.keys(node1.switch.muxedConns).length).to.equal(1)
expect(Object.keys(node2.switch.muxedConns).length).to.equal(1)
done()
}
}
PeerId.create((err, id3) => {
expect(err).to.not.exist()
const peer3 = new PeerInfo(id3)
const ma3 = '/ip4/127.0.0.1/tcp/14444/ws/p2p-websocket-star/ipfs/' + id3.toB58String()
peer3.multiaddrs.add(ma3)
node1.on('peer:discovery', (peerInfo) => node1.dial(peerInfo, check))
node2.on('peer:discovery', (peerInfo) => node2.dial(peerInfo, check))
const node3 = new Node(peer3, null, { wsStar: true })
node3.start(check)
})
})
})
})

652
test/transports.node.js Normal file
View File

@ -0,0 +1,652 @@
/* eslint-env mocha */
'use strict'
const chai = require('chai')
chai.use(require('dirty-chai'))
const expect = chai.expect
const parallel = require('async/parallel')
const series = require('async/series')
const utils = require('./utils/node.js')
const signalling = require('libp2p-webrtc-star/src/sig-server')
const rendezvous = require('libp2p-websocket-star-rendezvous')
const WSStar = require('libp2p-websocket-star')
const WRTCStar = require('libp2p-webrtc-star')
const wrtc = require('wrtc')
const tryEcho = require('./utils/try-echo')
const createNode = utils.createNode
const echo = utils.echo
describe('transports', () => {
describe('TCP only', () => {
let nodeA
let nodeB
before((done) => {
parallel([
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
expect(err).to.not.exist()
nodeA = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode('/ip4/0.0.0.0/tcp/0', (err, node) => {
expect(err).to.not.exist()
nodeB = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
], done)
})
after((done) => {
parallel([
(cb) => nodeA.stop(cb),
(cb) => nodeB.stop(cb)
], done)
})
it('nodeA.dial nodeB using PeerInfo without proto (warmup)', (done) => {
nodeA.dial(nodeB.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(err).to.not.exist()
expect(Object.keys(peers)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeA.dial nodeB using PeerInfo', (done) => {
nodeA.dialProtocol(nodeB.peerInfo, '/echo/1.0.0', (err, conn) => {
expect(err).to.not.exist()
tryEcho(conn, done)
})
})
it('nodeA.hangUp nodeB using PeerInfo (first)', (done) => {
nodeA.hangUp(nodeB.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeA.dialProtocol nodeB using multiaddr', (done) => {
nodeA.dialProtocol(nodeB.peerInfo.multiaddrs.toArray()[0], '/echo/1.0.0', (err, conn) => {
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
expect(err).to.not.exist()
series([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
cb()
}
], () => tryEcho(conn, done))
}
})
})
it('nodeA.hangUp nodeB using multiaddr (second)', (done) => {
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeA.dialProtocol nodeB using PeerId', (done) => {
nodeA.dialProtocol(nodeB.peerInfo.id, '/echo/1.0.0', (err, conn) => {
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
expect(err).to.not.exist()
series([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(1)
cb()
}
], () => tryEcho(conn, done))
}
})
})
it('nodeA.hangUp nodeB using PeerId (third)', (done) => {
nodeA.hangUp(nodeB.peerInfo.multiaddrs.toArray()[0], (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeB.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeB.switch.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
})
describe('TCP + WebSockets', () => {
let nodeTCP
let nodeTCPnWS
let nodeWS
before((done) => {
parallel([
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0'
], (err, node) => {
expect(err).to.not.exist()
nodeTCP = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeTCPnWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/127.0.0.1/tcp/25022/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
], done)
})
after((done) => {
parallel([
(cb) => nodeTCP.stop(cb),
(cb) => nodeTCPnWS.stop(cb),
(cb) => nodeWS.stop(cb)
], done)
})
it('nodeTCP.dial nodeTCPnWS using PeerInfo', (done) => {
nodeTCP.dial(nodeTCPnWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.switch.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeTCP.hangUp nodeTCPnWS using PeerInfo', (done) => {
nodeTCP.hangUp(nodeTCPnWS.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCP.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCP.switch.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
it('nodeTCPnWS.dial nodeWS using PeerInfo', (done) => {
nodeTCPnWS.dial(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(1)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.switch.muxedConns)).to.have.length(1)
cb()
}
], done)
}
})
})
it('nodeTCPnWS.hangUp nodeWS using PeerInfo', (done) => {
nodeTCPnWS.hangUp(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(check, 500)
function check () {
parallel([
(cb) => {
const peers = nodeTCPnWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(2)
expect(Object.keys(nodeTCPnWS.switch.muxedConns)).to.have.length(0)
cb()
},
(cb) => {
const peers = nodeWS.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeWS.switch.muxedConns)).to.have.length(0)
cb()
}
], done)
}
})
})
// Until https://github.com/libp2p/js-libp2p/issues/46 is resolved
// Everynode will be able to dial in WebSockets
it.skip('nodeTCP.dial nodeWS using PeerInfo is unsuccesful', (done) => {
nodeTCP.dial(nodeWS.peerInfo, (err) => {
expect(err).to.exist()
done()
})
})
})
describe('TCP + WebSockets + WebRTCStar', () => {
let nodeAll
let nodeTCP
let nodeWS
let nodeWStar
let ss
before(function (done) {
this.timeout(5 * 1000)
parallel([
(cb) => {
signalling.start({ port: 24642 }, (err, server) => {
expect(err).to.not.exist()
ss = server
cb()
})
},
(cb) => {
const wstar = new WRTCStar({wrtc: wrtc})
createNode([
'/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws',
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeAll = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
},
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0'
], (err, node) => {
expect(err).to.not.exist()
nodeTCP = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/127.0.0.1/tcp/25022/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => {
const wstar = new WRTCStar({wrtc: wrtc})
createNode([
'/ip4/127.0.0.1/tcp/24642/ws/p2p-webrtc-star'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeWStar = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
}
], done)
})
after(function (done) {
this.timeout(10 * 1000)
parallel([
(cb) => nodeAll.stop(cb),
(cb) => nodeTCP.stop(cb),
(cb) => nodeWS.stop(cb),
(cb) => nodeWStar.stop(cb),
(cb) => ss.stop(cb)
], done)
})
function check (otherNode, muxed, peers, callback) {
let i = 1;
[nodeAll, otherNode].forEach((node) => {
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
expect(Object.keys(node.switch.muxedConns)).to.have.length(muxed)
})
callback()
}
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
nodeAll.dial(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeTCP, 1, 1, done), 500)
})
})
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeTCP, 0, 1, done), 500)
})
})
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
nodeAll.dial(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWS, 1, 2, done), 500)
})
})
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWS, 0, 2, done), 500)
})
})
it('nodeAll.dial nodeWStar using PeerInfo', function (done) {
this.timeout(40 * 1000)
nodeAll.dial(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWStar, 1, 3, done), 500)
})
})
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
setTimeout(() => check(nodeWStar, 0, 3, done), 500)
})
})
})
describe('TCP + WebSockets + WebSocketStar', () => {
let nodeAll
let nodeTCP
let nodeWS
let nodeWStar
let ss
before((done) => {
parallel([
(cb) => {
rendezvous.start({ port: 24642 }, (err, server) => {
expect(err).to.not.exist()
ss = server
cb()
})
},
(cb) => {
const wstar = new WSStar()
createNode([
'/ip4/0.0.0.0/tcp/0',
'/ip4/127.0.0.1/tcp/25011/ws',
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeAll = node
wstar.lazySetId(node.peerInfo.id)
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
},
(cb) => createNode([
'/ip4/0.0.0.0/tcp/0'
], (err, node) => {
expect(err).to.not.exist()
nodeTCP = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => createNode([
'/ip4/127.0.0.1/tcp/25022/ws'
], (err, node) => {
expect(err).to.not.exist()
nodeWS = node
node.handle('/echo/1.0.0', echo)
node.start(cb)
}),
(cb) => {
const wstar = new WSStar({})
createNode([
'/ip4/127.0.0.1/tcp/24642/ws/p2p-websocket-star'
], {
modules: {
transport: [wstar],
discovery: [wstar.discovery]
}
}, (err, node) => {
expect(err).to.not.exist()
nodeWStar = node
wstar.lazySetId(node.peerInfo.id)
node.handle('/echo/1.0.0', echo)
node.start(cb)
})
}
], done)
})
after((done) => {
parallel([
(cb) => nodeAll.stop(cb),
(cb) => nodeTCP.stop(cb),
(cb) => nodeWS.stop(cb),
(cb) => nodeWStar.stop(cb),
(cb) => ss.stop(cb)
], done)
})
function check (otherNode, muxed, peers, done) {
let i = 1;
[nodeAll, otherNode].forEach((node) => {
expect(Object.keys(node.peerBook.getAll())).to.have.length(i-- ? peers : 1)
expect(Object.keys(node.switch.muxedConns)).to.have.length(muxed)
})
done()
}
it('nodeAll.dial nodeTCP using PeerInfo', (done) => {
nodeAll.dial(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeTCP, 1, 1, done), 500)
})
})
it('nodeAll.hangUp nodeTCP using PeerInfo', (done) => {
nodeAll.hangUp(nodeTCP.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeTCP, 0, 1, done), 500)
})
})
it('nodeAll.dial nodeWS using PeerInfo', (done) => {
nodeAll.dial(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWS, 1, 2, done), 500)
})
})
it('nodeAll.hangUp nodeWS using PeerInfo', (done) => {
nodeAll.hangUp(nodeWS.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWS, 0, 2, done), 500)
})
})
it('nodeAll.dial nodeWStar using PeerInfo', (done) => {
nodeAll.dial(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWStar, 1, 3, done), 500)
})
})
it('nodeAll.hangUp nodeWStar using PeerInfo', (done) => {
nodeAll.hangUp(nodeWStar.peerInfo, (err) => {
expect(err).to.not.exist()
// Some time for Identify to finish
setTimeout(() => check(nodeWStar, 0, 3, done), 500)
})
})
})
})

View File

@ -7,9 +7,8 @@ const expect = chai.expect
const multiaddr = require('multiaddr')
const spawn = require('child_process').spawn
const path = require('path')
// const map = require('async/map')
const pull = require('pull-stream')
const utils = require('./utils')
const utils = require('./utils/node')
const createNode = utils.createNode
const echo = utils.echo
@ -57,11 +56,11 @@ describe('Turbolence tests', () => {
expect(Object.keys(peers)).to.have.length(1)
pull(
pull.values([new Buffer('hey')]),
pull.values([Buffer.from('hey')]),
conn,
pull.collect((err, data) => {
expect(err).to.not.exist()
expect(data).to.eql([new Buffer('hey')])
expect(data).to.eql([Buffer.from('hey')])
done()
})
)
@ -77,7 +76,7 @@ describe('Turbolence tests', () => {
function check () {
const peers = nodeA.peerBook.getAll()
expect(Object.keys(peers)).to.have.length(1)
expect(Object.keys(nodeA.swarm.muxedConns)).to.have.length(0)
expect(Object.keys(nodeA.switch.muxedConns)).to.have.length(0)
done()
}
})

View File

@ -2,6 +2,7 @@
const WS = require('libp2p-websockets')
const WebRTCStar = require('libp2p-webrtc-star')
const WebSocketStar = require('libp2p-websocket-star')
const spdy = require('libp2p-spdy')
const multiplex = require('libp2p-multiplex')
const secio = require('libp2p-secio')
@ -35,12 +36,14 @@ function getMuxers (options) {
class Node extends libp2p {
constructor (peerInfo, peerBook, options) {
options = options || {}
const webRTCStar = new WebRTCStar()
const wrtcStar = new WebRTCStar({ id: peerInfo.id })
const wsStar = new WebSocketStar({ id: peerInfo.id })
const modules = {
transport: [
new WS(),
webRTCStar
wrtcStar,
wsStar
],
connection: {
muxer: getMuxers(options.muxer),
@ -52,7 +55,11 @@ class Node extends libp2p {
}
if (options.webRTCStar) {
modules.discovery.push(webRTCStar.discovery)
modules.discovery.push(wrtcStar.discovery)
}
if (options.wsStar) {
modules.discovery.push(wsStar.discovery)
}
if (options.bootstrap) {

View File

@ -3,7 +3,7 @@
const chai = require('chai')
chai.use(require('dirty-chai'))
const Node = require('./nodejs-bundle')
const Node = require('./bundle.node')
const PeerInfo = require('peer-info')
const PeerId = require('peer-id')
const waterfall = require('async/waterfall')
@ -15,6 +15,8 @@ function createNode (multiaddrs, options, callback) {
options = {}
}
options = options || {}
if (!Array.isArray(multiaddrs)) {
multiaddrs = [multiaddrs]
}

21
test/utils/try-echo.js Normal file
View 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()
})
)
}