Compare commits

...

38 Commits

Author SHA1 Message Date
48656712ea chore: release version v0.29.4 2020-12-09 16:42:21 +01:00
1a5ae74741 chore: update contributors 2020-12-09 16:42:20 +01:00
8691465a52 feat: support custom listener options (#822)
* support custom listener options

* fix get listener options

* add doc to explain custom listener options

* add ut

* fix code style

* Apply suggestions from code review

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>

* add missing comma

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
2020-12-09 16:31:17 +01:00
6350a187c7 fix: dial self (#826) 2020-12-09 16:13:25 +01:00
8e3bb09279 chore: remove references to Solarnet (#820)
Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
2020-12-01 19:10:47 +01:00
73204958ee docs: use Libp2p.create() in examples (#811) (#814) 2020-11-30 11:15:09 +01:00
e9e4b731a5 docs: fix JSDOc for stop and create (#812) (#813) 2020-11-27 10:50:35 +01:00
d0a9fada32 feat: custom and store self agent version + store self protocol version (#800)
* feat: custom and store self protocol and agent version

* fix: do not enable custom protocolVersion
2020-11-20 15:14:01 +01:00
824a444f56 docs(fix): fix contentRouting.getMany (#803) 2020-11-18 10:28:43 +01:00
fef54b2b2c chore: release version v0.29.3 2020-11-04 14:05:08 +01:00
8f29a667a1 chore: update contributors 2020-11-04 14:05:08 +01:00
093c0ea13f feat: resolve multiaddrs before dial (#782) 2020-11-04 13:54:50 +01:00
61c36f9e09 chore: release version v0.29.2 2020-10-23 15:40:54 +02:00
f82da56901 chore: update contributors 2020-10-23 15:40:53 +02:00
06f26e586f fix: cleanup open streams on conn close (#791) 2020-10-23 15:34:59 +02:00
8879634363 chore: release version v0.29.1 2020-10-22 14:33:29 +02:00
4a80afce8f chore: update contributors 2020-10-22 14:33:28 +02:00
f75ae341bb test: lock ci on node 14 2020-10-22 14:29:52 +02:00
f2d010a3ab chore: update mplex 2020-10-22 14:29:52 +02:00
e04224a1e2 fix: catch error in upgrader close call 2020-10-22 14:29:52 +02:00
4c6be91588 fix: ensure streams are closed on connection close 2020-10-22 14:29:52 +02:00
5f50054d94 docs: fix typo in transports example readme (#788) 2020-10-22 11:02:00 +02:00
d7d8439e71 docs: update transport example (#770) 2020-10-15 17:28:01 +02:00
4c7a89b710 doc(pubsub): add topicValidators links in API.md table of contents 2020-10-12 12:57:33 +02:00
4eabe07bde chore: update node badge 2020-10-12 12:48:48 +02:00
2fd3b0a0e5 chore: examples not using secio (#747)
* chore: examples not using secio

* chore(docs): remove unused dep

* chore(docs): remove reference of secio in setup

* chore(docs): replace circuit secio reference with noise

Co-authored-by: Jacob Heun <jacobheun@gmail.com>
2020-10-07 16:16:36 +02:00
ec6f7d1cfd chore: lint issue fixed (#775) 2020-10-07 15:39:24 +02:00
a1053bdc54 chore: remove outdated events from libp2p js docs (#766) 2020-10-07 14:51:51 +02:00
0d48fc4f5a test: use ed25519 keys in tests (#669)
* chore: use ed25519 keys in tests

* fix: persisted keybook recheck keybook content for delete

* chore: only store if key not inline

* chore: update peer id

* chore: identify wait for closed streams
2020-10-07 14:50:01 +02:00
60d437f595 fix: flakey identify test firefox (#774) 2020-10-06 15:37:01 +02:00
96df4b7dc4 chore: update aegir and jsdocs for eslint changes (#773) 2020-10-06 14:59:43 +02:00
bb59b518f1 chore: complement 0.29 migration for pubsub subscribe (#755)
* chore: complement 0.29 migration for pubsub subscribe

* chore: update doc/migrations/v0.28-v0.29.md

Co-authored-by: Jacob Heun <jacobheun@gmail.com>
2020-09-16 15:46:05 +02:00
fb4b2734d3 chore: update delegate deps (#753) 2020-09-15 12:47:16 +02:00
0087218194 chore: update getting started connect event (#752) 2020-09-14 13:23:28 +02:00
58b793d700 chore: add libp2p examples repo to release checklist (#746) 2020-09-08 14:47:25 +02:00
63ba2f8fa3 chore: update docs after secio deprecation announcement (#745) 2020-09-08 14:07:06 +02:00
bd26bde876 chore: remove libp2p-pubsub from package table (#743) 2020-08-31 15:19:43 +02:00
3c2a45a9d2 docs: update examples for 0.29 (#742)
* docs: update examples for 0.29

* fix: update examples/libp2p-in-the-browser/package.json

Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>

Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>
2020-08-27 18:13:38 +02:00
98 changed files with 1317 additions and 620 deletions

View File

@ -7,7 +7,7 @@ stages:
node_js: node_js:
- 'lts/*' - 'lts/*'
- 'stable' - '14'
os: os:
- linux - linux

View File

@ -1,3 +1,51 @@
<a name="0.29.4"></a>
## [0.29.4](https://github.com/libp2p/js-libp2p/compare/v0.29.3...v0.29.4) (2020-12-09)
### Bug Fixes
* dial self ([#826](https://github.com/libp2p/js-libp2p/issues/826)) ([6350a18](https://github.com/libp2p/js-libp2p/commit/6350a18))
### Features
* custom and store self agent version + store self protocol version ([#800](https://github.com/libp2p/js-libp2p/issues/800)) ([d0a9fad](https://github.com/libp2p/js-libp2p/commit/d0a9fad))
* support custom listener options ([#822](https://github.com/libp2p/js-libp2p/issues/822)) ([8691465](https://github.com/libp2p/js-libp2p/commit/8691465))
<a name="0.29.3"></a>
## [0.29.3](https://github.com/libp2p/js-libp2p/compare/v0.29.2...v0.29.3) (2020-11-04)
### Features
* resolve multiaddrs before dial ([#782](https://github.com/libp2p/js-libp2p/issues/782)) ([093c0ea](https://github.com/libp2p/js-libp2p/commit/093c0ea))
<a name="0.29.2"></a>
## [0.29.2](https://github.com/libp2p/js-libp2p/compare/v0.29.1...v0.29.2) (2020-10-23)
### Bug Fixes
* cleanup open streams on conn close ([#791](https://github.com/libp2p/js-libp2p/issues/791)) ([06f26e5](https://github.com/libp2p/js-libp2p/commit/06f26e5))
<a name="0.29.1"></a>
## [0.29.1](https://github.com/libp2p/js-libp2p/compare/v0.29.0...v0.29.1) (2020-10-22)
### Bug Fixes
* catch error in upgrader close call ([e04224a](https://github.com/libp2p/js-libp2p/commit/e04224a))
* ensure streams are closed on connection close ([4c6be91](https://github.com/libp2p/js-libp2p/commit/4c6be91))
* flakey identify test firefox ([#774](https://github.com/libp2p/js-libp2p/issues/774)) ([60d437f](https://github.com/libp2p/js-libp2p/commit/60d437f))
<a name="0.29.0"></a> <a name="0.29.0"></a>
# [0.29.0](https://github.com/libp2p/js-libp2p/compare/v0.28.10...v0.29.0) (2020-08-27) # [0.29.0](https://github.com/libp2p/js-libp2p/compare/v0.28.10...v0.29.0) (2020-08-27)

View File

@ -24,7 +24,7 @@
<a href="https://github.com/feross/standard"><img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"></a> <a href="https://github.com/feross/standard"><img src="https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square"></a>
<a href="https://github.com/RichardLitt/standard-readme"><img src="https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square" /></a> <a href="https://github.com/RichardLitt/standard-readme"><img src="https://img.shields.io/badge/standard--readme-OK-green.svg?style=flat-square" /></a>
<a href=""><img src="https://img.shields.io/badge/npm-%3E%3D6.0.0-orange.svg?style=flat-square" /></a> <a href=""><img src="https://img.shields.io/badge/npm-%3E%3D6.0.0-orange.svg?style=flat-square" /></a>
<a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D10.0.0-orange.svg?style=flat-square" /></a> <a href=""><img src="https://img.shields.io/badge/Node.js-%3E%3D12.0.0-orange.svg?style=flat-square" /></a>
<br> <br>
</p> </p>
@ -168,7 +168,6 @@ List of packages currently in existence for libp2p
| **data types** | | **data types** |
| [`peer-id`](//github.com/libp2p/js-peer-id) | [![npm](https://img.shields.io/npm/v/peer-id.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-peer-id/releases) | [![Deps](https://david-dm.org/libp2p/js-peer-id.svg?style=flat-square)](https://david-dm.org/libp2p/js-peer-id) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-peer-id/master)](https://travis-ci.com/libp2p/js-peer-id) | [![codecov](https://codecov.io/gh/libp2p/js-peer-id/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-peer-id) | [Vasco Santos](mailto:santos.vasco10@gmail.com) | | [`peer-id`](//github.com/libp2p/js-peer-id) | [![npm](https://img.shields.io/npm/v/peer-id.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-peer-id/releases) | [![Deps](https://david-dm.org/libp2p/js-peer-id.svg?style=flat-square)](https://david-dm.org/libp2p/js-peer-id) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-peer-id/master)](https://travis-ci.com/libp2p/js-peer-id) | [![codecov](https://codecov.io/gh/libp2p/js-peer-id/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-peer-id) | [Vasco Santos](mailto:santos.vasco10@gmail.com) |
| **pubsub** | | **pubsub** |
| [`libp2p-pubsub`](//github.com/libp2p/js-libp2p-pubsub) | [![npm](https://img.shields.io/npm/v/libp2p-pubsub.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-pubsub/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-pubsub.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-pubsub) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-pubsub/master)](https://travis-ci.com/libp2p/js-libp2p-pubsub) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-pubsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-pubsub) | [Vasco Santos](mailto:santos.vasco10@gmail.com) |
| [`libp2p-floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/libp2p-floodsub.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-floodsub.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-floodsub) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-floodsub/master)](https://travis-ci.com/libp2p/js-libp2p-floodsub) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | [Vasco Santos](mailto:vasco.santos@moxy.studio) | | [`libp2p-floodsub`](//github.com/libp2p/js-libp2p-floodsub) | [![npm](https://img.shields.io/npm/v/libp2p-floodsub.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-floodsub/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-floodsub.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-floodsub) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-floodsub/master)](https://travis-ci.com/libp2p/js-libp2p-floodsub) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-floodsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-floodsub) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |
| [`libp2p-gossipsub`](//github.com/ChainSafe/js-libp2p-gossipsub) | [![npm](https://img.shields.io/npm/v/libp2p-gossipsub.svg?maxAge=86400&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/releases) | [![Deps](https://david-dm.org/ChainSafe/js-libp2p-gossipsub.svg?style=flat-square)](https://david-dm.org/ChainSafe/js-libp2p-gossipsub) | [![Travis CI](https://flat.badgen.net/travis/ChainSafe/js-libp2p-gossipsub/master)](https://travis-ci.com/ChainSafe/js-libp2p-gossipsub) | [![codecov](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub) | [Cayman Nava](mailto:caymannava@gmail.com) | | [`libp2p-gossipsub`](//github.com/ChainSafe/js-libp2p-gossipsub) | [![npm](https://img.shields.io/npm/v/libp2p-gossipsub.svg?maxAge=86400&style=flat-square)](//github.com/ChainSafe/js-libp2p-gossipsub/releases) | [![Deps](https://david-dm.org/ChainSafe/js-libp2p-gossipsub.svg?style=flat-square)](https://david-dm.org/ChainSafe/js-libp2p-gossipsub) | [![Travis CI](https://flat.badgen.net/travis/ChainSafe/js-libp2p-gossipsub/master)](https://travis-ci.com/ChainSafe/js-libp2p-gossipsub) | [![codecov](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/ChainSafe/js-libp2p-gossipsub) | [Cayman Nava](mailto:caymannava@gmail.com) |
| **extensions** | | **extensions** |

View File

@ -26,6 +26,7 @@
- Documentation - Documentation
- [ ] Ensure that README.md is up to date - [ ] Ensure that README.md is up to date
- [ ] Ensure that all the examples run - [ ] Ensure that all the examples run
- [ ] Ensure [libp2p/js-libp2p-examples](https://github.com/libp2p/js-libp2p-examples) is updated
- [ ] Ensure that [libp2p/docs](https://github.com/libp2p/docs) is updated - [ ] Ensure that [libp2p/docs](https://github.com/libp2p/docs) is updated
- Communication - Communication
- [ ] Create the release issue - [ ] Create the release issue

View File

@ -2,7 +2,7 @@
* [Static Functions](#static-functions) * [Static Functions](#static-functions)
* [`create`](#create) * [`create`](#create)
* [Instance Methods](#instance-methods) * [Instance Methods](#libp2p-instance-methods)
* [`start`](#start) * [`start`](#start)
* [`stop`](#stop) * [`stop`](#stop)
* [`dial`](#dial) * [`dial`](#dial)
@ -48,6 +48,8 @@
* [`pubsub.unsubscribe`](#pubsubunsubscribe) * [`pubsub.unsubscribe`](#pubsubunsubscribe)
* [`pubsub.on`](#pubsubon) * [`pubsub.on`](#pubsubon)
* [`pubsub.removeListener`](#pubsubremovelistener) * [`pubsub.removeListener`](#pubsubremovelistener)
* [`pubsub.topicValidators.set`](#pubsubtopicvalidatorsset)
* [`pubsub.topicValidators.delete`](#pubsubtopicvalidatorsdelete)
* [`connectionManager.get`](#connectionmanagerget) * [`connectionManager.get`](#connectionmanagerget)
* [`connectionManager.setPeerValue`](#connectionmanagersetpeervalue) * [`connectionManager.setPeerValue`](#connectionmanagersetpeervalue)
* [`connectionManager.size`](#connectionmanagersize) * [`connectionManager.size`](#connectionmanagersize)
@ -90,6 +92,7 @@ Creates an instance of Libp2p.
| options.modules | [`Array<object>`](./CONFIGURATION.md#modules) | libp2p [modules](./CONFIGURATION.md#modules) to use | | options.modules | [`Array<object>`](./CONFIGURATION.md#modules) | libp2p [modules](./CONFIGURATION.md#modules) to use |
| [options.addresses] | `{ listen: Array<string>, announce: Array<string>, noAnnounce: Array<string> }` | Addresses for transport listening and to advertise to the network | | [options.addresses] | `{ listen: Array<string>, announce: Array<string>, noAnnounce: Array<string> }` | Addresses for transport listening and to advertise to the network |
| [options.config] | `object` | libp2p modules configuration and core configuration | | [options.config] | `object` | libp2p modules configuration and core configuration |
| [options.host] | `{ agentVersion: string }` | libp2p host options |
| [options.connectionManager] | [`object`](./CONFIGURATION.md#configuring-connection-manager) | libp2p Connection Manager [configuration](./CONFIGURATION.md#configuring-connection-manager) | | [options.connectionManager] | [`object`](./CONFIGURATION.md#configuring-connection-manager) | libp2p Connection Manager [configuration](./CONFIGURATION.md#configuring-connection-manager) |
| [options.transportManager] | [`object`](./CONFIGURATION.md#configuring-transport-manager) | libp2p transport manager [configuration](./CONFIGURATION.md#configuring-transport-manager) | | [options.transportManager] | [`object`](./CONFIGURATION.md#configuring-transport-manager) | libp2p transport manager [configuration](./CONFIGURATION.md#configuring-transport-manager) |
| [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) | | [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) |
@ -111,12 +114,25 @@ For Libp2p configurations and modules details read the [Configuration Document](
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
// specify options async function main () {
const options = {} // specify options
const options = {
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p // create libp2p
const libp2p = await Libp2p.create(options) const libp2p = await Libp2p.create(options)
}
main()
``` ```
Note: The [`PeerId`][peer-id] option is not required and will be generated if it is not provided. Note: The [`PeerId`][peer-id] option is not required and will be generated if it is not provided.
@ -128,12 +144,30 @@ As an alternative, it is possible to create a Libp2p instance with the construct
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const PeerId = require('peer-id')
// specify options async function main () {
const options = {} const peerId = await PeerId.create();
// create libp2p // specify options
const libp2p = new Libp2p(options) // peerId is required when Libp2p is instantiated via the constructor
const options = {
peerId,
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p
const libp2p = new Libp2p(options)
}
main()
``` ```
Required keys in the `options` object: Required keys in the `options` object:
@ -663,7 +697,7 @@ Queries the DHT for the n values stored for the given key (without sorting).
// ... // ...
const key = '/key' const key = '/key'
const { from, val } = await libp2p.contentRouting.get(key) const records = await libp2p.contentRouting.getMany(key, 2)
``` ```
### peerRouting.findPeer ### peerRouting.findPeer

View File

@ -98,7 +98,7 @@ If you want to know more about libp2p stream multiplexing, you should read the f
Some available connection encryption protocols: Some available connection encryption protocols:
- [NodeFactoryIo/js-libp2p-noise](https://github.com/NodeFactoryIo/js-libp2p-noise) - [NodeFactoryIo/js-libp2p-noise](https://github.com/NodeFactoryIo/js-libp2p-noise)
- [libp2p/js-libp2p-secio](https://github.com/libp2p/js-libp2p-secio) - [libp2p/js-libp2p-secio](https://github.com/libp2p/js-libp2p-secio) ⚠️ [DEPRECATED](https://blog.ipfs.io/2020-08-07-deprecating-secio)
If none of the available connection encryption mechanisms fulfills your needs, you can create a libp2p compatible one. A libp2p connection encryption protocol just needs to be compliant with the [Crypto Interface](https://github.com/libp2p/js-interfaces/tree/master/src/crypto). If none of the available connection encryption mechanisms fulfills your needs, you can create a libp2p compatible one. A libp2p connection encryption protocol just needs to be compliant with the [Crypto Interface](https://github.com/libp2p/js-interfaces/tree/master/src/crypto).
@ -223,7 +223,7 @@ Besides the `modules` and `config`, libp2p allows other internal options and con
// Creating a libp2p node with: // Creating a libp2p node with:
// transport: websockets + tcp // transport: websockets + tcp
// stream-muxing: mplex // stream-muxing: mplex
// crypto-channel: secio // crypto-channel: noise
// discovery: multicast-dns // discovery: multicast-dns
// dht: kad-dht // dht: kad-dht
// pubsub: gossipsub // pubsub: gossipsub
@ -232,7 +232,7 @@ const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const WS = require('libp2p-websockets') const WS = require('libp2p-websockets')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
const DHT = require('libp2p-kad-dht') const DHT = require('libp2p-kad-dht')
const GossipSub = require('libp2p-gossipsub') const GossipSub = require('libp2p-gossipsub')
@ -244,7 +244,7 @@ const node = await Libp2p.create({
new WS() // It can take instances too! new WS() // It can take instances too!
], ],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
peerDiscovery: [MulticastDNS], peerDiscovery: [MulticastDNS],
dht: DHT, dht: DHT,
pubsub: GossipSub pubsub: GossipSub
@ -258,14 +258,14 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
peerDiscovery: [MulticastDNS] peerDiscovery: [MulticastDNS]
}, },
config: { config: {
@ -291,7 +291,7 @@ const Libp2p = require('libp2p')
const WS = require('libp2p-websockets') const WS = require('libp2p-websockets')
const WebRTCStar = require('libp2p-webrtc-star') const WebRTCStar = require('libp2p-webrtc-star')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
@ -300,7 +300,7 @@ const node = await Libp2p.create({
WebRTCStar WebRTCStar
], ],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
@ -318,14 +318,14 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const GossipSub = require('libp2p-gossipsub') const GossipSub = require('libp2p-gossipsub')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
pubsub: GossipSub pubsub: GossipSub
}, },
config: { config: {
@ -345,14 +345,14 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const DHT = require('libp2p-kad-dht') const DHT = require('libp2p-kad-dht')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
dht: DHT dht: DHT
}, },
config: { config: {
@ -375,7 +375,7 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
const DelegatedContentRouter = require('libp2p-delegated-content-routing') const DelegatedContentRouter = require('libp2p-delegated-content-routing')
const PeerId = require('peer-id') const PeerId = require('peer-id')
@ -387,7 +387,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO], connEncryption: [NOISE],
contentRouting: [ contentRouting: [
new DelegatedContentRouter(peerId) new DelegatedContentRouter(peerId)
], ],
@ -405,13 +405,13 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
config: { config: {
relay: { // Circuit Relay options (this config is part of libp2p core configurations) relay: { // Circuit Relay options (this config is part of libp2p core configurations)
@ -438,14 +438,14 @@ Libp2p allows you to setup a secure keychain to manage your keys. The keychain c
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const LevelStore = require('datastore-level') const LevelStore = require('datastore-level')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
keychain: { keychain: {
pass: 'notsafepassword123456789', pass: 'notsafepassword123456789',
@ -465,6 +465,7 @@ Dialing in libp2p can be configured to limit the rate of dialing, and how long d
| maxParallelDials | `number` | How many multiaddrs we can dial in parallel. | | maxParallelDials | `number` | How many multiaddrs we can dial in parallel. |
| maxDialsPerPeer | `number` | How many multiaddrs we can dial per peer, in parallel. | | maxDialsPerPeer | `number` | How many multiaddrs we can dial per peer, in parallel. |
| dialTimeout | `number` | Second dial timeout per peer in ms. | | dialTimeout | `number` | Second dial timeout per peer in ms. |
| resolvers | `object` | Dial [Resolvers](https://github.com/multiformats/js-multiaddr/blob/master/src/resolvers/index.js) for resolving multiaddrs |
The below configuration example shows how the dialer should be configured, with the current defaults: The below configuration example shows how the dialer should be configured, with the current defaults:
@ -472,18 +473,23 @@ The below configuration example shows how the dialer should be configured, with
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
dialer: { dialer: {
maxParallelDials: 100, maxParallelDials: 100,
maxDialsPerPeer: 4, maxDialsPerPeer: 4,
dialTimeout: 30e3 dialTimeout: 30e3,
resolvers: {
dnsaddr: dnsaddrResolver
}
} }
``` ```
@ -495,13 +501,13 @@ The Connection Manager prunes Connections in libp2p whenever certain limits are
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
connectionManager: { connectionManager: {
maxConnections: Infinity, maxConnections: Infinity,
@ -526,7 +532,7 @@ The Transport Manager is responsible for managing the libp2p transports life cyc
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const { FaultTolerance } = require('libp2p/src/transport-manager')} const { FaultTolerance } = require('libp2p/src/transport-manager')}
@ -534,7 +540,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
transportManager: { transportManager: {
faultTolerance: FaultTolerance.NO_FATAL faultTolerance: FaultTolerance.NO_FATAL
@ -560,13 +566,13 @@ The below configuration example shows how the metrics should be configured. Asid
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
metrics: { metrics: {
enabled: true, enabled: true,
@ -599,7 +605,7 @@ The below configuration example shows how the PeerStore should be configured. As
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const LevelStore = require('datastore-level') const LevelStore = require('datastore-level')
@ -607,7 +613,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
datastore: new LevelStore('path/to/store'), datastore: new LevelStore('path/to/store'),
peerStore: { peerStore: {
@ -625,7 +631,7 @@ Some Transports can be passed additional options when they are created. For exam
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const WebRTCStar = require('libp2p-webrtc-star') const WebRTCStar = require('libp2p-webrtc-star')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const wrtc = require('wrtc') const wrtc = require('wrtc')
const transportKey = WebRTCStar.prototype[Symbol.toStringTag] const transportKey = WebRTCStar.prototype[Symbol.toStringTag]
@ -633,7 +639,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [WebRTCStar], transport: [WebRTCStar],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
config: { config: {
transport: { transport: {
@ -645,6 +651,35 @@ const node = await Libp2p.create({
}) })
``` ```
During Libp2p startup, transport listeners will be created for the configured listen multiaddrs. Some transports support custom listener options and you can set them using the `listenerOptions` in the transport configuration. For example, [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) transport listener supports the configuration of its underlying [simple-peer](https://github.com/feross/simple-peer) ice server(STUN/TURN) config as follows:
```js
const transportKey = WebRTCStar.prototype[Symbol.toStringTag]
const node = await Libp2p.create({
modules: {
transport: [WebRTCStar],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
},
addresses: {
listen: ['/dns4/your-wrtc-star.pub/tcp/443/wss/p2p-webrtc-star'] // your webrtc dns multiaddr
},
config: {
transport: {
[transportKey]: {
listenerOptions: {
config: {
iceServers: [
{"urls": ["turn:YOUR.TURN.SERVER:3478"], "username": "YOUR.USER", "credential": "YOUR.PASSWORD"},
{"urls": ["stun:YOUR.STUN.SERVER:3478"], "username": "", "credential": ""}]
}
}
}
}
}
})
```
## Configuration examples ## Configuration examples
As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration: As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration:

View File

@ -112,13 +112,13 @@ npm install libp2p-mplex
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const WebSockets = require('libp2p-websockets') const WebSockets = require('libp2p-websockets')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [WebSockets], transport: [WebSockets],
connEncryption: [SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX] streamMuxer: [MPLEX]
} }
}) })
@ -139,7 +139,7 @@ Now that you have configured a [**Transport**][transport], [**Crypto**][crypto]
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const WebSockets = require('libp2p-websockets') const WebSockets = require('libp2p-websockets')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const node = await Libp2p.create({ const node = await Libp2p.create({
@ -148,7 +148,7 @@ const node = await Libp2p.create({
}, },
modules: { modules: {
transport: [WebSockets], transport: [WebSockets],
connEncryption: [SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX] streamMuxer: [MPLEX]
} }
}) })
@ -197,21 +197,21 @@ We can provide specific configurations for each protocol within a `config.peerDi
```js ```js
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const WebSockets = require('libp2p-websockets') const WebSockets = require('libp2p-websockets')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const Bootstrap = require('libp2p-bootstrap') const Bootstrap = require('libp2p-bootstrap')
// Known peers addresses // Known peers addresses
const bootstrapMultiaddrs = [ const bootstrapMultiaddrs = [
'/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3' '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN'
] ]
const node = await Libp2p.create({ const node = await Libp2p.create({
modules: { modules: {
transport: [WebSockets], transport: [WebSockets],
connEncryption: [SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
peerDiscovery: [Bootstrap] peerDiscovery: [Bootstrap]
}, },
@ -232,9 +232,9 @@ node.on('peer:discovery', (peer) => {
console.log('Discovered %s', peer.id.toB58String()) // Log discovered peer console.log('Discovered %s', peer.id.toB58String()) // Log discovered peer
}) })
node.on('peer:connect', (peer) => { node.connectionManager.on('peer:connect', (connection) => {
console.log('Connected to %s', peer.id.toB58String()) // Log connected peer console.log('Connected to %s', connection.remotePeer.toB58String()) // Log connected peer
}) })
// start libp2p // start libp2p
await node.start() await node.start()

View File

@ -90,6 +90,36 @@ libp2p.pubsub.on(topic, handler)
libp2p.pubsub.subscribe(topic) libp2p.pubsub.subscribe(topic)
``` ```
In the latest release, despite not being documented in `libp2p` the underlying pubsub routers supported subscribing to multiple topics at the same time. We removed that code complexity, since this is easily achieved in the application layer if needed.
**Before**
```js
const topics = ['a', 'b']
const handler = (msg) => {
// msg.data - pubsub data received
const data = msg.data.toString()
}
libp2p.pubsub.subscribe(topics, handler)
```
**After**
```js
const uint8ArrayToString = require('uint8arrays/to-string')
const topics = ['a', 'b']
const handler = (msg) => {
// msg.data - pubsub data received
const data = uint8ArrayToString(msg.data)
}
topics.forEach((topic) => {
libp2p.pubsub.on(topic, handler)
libp2p.pubsub.subscribe(topic)
})
```
#### Unsubscribe #### Unsubscribe
Handlers should not be directly bound to the subscription anymore. Handlers should not be directly bound to the subscription anymore.

View File

@ -3,7 +3,7 @@
const PeerId = require('peer-id') const PeerId = require('peer-id')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const { stdinToStream, streamToConsole } = require('./stream') const { stdinToStream, streamToConsole } = require('./stream')
async function run() { async function run() {
@ -13,7 +13,7 @@ async function run() {
]) ])
// Create a new libp2p node on localhost with a randomly chosen port // Create a new libp2p node on localhost with a randomly chosen port
const nodeDialer = new Node({ const nodeDialer = await createLibp2p({
peerId: idDialer, peerId: idDialer,
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']

View File

@ -3,26 +3,20 @@
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const WS = require('libp2p-websockets') const WS = require('libp2p-websockets')
const mplex = require('libp2p-mplex') const mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..') const libp2p = require('../../..')
class Node extends libp2p { async function createLibp2p(_options) {
constructor (_options) { const defaults = {
const defaults = { modules: {
modules: { transport: [TCP, WS],
transport: [ streamMuxer: [mplex],
TCP, connEncryption: [NOISE],
WS },
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE, SECIO ]
}
}
super(defaultsDeep(_options, defaults))
} }
return libp2p.create(defaultsDeep(_options, defaults))
} }
module.exports = Node module.exports = createLibp2p

View File

@ -1,15 +1,14 @@
'use strict' 'use strict'
/* eslint-disable no-console */ /* eslint-disable no-console */
const multaddr = require('multiaddr')
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle.js') const createLibp2p = require('./libp2p-bundle.js')
const { stdinToStream, streamToConsole } = require('./stream') const { stdinToStream, streamToConsole } = require('./stream')
async function run() { async function run() {
// Create a new libp2p node with the given multi-address // Create a new libp2p node with the given multi-address
const idListener = await PeerId.createFromJSON(require('./peer-id-listener')) const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
const nodeListener = new Node({ const nodeListener = await createLibp2p({
peerId: idListener, peerId: idListener,
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333'] listen: ['/ip4/0.0.0.0/tcp/10333']

View File

@ -3,7 +3,6 @@
const pipe = require('it-pipe') const pipe = require('it-pipe')
const lp = require('it-length-prefixed') const lp = require('it-length-prefixed')
const uint8ArrayToString = require('uint8arrays/to-string')
function stdinToStream(stream) { function stdinToStream(stream) {
// Read utf-8 from stdin // Read utf-8 from stdin
@ -29,7 +28,7 @@ function streamToConsole(stream) {
// For each chunk of data // For each chunk of data
for await (const msg of source) { for await (const msg of source) {
// Output the data as a utf8 string // Output the data as a utf8 string
console.log('> ' + uint8ArrayToString(msg).replace('\n', '')) console.log('> ' + msg.toString().replace('\n', ''))
} }
} }
) )

View File

@ -4,21 +4,17 @@
const Libp2p = require('../../') const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const Bootstrap = require('libp2p-bootstrap') const Bootstrap = require('libp2p-bootstrap')
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json // Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json
const bootstrapers = [ const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
] ]
;(async () => { ;(async () => {
@ -29,7 +25,7 @@ const bootstrapers = [
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
peerDiscovery: [Bootstrap] peerDiscovery: [Bootstrap]
}, },
config: { config: {

View File

@ -4,7 +4,6 @@
const Libp2p = require('../../') const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const MulticastDNS = require('libp2p-mdns') const MulticastDNS = require('libp2p-mdns')
@ -16,7 +15,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
peerDiscovery: [MulticastDNS] peerDiscovery: [MulticastDNS]
}, },
config: { config: {

View File

@ -8,7 +8,7 @@ These mechanisms save configuration and enable a node to operate without any exp
## 1. Bootstrap list of Peers when booting a node ## 1. Bootstrap list of Peers when booting a node
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and SECIO. You can see the complete example at [1.js](./1.js). For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and NOISE. You can see the complete example at [1.js](./1.js).
First, we create our libp2p node. First, we create our libp2p node.
@ -20,7 +20,7 @@ const node = Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
peerDiscovery: [ Bootstrap ] peerDiscovery: [ Bootstrap ]
}, },
config: { config: {
@ -40,14 +40,11 @@ In this configuration, we use a `bootstrappers` array listing peers to connect _
```JavaScript ```JavaScript
const bootstrapers = [ const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ', '/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64', '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
] ]
``` ```
@ -62,7 +59,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
peerDiscovery: [ Bootstrap ] peerDiscovery: [ Bootstrap ]
}, },
config: { config: {
@ -93,23 +90,17 @@ From running [1.js](./1.js), you should see the following:
```bash ```bash
> node 1.js > node 1.js
Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Discovered: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z Discovered: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Discovered: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM Discovered: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
Discovered: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm Discovered: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Discovered: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu Discovered: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Discovered: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 Discovered: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Connection established to: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z Connection established to: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Connection established to: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM Connection established to: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Connection established to: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm Connection established to: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Connection established to: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu Connection established to: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Connection established to: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64 Connection established to: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
Connection established to: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Connection established to: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Connection established to: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
``` ```
## 2. MulticastDNS to find other peers in the network ## 2. MulticastDNS to find other peers in the network
@ -130,7 +121,7 @@ const createNode = () => {
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
peerDiscovery: [ MulticastDNS ] peerDiscovery: [ MulticastDNS ]
}, },
config: { config: {

View File

@ -5,9 +5,8 @@
* Dialer Node * Dialer Node
*/ */
const multiaddr = require('multiaddr')
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe') const pipe = require('it-pipe')
async function run() { async function run() {
@ -17,7 +16,7 @@ async function run() {
]) ])
// Dialer // Dialer
const dialerNode = new Node({ const dialerNode = await createLibp2p({
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']
}, },

View File

@ -3,27 +3,21 @@
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const WS = require('libp2p-websockets') const WS = require('libp2p-websockets')
const mplex = require('libp2p-mplex') const mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep') const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..') const libp2p = require('../../..')
class Node extends libp2p { async function createLibp2p(_options) {
constructor (_options) { const defaults = {
const defaults = { modules: {
modules: { transport: [TCP, WS],
transport: [ streamMuxer: [mplex],
TCP, connEncryption: [NOISE],
WS },
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE, SECIO ]
}
}
super(defaultsDeep(_options, defaults))
} }
return libp2p.create(defaultsDeep(_options, defaults))
} }
module.exports = Node module.exports = createLibp2p

View File

@ -6,14 +6,14 @@
*/ */
const PeerId = require('peer-id') const PeerId = require('peer-id')
const Node = require('./libp2p-bundle') const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe') const pipe = require('it-pipe')
async function run() { async function run() {
const listenerId = await PeerId.createFromJSON(require('./id-l')) const listenerId = await PeerId.createFromJSON(require('./id-l'))
// Listener libp2p node // Listener libp2p node
const listenerNode = new Node({ const listenerNode = await createLibp2p({
addresses: { addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333'] listen: ['/ip4/0.0.0.0/tcp/10333']
}, },

View File

@ -4,7 +4,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -16,7 +15,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO] connEncryption: [NOISE]
} }
}) })

View File

@ -8,31 +8,24 @@ A byproduct of having these encrypted communications modules is that we can auth
# 1. Set up encrypted communications # 1. Set up encrypted communications
We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the modules `libp2p-secio`<sup>*</sup> and `libp2p-noise` to complete it, go ahead and `npm install libp2p-secio libp2p-noise`. We will build this example on top of example for [Protocol and Stream Multiplexing](../protocol-and-stream-multiplexing). You will need the `libp2p-noise` module to complete it, go ahead and `npm install libp2p-noise`.
To add them to your libp2p configuration, all you have to do is: To add them to your libp2p configuration, all you have to do is:
```JavaScript ```JavaScript
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const createNode = () => { const createNode = () => {
return Libp2p.create({ return Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
// Attach secio as the crypto channel to use // Attach noise as the crypto channel to use
connEncryption: [ NOISE, SECIO ] connEncryption: [ NOISE ]
} }
}) })
} }
``` ```
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. 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.
_<sup>*</sup> SECIO is the crypto channel developed for IPFS, it is a TLS 1.3 like crypto channel that established an encrypted communication channel between two peers._
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).
Important note: SECIO hasn't been audited and so, we do not recommend to trust its security. We intent to move to TLS 1.3 once the specification is finalized and an implementation exists that we can use.

View File

@ -3,9 +3,8 @@ import Libp2p from 'libp2p'
import Websockets from 'libp2p-websockets' import Websockets from 'libp2p-websockets'
import WebRTCStar from 'libp2p-webrtc-star' import WebRTCStar from 'libp2p-webrtc-star'
import { NOISE } from 'libp2p-noise' import { NOISE } from 'libp2p-noise'
import Secio from 'libp2p-secio'
import Mplex from 'libp2p-mplex' import Mplex from 'libp2p-mplex'
import Boostrap from 'libp2p-bootstrap' import Bootstrap from 'libp2p-bootstrap'
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
// Create our libp2p node // Create our libp2p node
@ -21,21 +20,22 @@ document.addEventListener('DOMContentLoaded', async () => {
}, },
modules: { modules: {
transport: [Websockets, WebRTCStar], transport: [Websockets, WebRTCStar],
connEncryption: [NOISE, Secio], connEncryption: [NOISE],
streamMuxer: [Mplex], streamMuxer: [Mplex],
peerDiscovery: [Boostrap] peerDiscovery: [Bootstrap]
}, },
config: { config: {
peerDiscovery: { peerDiscovery: {
bootstrap: { // The `tag` property will be searched when creating the instance of your Peer Discovery service.
// The associated object, will be passed to the service when it is instantiated.
[Bootstrap.tag]: {
enabled: true, enabled: true,
list: [ list: [
'/dns4/ams-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd', '/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/dns4/lon-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3', '/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/dns4/sfo-3.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM', '/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/dns4/sgp-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu', '/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/dns4/nyc-1.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm', '/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
'/dns4/nyc-2.bootstrap.libp2p.io/tcp/443/wss/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64'
] ]
} }
} }

View File

@ -16,12 +16,11 @@
"dependencies": { "dependencies": {
"@babel/preset-env": "^7.8.3", "@babel/preset-env": "^7.8.3",
"libp2p": "../../", "libp2p": "../../",
"libp2p-bootstrap": "^0.11", "libp2p-bootstrap": "^0.12.1",
"libp2p-mplex": "^0.9.3", "libp2p-mplex": "^0.10.0",
"libp2p-noise": "^1.1.0", "libp2p-noise": "^2.0.0",
"libp2p-secio": "^0.12.2", "libp2p-webrtc-star": "^0.20.0",
"libp2p-webrtc-star": "^0.18.0", "libp2p-websockets": "^0.14.0"
"libp2p-websockets": "^0.13.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.8.3", "@babel/cli": "^7.8.3",

View File

@ -5,7 +5,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const KadDHT = require('libp2p-kad-dht') const KadDHT = require('libp2p-kad-dht')
const delay = require('delay') const delay = require('delay')
@ -18,7 +17,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
dht: KadDHT dht: KadDHT
}, },
config: { config: {

View File

@ -4,7 +4,6 @@
const Libp2p = require('../../') const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const CID = require('cids') const CID = require('cids')
const KadDHT = require('libp2p-kad-dht') const KadDHT = require('libp2p-kad-dht')
@ -20,7 +19,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
dht: KadDHT dht: KadDHT
}, },
config: { config: {

View File

@ -23,7 +23,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
// we add the DHT module that will enable Peer and Content Routing // we add the DHT module that will enable Peer and Content Routing
dht: KadDHT dht: KadDHT
}, },

View File

@ -2,11 +2,7 @@
This example shows how to set up a private network of libp2p nodes. This example shows how to set up a private network of libp2p nodes.
## Setup ## Setup
Install dependencies: 1. Install the modules in the libp2p root directory, `npm install`.
```
npm install
```
## Run ## Run
Running the example will cause two nodes with the same swarm key to be started and exchange basic information. Running the example will cause two nodes with the same swarm key to be started and exchange basic information.

View File

@ -3,7 +3,6 @@
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const Protector = require('libp2p/src/pnet') const Protector = require('libp2p/src/pnet')
@ -24,7 +23,7 @@ const privateLibp2pNode = async (swarmKey) => {
streamMuxer: [MPLEX], // We're only using mplex muxing streamMuxer: [MPLEX], // We're only using mplex muxing
// Let's make sure to use identifying crypto in our pnet since the protector doesn't // Let's make sure to use identifying crypto in our pnet since the protector doesn't
// care about node identity, and only the presence of private keys // care about node identity, and only the presence of private keys
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
// Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's // Leave peer discovery empty, we don't want to find peers. We could omit the property, but it's
// being left in for explicit readability. // being left in for explicit readability.
// We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet // We should explicitly dial pnet peers, or use a custom discovery service for finding nodes in our pnet

View File

@ -1,20 +0,0 @@
{
"name": "pnet-ipfs-example",
"version": "1.0.0",
"description": "An example of private networking with IPFS",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"libp2p": "../..",
"libp2p-mplex": "^0.9.3",
"libp2p-noise": "^1.1.0",
"libp2p-secio": "^0.12.1",
"libp2p-tcp": "^0.14.2"
}
}

View File

@ -4,7 +4,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -16,7 +15,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [NOISE, SECIO] connEncryption: [NOISE]
} }
}) })

View File

@ -4,7 +4,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -16,7 +15,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [NOISE, SECIO] connEncryption: [NOISE]
} }
}) })

View File

@ -5,7 +5,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -17,7 +16,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [NOISE, SECIO] connEncryption: [NOISE]
} }
}) })

View File

@ -5,7 +5,6 @@ const Libp2p = require('../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const Gossipsub = require('libp2p-gossipsub') const Gossipsub = require('libp2p-gossipsub')
const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayToString = require('uint8arrays/to-string')
@ -18,7 +17,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
pubsub: Gossipsub pubsub: Gossipsub
} }
}) })

View File

@ -27,7 +27,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
// we add the Pubsub module we want // we add the Pubsub module we want
pubsub: Gossipsub pubsub: Gossipsub
} }

View File

@ -5,7 +5,6 @@ const Libp2p = require('../../../')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const Mplex = require('libp2p-mplex') const Mplex = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const Gossipsub = require('libp2p-gossipsub') const Gossipsub = require('libp2p-gossipsub')
const uint8ArrayFromString = require('uint8arrays/from-string') const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string') const uint8ArrayToString = require('uint8arrays/to-string')
@ -18,7 +17,7 @@ const createNode = async () => {
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [Mplex], streamMuxer: [Mplex],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
pubsub: Gossipsub pubsub: Gossipsub
} }
}) })

View File

@ -17,7 +17,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
streamMuxer: [ Mplex ], streamMuxer: [ Mplex ],
connEncryption: [ NOISE, SECIO ], connEncryption: [ NOISE ],
pubsub: Gossipsub pubsub: Gossipsub
} }
}) })

View File

@ -4,18 +4,17 @@
const Libp2p = require('../..') const Libp2p = require('../..')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const createNode = async () => { const createNode = async () => {
const node = await Libp2p.create({ const node = await Libp2p.create({
addresses: { addresses: {
// To signall the addresses we want to be available, we use // To signal the addresses we want to be available, we use
// the multiaddr format, a self describable address // the multiaddr format, a self describable address
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']
}, },
modules: { modules: {
transport: [TCP], transport: [TCP],
connEncryption: [NOISE, SECIO] connEncryption: [NOISE]
} }
}) })

View File

@ -4,7 +4,6 @@
const Libp2p = require('../..') const Libp2p = require('../..')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -13,13 +12,13 @@ const concat = require('it-concat')
const createNode = async () => { const createNode = async () => {
const node = await Libp2p.create({ const node = await Libp2p.create({
addresses: { addresses: {
// To signall the addresses we want to be available, we use // To signal the addresses we want to be available, we use
// the multiaddr format, a self describable address // the multiaddr format, a self describable address
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']
}, },
modules: { modules: {
transport: [TCP], transport: [TCP],
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX] streamMuxer: [MPLEX]
} }
}) })

View File

@ -5,7 +5,6 @@ const Libp2p = require('../..')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const WebSockets = require('libp2p-websockets') const WebSockets = require('libp2p-websockets')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const pipe = require('it-pipe') const pipe = require('it-pipe')
@ -17,11 +16,11 @@ const createNode = async (transports, addresses = []) => {
const node = await Libp2p.create({ const node = await Libp2p.create({
addresses: { addresses: {
listen: addresses.map((a) => a) listen: addresses
}, },
modules: { modules: {
transport: transports, transport: transports,
connEncryption: [NOISE, SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX] streamMuxer: [MPLEX]
} }
}) })

View File

@ -13,10 +13,10 @@ When using libp2p, you need properly configure it, that is, pick your set of mod
You will need 4 dependencies total, so go ahead and install all of them with: You will need 4 dependencies total, so go ahead and install all of them with:
```bash ```bash
> npm install libp2p libp2p-tcp libp2p-secio peer-info > npm install libp2p libp2p-tcp libp2p-noise
``` ```
Then, on your favorite text editor create a file with the `.js` extension. I've called mine `1.js`. Then, in your favorite text editor create a file with the `.js` extension. I've called mine `1.js`.
First thing is to create our own libp2p node! Insert: First thing is to create our own libp2p node! Insert:
@ -26,18 +26,17 @@ First thing is to create our own libp2p node! Insert:
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const { NOISE } = require('libp2p-noise') const { NOISE } = require('libp2p-noise')
const SECIO = require('libp2p-secio')
const createNode = async () => { const createNode = async () => {
const node = await Libp2p.create({ const node = await Libp2p.create({
addresses: { addresses: {
// To signall the addresses we want to be available, we use // To signal the addresses we want to be available, we use
// the multiaddr format, a self describable address // the multiaddr format, a self describable address
listen: ['/ip4/0.0.0.0/tcp/0'] listen: ['/ip4/0.0.0.0/tcp/0']
}, },
modules: { modules: {
transport: [ TCP ], transport: [ TCP ],
connEncryption: [ NOISE, SECIO ] connEncryption: [ NOISE ]
} }
}) })
@ -78,20 +77,41 @@ That `QmW2cKTakTYqbQkUzBTEGXgWYFj1YEPeUndE1YWs6CBzDQ` is the PeerId that was cre
Now that we have our `createNode` function, 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 `createNode` function, let's create two nodes and make them dial to each other! You can find the complete solution at [2.js](./2.js).
For this step, we will need one more dependency. For this step, we will need some more dependencies.
```bash ```bash
> npm install it-pipe it-buffer > npm install it-pipe it-concat libp2p-mplex
``` ```
And we also need to import the module on our .js file: And we also need to import the modules on our .js file:
```js ```js
const pipe = require('it-pipe') const pipe = require('it-pipe')
const { toBuffer } = require('it-buffer') const concat = require('it-concat')
const MPLEX = require('libp2p-mplex')
``` ```
We are going to reuse the `createNode` function from step 1, but this time to make things simpler, we will create another function to print the addrs to avoid duplicating code. We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`.
```js
const createNode = async () => {
const node = await Libp2p.create({
addresses: {
// To signal the addresses we want to be available, we use
// the multiaddr format, a self describable address
listen: ['/ip4/0.0.0.0/tcp/0']
},
modules: {
transport: [TCP],
connEncryption: [NOISE],
streamMuxer: [MPLEX] // <--- Add this line
}
})
await node.start()
return node
}
```
We will also make things simpler by creating another function to print the multiaddresses to avoid duplicating code.
```JavaScript ```JavaScript
function printAddrs (node, number) { function printAddrs (node, number) {
@ -100,7 +120,7 @@ function printAddrs (node, number) {
} }
``` ```
Then, Then add,
```js ```js
;(async () => { ;(async () => {
@ -112,18 +132,15 @@ Then,
printAddrs(node1, '1') printAddrs(node1, '1')
printAddrs(node2, '2') printAddrs(node2, '2')
node2.handle('/print', ({ stream }) => { node2.handle('/print', async ({ stream }) => {
pipe( const result = await pipe(
stream, stream,
async function (source) { concat
for await (const msg of source) {
console.log(msg.toString())
}
}
) )
console.log(result.toString())
}) })
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs) node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
const { stream } = await node1.dialProtocol(node2.peerId, '/print') const { stream } = await node1.dialProtocol(node2.peerId, '/print')
await pipe( await pipe(
@ -132,8 +149,9 @@ node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
) )
})(); })();
``` ```
For more information refer to the [docs](https://github.com/libp2p/js-libp2p/blob/master/doc/API.md).
The result should be look like: The result should look like:
```bash ```bash
> node 2.js > node 2.js
@ -148,33 +166,33 @@ Hello p2p world!
## 3. Using multiple transports ## 3. Using multiple transports
Next, we want to be available in multiple transports to increase our chances of having common transports in the network. A simple scenario, a node running in the browser only has access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport, for this node to dial to some other node, that other node needs to share a common transport. Next, we want nodes to have multiple transports available to increase their chances of having a common transport in the network to communicate over. A simple scenario is a node running in the browser only having access to HTTP, WebSockets and WebRTC since the browser doesn't let you open any other kind of transport. For this node to dial to some other node, that other node needs to share a common transport.
What we are going to do in this step is to create 3 nodes, one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js). What we are going to do in this step is to create 3 nodes: one with TCP, another with TCP+WebSockets and another one with just WebSockets. The full solution can be found on [3.js](./3.js).
In this example, we will need to also install `libp2p-websockets`, go ahead and install: In this example, we will need to also install `libp2p-websockets`:
```bash ```bash
> npm install libp2p-websockets > npm install libp2p-websockets
``` ```
We want to create 3 nodes, one with TCP, one with TCP+WebSockets and one with just WebSockets. We need to update our `createNode` function to contemplate WebSockets as well. Moreover, let's upgrade our function to enable us to pick the addrs in which a node will start a listener: We want to create 3 nodes: one with TCP, one with TCP+WebSockets and one with just WebSockets. We need to update our `createNode` function to accept WebSocket connections as well. Moreover, let's upgrade our function to enable us to pick the addresses over which a node will start a listener:
```JavaScript ```JavaScript
// ... // ...
const createNode = async (transports, multiaddrs = []) => { const createNode = async (transports, addresses = []) => {
if (!Array.isArray(multiaddrs)) { if (!Array.isArray(addresses)) {
multiaddrs = [multiaddrs] addresses = [addresses]
} }
const node = await Libp2p.create({ const node = await Libp2p.create({
addresses: { addresses: {
listen: multiaddrs.map((a) => multiaddr(a)) listen: addresses
}, },
modules: { modules: {
transport: transports, transport: transports,
connEncryption: [SECIO], connEncryption: [NOISE],
streamMuxer: [MPLEX] streamMuxer: [MPLEX]
} }
}) })
@ -232,7 +250,7 @@ try {
} }
``` ```
`print` is a function created using the code from 2.js, but factored into its own function to save lines, here it is: `print` is a function that prints each piece of data from a stream onto a new line but factored into its own function to save lines:
```JavaScript ```JavaScript
function print ({ stream }) { function print ({ stream }) {
@ -247,7 +265,7 @@ function print ({ stream }) {
} }
``` ```
If everything was set correctly, you now should see the following after you run the script: If everything was set correctly, you now should see something similar to the following after running the script:
```Bash ```Bash
> node 3.js > node 3.js
@ -266,13 +284,13 @@ node 3 failed to dial to node 1 with:
Error: No transport available for address /ip4/127.0.0.1/tcp/51482 Error: No transport available for address /ip4/127.0.0.1/tcp/51482
``` ```
As expected, we created 3 nodes, node 1 with TCP, node 2 with TCP+WebSockets and node 3 with just WebSockets. node 1 -> node 2 and node 2 -> node 3 managed to dial correctly because they shared a common transport, however, node 3 -> node 1 failed because they didn't share any. As expected, we created 3 nodes: node 1 with TCP, node 2 with TCP+WebSockets and node 3 with just WebSockets. node 1 -> node 2 and node 2 -> node 3 managed to dial correctly because they shared a common transport; however, node 3 -> node 1 failed because they didn't share any.
## 4. How to create a new libp2p transport ## 4. How to create a new libp2p transport
Today there are already several transports available and plenty to come, you can find these at [interface-transport implementations](https://github.com/libp2p/js-interfaces/tree/master/src/transport#modules-that-implement-the-interface) list. Today there are already several transports available and plenty to come. You can find these at [interface-transport implementations](https://github.com/libp2p/js-interfaces/tree/master/src/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 as far as libp2p is concerned, if it follows the interface defined at the [spec](https://github.com/libp2p/js-interfaces/tree/master/src/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 in the [spec](https://github.com/libp2p/js-interfaces/tree/master/src/transport#api) it will be able to use it.
If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well. If you decide to implement a transport yourself, please consider adding to the list so that others can use it as well.

View File

@ -51,7 +51,6 @@
["libp2p/js-peer-id", "peer-id"], ["libp2p/js-peer-id", "peer-id"],
"pubsub", "pubsub",
["libp2p/js-libp2p-pubsub", "libp2p-pubsub"],
["libp2p/js-libp2p-floodsub", "libp2p-floodsub"], ["libp2p/js-libp2p-floodsub", "libp2p-floodsub"],
["ChainSafe/js-libp2p-gossipsub", "libp2p-gossipsub"], ["ChainSafe/js-libp2p-gossipsub", "libp2p-gossipsub"],

View File

@ -1,6 +1,6 @@
{ {
"name": "libp2p", "name": "libp2p",
"version": "0.29.0", "version": "0.29.4",
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack", "description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>", "leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js", "main": "src/index.js",
@ -64,7 +64,7 @@
"mafmt": "^8.0.0", "mafmt": "^8.0.0",
"merge-options": "^2.0.0", "merge-options": "^2.0.0",
"moving-average": "^1.0.0", "moving-average": "^1.0.0",
"multiaddr": "^8.0.0", "multiaddr": "^8.1.0",
"multicodec": "^2.0.0", "multicodec": "^2.0.0",
"multistream-select": "^1.0.0", "multistream-select": "^1.0.0",
"mutable-proxy": "^1.0.0", "mutable-proxy": "^1.0.0",
@ -72,7 +72,7 @@
"p-any": "^3.0.0", "p-any": "^3.0.0",
"p-fifo": "^1.0.0", "p-fifo": "^1.0.0",
"p-settle": "^4.0.1", "p-settle": "^4.0.1",
"peer-id": "^0.14.0", "peer-id": "^0.14.2",
"protons": "^2.0.0", "protons": "^2.0.0",
"retimer": "^2.0.0", "retimer": "^2.0.0",
"sanitize-filename": "^1.6.3", "sanitize-filename": "^1.6.3",
@ -84,7 +84,7 @@
"devDependencies": { "devDependencies": {
"@nodeutils/defaults-deep": "^1.1.0", "@nodeutils/defaults-deep": "^1.1.0",
"abortable-iterator": "^3.0.0", "abortable-iterator": "^3.0.0",
"aegir": "^26.0.0", "aegir": "^27.0.0",
"chai": "^4.2.0", "chai": "^4.2.0",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
"chai-bytes": "^0.1.2", "chai-bytes": "^0.1.2",
@ -93,19 +93,19 @@
"delay": "^4.3.0", "delay": "^4.3.0",
"dirty-chai": "^2.0.1", "dirty-chai": "^2.0.1",
"interop-libp2p": "^0.3.0", "interop-libp2p": "^0.3.0",
"ipfs-http-client": "^46.0.0", "ipfs-http-client": "^47.0.1",
"it-concat": "^1.0.0", "it-concat": "^1.0.0",
"it-pair": "^1.0.0", "it-pair": "^1.0.0",
"it-pushable": "^1.4.0", "it-pushable": "^1.4.0",
"libp2p": ".", "libp2p": ".",
"libp2p-bootstrap": "^0.12.0", "libp2p-bootstrap": "^0.12.0",
"libp2p-delegated-content-routing": "^0.6.0", "libp2p-delegated-content-routing": "^0.7.0",
"libp2p-delegated-peer-routing": "^0.6.0", "libp2p-delegated-peer-routing": "^0.7.0",
"libp2p-floodsub": "^0.23.0", "libp2p-floodsub": "^0.23.0",
"libp2p-gossipsub": "^0.6.0", "libp2p-gossipsub": "^0.6.0",
"libp2p-kad-dht": "^0.20.0", "libp2p-kad-dht": "^0.20.0",
"libp2p-mdns": "^0.15.0", "libp2p-mdns": "^0.15.0",
"libp2p-mplex": "^0.10.0", "libp2p-mplex": "^0.10.1",
"libp2p-noise": "^2.0.0", "libp2p-noise": "^2.0.0",
"libp2p-secio": "^0.13.1", "libp2p-secio": "^0.13.1",
"libp2p-tcp": "^0.15.1", "libp2p-tcp": "^0.15.1",
@ -132,39 +132,44 @@
"Friedel Ziegelmayer <dignifiedquire@gmail.com>", "Friedel Ziegelmayer <dignifiedquire@gmail.com>",
"Maciej Krüger <mkg20001@gmail.com>", "Maciej Krüger <mkg20001@gmail.com>",
"Hugo Dias <mail@hugodias.me>", "Hugo Dias <mail@hugodias.me>",
"Volker Mische <volker.mische@gmail.com>",
"dirkmc <dirkmdev@gmail.com>", "dirkmc <dirkmdev@gmail.com>",
"Volker Mische <volker.mische@gmail.com>",
"Richard Littauer <richard.littauer@gmail.com>", "Richard Littauer <richard.littauer@gmail.com>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>", "a1300 <matthias-knopp@gmx.net>",
"Andrew Nesbitt <andrewnez@gmail.com>",
"Elven <mon.samuel@qq.com>", "Elven <mon.samuel@qq.com>",
"Andrew Nesbitt <andrewnez@gmail.com>",
"Giovanni T. Parra <fiatjaf@gmail.com>", "Giovanni T. Parra <fiatjaf@gmail.com>",
"Ryan Bell <ryan@piing.net>", "Ryan Bell <ryan@piing.net>",
"Thomas Eizinger <thomas@eizinger.io>", "Thomas Eizinger <thomas@eizinger.io>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Didrik Nordström <didrik@betamos.se>", "Didrik Nordström <didrik@betamos.se>",
"Francis Gulotta <wizard@roborooter.com>", "Irakli Gozalishvili <rfobic@gmail.com>",
"Florian-Merle <florian.david.merle@gmail.com>", "Ethan Lam <elmemphis2000@gmail.com>",
"Joel Gustafson <joelg@mit.edu>", "Joel Gustafson <joelg@mit.edu>",
"Julien Bouquillon <contact@revolunet.com>", "Julien Bouquillon <contact@revolunet.com>",
"Kevin Kwok <antimatter15@gmail.com>", "Kevin Kwok <antimatter15@gmail.com>",
"Felipe Martins <felipebrasil93@gmail.com>",
"Nuno Nogueira <nunofmn@gmail.com>", "Nuno Nogueira <nunofmn@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>",
"RasmusErik Voel Jensen <github@solsort.com>",
"Dmitriy Ryajov <dryajov@gmail.com>", "Dmitriy Ryajov <dryajov@gmail.com>",
"RasmusErik Voel Jensen <github@solsort.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"Samlior <samlior@foxmail.com>",
"Smite Chow <xiaopengyou@live.com>",
"Soeren <nikorpoulsen@gmail.com>", "Soeren <nikorpoulsen@gmail.com>",
"Sönke Hahn <soenkehahn@gmail.com>", "Sönke Hahn <soenkehahn@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"Tiago Alves <alvesjtiago@gmail.com>", "Tiago Alves <alvesjtiago@gmail.com>",
"Diogo Silva <fsdiogo@gmail.com>", "Daijiro Wachi <daijiro.wachi@gmail.com>",
"Yusef Napora <yusef@napora.org>", "Yusef Napora <yusef@napora.org>",
"Zane Starr <zcstarr@gmail.com>", "Zane Starr <zcstarr@gmail.com>",
"Daijiro Wachi <daijiro.wachi@gmail.com>", "Cindy Wu <ciindy.wu@gmail.com>",
"Chris Bratlien <chrisbratlien@gmail.com>", "Chris Bratlien <chrisbratlien@gmail.com>",
"ebinks <elizabethjbinks@gmail.com>", "ebinks <elizabethjbinks@gmail.com>",
"Bernd Strehl <bernd.strehl@gmail.com>", "Bernd Strehl <bernd.strehl@gmail.com>",
"Florian-Merle <florian.david.merle@gmail.com>",
"Francis Gulotta <wizard@roborooter.com>",
"Felipe Martins <felipebrasil93@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>", "isan_rivkin <isanrivkin@gmail.com>",
"Henrique Dias <hacdias@gmail.com>", "Henrique Dias <hacdias@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>", "Fei Liu <liu.feiwood@gmail.com>"
"Irakli Gozalishvili <rfobic@gmail.com>"
] ]
} }

View File

@ -15,11 +15,11 @@ const multiaddr = require('multiaddr')
*/ */
class AddressManager { class AddressManager {
/** /**
* @constructor * @class
* @param {object} [options] * @param {object} [options]
* @param {Array<string>} [options.listen = []] list of multiaddrs string representation to listen. * @param {Array<string>} [options.listen = []] - list of multiaddrs string representation to listen.
* @param {Array<string>} [options.announce = []] list of multiaddrs string representation to announce. * @param {Array<string>} [options.announce = []] - list of multiaddrs string representation to announce.
* @param {Array<string>} [options.noAnnounce = []] list of multiaddrs string representation to not announce. * @param {Array<string>} [options.noAnnounce = []] - list of multiaddrs string representation to not announce.
*/ */
constructor ({ listen = [], announce = [], noAnnounce = [] } = {}) { constructor ({ listen = [], announce = [], noAnnounce = [] } = {}) {
this.listen = new Set(listen) this.listen = new Set(listen)
@ -29,7 +29,8 @@ class AddressManager {
/** /**
* Get peer listen multiaddrs. * Get peer listen multiaddrs.
* @return {Array<Multiaddr>} *
* @returns {Array<Multiaddr>}
*/ */
getListenAddrs () { getListenAddrs () {
return Array.from(this.listen).map((a) => multiaddr(a)) return Array.from(this.listen).map((a) => multiaddr(a))
@ -37,7 +38,8 @@ class AddressManager {
/** /**
* Get peer announcing multiaddrs. * Get peer announcing multiaddrs.
* @return {Array<Multiaddr>} *
* @returns {Array<Multiaddr>}
*/ */
getAnnounceAddrs () { getAnnounceAddrs () {
return Array.from(this.announce).map((a) => multiaddr(a)) return Array.from(this.announce).map((a) => multiaddr(a))
@ -45,7 +47,8 @@ class AddressManager {
/** /**
* Get peer noAnnouncing multiaddrs. * Get peer noAnnouncing multiaddrs.
* @return {Array<Multiaddr>} *
* @returns {Array<Multiaddr>}
*/ */
getNoAnnounceAddrs () { getNoAnnounceAddrs () {
return Array.from(this.noAnnounce).map((a) => multiaddr(a)) return Array.from(this.noAnnounce).map((a) => multiaddr(a))

View File

@ -41,7 +41,7 @@ const multiaddr = require('multiaddr')
const Libp2p = require('libp2p') const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp') const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex') const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio') const { NOISE } = require('libp2p-noise')
const relayAddr = ... const relayAddr = ...
@ -52,7 +52,7 @@ const node = await Libp2p.create({
modules: { modules: {
transport: [TCP], transport: [TCP],
streamMuxer: [MPLEX], streamMuxer: [MPLEX],
connEncryption: [SECIO] connEncryption: [NOISE]
}, },
config: { config: {
relay: { // Circuit Relay options (this config is part of libp2p core configurations) relay: { // Circuit Relay options (this config is part of libp2p core configurations)

View File

@ -90,9 +90,8 @@ module.exports.handleHop = async function handleHop ({
* peer. A new, virtual, connection will be created between the two via the relay. * peer. A new, virtual, connection will be created between the two via the relay.
* *
* @param {object} options * @param {object} options
* @param {Connection} options.connection Connection to the relay * @param {Connection} options.connection - Connection to the relay
* @param {*} options.request * @param {*} options.request
* @param {Circuit} options.circuit
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
*/ */
module.exports.hop = async function hop ({ module.exports.hop = async function hop ({
@ -119,6 +118,11 @@ module.exports.hop = async function hop ({
/** /**
* Creates an unencoded CAN_HOP response based on the Circuits configuration * Creates an unencoded CAN_HOP response based on the Circuits configuration
*
* @param {Object} options
* @param {Connection} options.connection
* @param {StreamHandler} options.streamHandler
* @param {Circuit} options.circuit
* @private * @private
*/ */
module.exports.handleCanHop = function handleCanHop ({ module.exports.handleCanHop = function handleCanHop ({

View File

@ -15,7 +15,7 @@ log.error = debug('libp2p:circuit:stop:error')
* @private * @private
* @param {*} options * @param {*} options
* @param {Connection} options.connection * @param {Connection} options.connection
* @param {*} options.request The CircuitRelay protobuf request (unencoded) * @param {*} options.request - The CircuitRelay protobuf request (unencoded)
* @param {StreamHandler} options.streamHandler * @param {StreamHandler} options.streamHandler
* @returns {Promise<*>} Resolves a duplex iterable * @returns {Promise<*>} Resolves a duplex iterable
*/ */
@ -42,10 +42,11 @@ module.exports.handleStop = function handleStop ({
/** /**
* Creates a STOP request * Creates a STOP request
*
* @private * @private
* @param {*} options * @param {*} options
* @param {Connection} options.connection * @param {Connection} options.connection
* @param {*} options.request The CircuitRelay protobuf request (unencoded) * @param {*} options.request - The CircuitRelay protobuf request (unencoded)
* @returns {Promise<*>} Resolves a duplex iterable * @returns {Promise<*>} Resolves a duplex iterable
*/ */
module.exports.stop = async function stop ({ module.exports.stop = async function stop ({

View File

@ -14,7 +14,7 @@ class StreamHandler {
* *
* @param {object} options * @param {object} options
* @param {*} options.stream - A duplex iterable * @param {*} options.stream - A duplex iterable
* @param {Number} options.maxLength - max bytes length of message * @param {number} options.maxLength - max bytes length of message
*/ */
constructor ({ stream, maxLength = 4096 }) { constructor ({ stream, maxLength = 4096 }) {
this.stream = stream this.stream = stream
@ -25,6 +25,7 @@ class StreamHandler {
/** /**
* Read and decode message * Read and decode message
*
* @async * @async
* @returns {void} * @returns {void}
*/ */
@ -44,7 +45,7 @@ class StreamHandler {
/** /**
* Encode and write array of buffers * Encode and write array of buffers
* *
* @param {*} msg An unencoded CircuitRelay protobuf message * @param {*} msg - An unencoded CircuitRelay protobuf message
*/ */
write (msg) { write (msg) {
log('write message type %s', msg.type) log('write message type %s', msg.type)
@ -54,7 +55,7 @@ class StreamHandler {
/** /**
* Return the handshake rest stream and invalidate handler * Return the handshake rest stream and invalidate handler
* *
* @return {*} A duplex iterable * @returns {*} A duplex iterable
*/ */
rest () { rest () {
this.shake.rest() this.shake.rest()

View File

@ -19,7 +19,7 @@ function writeResponse (streamHandler, status) {
/** /**
* Validate incomming HOP/STOP message * Validate incomming HOP/STOP message
* *
* @param {*} msg A CircuitRelay unencoded protobuf message * @param {*} msg - A CircuitRelay unencoded protobuf message
* @param {StreamHandler} streamHandler * @param {StreamHandler} streamHandler
*/ */
function validateAddrs (msg, streamHandler) { function validateAddrs (msg, streamHandler) {

View File

@ -21,7 +21,7 @@ class Circuit {
/** /**
* Creates an instance of Circuit. * Creates an instance of Circuit.
* *
* @constructor * @class
* @param {object} options * @param {object} options
* @param {Libp2p} options.libp2p * @param {Libp2p} options.libp2p
* @param {Upgrader} options.upgrader * @param {Upgrader} options.upgrader
@ -152,7 +152,7 @@ class Circuit {
* *
* @param {any} options * @param {any} options
* @param {Function} handler * @param {Function} handler
* @return {listener} * @returns {listener}
*/ */
createListener (options, handler) { createListener (options, handler) {
if (typeof options === 'function') { if (typeof options === 'function') {

View File

@ -19,7 +19,7 @@ module.exports = (circuit) => {
* Add swarm handler and listen for incoming connections * Add swarm handler and listen for incoming connections
* *
* @param {Multiaddr} addr * @param {Multiaddr} addr
* @return {void} * @returns {void}
*/ */
listener.listen = async (addr) => { listener.listen = async (addr) => {
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '') const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
@ -34,7 +34,7 @@ module.exports = (circuit) => {
/** /**
* TODO: Remove the peers from our topology * TODO: Remove the peers from our topology
* *
* @return {void} * @returns {void}
*/ */
listener.close = () => {} listener.close = () => {}
@ -44,15 +44,15 @@ module.exports = (circuit) => {
* NOTE: This method will grab the peers multiaddrs and expand them such that: * NOTE: This method will grab the peers multiaddrs and expand them such that:
* *
* a) If it's an existing /p2p-circuit address for a specific relay i.e. * a) If it's an existing /p2p-circuit address for a specific relay i.e.
* `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit` this method will expand the * `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit` this method will expand the
* address to `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit/ipfs/QmPeer` where * address to `/ip4/0.0.0.0/tcp/0/ipfs/QmRelay/p2p-circuit/ipfs/QmPeer` where
* `QmPeer` is this peers id * `QmPeer` is this peers id
* b) If it's not a /p2p-circuit address, it will encapsulate the address as a /p2p-circuit * b) If it's not a /p2p-circuit address, it will encapsulate the address as a /p2p-circuit
* addr, such when dialing over a relay with this address, it will create the circuit using * addr, such when dialing over a relay with this address, it will create the circuit using
* the encapsulated transport address. This is useful when for example, a peer should only * the encapsulated transport address. This is useful when for example, a peer should only
* be dialed over TCP rather than any other transport * be dialed over TCP rather than any other transport
* *
* @return {Multiaddr[]} * @returns {Multiaddr[]}
*/ */
listener.getAddrs = () => { listener.getAddrs = () => {
const addrs = [] const addrs = []

View File

@ -1,7 +1,10 @@
'use strict' 'use strict'
const mergeOptions = require('merge-options') const mergeOptions = require('merge-options')
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
const Constants = require('./constants') const Constants = require('./constants')
const { AGENT_VERSION } = require('./identify/consts')
const { FaultTolerance } = require('./transport-manager') const { FaultTolerance } = require('./transport-manager')
@ -20,7 +23,13 @@ const DefaultConfig = {
dialer: { dialer: {
maxParallelDials: Constants.MAX_PARALLEL_DIALS, maxParallelDials: Constants.MAX_PARALLEL_DIALS,
maxDialsPerPeer: Constants.MAX_PER_PEER_DIALS, maxDialsPerPeer: Constants.MAX_PER_PEER_DIALS,
dialTimeout: Constants.DIAL_TIMEOUT dialTimeout: Constants.DIAL_TIMEOUT,
resolvers: {
dnsaddr: dnsaddrResolver
}
},
host: {
agentVersion: AGENT_VERSION
}, },
metrics: { metrics: {
enabled: false enabled: false

View File

@ -32,25 +32,26 @@ const defaultOptions = {
/** /**
* Responsible for managing known connections. * Responsible for managing known connections.
*
* @fires ConnectionManager#peer:connect Emitted when a new peer is connected. * @fires ConnectionManager#peer:connect Emitted when a new peer is connected.
* @fires ConnectionManager#peer:disconnect Emitted when a peer is disconnected. * @fires ConnectionManager#peer:disconnect Emitted when a peer is disconnected.
*/ */
class ConnectionManager extends EventEmitter { class ConnectionManager extends EventEmitter {
/** /**
* @constructor * @class
* @param {Libp2p} libp2p * @param {Libp2p} libp2p
* @param {object} options * @param {object} options
* @param {Number} options.maxConnections The maximum number of connections allowed. Default=Infinity * @param {number} options.maxConnections - The maximum number of connections allowed. Default=Infinity
* @param {Number} options.minConnections The minimum number of connections to avoid pruning. Default=0 * @param {number} options.minConnections - The minimum number of connections to avoid pruning. Default=0
* @param {Number} options.maxData The max data (in and out), per average interval to allow. Default=Infinity * @param {number} options.maxData - The max data (in and out), per average interval to allow. Default=Infinity
* @param {Number} options.maxSentData The max outgoing data, per average interval to allow. Default=Infinity * @param {number} options.maxSentData - The max outgoing data, per average interval to allow. Default=Infinity
* @param {Number} options.maxReceivedData The max incoming data, per average interval to allow.. Default=Infinity * @param {number} options.maxReceivedData - The max incoming data, per average interval to allow.. Default=Infinity
* @param {Number} options.maxEventLoopDelay The upper limit the event loop can take to run. Default=Infinity * @param {number} options.maxEventLoopDelay - The upper limit the event loop can take to run. Default=Infinity
* @param {Number} options.pollInterval How often, in milliseconds, metrics and latency should be checked. Default=2000 * @param {number} options.pollInterval - How often, in milliseconds, metrics and latency should be checked. Default=2000
* @param {Number} options.movingAverageInterval How often, in milliseconds, to compute averages. Default=60000 * @param {number} options.movingAverageInterval - How often, in milliseconds, to compute averages. Default=60000
* @param {Number} options.defaultPeerValue The value of the peer. Default=1 * @param {number} options.defaultPeerValue - The value of the peer. Default=1
* @param {boolean} options.autoDial Should preemptively guarantee connections are above the low watermark. Default=true * @param {boolean} options.autoDial - Should preemptively guarantee connections are above the low watermark. Default=true
* @param {Number} options.autoDialInterval How often, in milliseconds, it should preemptively guarantee connections are above the low watermark. Default=10000 * @param {number} options.autoDialInterval - How often, in milliseconds, it should preemptively guarantee connections are above the low watermark. Default=10000
*/ */
constructor (libp2p, options) { constructor (libp2p, options) {
super() super()
@ -69,12 +70,14 @@ class ConnectionManager extends EventEmitter {
/** /**
* Map of peer identifiers to their peer value for pruning connections. * Map of peer identifiers to their peer value for pruning connections.
*
* @type {Map<string, number>} * @type {Map<string, number>}
*/ */
this._peerValues = new Map() this._peerValues = new Map()
/** /**
* Map of connections per peer * Map of connections per peer
*
* @type {Map<string, Array<conn>>} * @type {Map<string, Array<conn>>}
*/ */
this.connections = new Map() this.connections = new Map()
@ -119,6 +122,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Stops the Connection Manager * Stops the Connection Manager
*
* @async * @async
*/ */
async stop () { async stop () {
@ -133,6 +137,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Cleans up the connections * Cleans up the connections
*
* @async * @async
*/ */
async _close () { async _close () {
@ -151,8 +156,9 @@ class ConnectionManager extends EventEmitter {
/** /**
* Sets the value of the given peer. Peers with lower values * Sets the value of the given peer. Peers with lower values
* will be disconnected first. * will be disconnected first.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {number} value A number between 0 and 1 * @param {number} value - A number between 0 and 1
*/ */
setPeerValue (peerId, value) { setPeerValue (peerId, value) {
if (value < 0 || value > 1) { if (value < 0 || value > 1) {
@ -167,6 +173,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Checks the libp2p metrics to determine if any values have exceeded * Checks the libp2p metrics to determine if any values have exceeded
* the configured maximums. * the configured maximums.
*
* @private * @private
*/ */
_checkMetrics () { _checkMetrics () {
@ -183,6 +190,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Tracks the incoming connection and check the connection limit * Tracks the incoming connection and check the connection limit
*
* @param {Connection} connection * @param {Connection} connection
*/ */
onConnect (connection) { onConnect (connection) {
@ -208,6 +216,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Removes the connection from tracking * Removes the connection from tracking
*
* @param {Connection} connection * @param {Connection} connection
*/ */
onDisconnect (connection) { onDisconnect (connection) {
@ -226,6 +235,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Get a connection with a peer. * Get a connection with a peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Connection} * @returns {Connection}
*/ */
@ -239,6 +249,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* Get all open connections with a peer. * Get all open connections with a peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Array<Connection>} * @returns {Array<Connection>}
*/ */
@ -259,8 +270,9 @@ class ConnectionManager extends EventEmitter {
/** /**
* If the event loop is slow, maybe close a connection * If the event loop is slow, maybe close a connection
*
* @private * @private
* @param {*} summary The LatencyMonitor summary * @param {*} summary - The LatencyMonitor summary
*/ */
_onLatencyMeasure (summary) { _onLatencyMeasure (summary) {
this._checkMaxLimit('maxEventLoopDelay', summary.avgMs) this._checkMaxLimit('maxEventLoopDelay', summary.avgMs)
@ -268,9 +280,10 @@ class ConnectionManager extends EventEmitter {
/** /**
* If the `value` of `name` has exceeded its limit, maybe close a connection * If the `value` of `name` has exceeded its limit, maybe close a connection
*
* @private * @private
* @param {string} name The name of the field to check limits for * @param {string} name - The name of the field to check limits for
* @param {number} value The current value of the field * @param {number} value - The current value of the field
*/ */
_checkMaxLimit (name, value) { _checkMaxLimit (name, value) {
const limit = this._options[name] const limit = this._options[name]
@ -285,6 +298,7 @@ class ConnectionManager extends EventEmitter {
* Proactively tries to connect to known peers stored in the PeerStore. * Proactively tries to connect to known peers stored in the PeerStore.
* It will keep the number of connections below the upper limit and sort * It will keep the number of connections below the upper limit and sort
* the peers to connect based on wether we know their keys and protocols. * the peers to connect based on wether we know their keys and protocols.
*
* @async * @async
* @private * @private
*/ */
@ -330,6 +344,7 @@ class ConnectionManager extends EventEmitter {
/** /**
* If we have more connections than our maximum, close a connection * If we have more connections than our maximum, close a connection
* to the lowest valued peer. * to the lowest valued peer.
*
* @private * @private
*/ */
_maybeDisconnectOne () { _maybeDisconnectOne () {

View File

@ -12,11 +12,11 @@ const debug = require('debug')('latency-monitor:LatencyMonitor')
/** /**
* @typedef {Object} SummaryObject * @typedef {Object} SummaryObject
* @property {Number} events How many events were called * @property {number} events How many events were called
* @property {Number} minMS What was the min time for a cb to be called * @property {number} minMS What was the min time for a cb to be called
* @property {Number} maxMS What was the max time for a cb to be called * @property {number} maxMS What was the max time for a cb to be called
* @property {Number} avgMs What was the average time for a cb to be called * @property {number} avgMs What was the average time for a cb to be called
* @property {Number} lengthMs How long this interval was in ms * @property {number} lengthMs How long this interval was in ms
*/ */
/** /**
@ -37,11 +37,12 @@ const debug = require('debug')('latency-monitor:LatencyMonitor')
*/ */
class LatencyMonitor extends EventEmitter { class LatencyMonitor extends EventEmitter {
/** /**
* @param {Number} [latencyCheckIntervalMs=500] How often to add a latency check event (ms) * @param {object} [options]
* @param {Number} [dataEmitIntervalMs=5000] How often to summarize latency check events. null or 0 disables event firing * @param {number} [options.latencyCheckIntervalMs=500] - How often to add a latency check event (ms)
* @param {function} [asyncTestFn] What cb-style async function to use * @param {number} [options.dataEmitIntervalMs=5000] - How often to summarize latency check events. null or 0 disables event firing
* @param {Number} [latencyRandomPercentage=5] What percent (+/-) of latencyCheckIntervalMs should we randomly use? This helps avoid alignment to other events. * @param {Function} [options.asyncTestFn] - What cb-style async function to use
*/ * @param {number} [options.latencyRandomPercentage=5] - What percent (+/-) of latencyCheckIntervalMs should we randomly use? This helps avoid alignment to other events.
*/
constructor ({ latencyCheckIntervalMs, dataEmitIntervalMs, asyncTestFn, latencyRandomPercentage } = {}) { constructor ({ latencyCheckIntervalMs, dataEmitIntervalMs, asyncTestFn, latencyRandomPercentage } = {}) {
super() super()
const that = this const that = this
@ -106,9 +107,10 @@ class LatencyMonitor extends EventEmitter {
} }
/** /**
* Start internal timers * Start internal timers
* @private *
*/ * @private
*/
_startTimers () { _startTimers () {
// Timer already started, ignore this // Timer already started, ignore this
if (this._checkLatencyID) { if (this._checkLatencyID) {
@ -124,9 +126,10 @@ class LatencyMonitor extends EventEmitter {
} }
/** /**
* Stop internal timers * Stop internal timers
* @private *
*/ * @private
*/
_stopTimers () { _stopTimers () {
if (this._checkLatencyID) { if (this._checkLatencyID) {
clearTimeout(this._checkLatencyID) clearTimeout(this._checkLatencyID)
@ -139,9 +142,10 @@ class LatencyMonitor extends EventEmitter {
} }
/** /**
* Emit summary only if there were events. It might not have any events if it was forced via a page hidden/show * Emit summary only if there were events. It might not have any events if it was forced via a page hidden/show
* @private *
*/ * @private
*/
_emitSummary () { _emitSummary () {
const summary = this.getSummary() const summary = this.getSummary()
if (summary.events > 0) { if (summary.events > 0) {
@ -150,10 +154,11 @@ class LatencyMonitor extends EventEmitter {
} }
/** /**
* Calling this function will end the collection period. If a timing event was already fired and somewhere in the queue, * Calling this function will end the collection period. If a timing event was already fired and somewhere in the queue,
* it will not count for this time period * it will not count for this time period
* @returns {SummaryObject} *
*/ * @returns {SummaryObject}
*/
getSummary () { getSummary () {
// We might want to adjust for the number of expected events // We might want to adjust for the number of expected events
// Example: first 1 event it comes back, then such a long blocker that the next emit check comes // Example: first 1 event it comes back, then such a long blocker that the next emit check comes
@ -173,11 +178,11 @@ class LatencyMonitor extends EventEmitter {
} }
/** /**
* Randomly calls an async fn every roughly latencyCheckIntervalMs (plus some randomness). If no async fn is found, * Randomly calls an async fn every roughly latencyCheckIntervalMs (plus some randomness). If no async fn is found,
* it will simply report on event loop latency. * it will simply report on event loop latency.
* *
* @private * @private
*/ */
_checkLatency () { _checkLatency () {
const that = this const that = this
// Randomness is needed to avoid alignment by accident to regular things in the event loop // Randomness is needed to avoid alignment by accident to regular things in the event loop

View File

@ -34,8 +34,8 @@ const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
*/ */
module.exports = class VisibilityChangeEmitter extends EventEmitter { module.exports = class VisibilityChangeEmitter extends EventEmitter {
/** /**
* Creates a VisibilityChangeEmitter * Creates a VisibilityChangeEmitter
*/ */
constructor () { constructor () {
super() super()
if (typeof document === 'undefined') { if (typeof document === 'undefined') {
@ -47,13 +47,14 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
} }
/** /**
* document.hidden and document.visibilityChange are the two variables we need to check for; * document.hidden and document.visibilityChange are the two variables we need to check for;
* Since these variables are named differently in different browsers, this function sets * Since these variables are named differently in different browsers, this function sets
* the appropriate name based on the browser being used. Once executed, tha actual names of * the appropriate name based on the browser being used. Once executed, tha actual names of
* document.hidden and document.visibilityChange are found in this._hidden and this._visibilityChange * document.hidden and document.visibilityChange are found in this._hidden and this._visibilityChange
* respectively * respectively
* @private *
*/ * @private
*/
_initializeVisibilityVarNames () { _initializeVisibilityVarNames () {
let hidden let hidden
let visibilityChange let visibilityChange
@ -75,10 +76,11 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
} }
/** /**
* Adds an event listener on the document that listens to changes in document.visibilityChange * Adds an event listener on the document that listens to changes in document.visibilityChange
* (or whatever name by which the visibilityChange variable is known in the browser) * (or whatever name by which the visibilityChange variable is known in the browser)
* @private *
*/ * @private
*/
_addVisibilityChangeListener () { _addVisibilityChangeListener () {
if (typeof document.addEventListener === 'undefined' || if (typeof document.addEventListener === 'undefined' ||
typeof document[this._hidden] === 'undefined') { typeof document[this._hidden] === 'undefined') {
@ -90,10 +92,11 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
} }
/** /**
* The function returns ```true``` if the page is visible or ```false``` if the page is not visible and * The function returns ```true``` if the page is visible or ```false``` if the page is not visible and
* ```undefined``` if the page visibility API is not supported by the browser. * ```undefined``` if the page visibility API is not supported by the browser.
* @returns {Boolean|void} whether the page is now visible or not (undefined is unknown) *
*/ * @returns {boolean | void} whether the page is now visible or not (undefined is unknown)
*/
isVisible () { isVisible () {
if (this._hidden === undefined || document[this._hidden] === undefined) { if (this._hidden === undefined || document[this._hidden] === undefined) {
return undefined return undefined
@ -103,12 +106,12 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
} }
/** /**
* The function that is called when document.visibilityChange has changed * The function that is called when document.visibilityChange has changed
* It emits an event called visibilityChange and sends the value of document.hidden as a * It emits an event called visibilityChange and sends the value of document.hidden as a
* parameter * parameter
* *
* @private * @private
*/ */
_handleVisibilityChange () { _handleVisibilityChange () {
const visible = !document[this._hidden] const visible = !document[this._hidden]
debug(visible ? 'Page Visible' : 'Page Hidden') debug(visible ? 'Page Visible' : 'Page Hidden')

View File

@ -20,9 +20,9 @@ module.exports = (node) => {
* Iterates over all content routers in series to find providers of the given key. * Iterates over all content routers in series to find providers of the given key.
* Once a content router succeeds, iteration will stop. * Once a content router succeeds, iteration will stop.
* *
* @param {CID} key The CID key of the content to find * @param {CID} key - The CID key of the content to find
* @param {object} [options] * @param {object} [options]
* @param {number} [options.timeout] How long the query should run * @param {number} [options.timeout] - How long the query should run
* @param {number} [options.maxNumProviders] - maximum number of providers to find * @param {number} [options.maxNumProviders] - maximum number of providers to find
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>} * @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>}
*/ */
@ -51,7 +51,7 @@ module.exports = (node) => {
* Iterates over all content routers in parallel to notify it is * Iterates over all content routers in parallel to notify it is
* a provider of the given key. * a provider of the given key.
* *
* @param {CID} key The CID key of the content to find * @param {CID} key - The CID key of the content to find
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async provide (key) { // eslint-disable-line require-await async provide (key) { // eslint-disable-line require-await
@ -64,6 +64,7 @@ module.exports = (node) => {
/** /**
* Store the given key/value pair in the DHT. * Store the given key/value pair in the DHT.
*
* @param {Uint8Array} key * @param {Uint8Array} key
* @param {Uint8Array} value * @param {Uint8Array} value
* @param {Object} [options] - put options * @param {Object} [options] - put options
@ -81,6 +82,7 @@ module.exports = (node) => {
/** /**
* Get the value to the given key. * Get the value to the given key.
* Times out after 1 minute by default. * Times out after 1 minute by default.
*
* @param {Uint8Array} key * @param {Uint8Array} key
* @param {Object} [options] - get options * @param {Object} [options] - get options
* @param {number} [options.timeout] - optional timeout (default: 60000) * @param {number} [options.timeout] - optional timeout (default: 60000)
@ -96,6 +98,7 @@ module.exports = (node) => {
/** /**
* Get the `n` values to the given key without sorting. * Get the `n` values to the given key without sorting.
*
* @param {Uint8Array} key * @param {Uint8Array} key
* @param {number} nVals * @param {number} nVals
* @param {Object} [options] - get options * @param {Object} [options] - get options

View File

@ -16,6 +16,7 @@ class DialRequest {
* from `dialer.getTokens`. Once a DialRequest is created, it can be * from `dialer.getTokens`. Once a DialRequest is created, it can be
* started using `DialRequest.run(options)`. Once a single dial has succeeded, * started using `DialRequest.run(options)`. Once a single dial has succeeded,
* all other dials in the request will be cancelled. * all other dials in the request will be cancelled.
*
* @param {object} options * @param {object} options
* @param {Multiaddr[]} options.addrs * @param {Multiaddr[]} options.addrs
* @param {function(Multiaddr):Promise<Connection>} options.dialAction * @param {function(Multiaddr):Promise<Connection>} options.dialAction
@ -34,7 +35,7 @@ class DialRequest {
/** /**
* @async * @async
* @param {object} options * @param {object} options
* @param {AbortSignal} options.signal An AbortController signal * @param {AbortSignal} options.signal - An AbortController signal
* @returns {Connection} * @returns {Connection}
*/ */
async run (options) { async run (options) {

View File

@ -20,19 +20,22 @@ const {
class Dialer { class Dialer {
/** /**
* @constructor * @class
* @param {object} options * @param {object} options
* @param {TransportManager} options.transportManager * @param {TransportManager} options.transportManager
* @param {Peerstore} peerStore * @param {Peerstore} options.peerStore
* @param {number} options.concurrency Number of max concurrent dials. Defaults to `MAX_PARALLEL_DIALS` * @param {number} [options.concurrency = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
* @param {number} options.timeout How long a dial attempt is allowed to take. Defaults to `DIAL_TIMEOUT` * @param {number} [options.perPeerLimit = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
* @param {number} [options.timeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
* @param {object} [options.resolvers = {}] - multiaddr resolvers to use when dialing
*/ */
constructor ({ constructor ({
transportManager, transportManager,
peerStore, peerStore,
concurrency = MAX_PARALLEL_DIALS, concurrency = MAX_PARALLEL_DIALS,
timeout = DIAL_TIMEOUT, timeout = DIAL_TIMEOUT,
perPeerLimit = MAX_PER_PEER_DIALS perPeerLimit = MAX_PER_PEER_DIALS,
resolvers = {}
}) { }) {
this.transportManager = transportManager this.transportManager = transportManager
this.peerStore = peerStore this.peerStore = peerStore
@ -41,6 +44,10 @@ class Dialer {
this.perPeerLimit = perPeerLimit this.perPeerLimit = perPeerLimit
this.tokens = [...new Array(concurrency)].map((_, index) => index) this.tokens = [...new Array(concurrency)].map((_, index) => index)
this._pendingDials = new Map() this._pendingDials = new Map()
for (const [key, value] of Object.entries(resolvers)) {
multiaddr.resolvers.set(key, value)
}
} }
/** /**
@ -62,13 +69,13 @@ class Dialer {
* The dial to the first address that is successfully able to upgrade a connection * The dial to the first address that is successfully able to upgrade a connection
* will be used. * will be used.
* *
* @param {PeerId|Multiaddr|string} peer The peer to dial * @param {PeerId|Multiaddr|string} peer - The peer to dial
* @param {object} [options] * @param {object} [options]
* @param {AbortSignal} [options.signal] An AbortController signal * @param {AbortSignal} [options.signal] - An AbortController signal
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
*/ */
async connectToPeer (peer, options = {}) { async connectToPeer (peer, options = {}) {
const dialTarget = this._createDialTarget(peer) const dialTarget = await this._createDialTarget(peer)
if (!dialTarget.addrs.length) { if (!dialTarget.addrs.length) {
throw errCode(new Error('The dial request has no addresses'), codes.ERR_NO_VALID_ADDRESSES) throw errCode(new Error('The dial request has no addresses'), codes.ERR_NO_VALID_ADDRESSES)
@ -101,24 +108,31 @@ class Dialer {
* Creates a DialTarget. The DialTarget is used to create and track * Creates a DialTarget. The DialTarget is used to create and track
* the DialRequest to a given peer. * the DialRequest to a given peer.
* If a multiaddr is received it should be the first address attempted. * If a multiaddr is received it should be the first address attempted.
*
* @private * @private
* @param {PeerId|Multiaddr|string} peer A PeerId or Multiaddr * @param {PeerId|Multiaddr|string} peer - A PeerId or Multiaddr
* @returns {DialTarget} * @returns {Promise<DialTarget>}
*/ */
_createDialTarget (peer) { async _createDialTarget (peer) {
const { id, multiaddrs } = getPeer(peer) const { id, multiaddrs } = getPeer(peer)
if (multiaddrs) { if (multiaddrs) {
this.peerStore.addressBook.add(id, multiaddrs) this.peerStore.addressBook.add(id, multiaddrs)
} }
let addrs = this.peerStore.addressBook.getMultiaddrsForPeer(id) || [] let knownAddrs = this.peerStore.addressBook.getMultiaddrsForPeer(id) || []
// If received a multiaddr to dial, it should be the first to use // If received a multiaddr to dial, it should be the first to use
// But, if we know other multiaddrs for the peer, we should try them too. // But, if we know other multiaddrs for the peer, we should try them too.
if (multiaddr.isMultiaddr(peer)) { if (multiaddr.isMultiaddr(peer)) {
addrs = addrs.filter((addr) => !peer.equals(addr)) knownAddrs = knownAddrs.filter((addr) => !peer.equals(addr))
addrs.unshift(peer) knownAddrs.unshift(peer)
}
const addrs = []
for (const a of knownAddrs) {
const resolvedAddrs = await this._resolve(a)
resolvedAddrs.forEach(ra => addrs.push(ra))
} }
return { return {
@ -137,10 +151,11 @@ class Dialer {
/** /**
* Creates a PendingDial that wraps the underlying DialRequest * Creates a PendingDial that wraps the underlying DialRequest
*
* @private * @private
* @param {DialTarget} dialTarget * @param {DialTarget} dialTarget
* @param {object} [options] * @param {object} [options]
* @param {AbortSignal} [options.signal] An AbortController signal * @param {AbortSignal} [options.signal] - An AbortController signal
* @returns {PendingDial} * @returns {PendingDial}
*/ */
_createPendingDial (dialTarget, options) { _createPendingDial (dialTarget, options) {
@ -187,6 +202,52 @@ class Dialer {
log('token %d released', token) log('token %d released', token)
this.tokens.push(token) this.tokens.push(token)
} }
/**
* Resolve multiaddr recursively.
*
* @param {Multiaddr} ma
* @returns {Promise<Array<Multiaddr>>}
*/
async _resolve (ma) {
// TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
// Now only supporting resolve for dnsaddr
const resolvableProto = ma.protoNames().includes('dnsaddr')
// Multiaddr is not resolvable? End recursion!
if (!resolvableProto) {
return [ma]
}
const resolvedMultiaddrs = await this._resolveRecord(ma)
const recursiveMultiaddrs = await Promise.all(resolvedMultiaddrs.map((nm) => {
return this._resolve(nm)
}))
return recursiveMultiaddrs.flat().reduce((array, newM) => {
if (!array.find(m => m.equals(newM))) {
array.push(newM)
}
return array
}, []) // Unique addresses
}
/**
* Resolve a given multiaddr. If this fails, an empty array will be returned
*
* @param {Multiaddr} ma
* @returns {Promise<Array<Multiaddr>>}
*/
async _resolveRecord (ma) {
try {
ma = multiaddr(ma.toString()) // Use current multiaddr module
const multiaddrs = await ma.resolve()
return multiaddrs
} catch (_) {
log.error(`multiaddr ${ma} could not be resolved`)
return []
}
}
} }
module.exports = Dialer module.exports = Dialer

View File

@ -16,6 +16,7 @@ exports.codes = {
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED', ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED', ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES', ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF', ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT', ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
ERR_ENCRYPTION_FAILED: 'ERR_ENCRYPTION_FAILED', ERR_ENCRYPTION_FAILED: 'ERR_ENCRYPTION_FAILED',

View File

@ -9,8 +9,8 @@ const { codes } = require('./errors')
/** /**
* Converts the given `peer` to a `Peer` object. * Converts the given `peer` to a `Peer` object.
* If a multiaddr is received, the addressBook is updated. * If a multiaddr is received, the addressBook is updated.
*
* @param {PeerId|Multiaddr|string} peer * @param {PeerId|Multiaddr|string} peer
* @param {PeerStore} peerStore
* @returns {{ id: PeerId, multiaddrs: Array<Multiaddr> }} * @returns {{ id: PeerId, multiaddrs: Array<Multiaddr> }}
*/ */
function getPeer (peer) { function getPeer (peer) {

View File

@ -32,7 +32,8 @@ const { codes } = require('../errors')
class IdentifyService { class IdentifyService {
/** /**
* Takes the `addr` and converts it to a Multiaddr if possible * Takes the `addr` and converts it to a Multiaddr if possible
* @param {Uint8Array|String} addr *
* @param {Uint8Array | string} addr
* @returns {Multiaddr|null} * @returns {Multiaddr|null}
*/ */
static getCleanMultiaddr (addr) { static getCleanMultiaddr (addr) {
@ -47,10 +48,10 @@ class IdentifyService {
} }
/** /**
* @constructor * @class
* @param {object} options * @param {object} options
* @param {Libp2p} options.libp2p * @param {Libp2p} options.libp2p
* @param {Map<string, handler>} options.protocols A reference to the protocols we support * @param {Map<string, handler>} options.protocols - A reference to the protocols we support
*/ */
constructor ({ libp2p, protocols }) { constructor ({ libp2p, protocols }) {
/** /**
@ -82,10 +83,21 @@ class IdentifyService {
this._protocols = protocols this._protocols = protocols
this.handleMessage = this.handleMessage.bind(this) this.handleMessage = this.handleMessage.bind(this)
// Store self host metadata
this._host = {
agentVersion: AGENT_VERSION,
protocolVersion: PROTOCOL_VERSION,
...libp2p._options.host
}
this.peerStore.metadataBook.set(this.peerId, 'AgentVersion', uint8ArrayFromString(this._host.agentVersion))
this.peerStore.metadataBook.set(this.peerId, 'ProtocolVersion', uint8ArrayFromString(this._host.protocolVersion))
} }
/** /**
* Send an Identify Push update to the list of connections * Send an Identify Push update to the list of connections
*
* @param {Array<Connection>} connections * @param {Array<Connection>} connections
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
@ -119,6 +131,7 @@ class IdentifyService {
/** /**
* Calls `push` for all peers in the `peerStore` that are connected * Calls `push` for all peers in the `peerStore` that are connected
*
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
pushToPeerStore (peerStore) { pushToPeerStore (peerStore) {
@ -209,7 +222,7 @@ class IdentifyService {
* A handler to register with Libp2p to process identify messages. * A handler to register with Libp2p to process identify messages.
* *
* @param {object} options * @param {object} options
* @param {String} options.protocol * @param {string} options.protocol
* @param {*} options.stream * @param {*} options.stream
* @param {Connection} options.connection * @param {Connection} options.connection
* @returns {Promise<void>} * @returns {Promise<void>}
@ -228,6 +241,7 @@ class IdentifyService {
/** /**
* Sends the `Identify` response with the Signed Peer Record * Sends the `Identify` response with the Signed Peer Record
* to the requesting peer over the given `connection` * to the requesting peer over the given `connection`
*
* @private * @private
* @param {object} options * @param {object} options
* @param {*} options.stream * @param {*} options.stream
@ -242,8 +256,8 @@ class IdentifyService {
const signedPeerRecord = await this._getSelfPeerRecord() const signedPeerRecord = await this._getSelfPeerRecord()
const message = Message.encode({ const message = Message.encode({
protocolVersion: PROTOCOL_VERSION, protocolVersion: this._host.protocolVersion,
agentVersion: AGENT_VERSION, agentVersion: this._host.agentVersion,
publicKey, publicKey,
listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes), listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes),
signedPeerRecord, signedPeerRecord,
@ -265,6 +279,7 @@ class IdentifyService {
/** /**
* Reads the Identify Push message from the given `connection` * Reads the Identify Push message from the given `connection`
*
* @private * @private
* @param {object} options * @param {object} options
* @param {*} options.stream * @param {*} options.stream
@ -311,7 +326,8 @@ class IdentifyService {
/** /**
* Get self signed peer record raw envelope. * Get self signed peer record raw envelope.
* @return {Uint8Array} *
* @returns {Uint8Array}
*/ */
async _getSelfPeerRecord () { async _getSelfPeerRecord () {
const selfSignedPeerRecord = this.peerStore.addressBook.getRawEnvelope(this.peerId) const selfSignedPeerRecord = this.peerStore.addressBook.getRawEnvelope(this.peerId)
@ -340,6 +356,7 @@ class IdentifyService {
module.exports.IdentifyService = IdentifyService module.exports.IdentifyService = IdentifyService
/** /**
* The protocols the IdentifyService supports * The protocols the IdentifyService supports
*
* @property multicodecs * @property multicodecs
*/ */
module.exports.multicodecs = { module.exports.multicodecs = {

View File

@ -35,8 +35,6 @@ const {
/** /**
* @fires Libp2p#error Emitted when an error occurs * @fires Libp2p#error Emitted when an error occurs
* @fires Libp2p#peer:connect Emitted when a peer is connected to this node
* @fires Libp2p#peer:disconnect Emitted when a peer disconnects from this node
* @fires Libp2p#peer:discovery Emitted when a peer is discovered * @fires Libp2p#peer:discovery Emitted when a peer is discovered
*/ */
class Libp2p extends EventEmitter { class Libp2p extends EventEmitter {
@ -136,7 +134,8 @@ class Libp2p extends EventEmitter {
peerStore: this.peerStore, peerStore: this.peerStore,
concurrency: this._options.dialer.maxParallelDials, concurrency: this._options.dialer.maxParallelDials,
perPeerLimit: this._options.dialer.maxDialsPerPeer, perPeerLimit: this._options.dialer.maxDialsPerPeer,
timeout: this._options.dialer.dialTimeout timeout: this._options.dialer.dialTimeout,
resolvers: this._options.dialer.resolvers
}) })
this._modules.transport.forEach((Transport) => { this._modules.transport.forEach((Transport) => {
@ -206,6 +205,7 @@ class Libp2p extends EventEmitter {
/** /**
* Overrides EventEmitter.emit to conditionally emit errors * Overrides EventEmitter.emit to conditionally emit errors
* if there is a handler. If not, errors will be logged. * if there is a handler. If not, errors will be logged.
*
* @param {string} eventName * @param {string} eventName
* @param {...any} args * @param {...any} args
* @returns {void} * @returns {void}
@ -240,8 +240,9 @@ class Libp2p extends EventEmitter {
/** /**
* Stop the libp2p node by closing its listeners and open connections * Stop the libp2p node by closing its listeners and open connections
*
* @async * @async
* @returns {void} * @returns {Promise<void>}
*/ */
async stop () { async stop () {
log('libp2p is stopping') log('libp2p is stopping')
@ -281,6 +282,7 @@ class Libp2p extends EventEmitter {
/** /**
* Load keychain keys from the datastore. * Load keychain keys from the datastore.
* Imports the private key as 'self', if needed. * Imports the private key as 'self', if needed.
*
* @async * @async
* @returns {void} * @returns {void}
*/ */
@ -299,6 +301,7 @@ class Libp2p extends EventEmitter {
/** /**
* Gets a Map of the current connections. The keys are the stringified * Gets a Map of the current connections. The keys are the stringified
* `PeerId` of the peer. The value is an array of Connections to that peer. * `PeerId` of the peer. The value is an array of Connections to that peer.
*
* @returns {Map<string, Connection[]>} * @returns {Map<string, Connection[]>}
*/ */
get connections () { get connections () {
@ -308,7 +311,8 @@ class Libp2p extends EventEmitter {
/** /**
* Dials to the provided peer. If successful, the known metadata of the * Dials to the provided peer. If successful, the known metadata of the
* peer will be added to the nodes `peerStore` * peer will be added to the nodes `peerStore`
* @param {PeerId|Multiaddr|string} peer The peer to dial *
* @param {PeerId|Multiaddr|string} peer - The peer to dial
* @param {object} options * @param {object} options
* @param {AbortSignal} [options.signal] * @param {AbortSignal} [options.signal]
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
@ -321,8 +325,9 @@ class Libp2p extends EventEmitter {
* Dials to the provided peer and handshakes with the given protocol. * Dials to the provided peer and handshakes with the given protocol.
* If successful, the known metadata of the peer will be added to the nodes `peerStore`, * If successful, the known metadata of the peer will be added to the nodes `peerStore`,
* and the `Connection` will be returned * and the `Connection` will be returned
*
* @async * @async
* @param {PeerId|Multiaddr|string} peer The peer to dial * @param {PeerId|Multiaddr|string} peer - The peer to dial
* @param {string[]|string} protocols * @param {string[]|string} protocols
* @param {object} options * @param {object} options
* @param {AbortSignal} [options.signal] * @param {AbortSignal} [options.signal]
@ -330,6 +335,11 @@ class Libp2p extends EventEmitter {
*/ */
async dialProtocol (peer, protocols, options) { async dialProtocol (peer, protocols, options) {
const { id, multiaddrs } = getPeer(peer) const { id, multiaddrs } = getPeer(peer)
if (id.equals(this.peerId)) {
throw errCode(new Error('Cannot dial self'), codes.ERR_DIALED_SELF)
}
let connection = this.connectionManager.get(id) let connection = this.connectionManager.get(id)
if (!connection) { if (!connection) {
@ -350,7 +360,8 @@ class Libp2p extends EventEmitter {
* Get peer advertising multiaddrs by concating the addresses used * Get peer advertising multiaddrs by concating the addresses used
* by transports to listen with the announce addresses. * by transports to listen with the announce addresses.
* Duplicated addresses and noAnnounce addresses are filtered out. * Duplicated addresses and noAnnounce addresses are filtered out.
* @return {Array<Multiaddr>} *
* @returns {Array<Multiaddr>}
*/ */
get multiaddrs () { get multiaddrs () {
// Filter noAnnounce multiaddrs // Filter noAnnounce multiaddrs
@ -376,7 +387,8 @@ class Libp2p extends EventEmitter {
/** /**
* Disconnects all connections to the given `peer` * Disconnects all connections to the given `peer`
* @param {PeerId|multiaddr|string} peer the peer to close connections to *
* @param {PeerId|multiaddr|string} peer - the peer to close connections to
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async hangUp (peer) { async hangUp (peer) {
@ -397,7 +409,8 @@ class Libp2p extends EventEmitter {
/** /**
* Pings the given peer in order to obtain the operation latency. * Pings the given peer in order to obtain the operation latency.
* @param {PeerId|Multiaddr|string} peer The peer to ping *
* @param {PeerId|Multiaddr|string} peer - The peer to ping
* @returns {Promise<number>} * @returns {Promise<number>}
*/ */
ping (peer) { ping (peer) {
@ -413,6 +426,7 @@ class Libp2p extends EventEmitter {
/** /**
* Registers the `handler` for each protocol * Registers the `handler` for each protocol
*
* @param {string[]|string} protocols * @param {string[]|string} protocols
* @param {function({ connection:*, stream:*, protocol:string })} handler * @param {function({ connection:*, stream:*, protocol:string })} handler
*/ */
@ -431,6 +445,7 @@ class Libp2p extends EventEmitter {
/** /**
* Removes the handler for each protocol. The protocol * Removes the handler for each protocol. The protocol
* will no longer be supported on streams. * will no longer be supported on streams.
*
* @param {string[]|string} protocols * @param {string[]|string} protocols
*/ */
unhandle (protocols) { unhandle (protocols) {
@ -471,6 +486,7 @@ class Libp2p extends EventEmitter {
/** /**
* Called when libp2p has started and before it returns * Called when libp2p has started and before it returns
*
* @private * @private
*/ */
async _onDidStart () { async _onDidStart () {
@ -496,6 +512,7 @@ class Libp2p extends EventEmitter {
/** /**
* Called whenever peer discovery services emit `peer` events. * Called whenever peer discovery services emit `peer` events.
* Known peers may be emitted. * Known peers may be emitted.
*
* @private * @private
* @param {{ id: PeerId, multiaddrs: Array<Multiaddr>, protocols: Array<string> }} peer * @param {{ id: PeerId, multiaddrs: Array<Multiaddr>, protocols: Array<string> }} peer
*/ */
@ -513,6 +530,7 @@ class Libp2p extends EventEmitter {
* Will dial to the given `peerId` if the current number of * Will dial to the given `peerId` if the current number of
* connected peers is less than the configured `ConnectionManager` * connected peers is less than the configured `ConnectionManager`
* minConnections. * minConnections.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
*/ */
@ -586,8 +604,9 @@ class Libp2p extends EventEmitter {
/** /**
* Like `new Libp2p(options)` except it will create a `PeerId` * Like `new Libp2p(options)` except it will create a `PeerId`
* instance if one is not provided in options. * instance if one is not provided in options.
* @param {object} options Libp2p configuration options *
* @returns {Libp2p} * @param {object} options - Libp2p configuration options
* @returns {Promise<Libp2p>}
*/ */
Libp2p.create = async function create (options = {}) { Libp2p.create = async function create (options = {}) {
if (options.peerId) { if (options.peerId) {

View File

@ -228,7 +228,7 @@ class Keychain {
/** /**
* List all the keys. * List all the keys.
* *
* @returns {KeyInfo[]} * @returns {KeyInfo[]}
*/ */
async listKeys () { async listKeys () {
const self = this const self = this
@ -248,7 +248,7 @@ class Keychain {
* Find a key by it's id. * Find a key by it's id.
* *
* @param {string} id - The universally unique key identifier. * @param {string} id - The universally unique key identifier.
* @returns {KeyInfo} * @returns {KeyInfo}
*/ */
async findKeyById (id) { async findKeyById (id) {
try { try {
@ -263,7 +263,7 @@ class Keychain {
* Find a key by it's name. * Find a key by it's name.
* *
* @param {string} name - The local key name. * @param {string} name - The local key name.
* @returns {KeyInfo} * @returns {KeyInfo}
*/ */
async findKeyByName (name) { async findKeyByName (name) {
if (!validateKeyName(name)) { if (!validateKeyName(name)) {
@ -283,7 +283,7 @@ class Keychain {
* Remove an existing key. * Remove an existing key.
* *
* @param {string} name - The local key name; must already exist. * @param {string} name - The local key name; must already exist.
* @returns {KeyInfo} * @returns {KeyInfo}
*/ */
async removeKey (name) { async removeKey (name) {
const self = this const self = this
@ -304,7 +304,7 @@ class Keychain {
* *
* @param {string} oldName - The old local key name; must already exist. * @param {string} oldName - The old local key name; must already exist.
* @param {string} newName - The new local key name; must not already exist. * @param {string} newName - The new local key name; must not already exist.
* @returns {KeyInfo} * @returns {KeyInfo}
*/ */
async renameKey (oldName, newName) { async renameKey (oldName, newName) {
const self = this const self = this
@ -345,7 +345,7 @@ class Keychain {
* *
* @param {string} name - The local key name; must already exist. * @param {string} name - The local key name; must already exist.
* @param {string} password - The password * @param {string} password - The password
* @returns {string} * @returns {string}
*/ */
async exportKey (name, password) { async exportKey (name, password) {
if (!validateKeyName(name)) { if (!validateKeyName(name)) {
@ -372,7 +372,7 @@ class Keychain {
* @param {string} name - The local key name; must not already exist. * @param {string} name - The local key name; must not already exist.
* @param {string} pem - The PEM encoded PKCS #8 string * @param {string} pem - The PEM encoded PKCS #8 string
* @param {string} password - The password. * @param {string} password - The password.
* @returns {KeyInfo} * @returns {KeyInfo}
*/ */
async importKey (name, pem, password) { async importKey (name, pem, password) {
const self = this const self = this
@ -448,7 +448,7 @@ class Keychain {
* Gets the private key as PEM encoded PKCS #8 string. * Gets the private key as PEM encoded PKCS #8 string.
* *
* @param {string} name * @param {string} name
* @returns {string} * @returns {string}
* @private * @private
*/ */
async _getPrivateKey (name) { async _getPrivateKey (name) {

View File

@ -77,7 +77,7 @@ exports.certificateForKey = (key, privateKey) => {
* resolve to either `true` or `false`. * resolve to either `true` or `false`.
* *
* @param {Array} array * @param {Array} array
* @param {function(*)} asyncCompare An async function that returns a boolean * @param {function(*)} asyncCompare - An async function that returns a boolean
*/ */
async function findAsync (array, asyncCompare) { async function findAsync (array, asyncCompare) {
const promises = array.map(asyncCompare) const promises = array.map(asyncCompare)

View File

@ -66,6 +66,7 @@ class Metrics {
/** /**
* Gets the global `Stats` object * Gets the global `Stats` object
*
* @returns {Stats} * @returns {Stats}
*/ */
get global () { get global () {
@ -74,6 +75,7 @@ class Metrics {
/** /**
* Returns a list of `PeerId` strings currently being tracked * Returns a list of `PeerId` strings currently being tracked
*
* @returns {Array<string>} * @returns {Array<string>}
*/ */
get peers () { get peers () {
@ -83,6 +85,7 @@ class Metrics {
/** /**
* Returns the `Stats` object for the given `PeerId` whether it * Returns the `Stats` object for the given `PeerId` whether it
* is a live peer, or in the disconnected peer LRU cache. * is a live peer, or in the disconnected peer LRU cache.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Stats} * @returns {Stats}
*/ */
@ -93,6 +96,7 @@ class Metrics {
/** /**
* Returns a list of all protocol strings currently being tracked. * Returns a list of all protocol strings currently being tracked.
*
* @returns {Array<string>} * @returns {Array<string>}
*/ */
get protocols () { get protocols () {
@ -101,6 +105,7 @@ class Metrics {
/** /**
* Returns the `Stats` object for the given `protocol`. * Returns the `Stats` object for the given `protocol`.
*
* @param {string} protocol * @param {string} protocol
* @returns {Stats} * @returns {Stats}
*/ */
@ -112,6 +117,7 @@ class Metrics {
* Should be called when all connections to a given peer * Should be called when all connections to a given peer
* have closed. The `Stats` collection for the peer will * have closed. The `Stats` collection for the peer will
* be stopped and moved to an LRU for temporary retention. * be stopped and moved to an LRU for temporary retention.
*
* @param {PeerId} peerId * @param {PeerId} peerId
*/ */
onPeerDisconnected (peerId) { onPeerDisconnected (peerId) {
@ -131,10 +137,10 @@ class Metrics {
* *
* @private * @private
* @param {object} params * @param {object} params
* @param {PeerId} params.remotePeer Remote peer * @param {PeerId} params.remotePeer - Remote peer
* @param {string} [params.protocol] Protocol string the stream is running * @param {string} [params.protocol] - Protocol string the stream is running
* @param {string} params.direction One of ['in','out'] * @param {string} params.direction - One of ['in','out']
* @param {number} params.dataLength Size of the message * @param {number} params.dataLength - Size of the message
* @returns {void} * @returns {void}
*/ */
_onMessage ({ remotePeer, protocol, direction, dataLength }) { _onMessage ({ remotePeer, protocol, direction, dataLength }) {
@ -167,7 +173,8 @@ class Metrics {
* Replaces the `PeerId` string with the given `peerId`. * Replaces the `PeerId` string with the given `peerId`.
* If stats are already being tracked for the given `peerId`, the * If stats are already being tracked for the given `peerId`, the
* placeholder stats will be merged with the existing stats. * placeholder stats will be merged with the existing stats.
* @param {PeerId} placeholder A peerId string *
* @param {PeerId} placeholder - A peerId string
* @param {PeerId} peerId * @param {PeerId} peerId
*/ */
updatePlaceholder (placeholder, peerId) { updatePlaceholder (placeholder, peerId) {
@ -198,9 +205,9 @@ class Metrics {
* with the placeholder string returned from here, and the known `PeerId`. * with the placeholder string returned from here, and the known `PeerId`.
* *
* @param {Object} options * @param {Object} options
* @param {{ sink: function(*), source: function() }} options.stream A duplex iterable stream * @param {{ sink: function(*), source: function() }} options.stream - A duplex iterable stream
* @param {PeerId} [options.peerId] The id of the remote peer that's connected * @param {PeerId} [options.remotePeer] - The id of the remote peer that's connected
* @param {string} [options.protocol] The protocol the stream is running * @param {string} [options.protocol] - The protocol the stream is running
* @returns {string} The peerId string or placeholder string * @returns {string} The peerId string or placeholder string
*/ */
trackStream ({ stream, remotePeer, protocol }) { trackStream ({ stream, remotePeer, protocol }) {
@ -233,6 +240,7 @@ class Metrics {
/** /**
* Merges `other` into `target`. `target` will be modified * Merges `other` into `target`. `target` will be modified
* and returned. * and returned.
*
* @param {Stats} target * @param {Stats} target
* @param {Stats} other * @param {Stats} other
* @returns {Stats} * @returns {Stats}

View File

@ -5,7 +5,7 @@ const LRU = require('hashlru')
/** /**
* Creates and returns a Least Recently Used Cache * Creates and returns a Least Recently Used Cache
* *
* @param {Number} maxSize * @param {number} maxSize
* @returns {LRUCache} * @returns {LRUCache}
*/ */
module.exports = (maxSize) => { module.exports = (maxSize) => {

View File

@ -196,8 +196,8 @@ class Stats extends EventEmitter {
* *
* @private * @private
* @param {string} key * @param {string} key
* @param {number} timeDiffMS Time in milliseconds * @param {number} timeDiffMS - Time in milliseconds
* @param {Timestamp} latestTime Time in ticks * @param {Timestamp} latestTime - Time in ticks
* @returns {void} * @returns {void}
*/ */
_updateFrequencyFor (key, timeDiffMS, latestTime) { _updateFrequencyFor (key, timeDiffMS, latestTime) {

View File

@ -15,9 +15,9 @@ module.exports = (node) => {
/** /**
* Iterates over all peer routers in series to find the given peer. * Iterates over all peer routers in series to find the given peer.
* *
* @param {String} id The id of the peer to find * @param {string} id - The id of the peer to find
* @param {object} [options] * @param {object} [options]
* @param {number} [options.timeout] How long the query should run * @param {number} [options.timeout] - How long the query should run
* @returns {Promise<{ id: PeerId, multiaddrs: Multiaddr[] }>} * @returns {Promise<{ id: PeerId, multiaddrs: Multiaddr[] }>}
*/ */
findPeer: async (id, options) => { // eslint-disable-line require-await findPeer: async (id, options) => { // eslint-disable-line require-await

View File

@ -23,29 +23,32 @@ const Envelope = require('../record/envelope')
class AddressBook extends Book { class AddressBook extends Book {
/** /**
* Address object * Address object
*
* @typedef {Object} Address * @typedef {Object} Address
* @property {Multiaddr} multiaddr peer multiaddr. * @property {Multiaddr} multiaddr peer multiaddr.
* @property {boolean} isCertified obtained from a signed peer record. * @property {boolean} isCertified obtained from a signed peer record.
*/ */
/** /**
* CertifiedRecord object * CertifiedRecord object
* @typedef {Object} CertifiedRecord *
* @property {Uint8Array} raw raw envelope. * @typedef {Object} CertifiedRecord
* @property {number} seqNumber seq counter. * @property {Uint8Array} raw raw envelope.
*/ * @property {number} seqNumber seq counter.
*/
/** /**
* Entry object for the addressBook * Entry object for the addressBook
* @typedef {Object} Entry *
* @property {Array<Address>} addresses peer Addresses. * @typedef {Object} Entry
* @property {CertifiedRecord} record certified peer record. * @property {Array<Address>} addresses peer Addresses.
*/ * @property {CertifiedRecord} record certified peer record.
*/
/** /**
* @constructor * @class
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
constructor (peerStore) { constructor (peerStore) {
/** /**
* PeerStore Event emitter, used by the AddressBook to emit: * PeerStore Event emitter, used by the AddressBook to emit:
@ -66,6 +69,7 @@ class AddressBook extends Book {
/** /**
* Map known peers to their known Address Entries. * Map known peers to their known Address Entries.
*
* @type {Map<string, Array<Entry>>} * @type {Map<string, Array<Entry>>}
*/ */
this.data = new Map() this.data = new Map()
@ -75,8 +79,9 @@ class AddressBook extends Book {
* ConsumePeerRecord adds addresses from a signed peer record contained in a record envelope. * ConsumePeerRecord adds addresses from a signed peer record contained in a record envelope.
* This will return a boolean that indicates if the record was successfully processed and added * This will return a boolean that indicates if the record was successfully processed and added
* into the AddressBook. * into the AddressBook.
*
* @param {Envelope} envelope * @param {Envelope} envelope
* @return {boolean} * @returns {boolean}
*/ */
consumePeerRecord (envelope) { consumePeerRecord (envelope) {
let peerRecord let peerRecord
@ -127,8 +132,9 @@ class AddressBook extends Book {
/** /**
* Get the raw Envelope for a peer. Returns * Get the raw Envelope for a peer. Returns
* undefined if no Envelope is found. * undefined if no Envelope is found.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @return {Uint8Array|undefined} * @returns {Uint8Array|undefined}
*/ */
getRawEnvelope (peerId) { getRawEnvelope (peerId) {
const entry = this.data.get(peerId.toB58String()) const entry = this.data.get(peerId.toB58String())
@ -143,8 +149,9 @@ class AddressBook extends Book {
/** /**
* Get an Envelope containing a PeerRecord for the given peer. * Get an Envelope containing a PeerRecord for the given peer.
* Returns undefined if no record exists. * Returns undefined if no record exists.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @return {Promise<Envelope|void>} * @returns {Promise<Envelope|void>}
*/ */
getPeerRecord (peerId) { getPeerRecord (peerId) {
const raw = this.getRawEnvelope(peerId) const raw = this.getRawEnvelope(peerId)
@ -161,6 +168,7 @@ class AddressBook extends Book {
* This will replace previously stored multiaddrs, if available. * This will replace previously stored multiaddrs, if available.
* Replacing stored multiaddrs might result in losing obtained certified addresses. * Replacing stored multiaddrs might result in losing obtained certified addresses.
* If you are not sure, it's recommended to use `add` instead. * If you are not sure, it's recommended to use `add` instead.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<Multiaddr>} multiaddrs * @param {Array<Multiaddr>} multiaddrs
@ -211,6 +219,7 @@ class AddressBook extends Book {
/** /**
* Add known addresses of a provided peer. * Add known addresses of a provided peer.
* If the peer is not known, it is set with the given addresses. * If the peer is not known, it is set with the given addresses.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<Multiaddr>} multiaddrs * @param {Array<Multiaddr>} multiaddrs
* @returns {AddressBook} * @returns {AddressBook}
@ -258,6 +267,7 @@ class AddressBook extends Book {
/** /**
* Get the known data of a provided peer. * Get the known data of a provided peer.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Array<data>} * @returns {Array<data>}
@ -274,6 +284,7 @@ class AddressBook extends Book {
/** /**
* Transforms received multiaddrs into Address. * Transforms received multiaddrs into Address.
*
* @private * @private
* @param {Array<Multiaddr>} multiaddrs * @param {Array<Multiaddr>} multiaddrs
* @param {boolean} [isCertified] * @param {boolean} [isCertified]
@ -306,6 +317,7 @@ class AddressBook extends Book {
* Get the known multiaddrs for a given peer. All returned multiaddrs * Get the known multiaddrs for a given peer. All returned multiaddrs
* will include the encapsulated `PeerId` of the peer. * will include the encapsulated `PeerId` of the peer.
* Returns `undefined` if there are no known multiaddrs for the given peer. * Returns `undefined` if there are no known multiaddrs for the given peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Array<Multiaddr>|undefined} * @returns {Array<Multiaddr>|undefined}
*/ */

View File

@ -14,12 +14,12 @@ const passthrough = data => data
*/ */
class Book { class Book {
/** /**
* @constructor * @class
* @param {Object} properties * @param {Object} properties
* @param {PeerStore} properties.peerStore PeerStore instance. * @param {PeerStore} properties.peerStore - PeerStore instance.
* @param {string} properties.eventName Name of the event to emit by the PeerStore. * @param {string} properties.eventName - Name of the event to emit by the PeerStore.
* @param {string} properties.eventProperty Name of the property to emit by the PeerStore. * @param {string} properties.eventProperty - Name of the property to emit by the PeerStore.
* @param {function} [properties.eventTransformer] Transformer function of the provided data for being emitted. * @param {Function} [properties.eventTransformer] - Transformer function of the provided data for being emitted.
*/ */
constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough }) { constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough }) {
this._ps = peerStore this._ps = peerStore
@ -29,6 +29,7 @@ class Book {
/** /**
* Map known peers to their data. * Map known peers to their data.
*
* @type {Map<string, Array<Data>} * @type {Map<string, Array<Data>}
*/ */
this.data = new Map() this.data = new Map()
@ -36,6 +37,7 @@ class Book {
/** /**
* Set known data of a provided peer. * Set known data of a provided peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<Data>|Data} data * @param {Array<Data>|Data} data
*/ */
@ -45,12 +47,13 @@ class Book {
/** /**
* Set data into the datastructure, persistence and emit it using the provided transformers. * Set data into the datastructure, persistence and emit it using the provided transformers.
*
* @private * @private
* @param {PeerId} peerId peerId of the data to store * @param {PeerId} peerId - peerId of the data to store
* @param {*} data data to store. * @param {*} data - data to store.
* @param {Object} [options] storing options. * @param {Object} [options] - storing options.
* @param {boolean} [options.emit = true] emit the provided data. * @param {boolean} [options.emit = true] - emit the provided data.
* @return {void} * @returns {void}
*/ */
_setData (peerId, data, { emit = true } = {}) { _setData (peerId, data, { emit = true } = {}) {
const b58key = peerId.toB58String() const b58key = peerId.toB58String()
@ -64,6 +67,7 @@ class Book {
/** /**
* Emit data. * Emit data.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {*} data * @param {*} data
@ -78,6 +82,7 @@ class Book {
/** /**
* Get the known data of a provided peer. * Get the known data of a provided peer.
* Returns `undefined` if there is no available data for the given peer. * Returns `undefined` if there is no available data for the given peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Array<Data>|undefined} * @returns {Array<Data>|undefined}
*/ */
@ -93,6 +98,7 @@ class Book {
/** /**
* Deletes the provided peer from the book. * Deletes the provided peer from the book.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {boolean} * @returns {boolean}
*/ */

View File

@ -19,6 +19,7 @@ const {
/** /**
* Responsible for managing known peers, as well as their addresses, protocols and metadata. * Responsible for managing known peers, as well as their addresses, protocols and metadata.
*
* @fires PeerStore#peer Emitted when a new peer is added. * @fires PeerStore#peer Emitted when a new peer is added.
* @fires PeerStore#change:protocols Emitted when a known peer supports a different set of protocols. * @fires PeerStore#change:protocols Emitted when a known peer supports a different set of protocols.
* @fires PeerStore#change:multiaddrs Emitted when a known peer has a different set of multiaddrs. * @fires PeerStore#change:multiaddrs Emitted when a known peer has a different set of multiaddrs.
@ -28,6 +29,7 @@ const {
class PeerStore extends EventEmitter { class PeerStore extends EventEmitter {
/** /**
* Peer object * Peer object
*
* @typedef {Object} Peer * @typedef {Object} Peer
* @property {PeerId} id peer's peer-id instance. * @property {PeerId} id peer's peer-id instance.
* @property {Array<Address>} addresses peer's addresses containing its multiaddrs and metadata. * @property {Array<Address>} addresses peer's addresses containing its multiaddrs and metadata.
@ -36,7 +38,9 @@ class PeerStore extends EventEmitter {
*/ */
/** /**
* @constructor * @param {object} options
* @param {PeerId} options.peerId
* @class
*/ */
constructor ({ peerId }) { constructor ({ peerId }) {
super() super()
@ -76,6 +80,7 @@ class PeerStore extends EventEmitter {
/** /**
* Get all the stored information of every peer known. * Get all the stored information of every peer known.
*
* @returns {Map<string, Peer>} * @returns {Map<string, Peer>}
*/ */
get peers () { get peers () {
@ -99,6 +104,7 @@ class PeerStore extends EventEmitter {
/** /**
* Delete the information of the given peer in every book. * Delete the information of the given peer in every book.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {boolean} true if found and removed * @returns {boolean} true if found and removed
*/ */
@ -113,6 +119,7 @@ class PeerStore extends EventEmitter {
/** /**
* Get the stored information of a given peer. * Get the stored information of a given peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Peer} * @returns {Peer}
*/ */

View File

@ -18,9 +18,9 @@ const {
*/ */
class KeyBook extends Book { class KeyBook extends Book {
/** /**
* @constructor * @class
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
constructor (peerStore) { constructor (peerStore) {
super({ super({
peerStore, peerStore,
@ -31,6 +31,7 @@ class KeyBook extends Book {
/** /**
* Map known peers to their known Public Key. * Map known peers to their known Public Key.
*
* @type {Map<string, PeerId>} * @type {Map<string, PeerId>}
*/ */
this.data = new Map() this.data = new Map()
@ -38,11 +39,12 @@ class KeyBook extends Book {
/** /**
* Set the Peer public key. * Set the Peer public key.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey} publicKey * @param {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey} publicKey
* @return {KeyBook} * @returns {KeyBook}
*/ */
set (peerId, publicKey) { set (peerId, publicKey) {
if (!PeerId.isPeerId(peerId)) { if (!PeerId.isPeerId(peerId)) {
log.error('peerId must be an instance of peer-id to store data') log.error('peerId must be an instance of peer-id to store data')
@ -67,9 +69,10 @@ class KeyBook extends Book {
/** /**
* Get Public key of the given PeerId, if stored. * Get Public key of the given PeerId, if stored.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @return {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey} * @returns {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey}
*/ */
get (peerId) { get (peerId) {
if (!PeerId.isPeerId(peerId)) { if (!PeerId.isPeerId(peerId)) {

View File

@ -17,13 +17,14 @@ const {
/** /**
* The MetadataBook is responsible for keeping the known supported * The MetadataBook is responsible for keeping the known supported
* protocols of a peer. * protocols of a peer.
*
* @fires MetadataBook#change:metadata * @fires MetadataBook#change:metadata
*/ */
class MetadataBook extends Book { class MetadataBook extends Book {
/** /**
* @constructor * @class
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
constructor (peerStore) { constructor (peerStore) {
/** /**
* PeerStore Event emitter, used by the MetadataBook to emit: * PeerStore Event emitter, used by the MetadataBook to emit:
@ -37,6 +38,7 @@ class MetadataBook extends Book {
/** /**
* Map known peers to their known protocols. * Map known peers to their known protocols.
*
* @type {Map<string, Map<string, Uint8Array>>} * @type {Map<string, Map<string, Uint8Array>>}
*/ */
this.data = new Map() this.data = new Map()
@ -44,10 +46,11 @@ class MetadataBook extends Book {
/** /**
* Set metadata key and value of a provided peer. * Set metadata key and value of a provided peer.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {string} key metadata key * @param {string} key - metadata key
* @param {Uint8Array} value metadata value * @param {Uint8Array} value - metadata value
* @returns {ProtoBook} * @returns {ProtoBook}
*/ */
set (peerId, key, value) { set (peerId, key, value) {
@ -68,6 +71,7 @@ class MetadataBook extends Book {
/** /**
* Set data into the datastructure * Set data into the datastructure
*
* @override * @override
*/ */
_setValue (peerId, key, value, { emit = true } = {}) { _setValue (peerId, key, value, { emit = true } = {}) {
@ -89,6 +93,7 @@ class MetadataBook extends Book {
/** /**
* Get the known data of a provided peer. * Get the known data of a provided peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Map<string, Uint8Array>} * @returns {Map<string, Uint8Array>}
*/ */
@ -102,6 +107,7 @@ class MetadataBook extends Book {
/** /**
* Get specific metadata value, if it exists * Get specific metadata value, if it exists
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {string} key * @param {string} key
* @returns {Uint8Array} * @returns {Uint8Array}
@ -117,6 +123,7 @@ class MetadataBook extends Book {
/** /**
* Deletes the provided peer from the book. * Deletes the provided peer from the book.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {boolean} * @returns {boolean}
*/ */
@ -136,6 +143,7 @@ class MetadataBook extends Book {
/** /**
* Deletes the provided peer metadata key from the book. * Deletes the provided peer metadata key from the book.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {string} key * @param {string} key
* @returns {boolean} * @returns {boolean}

View File

@ -26,11 +26,11 @@ const Protocols = require('./pb/proto-book.proto')
*/ */
class PersistentPeerStore extends PeerStore { class PersistentPeerStore extends PeerStore {
/** /**
* @constructor * @class
* @param {Object} properties * @param {Object} properties
* @param {PeerId} properties.peerId * @param {PeerId} properties.peerId
* @param {Datastore} properties.datastore Datastore to persist data. * @param {Datastore} properties.datastore - Datastore to persist data.
* @param {number} [properties.threshold = 5] Number of dirty peers allowed before commit data. * @param {number} [properties.threshold = 5] - Number of dirty peers allowed before commit data.
*/ */
constructor ({ peerId, datastore, threshold = 5 }) { constructor ({ peerId, datastore, threshold = 5 }) {
super({ peerId }) super({ peerId })
@ -47,6 +47,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Peers metadata changed mapping peer identifers to metadata changed. * Peers metadata changed mapping peer identifers to metadata changed.
*
* @type {Map<string, Set<string>>} * @type {Map<string, Set<string>>}
*/ */
this._dirtyMetadata = new Map() this._dirtyMetadata = new Map()
@ -57,7 +58,8 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Start Persistent PeerStore. * Start Persistent PeerStore.
* @return {Promise<void>} *
* @returns {Promise<void>}
*/ */
async start () { async start () {
log('PeerStore is starting') log('PeerStore is starting')
@ -65,7 +67,7 @@ class PersistentPeerStore extends PeerStore {
// Handlers for dirty peers // Handlers for dirty peers
this.on('change:protocols', this._addDirtyPeer) this.on('change:protocols', this._addDirtyPeer)
this.on('change:multiaddrs', this._addDirtyPeer) this.on('change:multiaddrs', this._addDirtyPeer)
this.on('change:pubkey', this._addDirtyPeer) this.on('change:pubkey', this._addDirtyPeerKey)
this.on('change:metadata', this._addDirtyPeerMetadata) this.on('change:metadata', this._addDirtyPeerMetadata)
// Load data // Load data
@ -76,6 +78,11 @@ class PersistentPeerStore extends PeerStore {
log('PeerStore started') log('PeerStore started')
} }
/**
* Stop Persistent PeerStore.
*
* @returns {Promise<void>}
*/
async stop () { async stop () {
log('PeerStore is stopping') log('PeerStore is stopping')
this.removeAllListeners() this.removeAllListeners()
@ -85,6 +92,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add modified peer to the dirty set * Add modified peer to the dirty set
*
* @private * @private
* @param {Object} params * @param {Object} params
* @param {PeerId} params.peerId * @param {PeerId} params.peerId
@ -103,8 +111,35 @@ class PersistentPeerStore extends PeerStore {
} }
} }
/**
* Add modified peer key to the dirty set
*
* @private
* @param {Object} params
* @param {PeerId} params.peerId
*/
_addDirtyPeerKey ({ peerId }) {
// Not add if inline key available
if (peerId.hasInlinePublicKey()) {
return
}
const peerIdstr = peerId.toB58String()
log('add dirty peer key', peerIdstr)
this._dirtyPeers.add(peerIdstr)
if (this._dirtyPeers.size >= this.threshold) {
// Commit current data
this._commitData().catch(err => {
log.error('error committing data', err)
})
}
}
/** /**
* Add modified metadata peer to the set. * Add modified metadata peer to the set.
*
* @private * @private
* @param {Object} params * @param {Object} params
* @param {PeerId} params.peerId * @param {PeerId} params.peerId
@ -131,9 +166,9 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add all the peers current data to a datastore batch and commit it. * Add all the peers current data to a datastore batch and commit it.
*
* @private * @private
* @param {Array<string>} peers * @returns {Promise<void>}
* @return {Promise<void>}
*/ */
async _commitData () { async _commitData () {
const commitPeers = Array.from(this._dirtyPeers) const commitPeers = Array.from(this._dirtyPeers)
@ -155,7 +190,7 @@ class PersistentPeerStore extends PeerStore {
this._batchAddressBook(peerId, batch) this._batchAddressBook(peerId, batch)
// Key Book // Key Book
this._batchKeyBook(peerId, batch) !peerId.hasInlinePublicKey() && this._batchKeyBook(peerId, batch)
// Metadata Book // Metadata Book
this._batchMetadataBook(peerId, batch) this._batchMetadataBook(peerId, batch)
@ -170,6 +205,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add address book data of the peer to the batch. * Add address book data of the peer to the batch.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Object} batch * @param {Object} batch
@ -206,6 +242,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add Key book data of the peer to the batch. * Add Key book data of the peer to the batch.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Object} batch * @param {Object} batch
@ -231,6 +268,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add metadata book data of the peer to the batch. * Add metadata book data of the peer to the batch.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Object} batch * @param {Object} batch
@ -257,6 +295,7 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Add proto book data of the peer to the batch. * Add proto book data of the peer to the batch.
*
* @private * @private
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Object} batch * @param {Object} batch
@ -284,11 +323,12 @@ class PersistentPeerStore extends PeerStore {
/** /**
* Process datastore entry and add its data to the correct book. * Process datastore entry and add its data to the correct book.
*
* @private * @private
* @param {Object} params * @param {Object} params
* @param {Key} params.key datastore key * @param {Key} params.key - datastore key
* @param {Uint8Array} params.value datastore value stored * @param {Uint8Array} params.value - datastore value stored
* @return {Promise<void>} * @returns {Promise<void>}
*/ */
async _processDatastoreEntry ({ key, value }) { async _processDatastoreEntry ({ key, value }) {
try { try {

View File

@ -16,13 +16,14 @@ const {
/** /**
* The ProtoBook is responsible for keeping the known supported * The ProtoBook is responsible for keeping the known supported
* protocols of a peer. * protocols of a peer.
*
* @fires ProtoBook#change:protocols * @fires ProtoBook#change:protocols
*/ */
class ProtoBook extends Book { class ProtoBook extends Book {
/** /**
* @constructor * @class
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
constructor (peerStore) { constructor (peerStore) {
/** /**
* PeerStore Event emitter, used by the ProtoBook to emit: * PeerStore Event emitter, used by the ProtoBook to emit:
@ -37,6 +38,7 @@ class ProtoBook extends Book {
/** /**
* Map known peers to their known protocols. * Map known peers to their known protocols.
*
* @type {Map<string, Set<string>>} * @type {Map<string, Set<string>>}
*/ */
this.data = new Map() this.data = new Map()
@ -45,6 +47,7 @@ class ProtoBook extends Book {
/** /**
* Set known protocols of a provided peer. * Set known protocols of a provided peer.
* If the peer was not known before, it will be added. * If the peer was not known before, it will be added.
*
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<string>} protocols * @param {Array<string>} protocols
@ -83,6 +86,7 @@ class ProtoBook extends Book {
/** /**
* Adds known protocols of a provided peer. * Adds known protocols of a provided peer.
* If the peer was not known before, it will be added. * If the peer was not known before, it will be added.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<string>} protocols * @param {Array<string>} protocols
* @returns {ProtoBook} * @returns {ProtoBook}

View File

@ -14,9 +14,10 @@ const { PROTOCOL, PING_LENGTH } = require('./constants')
/** /**
* Ping a given peer and wait for its response, getting the operation latency. * Ping a given peer and wait for its response, getting the operation latency.
*
* @param {Libp2p} node * @param {Libp2p} node
* @param {PeerId|multiaddr} peer * @param {PeerId|multiaddr} peer
* @returns {Promise<Number>} * @returns {Promise<number>}
*/ */
async function ping (node, peer) { async function ping (node, peer) {
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer) log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
@ -44,6 +45,7 @@ async function ping (node, peer) {
/** /**
* Subscribe ping protocol handler. * Subscribe ping protocol handler.
*
* @param {Libp2p} node * @param {Libp2p} node
*/ */
function mount (node) { function mount (node) {
@ -52,6 +54,7 @@ function mount (node) {
/** /**
* Unsubscribe ping protocol handler. * Unsubscribe ping protocol handler.
*
* @param {Libp2p} node * @param {Libp2p} node
*/ */
function unmount (node) { function unmount (node) {

View File

@ -12,10 +12,10 @@ log.trace = debug('libp2p:pnet:trace')
log.error = debug('libp2p:pnet:err') log.error = debug('libp2p:pnet:err')
/** /**
* Creates a stream iterable to encrypt messages in a private network * Creates a stream iterable to encrypt messages in a private network
* *
* @param {Uint8Array} nonce The nonce to use in encryption * @param {Uint8Array} nonce - The nonce to use in encryption
* @param {Uint8Array} psk The private shared key to use in encryption * @param {Uint8Array} psk - The private shared key to use in encryption
* @returns {*} a through iterable * @returns {*} a through iterable
*/ */
module.exports.createBoxStream = (nonce, psk) => { module.exports.createBoxStream = (nonce, psk) => {
@ -28,10 +28,10 @@ module.exports.createBoxStream = (nonce, psk) => {
} }
/** /**
* Creates a stream iterable to decrypt messages in a private network * Creates a stream iterable to decrypt messages in a private network
* *
* @param {Uint8Array} nonce The nonce of the remote peer * @param {Uint8Array} nonce - The nonce of the remote peer
* @param {Uint8Array} psk The private shared key to use in decryption * @param {Uint8Array} psk - The private shared key to use in decryption
* @returns {*} a through iterable * @returns {*} a through iterable
*/ */
module.exports.createUnboxStream = (nonce, psk) => { module.exports.createUnboxStream = (nonce, psk) => {

View File

@ -25,8 +25,8 @@ log.error = debug('libp2p:pnet:err')
*/ */
class Protector { class Protector {
/** /**
* @param {Uint8Array} keyBuffer The private shared key buffer * @param {Uint8Array} keyBuffer - The private shared key buffer
* @constructor * @class
*/ */
constructor (keyBuffer) { constructor (keyBuffer) {
const decodedPSK = decodeV1PSK(keyBuffer) const decodedPSK = decodeV1PSK(keyBuffer)
@ -39,7 +39,7 @@ class Protector {
* between its two peers from the PSK the Protector instance was * between its two peers from the PSK the Protector instance was
* created with. * created with.
* *
* @param {Connection} connection The connection to protect * @param {Connection} connection - The connection to protect
* @returns {*} A protected duplex iterable * @returns {*} A protected duplex iterable
*/ */
async protect (connection) { async protect (connection) {

View File

@ -7,7 +7,8 @@ const uint8ArrayFromString = require('uint8arrays/from-string')
/** /**
* Generates a PSK that can be used in a libp2p-pnet private network * Generates a PSK that can be used in a libp2p-pnet private network
* @param {Uint8Array} bytes An object to write the psk into *
* @param {Uint8Array} bytes - An object to write the psk into
* @returns {void} * @returns {void}
*/ */
function generate (bytes) { function generate (bytes) {

View File

@ -5,6 +5,7 @@ module.exports = (PubsubRouter, libp2p, options) => {
class Pubsub extends PubsubRouter { class Pubsub extends PubsubRouter {
/** /**
* Subscribes to a given topic. * Subscribes to a given topic.
*
* @override * @override
* @param {string} topic * @param {string} topic
* @param {function(msg: InMessage)} [handler] * @param {function(msg: InMessage)} [handler]
@ -18,6 +19,7 @@ module.exports = (PubsubRouter, libp2p, options) => {
/** /**
* Unsubscribe from the given topic. * Unsubscribe from the given topic.
*
* @override * @override
* @param {string} topic * @param {string} topic
* @param {function(msg: InMessage)} [handler] * @param {function(msg: InMessage)} [handler]

View File

@ -20,12 +20,12 @@ const Protobuf = require('./envelope.proto')
*/ */
class Envelope { class Envelope {
/** /**
* @constructor * @class
* @param {object} params * @param {object} params
* @param {PeerId} params.peerId * @param {PeerId} params.peerId
* @param {Uint8Array} params.payloadType * @param {Uint8Array} params.payloadType
* @param {Uint8Array} params.payload marshaled record * @param {Uint8Array} params.payload - marshaled record
* @param {Uint8Array} params.signature signature of the domain string :: type hint :: payload. * @param {Uint8Array} params.signature - signature of the domain string :: type hint :: payload.
*/ */
constructor ({ peerId, payloadType, payload, signature }) { constructor ({ peerId, payloadType, payload, signature }) {
this.peerId = peerId this.peerId = peerId
@ -39,7 +39,8 @@ class Envelope {
/** /**
* Marshal the envelope content. * Marshal the envelope content.
* @return {Uint8Array} *
* @returns {Uint8Array}
*/ */
marshal () { marshal () {
if (this._marshal) { if (this._marshal) {
@ -60,8 +61,9 @@ class Envelope {
/** /**
* Verifies if the other Envelope is identical to this one. * Verifies if the other Envelope is identical to this one.
*
* @param {Envelope} other * @param {Envelope} other
* @return {boolean} * @returns {boolean}
*/ */
equals (other) { equals (other) {
return uint8arraysEquals(this.peerId.pubKey.bytes, other.peerId.pubKey.bytes) && return uint8arraysEquals(this.peerId.pubKey.bytes, other.peerId.pubKey.bytes) &&
@ -72,8 +74,9 @@ class Envelope {
/** /**
* Validate envelope data signature for the given domain. * Validate envelope data signature for the given domain.
*
* @param {string} domain * @param {string} domain
* @return {Promise<boolean>} * @returns {Promise<boolean>}
*/ */
validate (domain) { validate (domain) {
const signData = formatSignaturePayload(domain, this.payloadType, this.payload) const signData = formatSignaturePayload(domain, this.payloadType, this.payload)
@ -84,10 +87,11 @@ class Envelope {
/** /**
* Helper function that prepares a Uint8Array to sign or verify a signature. * Helper function that prepares a Uint8Array to sign or verify a signature.
*
* @param {string} domain * @param {string} domain
* @param {Uint8Array} payloadType * @param {Uint8Array} payloadType
* @param {Uint8Array} payload * @param {Uint8Array} payload
* @return {Uint8Array} * @returns {Uint8Array}
*/ */
const formatSignaturePayload = (domain, payloadType, payload) => { const formatSignaturePayload = (domain, payloadType, payload) => {
// When signing, a peer will prepare a Uint8Array by concatenating the following: // When signing, a peer will prepare a Uint8Array by concatenating the following:
@ -115,8 +119,9 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
/** /**
* Unmarshal a serialized Envelope protobuf message. * Unmarshal a serialized Envelope protobuf message.
*
* @param {Uint8Array} data * @param {Uint8Array} data
* @return {Promise<Envelope>} * @returns {Promise<Envelope>}
*/ */
Envelope.createFromProtobuf = async (data) => { Envelope.createFromProtobuf = async (data) => {
const envelopeData = Protobuf.decode(data) const envelopeData = Protobuf.decode(data)
@ -131,13 +136,14 @@ Envelope.createFromProtobuf = async (data) => {
} }
/** /**
* Seal marshals the given Record, places the marshaled bytes inside an Envelope * Seal marshals the given Record, places the marshaled bytes inside an Envelope
* and signs it with the given peerId's private key. * and signs it with the given peerId's private key.
* @async *
* @param {Record} record * @async
* @param {PeerId} peerId * @param {Record} record
* @return {Envelope} * @param {PeerId} peerId
*/ * @returns {Envelope}
*/
Envelope.seal = async (record, peerId) => { Envelope.seal = async (record, peerId) => {
const domain = record.domain const domain = record.domain
const payloadType = record.codec const payloadType = record.codec
@ -157,9 +163,10 @@ Envelope.seal = async (record, peerId) => {
/** /**
* Open and certify a given marshalled envelope. * Open and certify a given marshalled envelope.
* Data is unmarshalled and the signature validated for the given domain. * Data is unmarshalled and the signature validated for the given domain.
*
* @param {Uint8Array} data * @param {Uint8Array} data
* @param {string} domain * @param {string} domain
* @return {Envelope} * @returns {Envelope}
*/ */
Envelope.openAndCertify = async (data, domain) => { Envelope.openAndCertify = async (data, domain) => {
const envelope = await Envelope.createFromProtobuf(data) const envelope = await Envelope.createFromProtobuf(data)

View File

@ -17,11 +17,11 @@ const {
*/ */
class PeerRecord extends Record { class PeerRecord extends Record {
/** /**
* @constructor * @class
* @param {object} params * @param {object} params
* @param {PeerId} params.peerId * @param {PeerId} params.peerId
* @param {Array<multiaddr>} params.multiaddrs addresses of the associated peer. * @param {Array<multiaddr>} params.multiaddrs - addresses of the associated peer.
* @param {number} [params.seqNumber] monotonically-increasing sequence counter that's used to order PeerRecords in time. * @param {number} [params.seqNumber] - monotonically-increasing sequence counter that's used to order PeerRecords in time.
*/ */
constructor ({ peerId, multiaddrs = [], seqNumber = Date.now() }) { constructor ({ peerId, multiaddrs = [], seqNumber = Date.now() }) {
super(ENVELOPE_DOMAIN_PEER_RECORD, ENVELOPE_PAYLOAD_TYPE_PEER_RECORD) super(ENVELOPE_DOMAIN_PEER_RECORD, ENVELOPE_PAYLOAD_TYPE_PEER_RECORD)
@ -36,7 +36,8 @@ class PeerRecord extends Record {
/** /**
* Marshal a record to be used in an envelope. * Marshal a record to be used in an envelope.
* @return {Uint8Array} *
* @returns {Uint8Array}
*/ */
marshal () { marshal () {
if (this._marshal) { if (this._marshal) {
@ -56,8 +57,9 @@ class PeerRecord extends Record {
/** /**
* Returns true if `this` record equals the `other`. * Returns true if `this` record equals the `other`.
*
* @param {Record} other * @param {Record} other
* @return {boolean} * @returns {boolean}
*/ */
equals (other) { equals (other) {
// Validate PeerId // Validate PeerId
@ -81,8 +83,9 @@ class PeerRecord extends Record {
/** /**
* Unmarshal Peer Record Protobuf. * Unmarshal Peer Record Protobuf.
* @param {Uint8Array} buf marshaled peer record. *
* @return {PeerRecord} * @param {Uint8Array} buf - marshaled peer record.
* @returns {PeerRecord}
*/ */
PeerRecord.createFromProtobuf = (buf) => { PeerRecord.createFromProtobuf = (buf) => {
// Decode // Decode

View File

@ -18,7 +18,7 @@ class Registrar {
* @param {Object} props * @param {Object} props
* @param {PeerStore} props.peerStore * @param {PeerStore} props.peerStore
* @param {connectionManager} props.connectionManager * @param {connectionManager} props.connectionManager
* @constructor * @class
*/ */
constructor ({ peerStore, connectionManager }) { constructor ({ peerStore, connectionManager }) {
// Used on topology to listen for protocol changes // Used on topology to listen for protocol changes
@ -49,6 +49,7 @@ class Registrar {
/** /**
* Get a connection with a peer. * Get a connection with a peer.
*
* @param {PeerId} peerId * @param {PeerId} peerId
* @returns {Connection} * @returns {Connection}
*/ */
@ -58,8 +59,9 @@ class Registrar {
/** /**
* Register handlers for a set of multicodecs given * Register handlers for a set of multicodecs given
* @param {Topology} topology protocol topology *
* @return {string} registrar identifier * @param {Topology} topology - protocol topology
* @returns {string} registrar identifier
*/ */
register (topology) { register (topology) {
if (!Topology.isTopology(topology)) { if (!Topology.isTopology(topology)) {
@ -79,8 +81,9 @@ class Registrar {
/** /**
* Unregister topology. * Unregister topology.
* @param {string} id registrar identifier *
* @return {boolean} unregistered successfully * @param {string} id - registrar identifier
* @returns {boolean} unregistered successfully
*/ */
unregister (id) { unregister (id) {
return this.topologies.delete(id) return this.topologies.delete(id)
@ -88,6 +91,7 @@ class Registrar {
/** /**
* Remove a disconnected peer from the record * Remove a disconnected peer from the record
*
* @param {Connection} connection * @param {Connection} connection
* @param {Error} [error] * @param {Error} [error]
* @returns {void} * @returns {void}

View File

@ -9,26 +9,27 @@ log.error = debug('libp2p:transports:error')
class TransportManager { class TransportManager {
/** /**
* @constructor * @class
* @param {object} options * @param {object} options
* @param {Libp2p} options.libp2p The Libp2p instance. It will be passed to the transports. * @param {Libp2p} options.libp2p - The Libp2p instance. It will be passed to the transports.
* @param {Upgrader} options.upgrader The upgrader to provide to the transports * @param {Upgrader} options.upgrader - The upgrader to provide to the transports
* @param {boolean} [options.faultTolerance = FAULT_TOLERANCE.FATAL_ALL] Address listen error tolerance. * @param {boolean} [options.faultTolerance = FAULT_TOLERANCE.FATAL_ALL] - Address listen error tolerance.
*/ */
constructor ({ libp2p, upgrader, faultTolerance = FAULT_TOLERANCE.FATAL_ALL }) { constructor ({ libp2p, upgrader, faultTolerance = FAULT_TOLERANCE.FATAL_ALL }) {
this.libp2p = libp2p this.libp2p = libp2p
this.upgrader = upgrader this.upgrader = upgrader
this._transports = new Map() this._transports = new Map()
this._listeners = new Map() this._listeners = new Map()
this._listenerOptions = new Map()
this.faultTolerance = faultTolerance this.faultTolerance = faultTolerance
} }
/** /**
* Adds a `Transport` to the manager * Adds a `Transport` to the manager
* *
* @param {String} key * @param {string} key
* @param {Transport} Transport * @param {Transport} Transport
* @param {*} transportOptions Additional options to pass to the transport * @param {*} transportOptions - Additional options to pass to the transport
* @returns {void} * @returns {void}
*/ */
add (key, Transport, transportOptions = {}) { add (key, Transport, transportOptions = {}) {
@ -47,6 +48,7 @@ class TransportManager {
}) })
this._transports.set(key, transport) this._transports.set(key, transport)
this._listenerOptions.set(key, transportOptions.listenerOptions || {})
if (!this._listeners.has(key)) { if (!this._listeners.has(key)) {
this._listeners.set(key, []) this._listeners.set(key, [])
} }
@ -54,6 +56,7 @@ class TransportManager {
/** /**
* Stops all listeners * Stops all listeners
*
* @async * @async
*/ */
async close () { async close () {
@ -75,6 +78,7 @@ class TransportManager {
/** /**
* Dials the given Multiaddr over it's supported transport * Dials the given Multiaddr over it's supported transport
*
* @param {Multiaddr} ma * @param {Multiaddr} ma
* @param {*} options * @param {*} options
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
@ -95,6 +99,7 @@ class TransportManager {
/** /**
* Returns all Multiaddr's the listeners are using * Returns all Multiaddr's the listeners are using
*
* @returns {Multiaddr[]} * @returns {Multiaddr[]}
*/ */
getAddrs () { getAddrs () {
@ -109,6 +114,7 @@ class TransportManager {
/** /**
* Returns all the transports instances. * Returns all the transports instances.
*
* @returns {Iterator<Transport>} * @returns {Iterator<Transport>}
*/ */
getTransports () { getTransports () {
@ -117,6 +123,7 @@ class TransportManager {
/** /**
* Finds a transport that matches the given Multiaddr * Finds a transport that matches the given Multiaddr
*
* @param {Multiaddr} ma * @param {Multiaddr} ma
* @returns {Transport|null} * @returns {Transport|null}
*/ */
@ -130,6 +137,7 @@ class TransportManager {
/** /**
* Starts listeners for each listen Multiaddr. * Starts listeners for each listen Multiaddr.
*
* @async * @async
*/ */
async listen () { async listen () {
@ -148,7 +156,7 @@ class TransportManager {
// For each supported multiaddr, create a listener // For each supported multiaddr, create a listener
for (const addr of supportedAddrs) { for (const addr of supportedAddrs) {
log('creating listener for %s on %s', key, addr) log('creating listener for %s on %s', key, addr)
const listener = transport.createListener({}, this.onConnection) const listener = transport.createListener(this._listenerOptions.get(key), this.onConnection)
this._listeners.get(key).push(listener) this._listeners.get(key).push(listener)
// We need to attempt to listen on everything // We need to attempt to listen on everything
@ -206,6 +214,7 @@ class TransportManager {
/** /**
* Removes all transports from the manager. * Removes all transports from the manager.
* If any listeners are running, they will be closed. * If any listeners are running, they will be closed.
*
* @async * @async
*/ */
async removeAll () { async removeAll () {
@ -222,6 +231,7 @@ class TransportManager {
* Enum Transport Manager Fault Tolerance values. * Enum Transport Manager Fault Tolerance values.
* FATAL_ALL should be used for failing in any listen circumstance. * FATAL_ALL should be used for failing in any listen circumstance.
* NO_FATAL should be used for not failing when not listening. * NO_FATAL should be used for not failing when not listening.
*
* @readonly * @readonly
* @enum {number} * @enum {number}
*/ */

View File

@ -5,6 +5,7 @@ const log = debug('libp2p:upgrader')
log.error = debug('libp2p:upgrader:error') log.error = debug('libp2p:upgrader:error')
const Multistream = require('multistream-select') const Multistream = require('multistream-select')
const { Connection } = require('libp2p-interfaces/src/connection') const { Connection } = require('libp2p-interfaces/src/connection')
const ConnectionStatus = require('libp2p-interfaces/src/connection/status')
const PeerId = require('peer-id') const PeerId = require('peer-id')
const pipe = require('it-pipe') const pipe = require('it-pipe')
const errCode = require('err-code') const errCode = require('err-code')
@ -14,7 +15,7 @@ const { codes } = require('./errors')
/** /**
* @typedef MultiaddrConnection * @typedef MultiaddrConnection
* @property {function} sink * @property {Function} sink
* @property {AsyncIterator} source * @property {AsyncIterator} source
* @property {*} conn * @property {*} conn
* @property {Multiaddr} remoteAddr * @property {Multiaddr} remoteAddr
@ -34,7 +35,7 @@ class Upgrader {
* @param {Metrics} options.metrics * @param {Metrics} options.metrics
* @param {Map<string, Crypto>} options.cryptos * @param {Map<string, Crypto>} options.cryptos
* @param {Map<string, Muxer>} options.muxers * @param {Map<string, Muxer>} options.muxers
* @param {function(Connection)} options.onConnection Called when a connection is upgraded * @param {function(Connection)} options.onConnection - Called when a connection is upgraded
* @param {function(Connection)} options.onConnectionEnd * @param {function(Connection)} options.onConnectionEnd
*/ */
constructor ({ constructor ({
@ -57,6 +58,7 @@ class Upgrader {
/** /**
* Upgrades an inbound connection * Upgrades an inbound connection
*
* @async * @async
* @param {MultiaddrConnection} maConn * @param {MultiaddrConnection} maConn
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
@ -124,6 +126,7 @@ class Upgrader {
/** /**
* Upgrades an outbound connection * Upgrades an outbound connection
*
* @async * @async
* @param {MultiaddrConnection} maConn * @param {MultiaddrConnection} maConn
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
@ -198,14 +201,15 @@ class Upgrader {
/** /**
* A convenience method for generating a new `Connection` * A convenience method for generating a new `Connection`
*
* @private * @private
* @param {object} options * @param {object} options
* @param {string} cryptoProtocol The crypto protocol that was negotiated * @param {string} options.cryptoProtocol - The crypto protocol that was negotiated
* @param {string} direction One of ['inbound', 'outbound'] * @param {string} options.direction - One of ['inbound', 'outbound']
* @param {MultiaddrConnection} maConn The transport layer connection * @param {MultiaddrConnection} options.maConn - The transport layer connection
* @param {*} upgradedConn A duplex connection returned from multiplexer and/or crypto selection * @param {*} options.upgradedConn - A duplex connection returned from multiplexer and/or crypto selection
* @param {Muxer} Muxer The muxer to be used for muxing * @param {Muxer} options.Muxer - The muxer to be used for muxing
* @param {PeerId} remotePeer The peer the connection is with * @param {PeerId} options.remotePeer - The peer the connection is with
* @returns {Connection} * @returns {Connection}
*/ */
_createConnection ({ _createConnection ({
@ -265,8 +269,18 @@ class Upgrader {
maConn.timeline = new Proxy(_timeline, { maConn.timeline = new Proxy(_timeline, {
set: (...args) => { set: (...args) => {
if (connection && args[1] === 'close' && args[2] && !_timeline.close) { if (connection && args[1] === 'close' && args[2] && !_timeline.close) {
connection.stat.status = 'closed' // Wait for close to finish before notifying of the closure
this.onConnectionEnd(connection) (async () => {
try {
if (connection.stat.status === ConnectionStatus.OPEN) {
await connection.close()
}
} catch (err) {
log.error(err)
} finally {
this.onConnectionEnd(connection)
}
})()
} }
return Reflect.set(...args) return Reflect.set(...args)
@ -292,7 +306,13 @@ class Upgrader {
}, },
newStream: newStream || errConnectionNotMultiplexed, newStream: newStream || errConnectionNotMultiplexed,
getStreams: () => muxer ? muxer.streams : errConnectionNotMultiplexed, getStreams: () => muxer ? muxer.streams : errConnectionNotMultiplexed,
close: err => maConn.close(err) close: async (err) => {
await maConn.close(err)
// Ensure remaining streams are aborted
if (muxer) {
muxer.streams.map(stream => stream.abort(err))
}
}
}) })
this.onConnection(connection) this.onConnection(connection)
@ -302,9 +322,10 @@ class Upgrader {
/** /**
* Routes incoming streams to the correct handler * Routes incoming streams to the correct handler
*
* @private * @private
* @param {object} options * @param {object} options
* @param {Connection} options.connection The connection the stream belongs to * @param {Connection} options.connection - The connection the stream belongs to
* @param {Stream} options.stream * @param {Stream} options.stream
* @param {string} options.protocol * @param {string} options.protocol
*/ */
@ -315,9 +336,10 @@ class Upgrader {
/** /**
* Attempts to encrypt the incoming `connection` with the provided `cryptos`. * Attempts to encrypt the incoming `connection` with the provided `cryptos`.
*
* @private * @private
* @async * @async
* @param {PeerId} localPeer The initiators PeerId * @param {PeerId} localPeer - The initiators PeerId
* @param {*} connection * @param {*} connection
* @param {Map<string, Crypto>} cryptos * @param {Map<string, Crypto>} cryptos
* @returns {CryptoResult} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used * @returns {CryptoResult} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used
@ -344,9 +366,10 @@ class Upgrader {
/** /**
* Attempts to encrypt the given `connection` with the provided `cryptos`. * Attempts to encrypt the given `connection` with the provided `cryptos`.
* The first `Crypto` module to succeed will be used * The first `Crypto` module to succeed will be used
*
* @private * @private
* @async * @async
* @param {PeerId} localPeer The initiators PeerId * @param {PeerId} localPeer - The initiators PeerId
* @param {*} connection * @param {*} connection
* @param {PeerId} remotePeerId * @param {PeerId} remotePeerId
* @param {Map<string, Crypto>} cryptos * @param {Map<string, Crypto>} cryptos
@ -374,10 +397,11 @@ class Upgrader {
/** /**
* Selects one of the given muxers via multistream-select. That * Selects one of the given muxers via multistream-select. That
* muxer will be used for all future streams on the connection. * muxer will be used for all future streams on the connection.
*
* @private * @private
* @async * @async
* @param {*} connection A basic duplex connection to multiplex * @param {*} connection - A basic duplex connection to multiplex
* @param {Map<string, Muxer>} muxers The muxers to attempt multiplexing with * @param {Map<string, Muxer>} muxers - The muxers to attempt multiplexing with
* @returns {*} A muxed connection * @returns {*} A muxed connection
*/ */
async _multiplexOutbound (connection, muxers) { async _multiplexOutbound (connection, muxers) {
@ -397,10 +421,11 @@ class Upgrader {
/** /**
* Registers support for one of the given muxers via multistream-select. The * Registers support for one of the given muxers via multistream-select. The
* selected muxer will be used for all future streams on the connection. * selected muxer will be used for all future streams on the connection.
*
* @private * @private
* @async * @async
* @param {*} connection A basic duplex connection to multiplex * @param {*} connection - A basic duplex connection to multiplex
* @param {Map<string, Muxer>} muxers The muxers to attempt multiplexing with * @param {Map<string, Muxer>} muxers - The muxers to attempt multiplexing with
* @returns {*} A muxed connection * @returns {*} A muxed connection
*/ */
async _multiplexInbound (connection, muxers) { async _multiplexInbound (connection, muxers) {

View File

@ -18,10 +18,16 @@ const listenMultiaddr = '/ip4/127.0.0.1/tcp/15002/ws'
describe('Connection Manager', () => { describe('Connection Manager', () => {
let libp2p let libp2p
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
beforeEach(async () => { beforeEach(async () => {
[libp2p] = await peerUtils.createPeer({ [libp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[0],
addresses: { addresses: {
listen: [listenMultiaddr] listen: [listenMultiaddr]
}, },
@ -33,12 +39,10 @@ describe('Connection Manager', () => {
afterEach(() => libp2p.stop()) afterEach(() => libp2p.stop())
it('should filter connections on disconnect, removing the closed one', async () => { it('should filter connections on disconnect, removing the closed one', async () => {
const [localPeer, remotePeer] = await peerUtils.createPeerId({ number: 2 }) const conn1 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn2 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn1 = await mockConnection({ localPeer, remotePeer }) const id = peerIds[1].toB58String()
const conn2 = await mockConnection({ localPeer, remotePeer })
const id = remotePeer.toB58String()
// Add connection to the connectionManager // Add connection to the connectionManager
libp2p.connectionManager.onConnect(conn1) libp2p.connectionManager.onConnect(conn1)
@ -57,6 +61,7 @@ describe('Connection Manager', () => {
it('should add connection on dial and remove on node stop', async () => { it('should add connection on dial and remove on node stop', async () => {
const [remoteLibp2p] = await peerUtils.createPeer({ const [remoteLibp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[1],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws'] listen: ['/ip4/127.0.0.1/tcp/15003/ws']
}, },
@ -89,9 +94,16 @@ describe('Connection Manager', () => {
}) })
describe('libp2p.connections', () => { describe('libp2p.connections', () => {
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
it('libp2p.connections gets the connectionManager conns', async () => { it('libp2p.connections gets the connectionManager conns', async () => {
const [libp2p] = await peerUtils.createPeer({ const [libp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[0],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws'] listen: ['/ip4/127.0.0.1/tcp/15003/ws']
}, },
@ -100,6 +112,7 @@ describe('libp2p.connections', () => {
}) })
const [remoteLibp2p] = await peerUtils.createPeer({ const [remoteLibp2p] = await peerUtils.createPeer({
config: { config: {
peerId: peerIds[1],
addresses: { addresses: {
listen: ['/ip4/127.0.0.1/tcp/15004/ws'] listen: ['/ip4/127.0.0.1/tcp/15004/ws']
}, },

View File

@ -12,6 +12,7 @@ const pDefer = require('p-defer')
const mergeOptions = require('merge-options') const mergeOptions = require('merge-options')
const CID = require('cids') const CID = require('cids')
const ipfsHttpClient = require('ipfs-http-client')
const DelegatedContentRouter = require('libp2p-delegated-content-routing') const DelegatedContentRouter = require('libp2p-delegated-content-routing')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
@ -99,11 +100,11 @@ describe('content-routing', () => {
beforeEach(async () => { beforeEach(async () => {
const [peerId] = await peerUtils.createPeerId({ fixture: true }) const [peerId] = await peerUtils.createPeerId({ fixture: true })
delegate = new DelegatedContentRouter(peerId, { delegate = new DelegatedContentRouter(peerId, ipfsHttpClient({
host: '0.0.0.0', host: '0.0.0.0',
protocol: 'http', protocol: 'http',
port: 60197 port: 60197
}, [ }), [
multiaddr('/ip4/0.0.0.0/tcp/60197') multiaddr('/ip4/0.0.0.0/tcp/60197')
]) ])
@ -230,11 +231,11 @@ describe('content-routing', () => {
beforeEach(async () => { beforeEach(async () => {
const [peerId] = await peerUtils.createPeerId({ fixture: true }) const [peerId] = await peerUtils.createPeerId({ fixture: true })
delegate = new DelegatedContentRouter(peerId, { delegate = new DelegatedContentRouter(peerId, ipfsHttpClient({
host: '0.0.0.0', host: '0.0.0.0',
protocol: 'http', protocol: 'http',
port: 60197 port: 60197
}, [ }), [
multiaddr('/ip4/0.0.0.0/tcp/60197') multiaddr('/ip4/0.0.0.0/tcp/60197')
]) ])

View File

@ -11,7 +11,9 @@ const PeerId = require('peer-id')
const delay = require('delay') const delay = require('delay')
const pDefer = require('p-defer') const pDefer = require('p-defer')
const pSettle = require('p-settle') const pSettle = require('p-settle')
const pWaitFor = require('p-wait-for')
const pipe = require('it-pipe') const pipe = require('it-pipe')
const pushable = require('it-pushable')
const AggregateError = require('aggregate-error') const AggregateError = require('aggregate-error')
const { Connection } = require('libp2p-interfaces/src/connection') const { Connection } = require('libp2p-interfaces/src/connection')
const { AbortError } = require('libp2p-interfaces/src/transport/errors') const { AbortError } = require('libp2p-interfaces/src/transport/errors')
@ -156,9 +158,9 @@ describe('Dialing (direct, TCP)', () => {
it('should dial to the max concurrency', async () => { it('should dial to the max concurrency', async () => {
const addrs = [ const addrs = [
'/ip4/0.0.0.0/tcp/8000', multiaddr('/ip4/0.0.0.0/tcp/8000'),
'/ip4/0.0.0.0/tcp/8001', multiaddr('/ip4/0.0.0.0/tcp/8001'),
'/ip4/0.0.0.0/tcp/8002' multiaddr('/ip4/0.0.0.0/tcp/8002')
] ]
const dialer = new Dialer({ const dialer = new Dialer({
transportManager: localTM, transportManager: localTM,
@ -299,6 +301,50 @@ describe('Dialing (direct, TCP)', () => {
expect(libp2p.dialer.connectToPeer.callCount).to.equal(1) expect(libp2p.dialer.connectToPeer.callCount).to.equal(1)
}) })
it('should close all streams when the connection closes', async () => {
libp2p = new Libp2p({
peerId,
modules: {
transport: [Transport],
streamMuxer: [Muxer],
connEncryption: [Crypto]
}
})
// register some stream handlers to simulate several protocols
libp2p.handle('/stream-count/1', ({ stream }) => pipe(stream, stream))
libp2p.handle('/stream-count/2', ({ stream }) => pipe(stream, stream))
remoteLibp2p.handle('/stream-count/3', ({ stream }) => pipe(stream, stream))
remoteLibp2p.handle('/stream-count/4', ({ stream }) => pipe(stream, stream))
libp2p.peerStore.addressBook.set(remotePeerId, remoteLibp2p.multiaddrs)
const connection = await libp2p.dial(remotePeerId)
// Create local to remote streams
const { stream } = await connection.newStream('/echo/1.0.0')
await connection.newStream('/stream-count/3')
await libp2p.dialProtocol(remoteLibp2p.peerId, '/stream-count/4')
// Partially write to the echo stream
const source = pushable()
stream.sink(source)
source.push('hello')
// Create remote to local streams
await remoteLibp2p.dialProtocol(libp2p.peerId, '/stream-count/1')
await remoteLibp2p.dialProtocol(libp2p.peerId, '/stream-count/2')
// Verify stream count
const remoteConn = remoteLibp2p.connectionManager.get(libp2p.peerId)
expect(connection.streams).to.have.length(5)
expect(remoteConn.streams).to.have.length(5)
// Close the connection and verify all streams have been closed
await connection.close()
await pWaitFor(() => connection.streams.length === 0)
await pWaitFor(() => remoteConn.streams.length === 0)
})
it('should be able to use hangup to close connections', async () => { it('should be able to use hangup to close connections', async () => {
libp2p = new Libp2p({ libp2p = new Libp2p({
peerId, peerId,

View File

@ -263,7 +263,6 @@ describe('Dialing (direct, WebSockets)', () => {
describe('libp2p.dialer', () => { describe('libp2p.dialer', () => {
let libp2p let libp2p
let remoteLibp2p
afterEach(async () => { afterEach(async () => {
sinon.restore() sinon.restore()
@ -271,10 +270,6 @@ describe('Dialing (direct, WebSockets)', () => {
libp2p = null libp2p = null
}) })
after(async () => {
remoteLibp2p && await remoteLibp2p.stop()
})
it('should create a dialer', () => { it('should create a dialer', () => {
libp2p = new Libp2p({ libp2p = new Libp2p({
peerId, peerId,
@ -414,5 +409,20 @@ describe('Dialing (direct, WebSockets)', () => {
expect(libp2p.dialer.destroy).to.have.property('callCount', 1) expect(libp2p.dialer.destroy).to.have.property('callCount', 1)
}) })
it('should fail to dial self', async () => {
libp2p = new Libp2p({
peerId,
modules: {
transport: [Transport],
streamMuxer: [Muxer],
connEncryption: [Crypto]
}
})
await expect(libp2p.dial(peerId))
.to.eventually.be.rejected()
.and.to.have.property('code', ErrorCodes.ERR_DIALED_SELF)
})
}) })
}) })

View File

@ -0,0 +1,176 @@
'use strict'
/* eslint-env mocha */
const { expect } = require('aegir/utils/chai')
const sinon = require('sinon')
const multiaddr = require('multiaddr')
const { Resolver } = require('multiaddr/src/resolvers/dns')
const { codes: ErrorCodes } = require('../../src/errors')
const peerUtils = require('../utils/creators/peer')
const baseOptions = require('../utils/base-options.browser')
const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
const relayAddr = MULTIADDRS_WEBSOCKETS[0]
const getDnsaddrStub = (peerId) => [
[`dnsaddr=/dnsaddr/ams-1.bootstrap.libp2p.io/p2p/${peerId}`],
[`dnsaddr=/dnsaddr/ams-2.bootstrap.libp2p.io/p2p/${peerId}`],
[`dnsaddr=/dnsaddr/lon-1.bootstrap.libp2p.io/p2p/${peerId}`],
[`dnsaddr=/dnsaddr/nrt-1.bootstrap.libp2p.io/p2p/${peerId}`],
[`dnsaddr=/dnsaddr/nyc-1.bootstrap.libp2p.io/p2p/${peerId}`],
[`dnsaddr=/dnsaddr/sfo-2.bootstrap.libp2p.io/p2p/${peerId}`]
]
const relayedAddr = (peerId) => `${relayAddr}/p2p-circuit/p2p/${peerId}`
const getDnsRelayedAddrStub = (peerId) => [
[`dnsaddr=${relayedAddr(peerId)}`]
]
describe('Dialing (resolvable addresses)', () => {
let libp2p, remoteLibp2p
beforeEach(async () => {
[libp2p, remoteLibp2p] = await peerUtils.createPeer({
number: 2,
config: {
modules: baseOptions.modules,
addresses: {
listen: [multiaddr(`${relayAddr}/p2p-circuit`)]
},
config: {
peerDiscovery: {
autoDial: false
}
}
},
started: true,
populateAddressBooks: false
})
})
afterEach(async () => {
sinon.restore()
await Promise.all([libp2p, remoteLibp2p].map(n => n.stop()))
})
it('resolves dnsaddr to ws local address', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
sinon.spy(transport, 'dial')
// Resolver stub
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
stub.onCall(0).returns(Promise.resolve(getDnsRelayedAddrStub(remoteId)))
// Dial with address resolve
const connection = await libp2p.dial(dialAddr)
expect(connection).to.exist()
expect(connection.remoteAddr.equals(relayedAddrFetched))
const dialArgs = transport.dial.firstCall.args
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
})
it('resolves a dnsaddr recursively', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
sinon.spy(transport, 'dial')
// Resolver stub
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
let firstCall = false
stub.callsFake(() => {
if (!firstCall) {
firstCall = true
// Return an array of dnsaddr
return Promise.resolve(getDnsaddrStub(remoteId))
}
return Promise.resolve(getDnsRelayedAddrStub(remoteId))
})
// Dial with address resolve
const connection = await libp2p.dial(dialAddr)
expect(connection).to.exist()
expect(connection.remoteAddr.equals(relayedAddrFetched))
const dialArgs = transport.dial.firstCall.args
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
})
// TODO: Temporary solution does not resolve dns4/dns6
// Resolver just returns the received multiaddrs
it('stops recursive resolve if finds dns4/dns6 and dials it', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
// Stub resolver
const dnsMa = multiaddr(`/dns4/ams-1.remote.libp2p.io/tcp/443/wss/p2p/${remoteId}`)
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')
stubResolve.returns(Promise.resolve([
[`dnsaddr=${dnsMa}`]
]))
// Stub transport
const transport = libp2p.transportManager._transports.get('WebSockets')
const stubTransport = sinon.stub(transport, 'dial')
stubTransport.callsFake((multiaddr) => {
expect(multiaddr.equals(dnsMa)).to.eql(true)
})
await libp2p.dial(dialAddr)
})
it('resolves a dnsaddr recursively not failing if one address fails to resolve', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
sinon.spy(transport, 'dial')
// Resolver stub
const stub = sinon.stub(Resolver.prototype, 'resolveTxt')
stub.onCall(0).callsFake(() => Promise.resolve(getDnsaddrStub(remoteId)))
stub.onCall(1).callsFake(() => Promise.reject(new Error()))
stub.callsFake(() => Promise.resolve(getDnsRelayedAddrStub(remoteId)))
// Dial with address resolve
const connection = await libp2p.dial(dialAddr)
expect(connection).to.exist()
expect(connection.remoteAddr.equals(relayedAddrFetched))
const dialArgs = transport.dial.firstCall.args
expect(dialArgs[0].equals(relayedAddrFetched)).to.eql(true)
})
it('fails to dial if resolve fails and there are no addresses to dial', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
// Stub resolver
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')
stubResolve.returns(Promise.reject(new Error()))
// Stub transport
const transport = libp2p.transportManager._transports.get('WebSockets')
const spy = sinon.spy(transport, 'dial')
await expect(libp2p.dial(dialAddr))
.to.eventually.be.rejectedWith(Error)
.and.to.have.nested.property('.code', ErrorCodes.ERR_NO_VALID_ADDRESSES)
expect(spy.callCount).to.eql(0)
})
})

View File

@ -3,5 +3,5 @@
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
module.exports.MULTIADDRS_WEBSOCKETS = [ module.exports.MULTIADDRS_WEBSOCKETS = [
multiaddr('/ip4/127.0.0.1/tcp/15001/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN') multiaddr('/ip4/127.0.0.1/tcp/15001/ws/p2p/12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5')
] ]

View File

@ -1,27 +1,27 @@
'use strict' 'use strict'
module.exports = [{ module.exports = [{
id: 'QmNMMAqSxPetRS1cVMmutW5BCN1qQQyEr4u98kUvZjcfEw', id: '12D3KooWNvSZnPi3RrhrTwEY4LuuBeB6K6facKUCJcyWG1aoDd2p',
privKey: 'CAASpQkwggShAgEAAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAECggEAB2H2uPRoRCAKU+T3gO4QeoiJaYKNjIO7UCplE0aMEeHDnEjAKC1HQ1G0DRdzZ8sb0fxuIGlNpFMZv5iZ2ZFg2zFfV//DaAwTek9tIOpQOAYHUtgHxkj5FIlg2BjlflGb+ZY3J2XsVB+2HNHkUEXOeKn2wpTxcoJE07NmywkO8Zfr1OL5oPxOPlRN1gI4ffYH2LbfaQVtRhwONR2+fs5ISfubk5iKso6BX4moMYkxubYwZbpucvKKi/rIjUA3SK86wdCUnno1KbDfdXSgCiUlvxt/IbRFXFURQoTV6BOi3sP5crBLw8OiVubMr9/8WE6KzJ0R7hPd5+eeWvYiYnWj4QKBgQD6jRlAFo/MgPO5NZ/HRAk6LUG+fdEWexA+GGV7CwJI61W/Dpbn9ZswPDhRJKo3rquyDFVZPdd7+RlXYg1wpmp1k54z++L1srsgj72vlg4I8wkZ4YLBg0+zVgHlQ0kxnp16DvQdOgiRFvMUUMEgetsoIx1CQWTd67hTExGsW+WAZQKBgQDT/WaHWvwyq9oaZ8G7F/tfeuXvNTk3HIJdfbWGgRXB7lJ7Gf6FsX4x7PeERfL5a67JLV6JdiLLVuYC2CBhipqLqC2DB962aKMvxobQpSljBBZvZyqP1IGPoKskrSo+2mqpYkeCLbDMuJ1nujgMP7gqVjabs2zj6ACKmmpYH/oNowJ/T0ZVtvFsjkg+1VsiMupUARRQuPUWMwa9HOibM1NIZcoQV2NGXB5Z++kR6JqxQO0DZlKArrviclderUdY+UuuY4VRiSEprpPeoW7ZlbTku/Ap8QZpWNEzZorQDro7bnfBW91fX9/81ets/gCPGrfEn+58U3pdb9oleCOQc/ifpQKBgBTYGbi9bYbd9vgZs6bd2M2um+VFanbMytS+g5bSIn2LHXkVOT2UEkB+eGf9KML1n54QY/dIMmukA8HL1oNAyalpw+/aWj+9Ui5kauUhGEywHjSeBEVYM9UXizxz+m9rsoktLLLUI0o97NxCJzitG0Kub3gn0FEogsUeIc7AdinZAoGBANnM1vcteSQDs7x94TDEnvvqwSkA2UWyLidD2jXgE0PG4V6tTkK//QPBmC9eq6TIqXkzYlsErSw4XeKO91knFofmdBzzVh/ddgx/NufJV4tXF+a2iTpqYBUJiz9wpIKgf43/Ob+P1EA99GAhSdxz1ess9O2aTqf3ANzn6v6g62Pv', privKey: 'CAESYHyCgD+3HtEHm6kzPO6fuwP+BAr/PxfJKlvAOWhc/IqAwrZjCNn0jz93sSl81cP6R6x/g+iVYmR5Wxmn4ZtzJFnCtmMI2fSPP3exKXzVw/pHrH+D6JViZHlbGafhm3MkWQ==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAE=' pubKey: 'CAESIMK2YwjZ9I8/d7EpfNXD+kesf4PolWJkeVsZp+GbcyRZ'
}, { }, {
id: 'QmW8rAgaaA6sRydK1k6vonShQME47aDxaFidbtMevWs73t', id: '12D3KooWLV3w42LqUb9MWE7oTzG7vwaFjPw9GvDqmsuDif5chTn9',
privKey: 'CAASpwkwggSjAgEAAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAECggEAHq2f8MqpYjLiAFZKl9IUs3uFZkEiZsgx9BmbMAb91Aec+WWJG4OLHrNVTG1KWp+IcaQablEa9bBvoToQnS7y5OpOon1d066egg7Ymfmv24NEMM5KRpktCNcOSA0CySpPIB6yrg6EiUr3ixiaFUGABKkxmwgVz/Q15IqM0ZMmCUsC174PMAz1COFZxD0ZX0zgHblOJQW3dc0X3XSzhht8vU02SMoVObQHQfeXEHv3K/RiVj/Ax0bTc5JVkT8dm8xksTtsFCNOzRBqFS6MYqX6U/u0Onz3Jm5Jt7fLWb5n97gZR4SleyGrqxYNb46d9X7mP0ie7E6bzFW0DsWBIeAqVQKBgQDW0We2L1n44yOvJaMs3evpj0nps13jWidt2I3RlZXjWzWHiYQfvhWUWqps/xZBnAYgnN/38xbKzHZeRNhrqOo+VB0WK1IYl0lZVE4l6TNKCsLsUfQzsb1pePkd1eRZA+TSqsi+I/IOQlQU7HA0bMrah/5FYyUBP0jYvCOvYTlZuwKBgQCvkcVRydVlzjUgv7lY5lYvT8IHV5iYO4Qkk2q6Wjv9VUKAJZauurMdiy05PboWfs5kbETdwFybXMBcknIvZO4ihxmwL8mcoNwDVZHI4bXapIKMTCyHgUKvJ9SeTcKGC7ZuQJ8mslRmYox/HloTOXEJgQgPRxXcwa3amzvdZI+6LwKBgQCLsnQqgxKUi0m6bdR2qf7vzTH4258z6X34rjpT0F5AEyF1edVFOz0XU/q+lQhpNEi7zqjLuvbYfSyA026WXKuwSsz7jMJ/oWqev/duKgAjp2npesY/E9gkjfobD+zGgoS9BzkyhXe1FCdP0A6L2S/1+zg88WOwMvJxl6/xLl24XwKBgCm60xSajX8yIQyUpWBM9yUtpueJ2Xotgz4ST+bVNbcEAddll8gWFiaqgug9FLLuFu5lkYTHiPtgc1RNdphvO+62/9MRuLDixwh/2TPO+iNqwKDKJjda8Nei9vVddCPaOtU/xNQ0xLzFJbG9LBmvqH9izOCcu8SJwGHaTcNUeJj/AoGADCJ26cY30c13F/8awAAmFYpZWCuTP5ppTsRmjd63ixlrqgkeLGpJ7kYb5fXkcTycRGYgP0e1kssBGcmE7DuG955fx3ZJESX3GQZ+XfMHvYGONwF1EiK1f0p6+GReC2VlQ7PIkoD9o0hojM6SnWvv9EXNjCPALEbfPFFvcniKVsE=', privKey: 'CAESYI44p8HiCHtCBhuUcetU9XdIEtWvon15a5ZLsfyssSj9nn3mt4oZI0t6wXTHOvIA0GSFWrYkdKp1338oFIambdKefea3ihkjS3rBdMc68gDQZIVatiR0qnXffygUhqZt0g==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAE=' pubKey: 'CAESIJ595reKGSNLesF0xzryANBkhVq2JHSqdd9/KBSGpm3S'
}, { }, {
id: 'QmZqCdSzgpsmB3Qweb9s4fojAoqELWzqku21UVrqtVSKi4', id: '12D3KooWDRHe5x3tEQfZi4yirsdhA3zgqhE8awxAjET7zVF23JHB',
privKey: 'CAASpgkwggSiAgEAAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAECggEAQ1N0qHoxl5pmvqv8iaFlqLSUmx5y6GbI6CGJMQpvV9kQQU68yjItr3VuIXx8d/CBZyEMAK4oko7OeOyMcr3MLKLy3gyQWnXgsopDjhZ/8fH8uwps8g2+IZuFJrO+6LaxEPGvFu06fOiphPUVfn40R2KN/iBjGeox+AaXijmCqaV2vEdNJJPpMfz6VKZBDLTrbiqvo/3GN1U99PUqfPWpOWR29oAhh/Au6blSqvqTUPXB2+D/X6e1JXv31mxMPK68atDHSUjZWKB9lE4FMK1bkSKJRbyXmNIlbZ9V8X4/0r8/6T7JnW7ZT8ugRkquohmwgG7KkDXB1YsOCKXYUqzVYQKBgQDtnopFXWYl7XUyePJ/2MA5i7eoko9jmF44L31irqmHc5unNf6JlNBjlxTNx3WyfzhUzrn3c18psnGkqtow0tkBj5hmqn8/WaPbc5UA/5R1FNaNf8W5khn7MDm6KtYRPjN9djqTDiVHyC6ljONYd+5S+MqyKVWZ3t/xvG60sw85qwKBgQCpmpDtL+2JBwkfeUr3LyDcQxvbfzcv8lXj2otopWxWiLiZF1HzcqgAa2CIwu9kCGEt9Zr+9E4uINbe1To0b01/FhvR6xKO/ukceGA/mBB3vsKDcRmvpBUp+3SmnhY0nOk+ArQl4DhJ34k8pDM3EDPrixPf8SfVdU/8IM32lsdHhQKBgHLgpvCKCwxjFLnmBzcPzz8C8TOqR3BbBZIcQ34l+wflOGdKj1hsfaLoM8KYn6pAHzfBCd88A9Hg11hI0VuxVACRL5jS7NnvuGwsIOluppNEE8Ys86aXn7/0vLPoab3EWJhbRE48FIHzobmft3nZ4XpzlWs02JGfUp1IAC2UM9QpAoGAeWy3pZhSr2/iEC5+hUmwdQF2yEbj8+fDpkWo2VrVnX506uXPPkQwE1zM2Bz31t5I9OaJ+U5fSpcoPpDaAwBMs1fYwwlRWB8YNdHY1q6/23svN3uZsC4BGPV2JnO34iMUudilsRg+NGVdk5TbNejbwx7nM8Urh59djFzQGGMKeSECgYA0QMCARPpdMY50Mf2xQaCP7HfMJhESSPaBq9V3xY6ToEOEnXgAR5pNjnU85wnspHp+82r5XrKfEQlFxGpj2YA4DRRmn239sjDa29qP42UNAFg1+C3OvXTht1d5oOabaGhU0udwKmkEKUbb0bG5xPQJ5qeSJ5T1gLzLk3SIP0GlSw==', privKey: 'CAESYP+GrxgDqKnx79W5l4sgpCEYvNF9bBlCSVu3McENPluhNYVEwxo5KboVuOPnYO6ZOeeTmglqc2vcN8pldRF8lq41hUTDGjkpuhW44+dg7pk555OaCWpza9w3ymV1EXyWrg==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAE=' pubKey: 'CAESIDWFRMMaOSm6Fbjj52DumTnnk5oJanNr3DfKZXURfJau'
}, { }, {
id: 'QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA', id: '12D3KooWQJMnsoT7js35ZgkboxzUjXpVhfvG8cMqZnBJTP4XPuhU',
privKey: 'CAASpwkwggSjAgEAAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAECggEAS64HK8JZfE09eYGJNWPe8ECmD1C7quw21BpwVe+GVPSTizvQHswPohbKDMNj0srXDMPxCnNw1OgqcaOwyjsGuZaOoXoTroTM8nOHRIX27+PUqzaStS6aCG2IsiCozKUHjGTuupftS7XRaF4eIsUtWtFcQ1ytZ9pJYHypRQTi5NMSrTze5ThjnWxtHilK7gnBXik+aR0mYEVfSn13czQEC4rMOs+b9RAc/iibDNoLopfIdvmCCvfxzmySnR7Cu1iSUAONkir7PB+2Mt/qRFCH6P+jMamtCgQ8AmifXgVmDUlun+4MnKg3KrPd6ZjOEKhVe9mCHtGozk65RDREShfDdQKBgQDi+x2MuRa9peEMOHnOyXTS+v+MFcfmG0InsO08rFNBKZChLB+c9UHBdIvexpfBHigSyERfuDye4z6lxi8ZnierWMYJP30nxmrnxwTGTk1MQquhfs1A0kpmDnPsjlOS/drEIEIssNx2WbfJ7YtMxLWBtp+BJzGpQmr0LKC+NHRSrwKBgQCXiy2kJESIUkIs2ihV55hhT6/bZo1B1O5DPA2nkjOBXqXF6fvijzMDX82JjLd07lQZlI0n1Q/Hw0p4iYi9YVd2bLkLXF5UIb2qOeHj76enVFOrPHUSkC9Y2g/0Xs+60Ths2xRd8RrrfQU3kl5iVpBywkCIrb2M5+wRnNTk1W3TtwKBgQCvplyrteAfSurpJhs9JzE8w/hWU9SqAZYkWQp91W1oE95Um2yrbjBAoQxMjaqKS+f/APPIjy56Vqj4aHGyhW11b/Fw3qzfxvCcBKtxOs8eoMlo5FO6QgJJEA4tlcafDcvp0nzjUMqK28safLU7503+33B35fjMXxWdd5u9FaKfCQKBgC4W6j6tuRosymuRvgrCcRnHfpify/5loEFallyMnpWOD6Tt0OnK25z/GifnYDRz96gAAh5HMpFy18dpLOlMHamqz2yhHx8/U8vd5tHIJZlCkF/X91M5/uxrBccwvsT2tM6Got8fYSyVzWxlW8dUxIHiinYHQUsFjkqdBDLEpq5pAoGASoTw5RBEWFM0GuAZdXsyNyxU+4S+grkTS7WdW/Ymkukh+bJZbnvF9a6MkSehqXnknthmufonds2AFNS//63gixENsoOhzT5+2cdfc6tJECvJ9xXVXkf85AoQ6T/RrXF0W4m9yQyCngNJUrKUOIH3oDIfdZITlYzOC3u1ojj7VuQ=', privKey: 'CAESYL1Fwm/+layh15V1ITWkK9tEQLuGeJFi16VkNDUU+GFs1y90DFs9vlkRziuJFZ/QtEIlYZWjFTsNRJxFA/etwCvXL3QMWz2+WRHOK4kVn9C0QiVhlaMVOw1EnEUD963AKw==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAE=' pubKey: 'CAESINcvdAxbPb5ZEc4riRWf0LRCJWGVoxU7DUScRQP3rcAr'
}, { }, {
id: 'QmScLDqRg7H6ipCYxm9fVk152UWavQFKscTdoT4YNHxgqp', id: '12D3KooWFYyvJysHGbbYiruVY8bgjKn7sYN9axgbnMxrWVkGXABF',
privKey: 'CAASpwkwggSjAgEAAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAECggEAdmt1dyswR2p4tdIeNpY7Pnj9JNIhTNDPznefI0dArCdBvBMhkVaYk6MoNIxcj6l7YOrDroAF8sXr0TZimMY6B/pERKCt/z1hPWTxRQBBAvnHhwvwRPq2jK6BfhAZoyM8IoBNKowP9mum5QUNdGV4Al8s73KyFX0IsCfgZSvNpRdlt+DzPh+hu/CyoZaMpRchJc1UmK8Fyk3KfO+m0DZNfHP5P08lXNfM6MZLgTJVVgERHyG+vBOzTd2RElMe19nVCzHwb3dPPRZSQ7Fnz3rA+GeLqsM2Zi4HNhfbD1OcD9C4wDj5tYL6hWTkdz4IlfVcjCeUHxgIOhdDV2K+OwbuAQKBgQD0FjUZ09UW2FQ/fitbvIB5f1SkXWPxTF9l6mAeuXhoGv2EtQUO4vq/PK6N08RjrZdWQy6UsqHgffi7lVQ8o3hvCKdbtf4sP+cM92OrY0WZV89os79ndj4tyvmnP8WojwRjt/2XEfgdoWcgWxW9DiYINTOQVimZX+X/3on4s8hEgQKBgQCdY3kOMbyQeLTRkqHXjVTY4ddO+v4S4wOUa1l4rTqAbq1W3JYWwoDQgFuIu3limIHmjnSJpCD4EioXFsM7p6csenoc20sHxsaHnJ6Mn5Te41UYmY9EW0otkQ0C3KbXM0hwQkjyplnEmZawGKmjEHW8DJ3vRYTv9TUCgYKxDHgOzQKBgB4A/NYH7BG61eBYKgxEx6YnuMfbkwV+Vdu5S8d7FQn3B2LgvZZu4FPRqcNVXLbEB+5ao8czjiKCWaj1Wj15+rvrXGcxn+Tglg5J+r5+nXeUC7LbJZQaPNp0MOwWMr3dlrSLUWjYlJ9Pz9VyXOG4c4Rexc/gR4zK9QLW4C7qKpwBAoGAZzyUb0cYlPtYQA+asTU3bnvVKy1f8yuNcZFowst+EDiI4u0WVh+HNzy6zdmLKa03p+/RaWeLaK0hhrubnEnAUmCUMNF3ScaM+u804LDcicc8TkKLwx7ObU0z56isl4RAA8K27tNHFrpYKXJD834cfBkaj5ReOrfw6Y/iFhhDuBECgYEA8gbC76uz7LSHhW30DSRTcqOzTyoe2oYKQaxuxYNp7vSSOkcdRen+mrdflDvud2q/zN2QdL4pgqdldHlR35M/lJ0f0B6zp74jlzbO9700wzsOqreezGc5eWiroDL100U9uIZ50BKb8CKtixIHpinUSPIUcVDkSAZ2y7mbfCxQwqQ=', privKey: 'CAESYCtlyHA9SQ9F0yO6frmkrFFmboLCzGt8syr0ix8QkuTcVTVAp9JiBXb2xI1lzK6Fn2mRJUxtQIuuW+3V2mu3DZZVNUCn0mIFdvbEjWXMroWfaZElTG1Ai65b7dXaa7cNlg==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAE=' pubKey: 'CAESIFU1QKfSYgV29sSNZcyuhZ9pkSVMbUCLrlvt1dprtw2W'
}, { }, {
id: 'QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN', id: '12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5',
privKey: 'CAASpwkwggSjAgEAAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAECggEBAKb5aN/1w3pBqz/HqRMbQpYLNuD33M3PexBNPAy+P0iFpDo63bh5Rz+A4lvuFNmzUX70MFz7qENlzi6+n/zolxMB29YtWBUH8k904rTEjXXl//NviQgITZk106tx+4k2x5gPEm57LYGfBOdFAUzNhzDnE2LkXwRNzkS161f7zKwOEsaGWRscj6UvhO4MIFxjb32CVwt5eK4yOVqtyMs9u30K4Og+AZYTlhtm+bHg6ndCCBO6CQurCQ3jD6YOkT+L3MotKqt1kORpvzIB0ujZRf49Um8wlcjC5G9aexBeGriXaVdPF62zm7GA7RMsbQM/6aRbA1fEQXvJhHUNF9UFeaECgYEA8wCjKqQA7UQnHjRwTsktdwG6szfxd7z+5MTqHHTWhWzgcQLgdh5/dO/zanEoOThadMk5C1Bqjq96gH2xim8dg5XQofSVtV3Ui0dDa+XRB3E3fyY4D3RF5hHv85O0GcvQc6DIb+Ja1oOhvHowFB1C+CT3yEgwzX/EK9xpe+KtYAkCgYEAv7hCnj/DcZFU3fAfS+unBLuVoVJT/drxv66P686s7J8UM6tW+39yDBZ1IcwY9vHFepBvxY2fFfEeLI02QFM+lZXVhNGzFkP90agNHK01psGgrmIufl9zAo8WOKgkLgbYbSHzkkDeqyjEPU+B0QSsZOCE+qLCHSdsnTmo/TjQhj0CgYAz1+j3yfGgrS+jVBC53lXi0+2fGspbf2jqKdDArXSvFqFzuudki/EpY6AND4NDYfB6hguzjD6PnoSGMUrVfAtR7X6LbwEZpqEX7eZGeMt1yQPMDr1bHrVi9mS5FMQR1NfuM1lP9Xzn00GIUpE7WVrWUhzDEBPJY/7YVLf0hFH08QKBgDWBRQZJIVBmkNrHktRrVddaSq4U/d/Q5LrsCrpymYwH8WliHgpeTQPWmKXwAd+ZJdXIzYjCt202N4eTeVqGYOb6Q/anV2WVYBbM4avpIxoA28kPGY6nML+8EyWIt2ApBOmgGgvtEreNzwaVU9NzjHEyv6n7FlVwlT1jxCe3XWq5AoGASYPKQoPeDlW+NmRG7z9EJXJRPVtmLL40fmGgtju9QIjLnjuK8XaczjAWT+ySI93Whu+Eujf2Uj7Q+NfUjvAEzJgwzuOd3jlQvoALq11kuaxlNQTn7rx0A1QhBgUJE8AkvShPC9FEnA4j/CLJU0re9H/8VvyN6qE0Mho0+YbjpP8=', privKey: 'CAESYLU/qFxBHsdsQa63w3MrP8VvxJDyAk7rB7gLnIN01CyibmZCtQc7a1gIEDOGb10maUltL8wJxEdmOw3Bpjo7xrpuZkK1BztrWAgQM4ZvXSZpSW0vzAnER2Y7DcGmOjvGug==',
pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAE=' pubKey: 'CAESIG5mQrUHO2tYCBAzhm9dJmlJbS/MCcRHZjsNwaY6O8a6'
}] }]

View File

@ -53,7 +53,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -63,7 +64,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -106,7 +108,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -116,7 +119,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols protocols
}) })
@ -165,7 +169,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
}, },
protocols protocols
}) })
@ -174,7 +179,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
}, },
protocols protocols
}) })
@ -201,6 +207,36 @@ describe('Identify', () => {
.and.to.have.property('code', Errors.ERR_INVALID_PEER) .and.to.have.property('code', Errors.ERR_INVALID_PEER)
}) })
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
const peerStore = new PeerStore({ peerId: localPeer })
sinon.spy(peerStore.metadataBook, 'set')
new IdentifyService({ // eslint-disable-line no-new
libp2p: {
peerId: localPeer,
connectionManager: new EventEmitter(),
peerStore,
multiaddrs: listenMaddrs,
_options: {
host: {
agentVersion
}
}
},
protocols
})
expect(peerStore.metadataBook.set.callCount).to.eql(2)
const storedAgentVersion = peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
describe('push', () => { describe('push', () => {
it('should be able to push identify updates to another peer', async () => { it('should be able to push identify updates to another peer', async () => {
const connectionManager = new EventEmitter() const connectionManager = new EventEmitter()
@ -211,7 +247,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols: new Map([ protocols: new Map([
[multicodecs.IDENTIFY], [multicodecs.IDENTIFY],
@ -224,7 +261,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager, connectionManager,
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
} }
}) })
@ -272,7 +310,8 @@ describe('Identify', () => {
peerId: localPeer, peerId: localPeer,
connectionManager: new EventEmitter(), connectionManager: new EventEmitter(),
peerStore: new PeerStore({ peerId: localPeer }), peerStore: new PeerStore({ peerId: localPeer }),
multiaddrs: listenMaddrs multiaddrs: listenMaddrs,
_options: { host: {} }
}, },
protocols: new Map([ protocols: new Map([
[multicodecs.IDENTIFY], [multicodecs.IDENTIFY],
@ -285,7 +324,8 @@ describe('Identify', () => {
peerId: remotePeer, peerId: remotePeer,
connectionManager, connectionManager,
peerStore: new PeerStore({ peerId: remotePeer }), peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [] multiaddrs: [],
_options: { host: {} }
} }
}) })
@ -364,7 +404,7 @@ describe('Identify', () => {
expect(libp2p.identifyService.identify.callCount).to.equal(1) expect(libp2p.identifyService.identify.callCount).to.equal(1)
// The connection should have no open streams // The connection should have no open streams
expect(connection.streams).to.have.length(0) await pWaitFor(() => connection.streams.length === 0)
await connection.close() await connection.close()
}) })
@ -404,5 +444,23 @@ describe('Identify', () => {
// Verify the streams close // Verify the streams close
await pWaitFor(() => connection.streams.length === 0) await pWaitFor(() => connection.streams.length === 0)
}) })
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
libp2p = new Libp2p({
...baseOptions,
peerId,
host: {
agentVersion
}
})
const storedAgentVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
}) })
}) })

View File

@ -10,6 +10,7 @@ const sinon = require('sinon')
const pDefer = require('p-defer') const pDefer = require('p-defer')
const mergeOptions = require('merge-options') const mergeOptions = require('merge-options')
const ipfsHttpClient = require('ipfs-http-client')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing') const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
const peerUtils = require('../utils/creators/peer') const peerUtils = require('../utils/creators/peer')
@ -72,11 +73,11 @@ describe('peer-routing', () => {
let delegate let delegate
beforeEach(async () => { beforeEach(async () => {
delegate = new DelegatedPeerRouter({ delegate = new DelegatedPeerRouter(ipfsHttpClient({
host: '0.0.0.0', host: '0.0.0.0',
protocol: 'http', protocol: 'http',
port: 60197 port: 60197
}) }))
;[node] = await peerUtils.createPeer({ ;[node] = await peerUtils.createPeer({
config: mergeOptions(baseOptions, { config: mergeOptions(baseOptions, {
@ -162,11 +163,11 @@ describe('peer-routing', () => {
let delegate let delegate
beforeEach(async () => { beforeEach(async () => {
delegate = new DelegatedPeerRouter({ delegate = new DelegatedPeerRouter(ipfsHttpClient({
host: '0.0.0.0', host: '0.0.0.0',
protocol: 'http', protocol: 'http',
port: 60197 port: 60197
}) }))
;[node] = await peerUtils.createPeer({ ;[node] = await peerUtils.createPeer({
config: mergeOptions(routingOptions, { config: mergeOptions(routingOptions, {

View File

@ -135,8 +135,7 @@ describe('Persisted PeerStore', () => {
peerStore.keyBook.set(peers[0], peers[0].pubKey) peerStore.keyBook.set(peers[0], peers[0].pubKey)
peerStore.keyBook.set(peers[1], peers[1].pubKey) peerStore.keyBook.set(peers[1], peers[1].pubKey)
// let batch commit complete // no batch commit as public key inline
await Promise.all(commitSpy.returnValues)
// ProtoBook // ProtoBook
peerStore.protoBook.set(peers[0], protocols) peerStore.protoBook.set(peers[0], protocols)
@ -151,7 +150,7 @@ describe('Persisted PeerStore', () => {
// let batch commit complete // let batch commit complete
await Promise.all(commitSpy.returnValues) await Promise.all(commitSpy.returnValues)
expect(spyDs).to.have.property('callCount', 7) // 2 Address + 2 Key + 2 Proto + 1 Metadata expect(spyDs).to.have.property('callCount', 5) // 2 Address + 2 Proto + 1 Metadata
expect(peerStore.peers.size).to.equal(2) expect(peerStore.peers.size).to.equal(2)
await peerStore.stop() await peerStore.stop()
@ -164,12 +163,12 @@ describe('Persisted PeerStore', () => {
await peerStore.start() await peerStore.start()
expect(spy).to.have.property('callCount', 7) expect(spy).to.have.property('callCount', 5)
expect(spyDs).to.have.property('callCount', 7) expect(spyDs).to.have.property('callCount', 5)
expect(peerStore.peers.size).to.equal(2) expect(peerStore.peers.size).to.equal(2)
expect(peerStore.addressBook.data.size).to.equal(2) expect(peerStore.addressBook.data.size).to.equal(2)
expect(peerStore.keyBook.data.size).to.equal(2) expect(peerStore.keyBook.data.size).to.equal(0)
expect(peerStore.protoBook.data.size).to.equal(2) expect(peerStore.protoBook.data.size).to.equal(2)
expect(peerStore.metadataBook.data.size).to.equal(1) expect(peerStore.metadataBook.data.size).to.equal(1)
}) })

View File

@ -10,6 +10,7 @@ const TransportManager = require('../../src/transport-manager')
const Transport = require('libp2p-tcp') const Transport = require('libp2p-tcp')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
const mockUpgrader = require('../utils/mockUpgrader') const mockUpgrader = require('../utils/mockUpgrader')
const sinon = require('sinon')
const addrs = [ const addrs = [
multiaddr('/ip4/127.0.0.1/tcp/0'), multiaddr('/ip4/127.0.0.1/tcp/0'),
multiaddr('/ip4/127.0.0.1/tcp/0') multiaddr('/ip4/127.0.0.1/tcp/0')
@ -40,7 +41,9 @@ describe('Transport Manager (TCP)', () => {
}) })
it('should be able to listen', async () => { it('should be able to listen', async () => {
tm.add(Transport.prototype[Symbol.toStringTag], Transport) tm.add(Transport.prototype[Symbol.toStringTag], Transport, { listenerOptions: { listen: 'carefully' } })
const transport = tm._transports.get(Transport.prototype[Symbol.toStringTag])
const spyListener = sinon.spy(transport, 'createListener')
await tm.listen() await tm.listen()
expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag]) expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag])
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(addrs.length) expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(addrs.length)
@ -48,6 +51,7 @@ describe('Transport Manager (TCP)', () => {
expect(tm.getAddrs().length).to.equal(addrs.length) expect(tm.getAddrs().length).to.equal(addrs.length)
await tm.close() await tm.close()
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(0) expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(0)
expect(spyListener.firstCall.firstArg).to.deep.equal({ listen: 'carefully' })
}) })
it('should be able to dial', async () => { it('should be able to dial', async () => {

View File

@ -125,7 +125,10 @@ describe('libp2p.transportManager', () => {
const spy = sinon.spy() const spy = sinon.spy()
const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy' const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy'
const customOptions = { const customOptions = {
another: 'value' another: 'value',
listenerOptions: {
listen: 'carefully'
}
} }
libp2p = new Libp2p({ libp2p = new Libp2p({
peerId, peerId,
@ -143,6 +146,7 @@ describe('libp2p.transportManager', () => {
expect(libp2p.transportManager).to.exist() expect(libp2p.transportManager).to.exist()
// Our transport and circuit relay // Our transport and circuit relay
expect(libp2p.transportManager._transports.size).to.equal(2) expect(libp2p.transportManager._transports.size).to.equal(2)
expect(libp2p.transportManager._listenerOptions.size).to.equal(2)
expect(spy).to.have.property('callCount', 1) expect(spy).to.have.property('callCount', 1)
expect(spy.getCall(0)).to.have.deep.property('args', [{ expect(spy.getCall(0)).to.have.deep.property('args', [{
...customOptions, ...customOptions,

View File

@ -13,13 +13,14 @@ const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
/** /**
* Create libp2p nodes. * Create libp2p nodes.
*
* @param {Object} [properties] * @param {Object} [properties]
* @param {Object} [properties.config] * @param {Object} [properties.config]
* @param {number} [properties.number] number of peers (default: 1). * @param {number} [properties.number] - number of peers (default: 1).
* @param {boolean} [properties.fixture] use fixture for peer-id generation (default: true) * @param {boolean} [properties.fixture] - use fixture for peer-id generation (default: true)
* @param {boolean} [properties.started] nodes should start (default: true) * @param {boolean} [properties.started] - nodes should start (default: true)
* @param {boolean} [properties.populateAddressBooks] nodes addressBooks should be populated with other peers (default: true) * @param {boolean} [properties.populateAddressBooks] - nodes addressBooks should be populated with other peers (default: true)
* @return {Promise<Array<Libp2p>>} * @returns {Promise<Array<Libp2p>>}
*/ */
async function createPeer ({ number = 1, fixture = true, started = true, populateAddressBooks = true, config = {} } = {}) { async function createPeer ({ number = 1, fixture = true, started = true, populateAddressBooks = true, config = {} } = {}) {
const peerIds = await createPeerId({ number, fixture }) const peerIds = await createPeerId({ number, fixture })
@ -53,10 +54,11 @@ function _populateAddressBooks (peers) {
/** /**
* Create Peer-ids. * Create Peer-ids.
*
* @param {Object} [properties] * @param {Object} [properties]
* @param {number} [properties.number] number of peers (default: 1). * @param {number} [properties.number] - number of peers (default: 1).
* @param {boolean} [properties.fixture] use fixture for peer-id generation (default: true) * @param {boolean} [properties.fixture] - use fixture for peer-id generation (default: true)
* @return {Promise<Array<PeerId>>} * @returns {Promise<Array<PeerId>>}
*/ */
function createPeerId ({ number = 1, fixture = true } = {}) { function createPeerId ({ number = 1, fixture = true } = {}) {
return pTimes(number, (i) => fixture return pTimes(number, (i) => fixture

View File

@ -58,9 +58,9 @@ module.exports = async (properties = {}) => {
* Creates a full connection pair, without the transport or encryption * Creates a full connection pair, without the transport or encryption
* *
* @param {object} options * @param {object} options
* @param {Multiaddr[]} options.addrs Should contain two addresses for the local and remote peer respectively * @param {Multiaddr[]} options.addrs - Should contain two addresses for the local and remote peer respectively
* @param {PeerId[]} options.remotePeer Should contain two peer ids, for the local and remote peer respectively * @param {Array<PeerId>} options.peers - Array containing local and remote peer ids
* @param {Map<string, function>} options.protocols The protocols the connections should support * @param {Map<string, Function>} options.protocols - The protocols the connections should support
* @returns {{inbound:Connection, outbound:Connection}} * @returns {{inbound:Connection, outbound:Connection}}
*/ */
module.exports.pair = function connectionPair ({ addrs, peers, protocols }) { module.exports.pair = function connectionPair ({ addrs, peers, protocols }) {

View File

@ -6,9 +6,10 @@ const AbortController = require('abort-controller')
/** /**
* Returns both sides of a mocked MultiaddrConnection * Returns both sides of a mocked MultiaddrConnection
*
* @param {object} options * @param {object} options
* @param {Multiaddr[]} options.addrs Should contain two addresses for the local and remote peer * @param {Multiaddr[]} options.addrs - Should contain two addresses for the local and remote peer
* @param {PeerId} options.remotePeer The peer that is being "dialed" * @param {PeerId} options.remotePeer - The peer that is being "dialed"
* @returns {{inbound:MultiaddrConnection, outbound:MultiaddrConnection}} * @returns {{inbound:MultiaddrConnection, outbound:MultiaddrConnection}}
*/ */
module.exports = function mockMultiaddrConnPair ({ addrs, remotePeer }) { module.exports = function mockMultiaddrConnPair ({ addrs, remotePeer }) {