mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-13 07:41:32 +00:00
Compare commits
1 Commits
v0.35.4
...
chore/use-
Author | SHA1 | Date | |
---|---|---|---|
7781075a7a |
65
.github/workflows/examples.yml
vendored
65
.github/workflows/examples.yml
vendored
@ -12,9 +12,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npx aegir lint
|
- run: npx aegir lint
|
||||||
- run: npx aegir ts -p check
|
- run: npx aegir ts -p check
|
||||||
@ -24,118 +21,82 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- auto-relay
|
- run: cd examples && npm install && npm run test -- auto-relay
|
||||||
test-chat-example:
|
test-chat-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- chat
|
- run: cd examples && npm install && npm run test -- chat
|
||||||
test-connection-encryption-example:
|
test-connection-encryption-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- connection-encryption
|
- run: cd examples && npm install && npm run test -- connection-encryption
|
||||||
test-discovery-mechanisms-example:
|
test-discovery-mechanisms-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- discovery-mechanisms
|
- run: cd examples && npm install && npm run test -- discovery-mechanisms
|
||||||
test-echo-example:
|
test-echo-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- echo
|
- run: cd examples && npm install && npm run test -- echo
|
||||||
test-libp2p-in-the-browser-example:
|
test-libp2p-in-the-browser-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- libp2p-in-the-browser
|
- run: cd examples && npm install && npm run test -- libp2p-in-the-browser
|
||||||
test-peer-and-content-routing-example:
|
test-peer-and-content-routing-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- peer-and-content-routing
|
- run: cd examples && npm install && npm run test -- peer-and-content-routing
|
||||||
test-pnet-example:
|
test-pnet-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- pnet
|
- run: cd examples && npm install && npm run test -- pnet
|
||||||
test-protocol-and-stream-muxing-example:
|
test-protocol-and-stream-muxing-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- protocol-and-stream-muxing
|
- run: cd examples && npm install && npm run test -- protocol-and-stream-muxing
|
||||||
test-pubsub-example:
|
test-pubsub-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- pubsub
|
- run: cd examples && npm install && npm run test -- pubsub
|
||||||
test-transports-example:
|
test-transports-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: 16
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: cd examples && npm i && npm run test -- transports
|
- run: cd examples && npm install && npm run test -- transports
|
||||||
test-webrtc-direct-example:
|
test-webrtc-direct-example:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- run: npm install
|
||||||
with:
|
- run: cd examples && npm install && npm run test -- webrtc-direct
|
||||||
node-version: 16
|
|
||||||
- run: npm install -g @mapbox/node-pre-gyp && npm install
|
|
||||||
- run: cd examples && npm i && npm run test -- webrtc-direct
|
|
27
.github/workflows/main.yml
vendored
27
.github/workflows/main.yml
vendored
@ -14,12 +14,13 @@ jobs:
|
|||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
- uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 14
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npx aegir lint
|
- run: npx aegir lint
|
||||||
|
- uses: gozala/typescript-error-reporter-action@v1.0.8
|
||||||
- run: npx aegir build
|
- run: npx aegir build
|
||||||
- run: npx aegir dep-check
|
- run: npx aegir dep-check
|
||||||
- uses: ipfs/aegir/actions/bundle-size
|
- uses: ipfs/aegir/actions/bundle-size@v32.1.0
|
||||||
name: size
|
name: size
|
||||||
with:
|
with:
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@ -29,7 +30,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||||
node: [16]
|
node: [14, 16]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
@ -37,36 +38,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run test:node -- --cov --bail
|
- run: npx aegir test -t node --cov --bail
|
||||||
- uses: codecov/codecov-action@v1
|
- uses: codecov/codecov-action@v1
|
||||||
test-chrome:
|
test-chrome:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: lts/*
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run test:browser -- -t browser -t webworker --bail
|
- run: npx aegir test -t browser -t webworker --bail
|
||||||
test-firefox:
|
test-firefox:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: lts/*
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run test:browser -- -t browser -t webworker --bail -- --browser firefox
|
- run: npx aegir test -t browser -t webworker --bail -- --browser firefox
|
||||||
test-ts:
|
test-ts:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: lts/*
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run test:ts
|
- run: npm run test:ts
|
||||||
test-interop:
|
test-interop:
|
||||||
@ -74,8 +66,5 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v2
|
|
||||||
with:
|
|
||||||
node-version: lts/*
|
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm run test:interop -- --bail -- --exit
|
- run: cd node_modules/interop-libp2p && yarn && LIBP2P_JS=${GITHUB_WORKSPACE}/src/index.js npx aegir test -t node --bail -- --exit
|
||||||
|
95
CHANGELOG.md
95
CHANGELOG.md
@ -1,98 +1,3 @@
|
|||||||
## [0.35.4](https://github.com/libp2p/js-libp2p/compare/v0.35.3...v0.35.4) (2021-12-15)
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* allow per-component metrics to be collected ([#1061](https://github.com/libp2p/js-libp2p/issues/1061)) ([2f0b311](https://github.com/libp2p/js-libp2p/commit/2f0b311df7127aa44512c2008142d4ca30268986)), closes [#1060](https://github.com/libp2p/js-libp2p/issues/1060)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.35.3](https://github.com/libp2p/js-libp2p/compare/v0.35.2...v0.35.3) (2021-12-13)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* clean up pending dial targets ([#1059](https://github.com/libp2p/js-libp2p/issues/1059)) ([bdc9f16](https://github.com/libp2p/js-libp2p/commit/bdc9f16d0cbe56ccf26822f11068e7795bcef046))
|
|
||||||
* fix uncaught promise rejection when finding peers ([#1044](https://github.com/libp2p/js-libp2p/issues/1044)) ([3b683e7](https://github.com/libp2p/js-libp2p/commit/3b683e715686163e229b7b5c3a892327dfd4fc63))
|
|
||||||
* make error codes consistent ([#1054](https://github.com/libp2p/js-libp2p/issues/1054)) ([b25e0fe](https://github.com/libp2p/js-libp2p/commit/b25e0fe5312db58a06c39500ae84c50fed3a93bd))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.35.2](https://github.com/libp2p/js-libp2p/compare/v0.33.0...v0.35.2) (2021-12-06)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* do not let closest peers run forever ([#1047](https://github.com/libp2p/js-libp2p/issues/1047)) ([91c2ec9](https://github.com/libp2p/js-libp2p/commit/91c2ec9856a3e972b7b2c9c4d9a4eda1d431c7ef))
|
|
||||||
* increase maxlisteners on event target ([#1050](https://github.com/libp2p/js-libp2p/issues/1050)) ([b70fb43](https://github.com/libp2p/js-libp2p/commit/b70fb43427b47df079b55929ec8956f69cbda966)), closes [#900](https://github.com/libp2p/js-libp2p/issues/900)
|
|
||||||
* private ip ts compile has no call signatures ([#1020](https://github.com/libp2p/js-libp2p/issues/1020)) ([77d7cb8](https://github.com/libp2p/js-libp2p/commit/77d7cb8f0815f2cdd3bfdfa8b641a7a186fe9520))
|
|
||||||
* stop dht before connection manager ([#1041](https://github.com/libp2p/js-libp2p/issues/1041)) ([3a9d5f6](https://github.com/libp2p/js-libp2p/commit/3a9d5f64d96719ebb4d3b083c4f5832db4fa0816)), closes [#1039](https://github.com/libp2p/js-libp2p/issues/1039)
|
|
||||||
|
|
||||||
|
|
||||||
### chore
|
|
||||||
|
|
||||||
* update peer id and libp2p crypto ([#1042](https://github.com/libp2p/js-libp2p/issues/1042)) ([9cbf36f](https://github.com/libp2p/js-libp2p/commit/9cbf36fcb54099e6fed35ceccc4a2376f0926c1f))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* update dht ([#1009](https://github.com/libp2p/js-libp2p/issues/1009)) ([2f598eb](https://github.com/libp2p/js-libp2p/commit/2f598eba09cff4301474af08196158065e3602d8))
|
|
||||||
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
* requires node 15+
|
|
||||||
* libp2p-kad-dht has a new event-based API which is exposed as `_dht`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.35.1](https://github.com/libp2p/js-libp2p/compare/v0.35.0...v0.35.1) (2021-12-03)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* do not let closest peers run forever ([#1047](https://github.com/libp2p/js-libp2p/issues/1047)) ([91c2ec9](https://github.com/libp2p/js-libp2p/commit/91c2ec9856a3e972b7b2c9c4d9a4eda1d431c7ef))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [0.35.0](https://github.com/libp2p/js-libp2p/compare/v0.34.0...v0.35.0) (2021-12-02)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* stop dht before connection manager ([#1041](https://github.com/libp2p/js-libp2p/issues/1041)) ([3a9d5f6](https://github.com/libp2p/js-libp2p/commit/3a9d5f64d96719ebb4d3b083c4f5832db4fa0816)), closes [#1039](https://github.com/libp2p/js-libp2p/issues/1039)
|
|
||||||
|
|
||||||
|
|
||||||
### chore
|
|
||||||
|
|
||||||
* update peer id and libp2p crypto ([#1042](https://github.com/libp2p/js-libp2p/issues/1042)) ([9cbf36f](https://github.com/libp2p/js-libp2p/commit/9cbf36fcb54099e6fed35ceccc4a2376f0926c1f))
|
|
||||||
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
* requires node 15+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [0.34.0](https://github.com/libp2p/js-libp2p/compare/v0.33.0...v0.34.0) (2021-11-25)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* private ip ts compile has no call signatures ([#1020](https://github.com/libp2p/js-libp2p/issues/1020)) ([77d7cb8](https://github.com/libp2p/js-libp2p/commit/77d7cb8f0815f2cdd3bfdfa8b641a7a186fe9520))
|
|
||||||
|
|
||||||
|
|
||||||
### Features
|
|
||||||
|
|
||||||
* update dht ([#1009](https://github.com/libp2p/js-libp2p/issues/1009)) ([2f598eb](https://github.com/libp2p/js-libp2p/commit/2f598eba09cff4301474af08196158065e3602d8))
|
|
||||||
|
|
||||||
|
|
||||||
### BREAKING CHANGES
|
|
||||||
|
|
||||||
* libp2p-kad-dht has a new event-based API which is exposed as `_dht`
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [0.33.0](https://github.com/libp2p/js-libp2p/compare/v0.32.5...v0.33.0) (2021-09-24)
|
# [0.33.0](https://github.com/libp2p/js-libp2p/compare/v0.32.5...v0.33.0) (2021-09-24)
|
||||||
|
|
||||||
|
|
||||||
|
@ -2086,7 +2086,7 @@ the NatManager performing NAT hole punching.
|
|||||||
|
|
||||||
[address]: https://github.com/libp2p/js-libp2p/tree/master/src/peer-store/address-book.js
|
[address]: https://github.com/libp2p/js-libp2p/tree/master/src/peer-store/address-book.js
|
||||||
[cid]: https://github.com/multiformats/js-cid
|
[cid]: https://github.com/multiformats/js-cid
|
||||||
[connection]: https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interfaces/src/connection
|
[connection]: https://github.com/libp2p/js-interfaces/tree/master/src/connection
|
||||||
[multiaddr]: https://github.com/multiformats/js-multiaddr
|
[multiaddr]: https://github.com/multiformats/js-multiaddr
|
||||||
[peer-id]: https://github.com/libp2p/js-peer-id
|
[peer-id]: https://github.com/libp2p/js-peer-id
|
||||||
[keys]: https://github.com/libp2p/js-libp2p-crypto/tree/master/src/keys
|
[keys]: https://github.com/libp2p/js-libp2p-crypto/tree/master/src/keys
|
||||||
|
@ -1,37 +1,37 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
- [Overview](#overview)
|
- [Configuration](#configuration)
|
||||||
- [Modules](#modules)
|
- [Overview](#overview)
|
||||||
- [Transport](#transport)
|
- [Modules](#modules)
|
||||||
- [Stream Multiplexing](#stream-multiplexing)
|
- [Transport](#transport)
|
||||||
- [Connection Encryption](#connection-encryption)
|
- [Stream Multiplexing](#stream-multiplexing)
|
||||||
- [Peer Discovery](#peer-discovery)
|
- [Connection Encryption](#connection-encryption)
|
||||||
- [Content Routing](#content-routing)
|
- [Peer Discovery](#peer-discovery)
|
||||||
- [Peer Routing](#peer-routing)
|
- [Content Routing](#content-routing)
|
||||||
- [DHT](#dht)
|
- [Peer Routing](#peer-routing)
|
||||||
- [Pubsub](#pubsub)
|
- [DHT](#dht)
|
||||||
- [Customizing libp2p](#customizing-libp2p)
|
- [Pubsub](#pubsub)
|
||||||
- [Examples](#examples)
|
- [Customizing libp2p](#customizing-libp2p)
|
||||||
- [Basic setup](#basic-setup)
|
- [Examples](#examples)
|
||||||
- [Customizing Peer Discovery](#customizing-peer-discovery)
|
- [Basic setup](#basic-setup)
|
||||||
- [Setup webrtc transport and discovery](#setup-webrtc-transport-and-discovery)
|
- [Customizing Peer Discovery](#customizing-peer-discovery)
|
||||||
- [Customizing Pubsub](#customizing-pubsub)
|
- [Setup webrtc transport and discovery](#setup-webrtc-transport-and-discovery)
|
||||||
- [Customizing DHT](#customizing-dht)
|
- [Customizing Pubsub](#customizing-pubsub)
|
||||||
- [Setup with Content and Peer Routing](#setup-with-content-and-peer-routing)
|
- [Customizing DHT](#customizing-dht)
|
||||||
- [Setup with Relay](#setup-with-relay)
|
- [Setup with Content and Peer Routing](#setup-with-content-and-peer-routing)
|
||||||
- [Setup with Auto Relay](#setup-with-auto-relay)
|
- [Setup with Relay](#setup-with-relay)
|
||||||
- [Setup with Keychain](#setup-with-keychain)
|
- [Setup with Auto Relay](#setup-with-auto-relay)
|
||||||
- [Configuring Dialing](#configuring-dialing)
|
- [Setup with Keychain](#setup-with-keychain)
|
||||||
- [Configuring Connection Manager](#configuring-connection-manager)
|
- [Configuring Dialing](#configuring-dialing)
|
||||||
- [Configuring Transport Manager](#configuring-transport-manager)
|
- [Configuring Connection Manager](#configuring-connection-manager)
|
||||||
- [Configuring Metrics](#configuring-metrics)
|
- [Configuring Transport Manager](#configuring-transport-manager)
|
||||||
- [Configuring PeerStore](#configuring-peerstore)
|
- [Configuring Metrics](#configuring-metrics)
|
||||||
- [Customizing Transports](#customizing-transports)
|
- [Configuring PeerStore](#configuring-peerstore)
|
||||||
- [Configuring the NAT Manager](#configuring-the-nat-manager)
|
- [Customizing Transports](#customizing-transports)
|
||||||
- [Browser support](#browser-support)
|
- [Configuring the NAT Manager](#configuring-the-nat-manager)
|
||||||
- [UPnP and NAT-PMP](#upnp-and-nat-pmp)
|
- [Browser support](#browser-support)
|
||||||
- [Configuring protocol name](#configuring-protocol-name)
|
- [UPnP and NAT-PMP](#upnp-and-nat-pmp)
|
||||||
- [Configuration examples](#configuration-examples)
|
- [Configuration examples](#configuration-examples)
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
@ -374,7 +374,11 @@ const node = await Libp2p.create({
|
|||||||
dht: { // The DHT options (and defaults) can be found in its documentation
|
dht: { // The DHT options (and defaults) can be found in its documentation
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
enabled: true, // This flag is required for DHT to run (disabled by default)
|
enabled: true, // This flag is required for DHT to run (disabled by default)
|
||||||
clientMode: false // Whether to run the WAN DHT in client or server mode (default: client mode)
|
randomWalk: {
|
||||||
|
enabled: true, // Allows to disable discovery (enabled by default)
|
||||||
|
interval: 300e3,
|
||||||
|
timeout: 10e3
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -497,9 +501,9 @@ 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 { NOISE } = require('libp2p-noise')
|
const { NOISE } = require('libp2p-noise')
|
||||||
const LevelDatastore = require('datastore-level')
|
const LevelStore = require('datastore-level')
|
||||||
|
|
||||||
const datastore = new LevelDatastore('path/to/store')
|
const datastore = new LevelStore('path/to/store')
|
||||||
await datastore.open()
|
await datastore.open()
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
@ -672,9 +676,9 @@ 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 { NOISE } = require('libp2p-noise')
|
const { NOISE } = require('libp2p-noise')
|
||||||
const LevelDatastore = require('datastore-level')
|
const LevelStore = require('datastore-level')
|
||||||
|
|
||||||
const datastore = new LevelDatastore('path/to/store')
|
const datastore = new LevelStore('path/to/store')
|
||||||
const dsInstant = await datastore.open()
|
const dsInstant = await datastore.open()
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
@ -784,7 +788,7 @@ By default under nodejs libp2p will attempt to use [UPnP](https://en.wikipedia.o
|
|||||||
|
|
||||||
#### Configuring protocol name
|
#### Configuring protocol name
|
||||||
|
|
||||||
Changing the protocol name prefix can isolate default public network (IPFS) for custom purposes.
|
Changing the protocol name prefix can isolate default public network (IPFS) for custom purposes.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"libp2p": "github:libp2p/js-libp2p#master",
|
"libp2p": "github:libp2p/js-libp2p#master",
|
||||||
"libp2p-delegated-content-routing": "~0.2.2",
|
"libp2p-delegated-content-routing": "~0.2.2",
|
||||||
"libp2p-delegated-peer-routing": "~0.2.2",
|
"libp2p-delegated-peer-routing": "~0.2.2",
|
||||||
"libp2p-kad-dht": "^0.26.5",
|
"libp2p-kad-dht": "~0.14.12",
|
||||||
"libp2p-mplex": "~0.8.5",
|
"libp2p-mplex": "~0.8.5",
|
||||||
"libp2p-secio": "~0.11.1",
|
"libp2p-secio": "~0.11.1",
|
||||||
"libp2p-webrtc-star": "~0.15.8",
|
"libp2p-webrtc-star": "~0.15.8",
|
||||||
|
@ -55,7 +55,7 @@ const node = await Libp2p.create({
|
|||||||
peerId,
|
peerId,
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: ['/ip4/0.0.0.0/tcp/0']
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
},
|
}
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
@ -117,7 +117,7 @@ const createNode = () => {
|
|||||||
return Libp2p.create({
|
return Libp2p.create({
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: ['/ip4/0.0.0.0/tcp/0']
|
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||||
},
|
}
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
@ -144,13 +144,8 @@ const [node1, node2] = await Promise.all([
|
|||||||
createNode()
|
createNode()
|
||||||
])
|
])
|
||||||
|
|
||||||
node1.on('peer:discovery', (peer) => console.log('Discovered:', peerId.toB58String()))
|
node1.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
node2.on('peer:discovery', (peer) => console.log('Discovered:', peerId.toB58String()))
|
node2.on('peer:discovery', (peer) => console.log('Discovered:', peer.id.toB58String()))
|
||||||
|
|
||||||
await Promise.all([
|
|
||||||
node1.start(),
|
|
||||||
node2.start()
|
|
||||||
])
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you run this example, you will see the other peers being discovered.
|
If you run this example, you will see the other peers being discovered.
|
||||||
|
@ -28,6 +28,6 @@
|
|||||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
"babel-plugin-transform-regenerator": "^6.26.0",
|
"babel-plugin-transform-regenerator": "^6.26.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"parcel": "^2.0.1"
|
"parcel": "next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ async function run() {
|
|||||||
)
|
)
|
||||||
await browser.close();
|
await browser.close();
|
||||||
|
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -41,13 +41,13 @@ const createNode = async () => {
|
|||||||
node1.pubsub.on(topic, (msg) => {
|
node1.pubsub.on(topic, (msg) => {
|
||||||
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
||||||
})
|
})
|
||||||
node1.pubsub.subscribe(topic)
|
await node1.pubsub.subscribe(topic)
|
||||||
|
|
||||||
// Will not receive own published messages by default
|
// Will not receive own published messages by default
|
||||||
node2.pubsub.on(topic, (msg) => {
|
node2.pubsub.on(topic, (msg) => {
|
||||||
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
||||||
})
|
})
|
||||||
node2.pubsub.subscribe(topic)
|
await node2.pubsub.subscribe(topic)
|
||||||
|
|
||||||
// node2 publishes "news" every second
|
// node2 publishes "news" every second
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
|
@ -81,7 +81,7 @@ function print ({ stream }) {
|
|||||||
// node 3 (listening WebSockets) can dial node 1 (TCP)
|
// node 3 (listening WebSockets) can dial node 1 (TCP)
|
||||||
try {
|
try {
|
||||||
await node3.dialProtocol(node1.peerId, '/print')
|
await node3.dialProtocol(node1.peerId, '/print')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
console.log('node 3 failed to dial to node 1 with:', err.message)
|
console.log('node 3 failed to dial to node 1 with:', err.message)
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -91,7 +91,7 @@ const concat = require('it-concat')
|
|||||||
const MPLEX = require('libp2p-mplex')
|
const MPLEX = require('libp2p-mplex')
|
||||||
```
|
```
|
||||||
|
|
||||||
We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`.
|
We are going to reuse the `createNode` function from step 1, but this time add a stream multiplexer from `libp2p-mplex`.
|
||||||
```js
|
```js
|
||||||
const createNode = async () => {
|
const createNode = async () => {
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
|
@ -9,7 +9,7 @@ async function isExecutable (command) {
|
|||||||
await fs.access(command, fs.constants.X_OK)
|
await fs.access(command, fs.constants.X_OK)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
if (err.code === 'ENOENT') {
|
if (err.code === 'ENOENT') {
|
||||||
return isExecutable(await which(command))
|
return isExecutable(await which(command))
|
||||||
}
|
}
|
||||||
@ -49,7 +49,7 @@ async function waitForOutput (expectedOutput, command, args = [], opts = {}) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await proc
|
await proc
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
if (!err.killed) {
|
if (!err.killed) {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,6 @@
|
|||||||
<main>
|
<main>
|
||||||
<pre id="output"></pre>
|
<pre id="output"></pre>
|
||||||
</main>
|
</main>
|
||||||
<script src="./dialer.js" type="module"></script>
|
<script src="./dialer.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"description": "",
|
"description": "",
|
||||||
|
"main": "dist/index.html",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1",
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
"build": "parcel build index.html",
|
"build": "parcel build index.html",
|
||||||
@ -15,7 +16,7 @@
|
|||||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
"babel-plugin-transform-regenerator": "^6.26.0",
|
"babel-plugin-transform-regenerator": "^6.26.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
"babel-polyfill": "^6.26.0",
|
||||||
"parcel": "^2.0.1",
|
"parcel-bundler": "1.12.3",
|
||||||
"util": "^0.12.3"
|
"util": "^0.12.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -24,7 +25,7 @@
|
|||||||
"libp2p-mplex": "^0.10.4",
|
"libp2p-mplex": "^0.10.4",
|
||||||
"@chainsafe/libp2p-noise": "^4.1.0",
|
"@chainsafe/libp2p-noise": "^4.1.0",
|
||||||
"libp2p-webrtc-direct": "^0.7.0",
|
"libp2p-webrtc-direct": "^0.7.0",
|
||||||
"peer-id": "^0.16.0"
|
"peer-id": "^0.15.0"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"ipfs": "ipfs/dist/index.min.js"
|
"ipfs": "ipfs/dist/index.min.js"
|
||||||
|
@ -72,7 +72,7 @@ async function test () {
|
|||||||
{ timeout: 10000 }
|
{ timeout: 10000 }
|
||||||
)
|
)
|
||||||
await browser.close();
|
await browser.close();
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
} finally {
|
} finally {
|
||||||
|
66
package.json
66
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p",
|
"name": "libp2p",
|
||||||
"version": "0.35.4",
|
"version": "0.33.0",
|
||||||
"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",
|
||||||
@ -41,7 +41,6 @@
|
|||||||
"test:node": "aegir test -t node -f \"./test/**/*.{node,spec}.js\"",
|
"test:node": "aegir test -t node -f \"./test/**/*.{node,spec}.js\"",
|
||||||
"test:browser": "aegir test -t browser",
|
"test:browser": "aegir test -t browser",
|
||||||
"test:examples": "cd examples && npm run test:all",
|
"test:examples": "cd examples && npm run test:all",
|
||||||
"test:interop": "LIBP2P_JS=$PWD npx aegir test -t node -f ./node_modules/libp2p-interop/test/*",
|
|
||||||
"prepare": "aegir build --no-bundle",
|
"prepare": "aegir build --no-bundle",
|
||||||
"release": "aegir release -t node -t browser",
|
"release": "aegir release -t node -t browser",
|
||||||
"release-minor": "aegir release --type minor -t node -t browser",
|
"release-minor": "aegir release --type minor -t node -t browser",
|
||||||
@ -66,23 +65,23 @@
|
|||||||
"homepage": "https://libp2p.io",
|
"homepage": "https://libp2p.io",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=15.0.0"
|
"node": ">=14.0.0"
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"nat-api": false
|
"@motrix/nat-api": false
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
"extends": "ipfs",
|
"extends": "ipfs",
|
||||||
"ignorePatterns": [
|
"ignorePatterns": [
|
||||||
"!.aegir.js",
|
"!.aegir.js",
|
||||||
"test/ts-use",
|
"test/ts-use"
|
||||||
"*.d.ts"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"abortable-iterator": "^3.0.0",
|
||||||
|
"@motrix/nat-api": "^0.3.1",
|
||||||
"@vascosantos/moving-average": "^1.1.0",
|
"@vascosantos/moving-average": "^1.1.0",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^3.0.0",
|
||||||
"abortable-iterator": "^3.0.0",
|
|
||||||
"aggregate-error": "^3.1.0",
|
"aggregate-error": "^3.1.0",
|
||||||
"any-signal": "^2.1.1",
|
"any-signal": "^2.1.1",
|
||||||
"bignumber.js": "^9.0.1",
|
"bignumber.js": "^9.0.1",
|
||||||
@ -104,8 +103,8 @@
|
|||||||
"it-merge": "^1.0.0",
|
"it-merge": "^1.0.0",
|
||||||
"it-pipe": "^1.1.0",
|
"it-pipe": "^1.1.0",
|
||||||
"it-take": "^1.0.0",
|
"it-take": "^1.0.0",
|
||||||
"libp2p-crypto": "^0.21.0",
|
"libp2p-crypto": "^0.19.4",
|
||||||
"libp2p-interfaces": "^2.0.1",
|
"libp2p-interfaces": "^1.0.0",
|
||||||
"libp2p-utils": "^0.4.0",
|
"libp2p-utils": "^0.4.0",
|
||||||
"mafmt": "^10.0.0",
|
"mafmt": "^10.0.0",
|
||||||
"merge-options": "^3.0.4",
|
"merge-options": "^3.0.4",
|
||||||
@ -113,61 +112,60 @@
|
|||||||
"multiformats": "^9.0.0",
|
"multiformats": "^9.0.0",
|
||||||
"multistream-select": "^2.0.0",
|
"multistream-select": "^2.0.0",
|
||||||
"mutable-proxy": "^1.0.0",
|
"mutable-proxy": "^1.0.0",
|
||||||
"nat-api": "^0.3.1",
|
|
||||||
"node-forge": "^0.10.0",
|
"node-forge": "^0.10.0",
|
||||||
"p-any": "^3.0.0",
|
"p-any": "^3.0.0",
|
||||||
"p-fifo": "^1.0.0",
|
"p-fifo": "^1.0.0",
|
||||||
"p-retry": "^4.4.0",
|
"p-retry": "^4.4.0",
|
||||||
"p-settle": "^4.1.1",
|
"p-settle": "^4.1.1",
|
||||||
"peer-id": "^0.16.0",
|
"peer-id": "^0.15.0",
|
||||||
"private-ip": "^2.1.0",
|
"private-ip": "^2.1.0",
|
||||||
"protobufjs": "^6.10.2",
|
"protobufjs": "^6.10.2",
|
||||||
"retimer": "^3.0.0",
|
"retimer": "^3.0.0",
|
||||||
"sanitize-filename": "^1.6.3",
|
"sanitize-filename": "^1.6.3",
|
||||||
"set-delayed-interval": "^1.0.0",
|
"set-delayed-interval": "^1.0.0",
|
||||||
"streaming-iterables": "^6.0.0",
|
"streaming-iterables": "^6.0.0",
|
||||||
"timeout-abort-controller": "^2.0.0",
|
"timeout-abort-controller": "^1.1.1",
|
||||||
"uint8arrays": "^3.0.0",
|
"uint8arrays": "^3.0.0",
|
||||||
"varint": "^6.0.0",
|
"varint": "^6.0.0",
|
||||||
"wherearewe": "^1.0.0",
|
"wherearewe": "^1.0.0",
|
||||||
"xsalsa20": "^1.1.0"
|
"xsalsa20": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@chainsafe/libp2p-noise": "^5.0.0",
|
"@chainsafe/libp2p-noise": "^4.0.0",
|
||||||
"@nodeutils/defaults-deep": "^1.1.0",
|
"@nodeutils/defaults-deep": "^1.1.0",
|
||||||
"@types/es6-promisify": "^6.0.0",
|
"@types/es6-promisify": "^6.0.0",
|
||||||
"@types/node": "^16.0.1",
|
"@types/node": "^16.0.1",
|
||||||
"@types/node-forge": "^0.10.1",
|
"@types/node-forge": "^0.10.1",
|
||||||
"@types/varint": "^6.0.0",
|
"@types/varint": "^6.0.0",
|
||||||
"aegir": "^36.0.0",
|
"aegir": "^33.1.1",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"datastore-core": "^6.0.7",
|
"datastore-core": "^6.0.7",
|
||||||
"delay": "^5.0.0",
|
"delay": "^5.0.0",
|
||||||
"into-stream": "^6.0.0",
|
"interop-libp2p": "^0.4.0",
|
||||||
"ipfs-http-client": "^54.0.2",
|
"into-stream": "^7.0.0",
|
||||||
|
"ipfs-http-client": "^52.0.2",
|
||||||
"it-concat": "^2.0.0",
|
"it-concat": "^2.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.14.0",
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
"libp2p-delegated-content-routing": "^0.11.0",
|
"libp2p-delegated-content-routing": "^0.11.0",
|
||||||
"libp2p-delegated-peer-routing": "^0.11.1",
|
"libp2p-delegated-peer-routing": "^0.10.0",
|
||||||
"libp2p-floodsub": "^0.27.0",
|
"libp2p-floodsub": "^0.27.0",
|
||||||
"libp2p-gossipsub": "^0.12.1",
|
"libp2p-gossipsub": "^0.11.0",
|
||||||
"libp2p-interfaces-compliance-tests": "^2.0.1",
|
"libp2p-interfaces-compliance-tests": "^1.0.0",
|
||||||
"libp2p-interop": "^0.5.0",
|
"libp2p-kad-dht": "^0.24.2",
|
||||||
"libp2p-kad-dht": "^0.27.1",
|
"libp2p-mdns": "^0.17.0",
|
||||||
"libp2p-mdns": "^0.18.0",
|
|
||||||
"libp2p-mplex": "^0.10.1",
|
"libp2p-mplex": "^0.10.1",
|
||||||
"libp2p-tcp": "^0.17.0",
|
"libp2p-tcp": "^0.17.0",
|
||||||
"libp2p-webrtc-star": "^0.25.0",
|
"libp2p-webrtc-star": "^0.23.0",
|
||||||
"libp2p-websockets": "^0.16.0",
|
"libp2p-websockets": "^0.16.0",
|
||||||
"nock": "^13.0.3",
|
"nock": "^13.0.3",
|
||||||
"p-defer": "^3.0.0",
|
"p-defer": "^3.0.0",
|
||||||
"p-times": "^3.0.0",
|
"p-times": "^3.0.0",
|
||||||
"p-wait-for": "^3.2.0",
|
"p-wait-for": "^3.2.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sinon": "^12.0.1",
|
"sinon": "^11.1.1",
|
||||||
"util": "^0.12.3"
|
"util": "^0.12.3"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
@ -181,28 +179,28 @@
|
|||||||
"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>",
|
||||||
"dirkmc <dirkmdev@gmail.com>",
|
|
||||||
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
||||||
|
"dirkmc <dirkmdev@gmail.com>",
|
||||||
"Volker Mische <volker.mische@gmail.com>",
|
"Volker Mische <volker.mische@gmail.com>",
|
||||||
"Robert Kiel <robert.kiel@hoprnet.org>",
|
|
||||||
"Richard Littauer <richard.littauer@gmail.com>",
|
|
||||||
"zeim839 <50573884+zeim839@users.noreply.github.com>",
|
"zeim839 <50573884+zeim839@users.noreply.github.com>",
|
||||||
|
"Richard Littauer <richard.littauer@gmail.com>",
|
||||||
"a1300 <matthias-knopp@gmx.net>",
|
"a1300 <matthias-knopp@gmx.net>",
|
||||||
"Ryan Bell <ryan@piing.net>",
|
"Ryan Bell <ryan@piing.net>",
|
||||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
|
||||||
"Franck Royer <franck@royer.one>",
|
"Franck Royer <franck@royer.one>",
|
||||||
"Thomas Eizinger <thomas@eizinger.io>",
|
"Thomas Eizinger <thomas@eizinger.io>",
|
||||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||||
"acolytec3 <17355484+acolytec3@users.noreply.github.com>",
|
"acolytec3 <17355484+acolytec3@users.noreply.github.com>",
|
||||||
"Alan Smithee <ggnore.alan.smithee@gmail.com>",
|
|
||||||
"Elven <mon.samuel@qq.com>",
|
"Elven <mon.samuel@qq.com>",
|
||||||
|
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||||
"Samlior <samlior@foxmail.com>",
|
"Samlior <samlior@foxmail.com>",
|
||||||
"Didrik Nordström <didrik.nordstrom@gmail.com>",
|
"Didrik Nordström <didrik.nordstrom@gmail.com>",
|
||||||
|
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||||
|
"Robert Kiel <robert.kiel@hoprnet.org>",
|
||||||
|
"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>",
|
||||||
"TJKoury <TJKoury@gmail.com>",
|
"TJKoury <TJKoury@gmail.com>",
|
||||||
"TheStarBoys <41286328+TheStarBoys@users.noreply.github.com>",
|
|
||||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||||
"XiaoZhang <zxinmyth@gmail.com>",
|
"XiaoZhang <zxinmyth@gmail.com>",
|
||||||
"Yusef Napora <yusef@napora.org>",
|
"Yusef Napora <yusef@napora.org>",
|
||||||
@ -212,7 +210,6 @@
|
|||||||
"isan_rivkin <isanrivkin@gmail.com>",
|
"isan_rivkin <isanrivkin@gmail.com>",
|
||||||
"mayerwin <mayerwin@users.noreply.github.com>",
|
"mayerwin <mayerwin@users.noreply.github.com>",
|
||||||
"mcclure <andi.m.mcclure@gmail.com>",
|
"mcclure <andi.m.mcclure@gmail.com>",
|
||||||
"patrickwoodhead <91056047+patrickwoodhead@users.noreply.github.com>",
|
|
||||||
"phillmac <phillmac@users.noreply.github.com>",
|
"phillmac <phillmac@users.noreply.github.com>",
|
||||||
"robertkiel <robert.kiel@validitylabs.org>",
|
"robertkiel <robert.kiel@validitylabs.org>",
|
||||||
"shresthagrawal <34920931+shresthagrawal@users.noreply.github.com>",
|
"shresthagrawal <34920931+shresthagrawal@users.noreply.github.com>",
|
||||||
@ -242,12 +239,9 @@
|
|||||||
"Lars Gierth <lgierth@users.noreply.github.com>",
|
"Lars Gierth <lgierth@users.noreply.github.com>",
|
||||||
"Leask Wong <i@leaskh.com>",
|
"Leask Wong <i@leaskh.com>",
|
||||||
"Marcin Tojek <mtojek@users.noreply.github.com>",
|
"Marcin Tojek <mtojek@users.noreply.github.com>",
|
||||||
"Marston Connell <34043723+TheMarstonConnell@users.noreply.github.com>",
|
|
||||||
"Michael Burns <5170+mburns@users.noreply.github.com>",
|
"Michael Burns <5170+mburns@users.noreply.github.com>",
|
||||||
"Miguel Mota <miguelmota2@gmail.com>",
|
"Miguel Mota <miguelmota2@gmail.com>",
|
||||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||||
"Philipp Muens <raute1337@gmx.de>",
|
"Philipp Muens <raute1337@gmx.de>"
|
||||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
|
||||||
"Smite Chow <xiaopengyou@live.com>"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ class AutoRelay {
|
|||||||
this._peerStore.metadataBook.set(peerId, HOP_METADATA_KEY, uint8ArrayFromString(HOP_METADATA_VALUE))
|
this._peerStore.metadataBook.set(peerId, HOP_METADATA_KEY, uint8ArrayFromString(HOP_METADATA_VALUE))
|
||||||
await this._addListenRelay(connection, id)
|
await this._addListenRelay(connection, id)
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
this._onError(err)
|
this._onError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ class AutoRelay {
|
|||||||
try {
|
try {
|
||||||
await this._transportManager.listen([new Multiaddr(listenAddr)])
|
await this._transportManager.listen([new Multiaddr(listenAddr)])
|
||||||
// Announce multiaddrs will update on listen success by TransportManager event being triggered
|
// Announce multiaddrs will update on listen success by TransportManager event being triggered
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
this._onError(err)
|
this._onError(err)
|
||||||
this._listenRelays.delete(id)
|
this._listenRelays.delete(id)
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ class AutoRelay {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
this._onError(err)
|
this._onError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,7 +279,7 @@ class AutoRelay {
|
|||||||
try {
|
try {
|
||||||
const connection = await this._libp2p.dial(peerId)
|
const connection = await this._libp2p.dial(peerId)
|
||||||
await this._addListenRelay(connection, peerId.toB58String())
|
await this._addListenRelay(connection, peerId.toB58String())
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
this._onError(err, `could not connect and listen on known hop relay ${peerId.toB58String()}`)
|
this._onError(err, `could not connect and listen on known hop relay ${peerId.toB58String()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ async function handleHop ({
|
|||||||
// Validate the HOP request has the required input
|
// Validate the HOP request has the required input
|
||||||
try {
|
try {
|
||||||
validateAddrs(request, streamHandler)
|
validateAddrs(request, streamHandler)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return log.error('invalid hop request via peer %s', connection.remotePeer.toB58String(), err)
|
return log.error('invalid hop request via peer %s', connection.remotePeer.toB58String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ async function handleHop ({
|
|||||||
connection: destinationConnection,
|
connection: destinationConnection,
|
||||||
request: stopRequest
|
request: stopRequest
|
||||||
})
|
})
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return log.error(err)
|
return log.error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ module.exports.handleStop = function handleStop ({
|
|||||||
// Validate the STOP request has the required input
|
// Validate the STOP request has the required input
|
||||||
try {
|
try {
|
||||||
validateAddrs(request, streamHandler)
|
validateAddrs(request, streamHandler)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return log.error('invalid stop request via peer %s', connection.remotePeer.toB58String(), err)
|
return log.error('invalid stop request via peer %s', connection.remotePeer.toB58String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ function validateAddrs (msg, streamHandler) {
|
|||||||
return new Multiaddr(addr)
|
return new Multiaddr(addr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
||||||
? CircuitRelay.Status.HOP_DST_MULTIADDR_INVALID
|
? CircuitRelay.Status.HOP_DST_MULTIADDR_INVALID
|
||||||
: CircuitRelay.Status.STOP_DST_MULTIADDR_INVALID)
|
: CircuitRelay.Status.STOP_DST_MULTIADDR_INVALID)
|
||||||
@ -47,7 +47,7 @@ function validateAddrs (msg, streamHandler) {
|
|||||||
return new Multiaddr(addr)
|
return new Multiaddr(addr)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
||||||
? CircuitRelay.Status.HOP_SRC_MULTIADDR_INVALID
|
? CircuitRelay.Status.HOP_SRC_MULTIADDR_INVALID
|
||||||
: CircuitRelay.Status.STOP_SRC_MULTIADDR_INVALID)
|
: CircuitRelay.Status.STOP_SRC_MULTIADDR_INVALID)
|
||||||
|
@ -4,7 +4,7 @@ const debug = require('debug')
|
|||||||
const log = Object.assign(debug('libp2p:relay'), {
|
const log = Object.assign(debug('libp2p:relay'), {
|
||||||
error: debug('libp2p:relay:err')
|
error: debug('libp2p:relay:err')
|
||||||
})
|
})
|
||||||
const { codes } = require('./../errors')
|
|
||||||
const {
|
const {
|
||||||
setDelayedInterval,
|
setDelayedInterval,
|
||||||
clearDelayedInterval
|
clearDelayedInterval
|
||||||
@ -87,8 +87,8 @@ class Relay {
|
|||||||
try {
|
try {
|
||||||
const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS)
|
const cid = await namespaceToCid(RELAY_RENDEZVOUS_NS)
|
||||||
await this._libp2p.contentRouting.provide(cid)
|
await this._libp2p.contentRouting.provide(cid)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
if (err.code === codes.ERR_NO_ROUTERS_AVAILABLE) {
|
if (err.code === 'NO_ROUTERS_AVAILABLE') {
|
||||||
log.error('a content router, such as a DHT, must be provided in order to advertise the relay service', err)
|
log.error('a content router, such as a DHT, must be provided in order to advertise the relay service', err)
|
||||||
// Stop the advertise
|
// Stop the advertise
|
||||||
this.stop()
|
this.stop()
|
||||||
|
@ -171,7 +171,7 @@ class Circuit {
|
|||||||
log('new outbound connection %s', maConn.remoteAddr)
|
log('new outbound connection %s', maConn.remoteAddr)
|
||||||
|
|
||||||
return this._upgrader.upgradeOutbound(maConn)
|
return this._upgrader.upgradeOutbound(maConn)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('Circuit relay dial failed', err)
|
log.error('Circuit relay dial failed', err)
|
||||||
disconnectOnFailure && await relayConnection.close()
|
disconnectOnFailure && await relayConnection.close()
|
||||||
throw err
|
throw err
|
||||||
|
@ -60,7 +60,13 @@ const DefaultConfig = {
|
|||||||
protocolPrefix: 'ipfs',
|
protocolPrefix: 'ipfs',
|
||||||
dht: {
|
dht: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
kBucketSize: 20
|
kBucketSize: 20,
|
||||||
|
randomWalk: {
|
||||||
|
enabled: false, // disabled waiting for https://github.com/libp2p/js-libp2p-kad-dht/issues/86
|
||||||
|
queriesPerPeriod: 1,
|
||||||
|
interval: 300e3,
|
||||||
|
timeout: 10e3
|
||||||
|
}
|
||||||
},
|
},
|
||||||
nat: {
|
nat: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const debug = require('debug')
|
|
||||||
const mergeOptions = require('merge-options')
|
|
||||||
// @ts-ignore retimer does not have types
|
|
||||||
const retimer = require('retimer')
|
|
||||||
|
|
||||||
const log = Object.assign(debug('libp2p:connection-manager:auto-dialler'), {
|
|
||||||
error: debug('libp2p:connection-manager:auto-dialler:err')
|
|
||||||
})
|
|
||||||
|
|
||||||
const defaultOptions = {
|
|
||||||
enabled: true,
|
|
||||||
minConnections: 0,
|
|
||||||
autoDialInterval: 10000
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('../index')} Libp2p
|
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {Object} AutoDiallerOptions
|
|
||||||
* @property {boolean} [enabled = true] - Should preemptively guarantee connections are above the low watermark
|
|
||||||
* @property {number} [minConnections = 0] - The minimum number of connections to avoid pruning
|
|
||||||
* @property {number} [autoDialInterval = 10000] - How often, in milliseconds, it should preemptively guarantee connections are above the low watermark
|
|
||||||
*/
|
|
||||||
|
|
||||||
class AutoDialler {
|
|
||||||
/**
|
|
||||||
* Proactively tries to connect to known peers stored in the PeerStore.
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* @class
|
|
||||||
* @param {Libp2p} libp2p
|
|
||||||
* @param {AutoDiallerOptions} options
|
|
||||||
*/
|
|
||||||
constructor (libp2p, options = {}) {
|
|
||||||
this._options = mergeOptions.call({ ignoreUndefined: true }, defaultOptions, options)
|
|
||||||
this._libp2p = libp2p
|
|
||||||
this._running = false
|
|
||||||
this._autoDialTimeout = null
|
|
||||||
this._autoDial = this._autoDial.bind(this)
|
|
||||||
|
|
||||||
log('options: %j', this._options)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the auto dialer
|
|
||||||
*/
|
|
||||||
start () {
|
|
||||||
if (!this._options.enabled) {
|
|
||||||
log('not enabled')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this._running = true
|
|
||||||
this._autoDial()
|
|
||||||
log('started')
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops the auto dialler
|
|
||||||
*/
|
|
||||||
async stop () {
|
|
||||||
if (!this._options.enabled) {
|
|
||||||
log('not enabled')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this._running = false
|
|
||||||
this._autoDialTimeout && this._autoDialTimeout.clear()
|
|
||||||
log('stopped')
|
|
||||||
}
|
|
||||||
|
|
||||||
async _autoDial () {
|
|
||||||
const minConnections = this._options.minConnections
|
|
||||||
|
|
||||||
// Already has enough connections
|
|
||||||
if (this._libp2p.connections.size >= minConnections) {
|
|
||||||
this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort peers on wether we know protocols of public keys for them
|
|
||||||
const peers = Array.from(this._libp2p.peerStore.peers.values())
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (b.protocols && b.protocols.length && (!a.protocols || !a.protocols.length)) {
|
|
||||||
return 1
|
|
||||||
} else if (b.id.pubKey && !a.id.pubKey) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
})
|
|
||||||
|
|
||||||
for (let i = 0; this._running && i < peers.length && this._libp2p.connections.size < minConnections; i++) {
|
|
||||||
if (!this._libp2p.connectionManager.get(peers[i].id)) {
|
|
||||||
log('connecting to a peerStore stored peer %s', peers[i].id.toB58String())
|
|
||||||
try {
|
|
||||||
await this._libp2p.dialer.connectToPeer(peers[i].id)
|
|
||||||
} catch (/** @type {any} */ err) {
|
|
||||||
log.error('could not connect to peerStore stored peer', err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connection Manager was stopped
|
|
||||||
if (!this._running) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = AutoDialler
|
|
@ -32,10 +32,6 @@ const defaultOptions = {
|
|||||||
defaultPeerValue: 1
|
defaultPeerValue: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const METRICS_COMPONENT = 'connection-manager'
|
|
||||||
const METRICS_PEER_CONNECTIONS = 'peer-connections'
|
|
||||||
const METRICS_ALL_CONNECTIONS = 'all-connections'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../')} Libp2p
|
* @typedef {import('../')} Libp2p
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
@ -98,7 +94,9 @@ class ConnectionManager extends EventEmitter {
|
|||||||
|
|
||||||
this._started = false
|
this._started = false
|
||||||
this._timer = null
|
this._timer = null
|
||||||
|
this._autoDialTimeout = null
|
||||||
this._checkMetrics = this._checkMetrics.bind(this)
|
this._checkMetrics = this._checkMetrics.bind(this)
|
||||||
|
this._autoDial = this._autoDial.bind(this)
|
||||||
|
|
||||||
this._latencyMonitor = new LatencyMonitor({
|
this._latencyMonitor = new LatencyMonitor({
|
||||||
latencyCheckIntervalMs: this._options.pollInterval,
|
latencyCheckIntervalMs: this._options.pollInterval,
|
||||||
@ -130,6 +128,8 @@ class ConnectionManager extends EventEmitter {
|
|||||||
|
|
||||||
this._started = true
|
this._started = true
|
||||||
log('started')
|
log('started')
|
||||||
|
|
||||||
|
this._options.autoDial && this._autoDial()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,6 +138,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
* @async
|
* @async
|
||||||
*/
|
*/
|
||||||
async stop () {
|
async stop () {
|
||||||
|
this._autoDialTimeout && this._autoDialTimeout.clear()
|
||||||
this._timer && this._timer.clear()
|
this._timer && this._timer.clear()
|
||||||
|
|
||||||
this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
||||||
@ -164,8 +165,6 @@ class ConnectionManager extends EventEmitter {
|
|||||||
|
|
||||||
await Promise.all(tasks)
|
await Promise.all(tasks)
|
||||||
this.connections.clear()
|
this.connections.clear()
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PEER_CONNECTIONS, 0)
|
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_ALL_CONNECTIONS, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,13 +216,10 @@ class ConnectionManager extends EventEmitter {
|
|||||||
const storedConn = this.connections.get(peerIdStr)
|
const storedConn = this.connections.get(peerIdStr)
|
||||||
|
|
||||||
this.emit('peer:connect', connection)
|
this.emit('peer:connect', connection)
|
||||||
|
|
||||||
if (storedConn) {
|
if (storedConn) {
|
||||||
storedConn.push(connection)
|
storedConn.push(connection)
|
||||||
} else {
|
} else {
|
||||||
this.connections.set(peerIdStr, [connection])
|
this.connections.set(peerIdStr, [connection])
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PEER_CONNECTIONS, this.connections.size)
|
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_ALL_CONNECTIONS, this.size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._libp2p.peerStore.keyBook.set(peerId, peerId.pubKey)
|
this._libp2p.peerStore.keyBook.set(peerId, peerId.pubKey)
|
||||||
@ -252,12 +248,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
this.connections.delete(peerId)
|
this.connections.delete(peerId)
|
||||||
this._peerValues.delete(connection.remotePeer.toB58String())
|
this._peerValues.delete(connection.remotePeer.toB58String())
|
||||||
this.emit('peer:disconnect', connection)
|
this.emit('peer:disconnect', connection)
|
||||||
|
|
||||||
this._libp2p.metrics && this._libp2p.metrics.onPeerDisconnected(connection.remotePeer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PEER_CONNECTIONS, this.connections.size)
|
|
||||||
this._libp2p.metrics && this._libp2p.metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_ALL_CONNECTIONS, this.size)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -321,6 +312,53 @@ class ConnectionManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proactively tries to connect to known peers stored in the PeerStore.
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @async
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
async _autoDial () {
|
||||||
|
const minConnections = this._options.minConnections
|
||||||
|
|
||||||
|
// Already has enough connections
|
||||||
|
if (this.size >= minConnections) {
|
||||||
|
this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort peers on wether we know protocols of public keys for them
|
||||||
|
const peers = Array.from(this._libp2p.peerStore.peers.values())
|
||||||
|
.sort((a, b) => {
|
||||||
|
if (b.protocols && b.protocols.length && (!a.protocols || !a.protocols.length)) {
|
||||||
|
return 1
|
||||||
|
} else if (b.id.pubKey && !a.id.pubKey) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
})
|
||||||
|
|
||||||
|
for (let i = 0; i < peers.length && this.size < minConnections; i++) {
|
||||||
|
if (!this.get(peers[i].id)) {
|
||||||
|
log('connecting to a peerStore stored peer %s', peers[i].id.toB58String())
|
||||||
|
try {
|
||||||
|
await this._libp2p.dialer.connectToPeer(peers[i].id)
|
||||||
|
|
||||||
|
// Connection Manager was stopped
|
||||||
|
if (!this._started) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
log.error('could not connect to peerStore stored peer', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._autoDialTimeout = retimer(this._autoDial, this._options.autoDialInterval)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
@ -8,10 +8,9 @@ const {
|
|||||||
requirePeers,
|
requirePeers,
|
||||||
maybeLimitSource
|
maybeLimitSource
|
||||||
} = require('./utils')
|
} = require('./utils')
|
||||||
const drain = require('it-drain')
|
|
||||||
const merge = require('it-merge')
|
const merge = require('it-merge')
|
||||||
const { pipe } = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const { DHTContentRouting } = require('../dht/dht-content-routing')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
@ -39,7 +38,7 @@ class ContentRouting {
|
|||||||
|
|
||||||
// If we have the dht, add it to the available content routers
|
// If we have the dht, add it to the available content routers
|
||||||
if (this.dht && libp2p._config.dht.enabled) {
|
if (this.dht && libp2p._config.dht.enabled) {
|
||||||
this.routers.push(new DHTContentRouting(this.dht))
|
this.routers.push(this.dht)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ class ContentRouting {
|
|||||||
*/
|
*/
|
||||||
async * findProviders (key, options = {}) {
|
async * findProviders (key, options = {}) {
|
||||||
if (!this.routers.length) {
|
if (!this.routers.length) {
|
||||||
throw errCode(new Error('No content this.routers available'), codes.ERR_NO_ROUTERS_AVAILABLE)
|
throw errCode(new Error('No content this.routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
yield * pipe(
|
yield * pipe(
|
||||||
@ -77,7 +76,7 @@ class ContentRouting {
|
|||||||
*/
|
*/
|
||||||
async provide (key) {
|
async provide (key) {
|
||||||
if (!this.routers.length) {
|
if (!this.routers.length) {
|
||||||
throw errCode(new Error('No content routers available'), codes.ERR_NO_ROUTERS_AVAILABLE)
|
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(this.routers.map((router) => router.provide(key)))
|
await Promise.all(this.routers.map((router) => router.provide(key)))
|
||||||
@ -92,12 +91,12 @@ class ContentRouting {
|
|||||||
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async put (key, value, options) {
|
put (key, value, options) {
|
||||||
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
await drain(this.dht.put(key, value, options))
|
return this.dht.put(key, value, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -109,18 +108,12 @@ class ContentRouting {
|
|||||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||||
* @returns {Promise<GetData>}
|
* @returns {Promise<GetData>}
|
||||||
*/
|
*/
|
||||||
async get (key, options) {
|
get (key, options) {
|
||||||
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
for await (const event of this.dht.get(key, options)) {
|
return this.dht.get(key, options)
|
||||||
if (event.name === 'VALUE') {
|
|
||||||
return { from: event.peerId, val: event.value }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw errCode(new Error(messages.NOT_FOUND), codes.ERR_NOT_FOUND)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -130,33 +123,14 @@ class ContentRouting {
|
|||||||
* @param {number} nVals
|
* @param {number} nVals
|
||||||
* @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)
|
||||||
|
* @returns {Promise<GetData[]>}
|
||||||
*/
|
*/
|
||||||
async * getMany (key, nVals, options) { // eslint-disable-line require-await
|
async getMany (key, nVals, options) { // eslint-disable-line require-await
|
||||||
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nVals) {
|
return this.dht.getMany(key, nVals, options)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let gotValues = 0
|
|
||||||
|
|
||||||
for await (const event of this.dht.get(key, options)) {
|
|
||||||
if (event.name === 'VALUE') {
|
|
||||||
yield { from: event.peerId, val: event.value }
|
|
||||||
|
|
||||||
gotValues++
|
|
||||||
|
|
||||||
if (gotValues === nVals) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gotValues === 0) {
|
|
||||||
throw errCode(new Error(messages.NOT_FOUND), codes.ERR_NOT_FOUND)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const drain = require('it-drain')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('peer-id')} PeerId
|
|
||||||
* @typedef {import('libp2p-interfaces/src/content-routing/types').ContentRouting} ContentRoutingModule
|
|
||||||
* @typedef {import('multiformats/cid').CID} CID
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper class to convert events into returned values
|
|
||||||
*
|
|
||||||
* @implements {ContentRoutingModule}
|
|
||||||
*/
|
|
||||||
class DHTContentRouting {
|
|
||||||
/**
|
|
||||||
* @param {import('libp2p-kad-dht').DHT} dht
|
|
||||||
*/
|
|
||||||
constructor (dht) {
|
|
||||||
this._dht = dht
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {CID} cid
|
|
||||||
*/
|
|
||||||
async provide (cid) {
|
|
||||||
await drain(this._dht.provide(cid))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {CID} cid
|
|
||||||
* @param {*} options
|
|
||||||
*/
|
|
||||||
async * findProviders (cid, options) {
|
|
||||||
for await (const event of this._dht.findProviders(cid, options)) {
|
|
||||||
if (event.name === 'PROVIDER') {
|
|
||||||
yield * event.providers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { DHTContentRouting }
|
|
@ -1,55 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const errCode = require('err-code')
|
|
||||||
const { messages, codes } = require('../errors')
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('peer-id')} PeerId
|
|
||||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types').PeerRouting} PeerRoutingModule
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrapper class to convert events into returned values
|
|
||||||
*
|
|
||||||
* @implements {PeerRoutingModule}
|
|
||||||
*/
|
|
||||||
class DHTPeerRouting {
|
|
||||||
/**
|
|
||||||
* @param {import('libp2p-kad-dht').DHT} dht
|
|
||||||
*/
|
|
||||||
constructor (dht) {
|
|
||||||
this._dht = dht
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {PeerId} peerId
|
|
||||||
* @param {any} options
|
|
||||||
*/
|
|
||||||
async findPeer (peerId, options = {}) {
|
|
||||||
for await (const event of this._dht.findPeer(peerId, options)) {
|
|
||||||
if (event.name === 'PEER_RESPONSE') {
|
|
||||||
const peer = event.closer.find(peerData => peerData.id.equals(peerId))
|
|
||||||
|
|
||||||
if (peer) {
|
|
||||||
return peer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw errCode(new Error(messages.NOT_FOUND), codes.ERR_NOT_FOUND)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Uint8Array} key
|
|
||||||
* @param {any} options
|
|
||||||
*/
|
|
||||||
async * getClosestPeers (key, options = {}) {
|
|
||||||
for await (const event of this._dht.getClosestPeers(key, options)) {
|
|
||||||
if (event.name === 'PEER_RESPONSE') {
|
|
||||||
yield * event.closer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { DHTPeerRouting }
|
|
@ -1,13 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
|
const AbortController = require('abort-controller').default
|
||||||
const { anySignal } = require('any-signal')
|
const { anySignal } = require('any-signal')
|
||||||
// @ts-ignore p-fifo does not export types
|
// @ts-ignore p-fifo does not export types
|
||||||
const FIFO = require('p-fifo')
|
const FIFO = require('p-fifo')
|
||||||
const pAny = require('p-any')
|
const pAny = require('p-any')
|
||||||
// @ts-expect-error setMaxListeners is missing from the types
|
|
||||||
const { setMaxListeners } = require('events')
|
|
||||||
const { codes } = require('../errors')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
@ -56,17 +54,12 @@ class DialRequest {
|
|||||||
const tokens = this.dialer.getTokens(this.addrs.length)
|
const tokens = this.dialer.getTokens(this.addrs.length)
|
||||||
// If no tokens are available, throw
|
// If no tokens are available, throw
|
||||||
if (tokens.length < 1) {
|
if (tokens.length < 1) {
|
||||||
throw errCode(new Error('No dial tokens available'), codes.ERR_NO_DIAL_TOKENS)
|
throw errCode(new Error('No dial tokens available'), 'ERR_NO_DIAL_TOKENS')
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenHolder = new FIFO()
|
const tokenHolder = new FIFO()
|
||||||
tokens.forEach(token => tokenHolder.push(token))
|
tokens.forEach(token => tokenHolder.push(token))
|
||||||
const dialAbortControllers = this.addrs.map(() => {
|
const dialAbortControllers = this.addrs.map(() => new AbortController())
|
||||||
const controller = new AbortController()
|
|
||||||
setMaxListeners && setMaxListeners(Infinity, controller.signal)
|
|
||||||
|
|
||||||
return controller
|
|
||||||
})
|
|
||||||
let completedDials = 0
|
let completedDials = 0
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -6,7 +6,8 @@ const log = Object.assign(debug('libp2p:dialer'), {
|
|||||||
})
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const { Multiaddr } = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const { TimeoutController } = require('timeout-abort-controller')
|
// @ts-ignore timeout-abourt-controles does not export types
|
||||||
|
const TimeoutController = require('timeout-abort-controller')
|
||||||
const { AbortError } = require('abortable-iterator')
|
const { AbortError } = require('abortable-iterator')
|
||||||
const { anySignal } = require('any-signal')
|
const { anySignal } = require('any-signal')
|
||||||
|
|
||||||
@ -22,10 +23,6 @@ const {
|
|||||||
MAX_ADDRS_TO_DIAL
|
MAX_ADDRS_TO_DIAL
|
||||||
} = require('../constants')
|
} = require('../constants')
|
||||||
|
|
||||||
const METRICS_COMPONENT = 'dialler'
|
|
||||||
const METRICS_PENDING_DIALS = 'pending-dials'
|
|
||||||
const METRICS_PENDING_DIAL_TARGETS = 'pending-dials-targers'
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
@ -48,7 +45,6 @@ const METRICS_PENDING_DIAL_TARGETS = 'pending-dials-targers'
|
|||||||
* @property {number} [maxDialsPerPeer = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
|
* @property {number} [maxDialsPerPeer = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
|
||||||
* @property {number} [dialTimeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
|
* @property {number} [dialTimeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
|
||||||
* @property {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
|
* @property {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
|
||||||
* @property {import('../metrics')} [metrics]
|
|
||||||
*
|
*
|
||||||
* @typedef DialTarget
|
* @typedef DialTarget
|
||||||
* @property {string} id
|
* @property {string} id
|
||||||
@ -74,8 +70,7 @@ class Dialer {
|
|||||||
maxAddrsToDial = MAX_ADDRS_TO_DIAL,
|
maxAddrsToDial = MAX_ADDRS_TO_DIAL,
|
||||||
dialTimeout = DIAL_TIMEOUT,
|
dialTimeout = DIAL_TIMEOUT,
|
||||||
maxDialsPerPeer = MAX_PER_PEER_DIALS,
|
maxDialsPerPeer = MAX_PER_PEER_DIALS,
|
||||||
resolvers = {},
|
resolvers = {}
|
||||||
metrics
|
|
||||||
}) {
|
}) {
|
||||||
this.transportManager = transportManager
|
this.transportManager = transportManager
|
||||||
this.peerStore = peerStore
|
this.peerStore = peerStore
|
||||||
@ -87,7 +82,6 @@ class Dialer {
|
|||||||
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
|
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
|
||||||
this._pendingDials = new Map()
|
this._pendingDials = new Map()
|
||||||
this._pendingDialTargets = new Map()
|
this._pendingDialTargets = new Map()
|
||||||
this._metrics = metrics
|
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(resolvers)) {
|
for (const [key, value] of Object.entries(resolvers)) {
|
||||||
Multiaddr.resolvers.set(key, value)
|
Multiaddr.resolvers.set(key, value)
|
||||||
@ -101,7 +95,7 @@ class Dialer {
|
|||||||
for (const dial of this._pendingDials.values()) {
|
for (const dial of this._pendingDials.values()) {
|
||||||
try {
|
try {
|
||||||
dial.controller.abort()
|
dial.controller.abort()
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,9 +105,6 @@ class Dialer {
|
|||||||
pendingTarget.reject(new AbortError('Dialer was destroyed'))
|
pendingTarget.reject(new AbortError('Dialer was destroyed'))
|
||||||
}
|
}
|
||||||
this._pendingDialTargets.clear()
|
this._pendingDialTargets.clear()
|
||||||
|
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIALS, 0)
|
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIAL_TARGETS, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -138,7 +129,7 @@ class Dialer {
|
|||||||
const connection = await pendingDial.promise
|
const connection = await pendingDial.promise
|
||||||
log('dial succeeded to %s', dialTarget.id)
|
log('dial succeeded to %s', dialTarget.id)
|
||||||
return connection
|
return connection
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
// Error is a timeout
|
// Error is a timeout
|
||||||
if (pendingDial.controller.signal.aborted) {
|
if (pendingDial.controller.signal.aborted) {
|
||||||
err.code = codes.ERR_TIMEOUT
|
err.code = codes.ERR_TIMEOUT
|
||||||
@ -163,20 +154,16 @@ class Dialer {
|
|||||||
const id = `${(parseInt(String(Math.random() * 1e9), 10)).toString() + Date.now()}`
|
const id = `${(parseInt(String(Math.random() * 1e9), 10)).toString() + Date.now()}`
|
||||||
const cancellablePromise = new Promise((resolve, reject) => {
|
const cancellablePromise = new Promise((resolve, reject) => {
|
||||||
this._pendingDialTargets.set(id, { resolve, reject })
|
this._pendingDialTargets.set(id, { resolve, reject })
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIAL_TARGETS, this._pendingDialTargets.size)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
try {
|
const dialTarget = await Promise.race([
|
||||||
const dialTarget = await Promise.race([
|
this._createDialTarget(peer),
|
||||||
this._createDialTarget(peer),
|
cancellablePromise
|
||||||
cancellablePromise
|
])
|
||||||
])
|
|
||||||
|
|
||||||
return dialTarget
|
this._pendingDialTargets.delete(id)
|
||||||
} finally {
|
|
||||||
this._pendingDialTargets.delete(id)
|
return dialTarget
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIAL_TARGETS, this._pendingDialTargets.size)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -264,13 +251,9 @@ class Dialer {
|
|||||||
destroy: () => {
|
destroy: () => {
|
||||||
timeoutController.clear()
|
timeoutController.clear()
|
||||||
this._pendingDials.delete(dialTarget.id)
|
this._pendingDials.delete(dialTarget.id)
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIALS, this._pendingDials.size)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._pendingDials.set(dialTarget.id, pendingDial)
|
this._pendingDials.set(dialTarget.id, pendingDial)
|
||||||
|
|
||||||
this._metrics && this._metrics.updateComponentMetric(METRICS_COMPONENT, METRICS_PENDING_DIALS, this._pendingDials.size)
|
|
||||||
|
|
||||||
return pendingDial
|
return pendingDial
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
exports.messages = {
|
exports.messages = {
|
||||||
NOT_STARTED_YET: 'The libp2p node is not started yet',
|
NOT_STARTED_YET: 'The libp2p node is not started yet',
|
||||||
DHT_DISABLED: 'DHT is not available',
|
DHT_DISABLED: 'DHT is not available',
|
||||||
CONN_ENCRYPTION_REQUIRED: 'At least one connection encryption module is required',
|
CONN_ENCRYPTION_REQUIRED: 'At least one connection encryption module is required'
|
||||||
NOT_FOUND: 'Not found'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.codes = {
|
exports.codes = {
|
||||||
@ -30,35 +29,10 @@ exports.codes = {
|
|||||||
ERR_INVALID_PARAMETERS: 'ERR_INVALID_PARAMETERS',
|
ERR_INVALID_PARAMETERS: 'ERR_INVALID_PARAMETERS',
|
||||||
ERR_INVALID_PEER: 'ERR_INVALID_PEER',
|
ERR_INVALID_PEER: 'ERR_INVALID_PEER',
|
||||||
ERR_MUXER_UNAVAILABLE: 'ERR_MUXER_UNAVAILABLE',
|
ERR_MUXER_UNAVAILABLE: 'ERR_MUXER_UNAVAILABLE',
|
||||||
ERR_NOT_FOUND: 'ERR_NOT_FOUND',
|
|
||||||
ERR_TIMEOUT: 'ERR_TIMEOUT',
|
ERR_TIMEOUT: 'ERR_TIMEOUT',
|
||||||
ERR_TRANSPORT_UNAVAILABLE: 'ERR_TRANSPORT_UNAVAILABLE',
|
ERR_TRANSPORT_UNAVAILABLE: 'ERR_TRANSPORT_UNAVAILABLE',
|
||||||
ERR_TRANSPORT_DIAL_FAILED: 'ERR_TRANSPORT_DIAL_FAILED',
|
ERR_TRANSPORT_DIAL_FAILED: 'ERR_TRANSPORT_DIAL_FAILED',
|
||||||
ERR_UNSUPPORTED_PROTOCOL: 'ERR_UNSUPPORTED_PROTOCOL',
|
ERR_UNSUPPORTED_PROTOCOL: 'ERR_UNSUPPORTED_PROTOCOL',
|
||||||
ERR_INVALID_MULTIADDR: 'ERR_INVALID_MULTIADDR',
|
ERR_INVALID_MULTIADDR: 'ERR_INVALID_MULTIADDR',
|
||||||
ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID',
|
ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID'
|
||||||
ERR_FIND_SELF: 'ERR_FIND_SELF',
|
|
||||||
ERR_NO_ROUTERS_AVAILABLE: 'ERR_NO_ROUTERS_AVAILABLE',
|
|
||||||
ERR_CONNECTION_NOT_MULTIPLEXED: 'ERR_CONNECTION_NOT_MULTIPLEXED',
|
|
||||||
ERR_NO_DIAL_TOKENS: 'ERR_NO_DIAL_TOKENS',
|
|
||||||
ERR_KEYCHAIN_REQUIRED: 'ERR_KEYCHAIN_REQUIRED',
|
|
||||||
ERR_INVALID_CMS: 'ERR_INVALID_CMS',
|
|
||||||
ERR_MISSING_KEYS: 'ERR_MISSING_KEYS',
|
|
||||||
ERR_NO_KEY: 'ERR_NO_KEY',
|
|
||||||
ERR_INVALID_KEY_NAME: 'ERR_INVALID_KEY_NAME',
|
|
||||||
ERR_INVALID_KEY_TYPE: 'ERR_INVALID_KEY_TYPE',
|
|
||||||
ERR_KEY_ALREADY_EXISTS: 'ERR_KEY_ALREADY_EXISTS',
|
|
||||||
ERR_INVALID_KEY_SIZE: 'ERR_INVALID_KEY_SIZE',
|
|
||||||
ERR_KEY_NOT_FOUND: 'ERR_KEY_NOT_FOUND',
|
|
||||||
ERR_OLD_KEY_NAME_INVALID: 'ERR_OLD_KEY_NAME_INVALID',
|
|
||||||
ERR_NEW_KEY_NAME_INVALID: 'ERR_NEW_KEY_NAME_INVALID',
|
|
||||||
ERR_PASSWORD_REQUIRED: 'ERR_PASSWORD_REQUIRED',
|
|
||||||
ERR_PEM_REQUIRED: 'ERR_PEM_REQUIRED',
|
|
||||||
ERR_CANNOT_READ_KEY: 'ERR_CANNOT_READ_KEY',
|
|
||||||
ERR_MISSING_PRIVATE_KEY: 'ERR_MISSING_PRIVATE_KEY',
|
|
||||||
ERR_INVALID_OLD_PASS_TYPE: 'ERR_INVALID_OLD_PASS_TYPE',
|
|
||||||
ERR_INVALID_NEW_PASS_TYPE: 'ERR_INVALID_NEW_PASS_TYPE',
|
|
||||||
ERR_INVALID_PASS_LENGTH: 'ERR_INVALID_PASS_LENGTH',
|
|
||||||
ERR_NOT_IMPLEMENTED: 'ERR_NOT_IMPLEMENTED',
|
|
||||||
ERR_WRONG_PING_ACK: 'ERR_WRONG_PING_ACK'
|
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ function getPeer (peer) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
peer = PeerId.createFromB58String(idStr)
|
peer = PeerId.createFromB58String(idStr)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(
|
throw errCode(
|
||||||
new Error(`${peer} is not a valid peer type`),
|
new Error(`${peer} is not a valid peer type`),
|
||||||
codes.ERR_INVALID_MULTIADDR
|
codes.ERR_INVALID_MULTIADDR
|
||||||
|
@ -124,7 +124,7 @@ class IdentifyService {
|
|||||||
stream,
|
stream,
|
||||||
consume
|
consume
|
||||||
)
|
)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
// Just log errors
|
// Just log errors
|
||||||
log.error('could not push identify update to peer', err)
|
log.error('could not push identify update to peer', err)
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ class IdentifyService {
|
|||||||
let message
|
let message
|
||||||
try {
|
try {
|
||||||
message = Message.Identify.decode(data)
|
message = Message.Identify.decode(data)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,14 +211,14 @@ class IdentifyService {
|
|||||||
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LEGACY: Update peers data in PeerStore
|
// LEGACY: Update peers data in PeerStore
|
||||||
try {
|
try {
|
||||||
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => new Multiaddr(addr)))
|
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => new Multiaddr(addr)))
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('received invalid addrs', err)
|
log.error('received invalid addrs', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,7 +287,7 @@ class IdentifyService {
|
|||||||
stream,
|
stream,
|
||||||
consume
|
consume
|
||||||
)
|
)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('could not respond to identify request', err)
|
log.error('could not respond to identify request', err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ class IdentifyService {
|
|||||||
collect
|
collect
|
||||||
)
|
)
|
||||||
message = Message.Identify.decode(data)
|
message = Message.Identify.decode(data)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return log.error('received invalid message', err)
|
return log.error('received invalid message', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,7 +325,7 @@ class IdentifyService {
|
|||||||
this.peerStore.protoBook.set(id, message.protocols)
|
this.peerStore.protoBook.set(id, message.protocols)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +333,7 @@ class IdentifyService {
|
|||||||
try {
|
try {
|
||||||
this.peerStore.addressBook.set(id,
|
this.peerStore.addressBook.set(id,
|
||||||
message.listenAddrs.map((addr) => new Multiaddr(addr)))
|
message.listenAddrs.map((addr) => new Multiaddr(addr)))
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('received invalid addrs', err)
|
log.error('received invalid addrs', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
45
src/index.js
45
src/index.js
@ -18,7 +18,6 @@ const { codes, messages } = require('./errors')
|
|||||||
|
|
||||||
const AddressManager = require('./address-manager')
|
const AddressManager = require('./address-manager')
|
||||||
const ConnectionManager = require('./connection-manager')
|
const ConnectionManager = require('./connection-manager')
|
||||||
const AutoDialler = require('./connection-manager/auto-dialler')
|
|
||||||
const Circuit = require('./circuit/transport')
|
const Circuit = require('./circuit/transport')
|
||||||
const Relay = require('./circuit')
|
const Relay = require('./circuit')
|
||||||
const Dialer = require('./dialer')
|
const Dialer = require('./dialer')
|
||||||
@ -56,9 +55,16 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
|||||||
* @property {MuxedStream} stream
|
* @property {MuxedStream} stream
|
||||||
* @property {string} protocol
|
* @property {string} protocol
|
||||||
*
|
*
|
||||||
|
* @typedef {Object} RandomWalkOptions
|
||||||
|
* @property {boolean} [enabled = false]
|
||||||
|
* @property {number} [queriesPerPeriod = 1]
|
||||||
|
* @property {number} [interval = 300e3]
|
||||||
|
* @property {number} [timeout = 10e3]
|
||||||
|
*
|
||||||
* @typedef {Object} DhtOptions
|
* @typedef {Object} DhtOptions
|
||||||
* @property {boolean} [enabled = false]
|
* @property {boolean} [enabled = false]
|
||||||
* @property {number} [kBucketSize = 20]
|
* @property {number} [kBucketSize = 20]
|
||||||
|
* @property {RandomWalkOptions} [randomWalk]
|
||||||
* @property {boolean} [clientMode]
|
* @property {boolean} [clientMode]
|
||||||
* @property {import('libp2p-interfaces/src/types').DhtSelectors} [selectors]
|
* @property {import('libp2p-interfaces/src/types').DhtSelectors} [selectors]
|
||||||
* @property {import('libp2p-interfaces/src/types').DhtValidators} [validators]
|
* @property {import('libp2p-interfaces/src/types').DhtValidators} [validators]
|
||||||
@ -187,21 +193,16 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
// Create the Connection Manager
|
// Create the Connection Manager
|
||||||
this.connectionManager = new ConnectionManager(this, {
|
this.connectionManager = new ConnectionManager(this, {
|
||||||
|
autoDial: this._config.peerDiscovery.autoDial,
|
||||||
...this._options.connectionManager
|
...this._options.connectionManager
|
||||||
})
|
})
|
||||||
this._autodialler = new AutoDialler(this, {
|
|
||||||
enabled: this._config.peerDiscovery.autoDial,
|
|
||||||
minConnections: this._options.connectionManager.minConnections,
|
|
||||||
autoDialInterval: this._options.connectionManager.autoDialInterval
|
|
||||||
})
|
|
||||||
|
|
||||||
// Create Metrics
|
// Create Metrics
|
||||||
if (this._options.metrics.enabled) {
|
if (this._options.metrics.enabled) {
|
||||||
const metrics = new Metrics({
|
this.metrics = new Metrics({
|
||||||
...this._options.metrics
|
...this._options.metrics,
|
||||||
|
connectionManager: this.connectionManager
|
||||||
})
|
})
|
||||||
|
|
||||||
this.metrics = metrics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create keychain
|
// Create keychain
|
||||||
@ -263,7 +264,6 @@ class Libp2p extends EventEmitter {
|
|||||||
this.dialer = new Dialer({
|
this.dialer = new Dialer({
|
||||||
transportManager: this.transportManager,
|
transportManager: this.transportManager,
|
||||||
peerStore: this.peerStore,
|
peerStore: this.peerStore,
|
||||||
metrics: this.metrics,
|
|
||||||
...this._options.dialer
|
...this._options.dialer
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -301,9 +301,14 @@ class Libp2p extends EventEmitter {
|
|||||||
// dht provided components (peerRouting, contentRouting, dht)
|
// dht provided components (peerRouting, contentRouting, dht)
|
||||||
if (this._modules.dht) {
|
if (this._modules.dht) {
|
||||||
const DHT = this._modules.dht
|
const DHT = this._modules.dht
|
||||||
// @ts-ignore TODO: types need fixing - DHT is an `object` which has no `create` method
|
// @ts-ignore Object is not constructable
|
||||||
this._dht = DHT.create({
|
this._dht = new DHT({
|
||||||
libp2p: this,
|
libp2p: this,
|
||||||
|
dialer: this.dialer,
|
||||||
|
peerId: this.peerId,
|
||||||
|
peerStore: this.peerStore,
|
||||||
|
registrar: this.registrar,
|
||||||
|
datastore: this.datastore,
|
||||||
...this._config.dht
|
...this._config.dht
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -358,7 +363,7 @@ class Libp2p extends EventEmitter {
|
|||||||
await this._onStarting()
|
await this._onStarting()
|
||||||
await this._onDidStart()
|
await this._onDidStart()
|
||||||
log('libp2p has started')
|
log('libp2p has started')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
this.emit('error', err)
|
this.emit('error', err)
|
||||||
log.error('An error occurred starting libp2p', err)
|
log.error('An error occurred starting libp2p', err)
|
||||||
await this.stop()
|
await this.stop()
|
||||||
@ -380,8 +385,6 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
this.relay && this.relay.stop()
|
this.relay && this.relay.stop()
|
||||||
this.peerRouting.stop()
|
this.peerRouting.stop()
|
||||||
this._autodialler.stop()
|
|
||||||
await (this._dht && this._dht.stop())
|
|
||||||
|
|
||||||
for (const service of this._discovery.values()) {
|
for (const service of this._discovery.values()) {
|
||||||
service.removeListener('peer', this._onDiscoveryPeer)
|
service.removeListener('peer', this._onDiscoveryPeer)
|
||||||
@ -396,6 +399,7 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.pubsub && this.pubsub.stop(),
|
this.pubsub && this.pubsub.stop(),
|
||||||
|
this._dht && this._dht.stop(),
|
||||||
this.metrics && this.metrics.stop()
|
this.metrics && this.metrics.stop()
|
||||||
])
|
])
|
||||||
|
|
||||||
@ -404,7 +408,7 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
ping.unmount(this)
|
ping.unmount(this)
|
||||||
this.dialer.destroy()
|
this.dialer.destroy()
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
this.emit('error', err)
|
this.emit('error', err)
|
||||||
@ -427,7 +431,7 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await this.keychain.findKeyByName('self')
|
await this.keychain.findKeyByName('self')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
await this.keychain.importPeer('self', this.peerId)
|
await this.keychain.importPeer('self', this.peerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -620,7 +624,7 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
// DHT subsystem
|
// DHT subsystem
|
||||||
if (this._config.dht.enabled) {
|
if (this._config.dht.enabled) {
|
||||||
this._dht && await this._dht.start()
|
this._dht && this._dht.start()
|
||||||
|
|
||||||
// TODO: this should be modified once random-walk is used as
|
// TODO: this should be modified once random-walk is used as
|
||||||
// the other discovery modules
|
// the other discovery modules
|
||||||
@ -651,7 +655,6 @@ class Libp2p extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.connectionManager.start()
|
this.connectionManager.start()
|
||||||
this._autodialler.start()
|
|
||||||
|
|
||||||
// Peer discovery
|
// Peer discovery
|
||||||
await this._setupPeerDiscovery()
|
await this._setupPeerDiscovery()
|
||||||
@ -695,7 +698,7 @@ class Libp2p extends EventEmitter {
|
|||||||
log('connecting to discovered peer %s', peerId.toB58String())
|
log('connecting to discovered peer %s', peerId.toB58String())
|
||||||
try {
|
try {
|
||||||
await this.dialer.connectToPeer(peerId)
|
await this.dialer.connectToPeer(peerId)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(`could not connect to discovered peer ${peerId.toB58String()} with ${err}`)
|
log.error(`could not connect to discovered peer ${peerId.toB58String()} with ${err}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ async function encrypt (localId, conn, remoteId) {
|
|||||||
let peerId
|
let peerId
|
||||||
try {
|
try {
|
||||||
peerId = await PeerId.createFromPubKey(id.pubkey.Data)
|
peerId = await PeerId.createFromPubKey(id.pubkey.Data)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
throw new InvalidCryptoExchangeError('Remote did not provide its public key')
|
throw new InvalidCryptoExchangeError('Remote did not provide its public key')
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ const { certificateForKey, findAsync } = require('./util')
|
|||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
|
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
|
||||||
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
|
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
|
||||||
const { codes } = require('../errors')
|
|
||||||
|
|
||||||
const privates = new WeakMap()
|
const privates = new WeakMap()
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ class CMS {
|
|||||||
*/
|
*/
|
||||||
constructor (keychain, dek) {
|
constructor (keychain, dek) {
|
||||||
if (!keychain) {
|
if (!keychain) {
|
||||||
throw errcode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED)
|
throw errcode(new Error('keychain is required'), 'ERR_KEYCHAIN_REQUIRED')
|
||||||
}
|
}
|
||||||
|
|
||||||
this.keychain = keychain
|
this.keychain = keychain
|
||||||
@ -50,7 +49,7 @@ class CMS {
|
|||||||
*/
|
*/
|
||||||
async encrypt (name, plain) {
|
async encrypt (name, plain) {
|
||||||
if (!(plain instanceof Uint8Array)) {
|
if (!(plain instanceof Uint8Array)) {
|
||||||
throw errcode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('Plain data must be a Uint8Array'), 'ERR_INVALID_PARAMS')
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = await this.keychain.findKeyByName(name)
|
const key = await this.keychain.findKeyByName(name)
|
||||||
@ -82,7 +81,7 @@ class CMS {
|
|||||||
*/
|
*/
|
||||||
async decrypt (cmsData) {
|
async decrypt (cmsData) {
|
||||||
if (!(cmsData instanceof Uint8Array)) {
|
if (!(cmsData instanceof Uint8Array)) {
|
||||||
throw errcode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS')
|
||||||
}
|
}
|
||||||
|
|
||||||
let cms
|
let cms
|
||||||
@ -91,8 +90,8 @@ class CMS {
|
|||||||
const obj = forge.asn1.fromDer(buf)
|
const obj = forge.asn1.fromDer(buf)
|
||||||
// @ts-ignore not defined
|
// @ts-ignore not defined
|
||||||
cms = forge.pkcs7.messageFromAsn1(obj)
|
cms = forge.pkcs7.messageFromAsn1(obj)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errcode(new Error('Invalid CMS: ' + err.message), codes.ERR_INVALID_CMS)
|
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find a recipient whose key we hold. We only deal with recipient certs
|
// Find a recipient whose key we hold. We only deal with recipient certs
|
||||||
@ -115,7 +114,7 @@ class CMS {
|
|||||||
try {
|
try {
|
||||||
const key = await this.keychain.findKeyById(recipient.keyId)
|
const key = await this.keychain.findKeyById(recipient.keyId)
|
||||||
if (key) return true
|
if (key) return true
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@ -124,7 +123,7 @@ class CMS {
|
|||||||
if (!r) {
|
if (!r) {
|
||||||
// @ts-ignore cms types not defined
|
// @ts-ignore cms types not defined
|
||||||
const missingKeys = recipients.map(r => r.keyId)
|
const missingKeys = recipients.map(r => r.keyId)
|
||||||
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), codes.ERR_MISSING_KEYS, {
|
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
|
||||||
missingKeys
|
missingKeys
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -132,7 +131,7 @@ class CMS {
|
|||||||
const key = await this.keychain.findKeyById(r.keyId)
|
const key = await this.keychain.findKeyById(r.keyId)
|
||||||
|
|
||||||
if (!key) {
|
if (!key) {
|
||||||
throw errcode(new Error('No key available to decrypto'), codes.ERR_NO_KEY)
|
throw errcode(new Error('No key available to decrypto'), 'ERR_NO_KEY')
|
||||||
}
|
}
|
||||||
|
|
||||||
const pem = await this.keychain._getPrivateKey(key.name)
|
const pem = await this.keychain._getPrivateKey(key.name)
|
||||||
|
@ -10,7 +10,6 @@ const crypto = require('libp2p-crypto')
|
|||||||
const { Key } = require('interface-datastore/key')
|
const { Key } = require('interface-datastore/key')
|
||||||
const CMS = require('./cms')
|
const CMS = require('./cms')
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const { codes } = require('../errors')
|
|
||||||
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
|
const { toString: uint8ArrayToString } = require('uint8arrays/to-string')
|
||||||
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
|
const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string')
|
||||||
|
|
||||||
@ -211,21 +210,21 @@ class Keychain {
|
|||||||
const self = this
|
const self = this
|
||||||
|
|
||||||
if (!validateKeyName(name) || name === 'self') {
|
if (!validateKeyName(name) || name === 'self') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof type !== 'string') {
|
if (typeof type !== 'string') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), codes.ERR_INVALID_KEY_TYPE))
|
return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), 'ERR_INVALID_KEY_TYPE'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
const exists = await self.store.has(dsname)
|
const exists = await self.store.has(dsname)
|
||||||
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
|
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
switch (type.toLowerCase()) {
|
||||||
case 'rsa':
|
case 'rsa':
|
||||||
if (!Number.isSafeInteger(size) || size < 2048) {
|
if (!Number.isSafeInteger(size) || size < 2048) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), codes.ERR_INVALID_KEY_SIZE))
|
return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), 'ERR_INVALID_KEY_SIZE'))
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
@ -249,7 +248,7 @@ class Keychain {
|
|||||||
batch.put(DsInfoName(name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
batch.put(DsInfoName(name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
||||||
|
|
||||||
await batch.commit()
|
await batch.commit()
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,7 +284,7 @@ class Keychain {
|
|||||||
try {
|
try {
|
||||||
const keys = await this.listKeys()
|
const keys = await this.listKeys()
|
||||||
return keys.find((k) => k.id === id)
|
return keys.find((k) => k.id === id)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -298,15 +297,15 @@ class Keychain {
|
|||||||
*/
|
*/
|
||||||
async findKeyByName (name) {
|
async findKeyByName (name) {
|
||||||
if (!validateKeyName(name)) {
|
if (!validateKeyName(name)) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsname = DsInfoName(name)
|
const dsname = DsInfoName(name)
|
||||||
try {
|
try {
|
||||||
const res = await this.store.get(dsname)
|
const res = await this.store.get(dsname)
|
||||||
return JSON.parse(uint8ArrayToString(res))
|
return JSON.parse(uint8ArrayToString(res))
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
|
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +318,7 @@ class Keychain {
|
|||||||
async removeKey (name) {
|
async removeKey (name) {
|
||||||
const self = this
|
const self = this
|
||||||
if (!validateKeyName(name) || name === 'self') {
|
if (!validateKeyName(name) || name === 'self') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
const keyInfo = await self.findKeyByName(name)
|
const keyInfo = await self.findKeyByName(name)
|
||||||
@ -340,10 +339,10 @@ class Keychain {
|
|||||||
async renameKey (oldName, newName) {
|
async renameKey (oldName, newName) {
|
||||||
const self = this
|
const self = this
|
||||||
if (!validateKeyName(oldName) || oldName === 'self') {
|
if (!validateKeyName(oldName) || oldName === 'self') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), codes.ERR_OLD_KEY_NAME_INVALID))
|
return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), 'ERR_OLD_KEY_NAME_INVALID'))
|
||||||
}
|
}
|
||||||
if (!validateKeyName(newName) || newName === 'self') {
|
if (!validateKeyName(newName) || newName === 'self') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), codes.ERR_NEW_KEY_NAME_INVALID))
|
return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), 'ERR_NEW_KEY_NAME_INVALID'))
|
||||||
}
|
}
|
||||||
const oldDsname = DsName(oldName)
|
const oldDsname = DsName(oldName)
|
||||||
const newDsname = DsName(newName)
|
const newDsname = DsName(newName)
|
||||||
@ -351,7 +350,7 @@ class Keychain {
|
|||||||
const newInfoName = DsInfoName(newName)
|
const newInfoName = DsInfoName(newName)
|
||||||
|
|
||||||
const exists = await self.store.has(newDsname)
|
const exists = await self.store.has(newDsname)
|
||||||
if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
|
if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const pem = await self.store.get(oldDsname)
|
const pem = await self.store.get(oldDsname)
|
||||||
@ -366,7 +365,7 @@ class Keychain {
|
|||||||
batch.delete(oldInfoName)
|
batch.delete(oldInfoName)
|
||||||
await batch.commit()
|
await batch.commit()
|
||||||
return keyInfo
|
return keyInfo
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,10 +379,10 @@ class Keychain {
|
|||||||
*/
|
*/
|
||||||
async exportKey (name, password) {
|
async exportKey (name, password) {
|
||||||
if (!validateKeyName(name)) {
|
if (!validateKeyName(name)) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
if (!password) {
|
if (!password) {
|
||||||
return throwDelayed(errcode(new Error('Password is required'), codes.ERR_PASSWORD_REQUIRED))
|
return throwDelayed(errcode(new Error('Password is required'), 'ERR_PASSWORD_REQUIRED'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
@ -394,7 +393,7 @@ class Keychain {
|
|||||||
const dek = privates.get(this).dek
|
const dek = privates.get(this).dek
|
||||||
const privateKey = await crypto.keys.import(pem, dek)
|
const privateKey = await crypto.keys.import(pem, dek)
|
||||||
return privateKey.export(password)
|
return privateKey.export(password)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,20 +409,20 @@ class Keychain {
|
|||||||
async importKey (name, pem, password) {
|
async importKey (name, pem, password) {
|
||||||
const self = this
|
const self = this
|
||||||
if (!validateKeyName(name) || name === 'self') {
|
if (!validateKeyName(name) || name === 'self') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
if (!pem) {
|
if (!pem) {
|
||||||
return throwDelayed(errcode(new Error('PEM encoded key is required'), codes.ERR_PEM_REQUIRED))
|
return throwDelayed(errcode(new Error('PEM encoded key is required'), 'ERR_PEM_REQUIRED'))
|
||||||
}
|
}
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
const exists = await self.store.has(dsname)
|
const exists = await self.store.has(dsname)
|
||||||
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
|
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
|
||||||
|
|
||||||
let privateKey
|
let privateKey
|
||||||
try {
|
try {
|
||||||
privateKey = await crypto.keys.import(pem, password)
|
privateKey = await crypto.keys.import(pem, password)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), codes.ERR_CANNOT_READ_KEY))
|
return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), 'ERR_CANNOT_READ_KEY'))
|
||||||
}
|
}
|
||||||
|
|
||||||
let kid
|
let kid
|
||||||
@ -432,7 +431,7 @@ class Keychain {
|
|||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const dek = privates.get(this).dek
|
const dek = privates.get(this).dek
|
||||||
pem = await privateKey.export(dek)
|
pem = await privateKey.export(dek)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,16 +457,16 @@ class Keychain {
|
|||||||
async importPeer (name, peer) {
|
async importPeer (name, peer) {
|
||||||
const self = this
|
const self = this
|
||||||
if (!validateKeyName(name)) {
|
if (!validateKeyName(name)) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
if (!peer || !peer.privKey) {
|
if (!peer || !peer.privKey) {
|
||||||
return throwDelayed(errcode(new Error('Peer.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY))
|
return throwDelayed(errcode(new Error('Peer.privKey is required'), 'ERR_MISSING_PRIVATE_KEY'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const privateKey = peer.privKey
|
const privateKey = peer.privKey
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
const exists = await self.store.has(dsname)
|
const exists = await self.store.has(dsname)
|
||||||
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS))
|
if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS'))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const kid = await privateKey.id()
|
const kid = await privateKey.id()
|
||||||
@ -483,7 +482,7 @@ class Keychain {
|
|||||||
batch.put(DsInfoName(name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
batch.put(DsInfoName(name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
||||||
await batch.commit()
|
await batch.commit()
|
||||||
return keyInfo
|
return keyInfo
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(err)
|
return throwDelayed(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -496,15 +495,15 @@ class Keychain {
|
|||||||
*/
|
*/
|
||||||
async _getPrivateKey (name) {
|
async _getPrivateKey (name) {
|
||||||
if (!validateKeyName(name)) {
|
if (!validateKeyName(name)) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME))
|
return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME'))
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const dsname = DsName(name)
|
const dsname = DsName(name)
|
||||||
const res = await this.store.get(dsname)
|
const res = await this.store.get(dsname)
|
||||||
return uint8ArrayToString(res)
|
return uint8ArrayToString(res)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND))
|
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -516,13 +515,13 @@ class Keychain {
|
|||||||
*/
|
*/
|
||||||
async rotateKeychainPass (oldPass, newPass) {
|
async rotateKeychainPass (oldPass, newPass) {
|
||||||
if (typeof oldPass !== 'string') {
|
if (typeof oldPass !== 'string') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), codes.ERR_INVALID_OLD_PASS_TYPE))
|
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE'))
|
||||||
}
|
}
|
||||||
if (typeof newPass !== 'string') {
|
if (typeof newPass !== 'string') {
|
||||||
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), codes.ERR_INVALID_NEW_PASS_TYPE))
|
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE'))
|
||||||
}
|
}
|
||||||
if (newPass.length < 20) {
|
if (newPass.length < 20) {
|
||||||
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), codes.ERR_INVALID_PASS_LENGTH))
|
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH'))
|
||||||
}
|
}
|
||||||
log('recreating keychain')
|
log('recreating keychain')
|
||||||
const oldDek = privates.get(this).dek
|
const oldDek = privates.get(this).dek
|
||||||
|
@ -24,6 +24,9 @@ const directionToEvent = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef MetricsProperties
|
||||||
|
* @property {import('../connection-manager')} connectionManager
|
||||||
|
*
|
||||||
* @typedef MetricsOptions
|
* @typedef MetricsOptions
|
||||||
* @property {number} [computeThrottleMaxQueueSize = defaultOptions.computeThrottleMaxQueueSize]
|
* @property {number} [computeThrottleMaxQueueSize = defaultOptions.computeThrottleMaxQueueSize]
|
||||||
* @property {number} [computeThrottleTimeout = defaultOptions.computeThrottleTimeout]
|
* @property {number} [computeThrottleTimeout = defaultOptions.computeThrottleTimeout]
|
||||||
@ -34,7 +37,7 @@ const directionToEvent = {
|
|||||||
class Metrics {
|
class Metrics {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {MetricsOptions} options
|
* @param {MetricsProperties & MetricsOptions} options
|
||||||
*/
|
*/
|
||||||
constructor (options) {
|
constructor (options) {
|
||||||
this._options = mergeOptions(defaultOptions, options)
|
this._options = mergeOptions(defaultOptions, options)
|
||||||
@ -44,7 +47,10 @@ class Metrics {
|
|||||||
this._oldPeers = oldPeerLRU(this._options.maxOldPeersRetention)
|
this._oldPeers = oldPeerLRU(this._options.maxOldPeersRetention)
|
||||||
this._running = false
|
this._running = false
|
||||||
this._onMessage = this._onMessage.bind(this)
|
this._onMessage = this._onMessage.bind(this)
|
||||||
this._componentMetrics = new Map()
|
this._connectionManager = options.connectionManager
|
||||||
|
this._connectionManager.on('peer:disconnect', (connection) => {
|
||||||
|
this.onPeerDisconnected(connection.remotePeer)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -88,22 +94,6 @@ class Metrics {
|
|||||||
return Array.from(this._peerStats.keys())
|
return Array.from(this._peerStats.keys())
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {Map}
|
|
||||||
*/
|
|
||||||
getComponentMetrics () {
|
|
||||||
return this._componentMetrics
|
|
||||||
}
|
|
||||||
|
|
||||||
updateComponentMetric (component, metric, value) {
|
|
||||||
if (!this._componentMetrics.has(component)) {
|
|
||||||
this._componentMetrics.set(component, new Map())
|
|
||||||
}
|
|
||||||
|
|
||||||
const map = this._componentMetrics.get(component)
|
|
||||||
map.set(metric, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// @ts-ignore nat-api does not export types
|
// @ts-ignore nat-api does not export types
|
||||||
const NatAPI = require('nat-api')
|
const NatAPI = require('@motrix/nat-api')
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const { promisify } = require('es6-promisify')
|
const { promisify } = require('es6-promisify')
|
||||||
const { Multiaddr } = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
@ -114,7 +114,7 @@ class NatManager {
|
|||||||
const client = this._getClient()
|
const client = this._getClient()
|
||||||
const publicIp = this._externalIp || await client.externalIp()
|
const publicIp = this._externalIp || await client.externalIp()
|
||||||
|
|
||||||
// @ts-expect-error types are wrong
|
// @ts-ignore isPrivate has no call signatures
|
||||||
if (isPrivateIp(publicIp)) {
|
if (isPrivateIp(publicIp)) {
|
||||||
throw new Error(`${publicIp} is private - please set config.nat.externalIp to an externally routable IP or ensure you are not behind a double NAT`)
|
throw new Error(`${publicIp} is private - please set config.nat.externalIp to an externally routable IP or ensure you are not behind a double NAT`)
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ class NatManager {
|
|||||||
try {
|
try {
|
||||||
await this._client.destroy()
|
await this._client.destroy()
|
||||||
this._client = null
|
this._client = null
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,11 @@ const log = Object.assign(debug('libp2p:peer-routing'), {
|
|||||||
error: debug('libp2p:peer-routing:err')
|
error: debug('libp2p:peer-routing:err')
|
||||||
})
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const errors = require('./errors')
|
|
||||||
const {
|
const {
|
||||||
storeAddresses,
|
storeAddresses,
|
||||||
uniquePeers,
|
uniquePeers,
|
||||||
requirePeers
|
requirePeers
|
||||||
} = require('./content-routing/utils')
|
} = require('./content-routing/utils')
|
||||||
const { TimeoutController } = require('timeout-abort-controller')
|
|
||||||
|
|
||||||
const merge = require('it-merge')
|
const merge = require('it-merge')
|
||||||
const { pipe } = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
@ -23,7 +21,6 @@ const {
|
|||||||
clearDelayedInterval
|
clearDelayedInterval
|
||||||
// @ts-ignore module with no types
|
// @ts-ignore module with no types
|
||||||
} = require('set-delayed-interval')
|
} = require('set-delayed-interval')
|
||||||
const { DHTPeerRouting } = require('./dht/dht-peer-routing')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
@ -36,7 +33,6 @@ const { DHTPeerRouting } = require('./dht/dht-peer-routing')
|
|||||||
* @property {boolean} [enabled = true] - Whether to enable the Refresh manager
|
* @property {boolean} [enabled = true] - Whether to enable the Refresh manager
|
||||||
* @property {number} [bootDelay = 6e5] - Boot delay to start the Refresh Manager (in ms)
|
* @property {number} [bootDelay = 6e5] - Boot delay to start the Refresh Manager (in ms)
|
||||||
* @property {number} [interval = 10e3] - Interval between each Refresh Manager run (in ms)
|
* @property {number} [interval = 10e3] - Interval between each Refresh Manager run (in ms)
|
||||||
* @property {number} [timeout = 10e3] - How long to let each refresh run (in ms)
|
|
||||||
*
|
*
|
||||||
* @typedef {Object} PeerRoutingOptions
|
* @typedef {Object} PeerRoutingOptions
|
||||||
* @property {RefreshManagerOptions} [refreshManager]
|
* @property {RefreshManagerOptions} [refreshManager]
|
||||||
@ -55,7 +51,7 @@ class PeerRouting {
|
|||||||
|
|
||||||
// If we have the dht, add it to the available peer routers
|
// If we have the dht, add it to the available peer routers
|
||||||
if (libp2p._dht && libp2p._config.dht.enabled) {
|
if (libp2p._dht && libp2p._config.dht.enabled) {
|
||||||
this._routers.push(new DHTPeerRouting(libp2p._dht))
|
this._routers.push(libp2p._dht)
|
||||||
}
|
}
|
||||||
|
|
||||||
this._refreshManagerOptions = libp2p._options.peerRouting.refreshManager
|
this._refreshManagerOptions = libp2p._options.peerRouting.refreshManager
|
||||||
@ -82,8 +78,8 @@ class PeerRouting {
|
|||||||
async _findClosestPeersTask () {
|
async _findClosestPeersTask () {
|
||||||
try {
|
try {
|
||||||
// nb getClosestPeers adds the addresses to the address book
|
// nb getClosestPeers adds the addresses to the address book
|
||||||
await drain(this.getClosestPeers(this._peerId.id, { timeout: this._refreshManagerOptions.timeout || 10e3 }))
|
await drain(this.getClosestPeers(this._peerId.id))
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -105,24 +101,19 @@ class PeerRouting {
|
|||||||
*/
|
*/
|
||||||
async findPeer (id, options) { // eslint-disable-line require-await
|
async findPeer (id, options) { // eslint-disable-line require-await
|
||||||
if (!this._routers.length) {
|
if (!this._routers.length) {
|
||||||
throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS_AVAILABLE)
|
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id.toB58String() === this._peerId.toB58String()) {
|
if (id.toB58String() === this._peerId.toB58String()) {
|
||||||
throw errCode(new Error('Should not try to find self'), errors.codes.ERR_FIND_SELF)
|
throw errCode(new Error('Should not try to find self'), 'ERR_FIND_SELF')
|
||||||
}
|
}
|
||||||
|
|
||||||
const output = await pipe(
|
const output = await pipe(
|
||||||
merge(
|
merge(
|
||||||
...this._routers.map(router => (async function * () {
|
...this._routers.map(router => [router.findPeer(id, options)])
|
||||||
try {
|
|
||||||
yield await router.findPeer(id, options)
|
|
||||||
} catch (err) {
|
|
||||||
log.error(err)
|
|
||||||
}
|
|
||||||
})())
|
|
||||||
),
|
),
|
||||||
(source) => filter(source, Boolean),
|
(source) => filter(source, Boolean),
|
||||||
|
// @ts-ignore findPeer resolves a Promise
|
||||||
(source) => storeAddresses(source, this._peerStore),
|
(source) => storeAddresses(source, this._peerStore),
|
||||||
(source) => first(source)
|
(source) => first(source)
|
||||||
)
|
)
|
||||||
@ -131,7 +122,7 @@ class PeerRouting {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
throw errCode(new Error(errors.messages.NOT_FOUND), errors.codes.ERR_NOT_FOUND)
|
throw errCode(new Error('not found'), 'NOT_FOUND')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,17 +130,12 @@ class PeerRouting {
|
|||||||
*
|
*
|
||||||
* @param {Uint8Array} key - A CID like key
|
* @param {Uint8Array} key - A CID like key
|
||||||
* @param {Object} [options]
|
* @param {Object} [options]
|
||||||
* @param {number} [options.timeout=30e3] - How long the query can take
|
* @param {number} [options.timeout=30e3] - How long the query can take.
|
||||||
* @param {AbortSignal} [options.signal] - An AbortSignal to abort the request
|
|
||||||
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>}
|
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>}
|
||||||
*/
|
*/
|
||||||
async * getClosestPeers (key, options = { timeout: 30e3 }) {
|
async * getClosestPeers (key, options = { timeout: 30e3 }) {
|
||||||
if (!this._routers.length) {
|
if (!this._routers.length) {
|
||||||
throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS_AVAILABLE)
|
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
|
||||||
|
|
||||||
if (options.timeout) {
|
|
||||||
options.signal = new TimeoutController(options.timeout).signal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yield * pipe(
|
yield * pipe(
|
||||||
|
@ -83,7 +83,7 @@ class AddressBook extends Book {
|
|||||||
let peerRecord
|
let peerRecord
|
||||||
try {
|
try {
|
||||||
peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
|
peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('invalid peer record received')
|
log.error('invalid peer record received')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const { codes } = require('../errors')
|
|
||||||
|
const {
|
||||||
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
|
} = require('../errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {any} data
|
* @param {any} data
|
||||||
@ -45,7 +48,7 @@ class Book {
|
|||||||
* @param {any[]|any} data
|
* @param {any[]|any} data
|
||||||
*/
|
*/
|
||||||
set (peerId, data) {
|
set (peerId, data) {
|
||||||
throw errcode(new Error('set must be implemented by the subclass'), codes.ERR_NOT_IMPLEMENTED)
|
throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -91,7 +94,7 @@ class Book {
|
|||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
const rec = this.data.get(peerId.toB58String())
|
const rec = this.data.get(peerId.toB58String())
|
||||||
@ -108,7 +111,7 @@ class Book {
|
|||||||
*/
|
*/
|
||||||
delete (peerId) {
|
delete (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.data.delete(peerId.toB58String())) {
|
if (!this.data.delete(peerId.toB58String())) {
|
||||||
|
@ -80,11 +80,10 @@ class MetadataBook extends Book {
|
|||||||
/**
|
/**
|
||||||
* Set data into the datastructure
|
* Set data into the datastructure
|
||||||
*
|
*
|
||||||
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {Uint8Array} value
|
* @param {Uint8Array} value
|
||||||
* @param {object} [opts]
|
|
||||||
* @param {boolean} [opts.emit]
|
|
||||||
*/
|
*/
|
||||||
_setValue (peerId, key, value, { emit = true } = {}) {
|
_setValue (peerId, key, value, { emit = true } = {}) {
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
|
@ -249,7 +249,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
}).finish()
|
}).finish()
|
||||||
|
|
||||||
batch.put(key, encodedData)
|
batch.put(key, encodedData)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,7 +275,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
const encodedData = peerId.marshalPubKey()
|
const encodedData = peerId.marshalPubKey()
|
||||||
|
|
||||||
batch.put(key, encodedData)
|
batch.put(key, encodedData)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -302,7 +302,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
batch.delete(key)
|
batch.delete(key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -330,7 +330,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
const encodedData = Protocols.encode({ protocols }).finish()
|
const encodedData = Protocols.encode({ protocols }).finish()
|
||||||
|
|
||||||
batch.put(key, encodedData)
|
batch.put(key, encodedData)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -399,7 +399,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
default:
|
default:
|
||||||
log('invalid data persisted for: ', key.toString())
|
log('invalid data persisted for: ', key.toString())
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ const log = Object.assign(debug('libp2p:ping'), {
|
|||||||
error: debug('libp2p:ping:err')
|
error: debug('libp2p:ping:err')
|
||||||
})
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const { codes } = require('../errors')
|
|
||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
const { pipe } = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
// @ts-ignore it-buffer has no types exported
|
// @ts-ignore it-buffer has no types exported
|
||||||
@ -50,7 +50,7 @@ async function ping (node, peer) {
|
|||||||
const end = Date.now()
|
const end = Date.now()
|
||||||
|
|
||||||
if (!equals(data, result)) {
|
if (!equals(data, result)) {
|
||||||
throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK)
|
throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK')
|
||||||
}
|
}
|
||||||
|
|
||||||
return end - start
|
return end - start
|
||||||
|
@ -77,7 +77,7 @@ module.exports.decodeV1PSK = (pskBuffer) => {
|
|||||||
codecName: codec,
|
codecName: codec,
|
||||||
psk: psk
|
psk: psk
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
throw new Error(Errors.INVALID_PSK)
|
throw new Error(Errors.INVALID_PSK)
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,6 @@ try {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
generate(process.stdout)
|
generate(process.stdout)
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ error) {
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ class TransportManager {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return await transport.dial(ma, options)
|
return await transport.dial(ma, options)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
if (!err.code) err.code = codes.ERR_TRANSPORT_DIAL_FAILED
|
if (!err.code) err.code = codes.ERR_TRANSPORT_DIAL_FAILED
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ class Upgrader {
|
|||||||
} else {
|
} else {
|
||||||
upgradedConn = encryptedConn
|
upgradedConn = encryptedConn
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('Failed to upgrade inbound connection', err)
|
log.error('Failed to upgrade inbound connection', err)
|
||||||
await maConn.close(err)
|
await maConn.close(err)
|
||||||
throw err
|
throw err
|
||||||
@ -181,7 +181,7 @@ class Upgrader {
|
|||||||
} else {
|
} else {
|
||||||
upgradedConn = encryptedConn
|
upgradedConn = encryptedConn
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('Failed to upgrade outbound connection', err)
|
log.error('Failed to upgrade outbound connection', err)
|
||||||
await maConn.close(err)
|
await maConn.close(err)
|
||||||
throw err
|
throw err
|
||||||
@ -245,7 +245,7 @@ class Upgrader {
|
|||||||
if (this.metrics) this.metrics.trackStream({ stream, remotePeer, protocol })
|
if (this.metrics) this.metrics.trackStream({ stream, remotePeer, protocol })
|
||||||
connection.addStream(muxedStream, { protocol })
|
connection.addStream(muxedStream, { protocol })
|
||||||
this._onStream({ connection, stream: { ...muxedStream, ...stream }, protocol })
|
this._onStream({ connection, stream: { ...muxedStream, ...stream }, protocol })
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -263,7 +263,7 @@ class Upgrader {
|
|||||||
const { stream, protocol } = await mss.select(protocols)
|
const { stream, protocol } = await mss.select(protocols)
|
||||||
if (this.metrics) this.metrics.trackStream({ stream, remotePeer, protocol })
|
if (this.metrics) this.metrics.trackStream({ stream, remotePeer, protocol })
|
||||||
return { stream: { ...muxedStream, ...stream }, protocol }
|
return { stream: { ...muxedStream, ...stream }, protocol }
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error('could not create new stream', err)
|
log.error('could not create new stream', err)
|
||||||
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
||||||
}
|
}
|
||||||
@ -283,7 +283,7 @@ class Upgrader {
|
|||||||
if (connection.stat.status === 'open') {
|
if (connection.stat.status === 'open') {
|
||||||
await connection.close()
|
await connection.close()
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
log.error(err)
|
log.error(err)
|
||||||
} finally {
|
} finally {
|
||||||
this.onConnectionEnd(connection)
|
this.onConnectionEnd(connection)
|
||||||
@ -297,7 +297,7 @@ class Upgrader {
|
|||||||
maConn.timeline.upgraded = Date.now()
|
maConn.timeline.upgraded = Date.now()
|
||||||
|
|
||||||
const errConnectionNotMultiplexed = () => {
|
const errConnectionNotMultiplexed = () => {
|
||||||
throw errCode(new Error('connection is not multiplexed'), codes.ERR_CONNECTION_NOT_MULTIPLEXED)
|
throw errCode(new Error('connection is not multiplexed'), 'ERR_CONNECTION_NOT_MULTIPLEXED')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the connection
|
// Create the connection
|
||||||
@ -371,7 +371,7 @@ class Upgrader {
|
|||||||
...await crypto.secureInbound(localPeer, stream),
|
...await crypto.secureInbound(localPeer, stream),
|
||||||
protocol
|
protocol
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_ENCRYPTION_FAILED)
|
throw errCode(err, codes.ERR_ENCRYPTION_FAILED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -406,7 +406,7 @@ class Upgrader {
|
|||||||
...await crypto.secureOutbound(localPeer, stream, remotePeerId),
|
...await crypto.secureOutbound(localPeer, stream, remotePeerId),
|
||||||
protocol
|
protocol
|
||||||
}
|
}
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_ENCRYPTION_FAILED)
|
throw errCode(err, codes.ERR_ENCRYPTION_FAILED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -430,7 +430,7 @@ class Upgrader {
|
|||||||
log('%s selected as muxer protocol', protocol)
|
log('%s selected as muxer protocol', protocol)
|
||||||
const Muxer = muxers.get(protocol)
|
const Muxer = muxers.get(protocol)
|
||||||
return { stream, Muxer }
|
return { stream, Muxer }
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_MUXER_UNAVAILABLE)
|
throw errCode(err, codes.ERR_MUXER_UNAVAILABLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -453,7 +453,7 @@ class Upgrader {
|
|||||||
const { stream, protocol } = await listener.handle(protocols)
|
const { stream, protocol } = await listener.handle(protocols)
|
||||||
const Muxer = muxers.get(protocol)
|
const Muxer = muxers.get(protocol)
|
||||||
return { stream, Muxer }
|
return { stream, Muxer }
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_MUXER_UNAVAILABLE)
|
throw errCode(err, codes.ERR_MUXER_UNAVAILABLE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,16 +34,16 @@ describe('content-routing', () => {
|
|||||||
try {
|
try {
|
||||||
for await (const _ of node.contentRouting.findProviders('a cid')) {} // eslint-disable-line
|
for await (const _ of node.contentRouting.findProviders('a cid')) {} // eslint-disable-line
|
||||||
throw new Error('.findProviders should return an error')
|
throw new Error('.findProviders should return an error')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err.code).to.equal('ERR_NO_ROUTERS_AVAILABLE')
|
expect(err.code).to.equal('NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('.provide should return an error', async () => {
|
it('.provide should return an error', async () => {
|
||||||
await expect(node.contentRouting.provide('a cid'))
|
await expect(node.contentRouting.provide('a cid'))
|
||||||
.to.eventually.be.rejected()
|
.to.eventually.be.rejected()
|
||||||
.and.to.have.property('code', 'ERR_NO_ROUTERS_AVAILABLE')
|
.and.to.have.property('code', 'NO_ROUTERS_AVAILABLE')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -87,11 +87,8 @@ describe('content-routing', () => {
|
|||||||
sinon.stub(nodes[0]._dht, 'findProviders').callsFake(function * () {
|
sinon.stub(nodes[0]._dht, 'findProviders').callsFake(function * () {
|
||||||
deferred.resolve()
|
deferred.resolve()
|
||||||
yield {
|
yield {
|
||||||
name: 'PROVIDER',
|
id: providerPeerId,
|
||||||
providers: [{
|
multiaddrs: []
|
||||||
id: providerPeerId,
|
|
||||||
multiaddrs: []
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -241,7 +238,7 @@ describe('content-routing', () => {
|
|||||||
try {
|
try {
|
||||||
for await (const _ of node.contentRouting.findProviders(cid)) { } // eslint-disable-line
|
for await (const _ of node.contentRouting.findProviders(cid)) { } // eslint-disable-line
|
||||||
throw new Error('should handle errors when finding providers')
|
throw new Error('should handle errors when finding providers')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,12 +361,7 @@ describe('content-routing', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findProviders').callsFake(async function * () {
|
sinon.stub(node._dht, 'findProviders').callsFake(async function * () {
|
||||||
yield {
|
yield result1
|
||||||
name: 'PROVIDER',
|
|
||||||
providers: [
|
|
||||||
result1
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
sinon.stub(delegate, 'findProviders').callsFake(async function * () {
|
sinon.stub(delegate, 'findProviders').callsFake(async function * () {
|
||||||
yield result2
|
yield result2
|
||||||
@ -390,8 +382,7 @@ describe('content-routing', () => {
|
|||||||
const dhtDeferred = pDefer()
|
const dhtDeferred = pDefer()
|
||||||
const delegatedDeferred = pDefer()
|
const delegatedDeferred = pDefer()
|
||||||
|
|
||||||
sinon.stub(node._dht, 'provide').callsFake(async function * () {
|
sinon.stub(node._dht, 'provide').callsFake(() => {
|
||||||
yield
|
|
||||||
dhtDeferred.resolve()
|
dhtDeferred.resolve()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -415,12 +406,7 @@ describe('content-routing', () => {
|
|||||||
}]
|
}]
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findProviders').callsFake(function * () {
|
sinon.stub(node._dht, 'findProviders').callsFake(function * () {
|
||||||
yield {
|
yield results[0]
|
||||||
name: 'PROVIDER',
|
|
||||||
providers: [
|
|
||||||
results[0]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
sinon.stub(delegate, 'findProviders').callsFake(function * () { // eslint-disable-line require-yield
|
sinon.stub(delegate, 'findProviders').callsFake(function * () { // eslint-disable-line require-yield
|
||||||
|
@ -38,13 +38,13 @@ describe('DHT subsystem is configurable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
libp2p = await create(customOptions)
|
libp2p = await create(customOptions)
|
||||||
expect(libp2p._dht.isStarted()).to.equal(false)
|
expect(libp2p._dht.isStarted).to.equal(false)
|
||||||
|
|
||||||
await libp2p.start()
|
await libp2p.start()
|
||||||
expect(libp2p._dht.isStarted()).to.equal(true)
|
expect(libp2p._dht.isStarted).to.equal(true)
|
||||||
|
|
||||||
await libp2p.stop()
|
await libp2p.stop()
|
||||||
expect(libp2p._dht.isStarted()).to.equal(false)
|
expect(libp2p._dht.isStarted).to.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not start if disabled once libp2p starts', async () => {
|
it('should not start if disabled once libp2p starts', async () => {
|
||||||
@ -63,10 +63,10 @@ describe('DHT subsystem is configurable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
libp2p = await create(customOptions)
|
libp2p = await create(customOptions)
|
||||||
expect(libp2p._dht.isStarted()).to.equal(false)
|
expect(libp2p._dht.isStarted).to.equal(false)
|
||||||
|
|
||||||
await libp2p.start()
|
await libp2p.start()
|
||||||
expect(libp2p._dht.isStarted()).to.equal(false)
|
expect(libp2p._dht.isStarted).to.equal(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow a manual start', async () => {
|
it('should allow a manual start', async () => {
|
||||||
@ -86,9 +86,9 @@ describe('DHT subsystem is configurable', () => {
|
|||||||
|
|
||||||
libp2p = await create(customOptions)
|
libp2p = await create(customOptions)
|
||||||
await libp2p.start()
|
await libp2p.start()
|
||||||
expect(libp2p._dht.isStarted()).to.equal(false)
|
expect(libp2p._dht.isStarted).to.equal(false)
|
||||||
|
|
||||||
await libp2p._dht.start()
|
await libp2p._dht.start()
|
||||||
expect(libp2p._dht.isStarted()).to.equal(true)
|
expect(libp2p._dht.isStarted).to.equal(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -60,8 +60,8 @@ describe('DHT subsystem operates correctly', () => {
|
|||||||
expect(connection).to.exist()
|
expect(connection).to.exist()
|
||||||
|
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
pWaitFor(() => libp2p._dht._lan._routingTable.size === 1),
|
pWaitFor(() => libp2p._dht.routingTable.size === 1),
|
||||||
pWaitFor(() => remoteLibp2p._dht._lan._routingTable.size === 1)
|
pWaitFor(() => remoteLibp2p._dht.routingTable.size === 1)
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -71,14 +71,14 @@ describe('DHT subsystem operates correctly', () => {
|
|||||||
|
|
||||||
await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
|
await libp2p.dialProtocol(remAddr, subsystemMulticodecs)
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
pWaitFor(() => libp2p._dht._lan._routingTable.size === 1),
|
pWaitFor(() => libp2p._dht.routingTable.size === 1),
|
||||||
pWaitFor(() => remoteLibp2p._dht._lan._routingTable.size === 1)
|
pWaitFor(() => remoteLibp2p._dht.routingTable.size === 1)
|
||||||
])
|
])
|
||||||
|
|
||||||
await libp2p.contentRouting.put(key, value)
|
await libp2p.contentRouting.put(key, value)
|
||||||
|
|
||||||
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
||||||
expect(fetchedValue).to.have.property('val').that.equalBytes(value)
|
|
||||||
|
expect(fetchedValue).to.eql(value)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -119,13 +119,11 @@ describe('DHT subsystem operates correctly', () => {
|
|||||||
const connection = await libp2p.dial(remAddr)
|
const connection = await libp2p.dial(remAddr)
|
||||||
|
|
||||||
expect(connection).to.exist()
|
expect(connection).to.exist()
|
||||||
expect(libp2p._dht._lan._routingTable.size).to.be.eql(0)
|
expect(libp2p._dht.routingTable.size).to.be.eql(0)
|
||||||
|
expect(remoteLibp2p._dht.routingTable.size).to.be.eql(0)
|
||||||
|
|
||||||
await remoteLibp2p._dht.start()
|
await remoteLibp2p._dht.start()
|
||||||
// should be 0 directly after start - TODO this may be susceptible to timing bugs, we should have
|
return pWaitFor(() => libp2p._dht.routingTable.size === 1)
|
||||||
// the ability to report stats on the DHT routing table instead of reaching into it's heart like this
|
|
||||||
expect(remoteLibp2p._dht._lan._routingTable.size).to.be.eql(0)
|
|
||||||
return pWaitFor(() => libp2p._dht._lan._routingTable.size === 1)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should put on a peer and get from the other', async () => {
|
it('should put on a peer and get from the other', async () => {
|
||||||
@ -135,12 +133,12 @@ describe('DHT subsystem operates correctly', () => {
|
|||||||
const value = uint8ArrayFromString('world')
|
const value = uint8ArrayFromString('world')
|
||||||
|
|
||||||
await remoteLibp2p._dht.start()
|
await remoteLibp2p._dht.start()
|
||||||
await pWaitFor(() => libp2p._dht._lan._routingTable.size === 1)
|
await pWaitFor(() => libp2p._dht.routingTable.size === 1)
|
||||||
|
|
||||||
await libp2p.contentRouting.put(key, value)
|
await libp2p.contentRouting.put(key, value)
|
||||||
|
|
||||||
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
const fetchedValue = await remoteLibp2p.contentRouting.get(key)
|
||||||
expect(fetchedValue).to.have.property('val').that.equalBytes(value)
|
expect(fetchedValue).to.eql(value)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const KadDht = require('libp2p-kad-dht')
|
const KadDht = require('libp2p-kad-dht')
|
||||||
|
const { multicodec } = require('libp2p-kad-dht')
|
||||||
const Crypto = require('../../../src/insecure/plaintext')
|
const Crypto = require('../../../src/insecure/plaintext')
|
||||||
const Muxer = require('libp2p-mplex')
|
const Muxer = require('libp2p-mplex')
|
||||||
const Transport = require('libp2p-tcp')
|
const Transport = require('libp2p-tcp')
|
||||||
@ -24,12 +25,13 @@ const subsystemOptions = mergeOptions(baseOptions, {
|
|||||||
config: {
|
config: {
|
||||||
dht: {
|
dht: {
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
|
randomWalk: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports.subsystemOptions = subsystemOptions
|
module.exports.subsystemOptions = subsystemOptions
|
||||||
module.exports.subsystemMulticodecs = [
|
module.exports.subsystemMulticodecs = [multicodec]
|
||||||
'/ipfs/lan/kad/1.0.0'
|
|
||||||
]
|
|
||||||
|
@ -13,6 +13,9 @@ const routingOptions = mergeOptions(baseOptions, {
|
|||||||
config: {
|
config: {
|
||||||
dht: {
|
dht: {
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
|
randomWalk: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ describe('Dial Request', () => {
|
|||||||
try {
|
try {
|
||||||
await dialRequest.run({ signal: controller.signal })
|
await dialRequest.run({ signal: controller.signal })
|
||||||
expect.fail('Should have thrown')
|
expect.fail('Should have thrown')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.be.an.instanceof(AggregateError)
|
expect(err).to.be.an.instanceof(AggregateError)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,7 +162,7 @@ describe('Dial Request', () => {
|
|||||||
try {
|
try {
|
||||||
await dialRequest.run({ signal: controller.signal })
|
await dialRequest.run({ signal: controller.signal })
|
||||||
expect.fail('Should have thrown')
|
expect.fail('Should have thrown')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.be.an.instanceof(AggregateError)
|
expect(err).to.be.an.instanceof(AggregateError)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ describe('Dial Request', () => {
|
|||||||
setTimeout(() => controller.abort(), 100)
|
setTimeout(() => controller.abort(), 100)
|
||||||
await dialRequest.run({ signal: controller.signal })
|
await dialRequest.run({ signal: controller.signal })
|
||||||
expect.fail('dial should have failed')
|
expect.fail('dial should have failed')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.be.an.instanceof(AggregateError)
|
expect(err).to.be.an.instanceof(AggregateError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ describe('Dialing (direct, TCP)', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await libp2p.dial(remoteLibp2p.transportManager.getAddrs()[0])
|
await libp2p.dial(remoteLibp2p.transportManager.getAddrs()[0])
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.have.property('code', ErrorCodes.ERR_INVALID_MULTIADDR)
|
expect(err).to.have.property('code', ErrorCodes.ERR_INVALID_MULTIADDR)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -304,7 +304,7 @@ describe('Dialing (direct, WebSockets)', () => {
|
|||||||
dialer.destroy()
|
dialer.destroy()
|
||||||
await dialPromise
|
await dialPromise
|
||||||
expect.fail('should have failed')
|
expect.fail('should have failed')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.be.an.instanceof(AggregateError)
|
expect(err).to.be.an.instanceof(AggregateError)
|
||||||
expect(dialer._pendingDials.size).to.equal(0) // 1 dial request
|
expect(dialer._pendingDials.size).to.equal(0) // 1 dial request
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,7 @@ describe('keychain', () => {
|
|||||||
it('requires plain data as a Uint8Array', async () => {
|
it('requires plain data as a Uint8Array', async () => {
|
||||||
const err = await ks.cms.encrypt(rsaKeyName, 'plain data').then(fail, err => err)
|
const err = await ks.cms.encrypt(rsaKeyName, 'plain data').then(fail, err => err)
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS')
|
expect(err).to.have.property('code', 'ERR_INVALID_PARAMS')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('encrypts', async () => {
|
it('encrypts', async () => {
|
||||||
@ -308,7 +308,7 @@ describe('keychain', () => {
|
|||||||
it('is a PKCS #7 message', async () => {
|
it('is a PKCS #7 message', async () => {
|
||||||
const err = await ks.cms.decrypt('not CMS').then(fail, err => err)
|
const err = await ks.cms.decrypt('not CMS').then(fail, err => err)
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS')
|
expect(err).to.have.property('code', 'ERR_INVALID_PARAMS')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('is a PKCS #7 binary message', async () => {
|
it('is a PKCS #7 binary message', async () => {
|
||||||
@ -519,7 +519,7 @@ describe('keychain', () => {
|
|||||||
it('should validate newPass is a string', async () => {
|
it('should validate newPass is a string', async () => {
|
||||||
try {
|
try {
|
||||||
await kc.rotateKeychainPass(oldPass, 1234567890)
|
await kc.rotateKeychainPass(oldPass, 1234567890)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -527,7 +527,7 @@ describe('keychain', () => {
|
|||||||
it('should validate oldPass is a string', async () => {
|
it('should validate oldPass is a string', async () => {
|
||||||
try {
|
try {
|
||||||
await kc.rotateKeychainPass(1234, 'newInsecurePassword1')
|
await kc.rotateKeychainPass(1234, 'newInsecurePassword1')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -535,7 +535,7 @@ describe('keychain', () => {
|
|||||||
it('should validate newPass is at least 20 characters', async () => {
|
it('should validate newPass is at least 20 characters', async () => {
|
||||||
try {
|
try {
|
||||||
await kc.rotateKeychainPass(oldPass, 'not20Chars')
|
await kc.rotateKeychainPass(oldPass, 'not20Chars')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -586,7 +586,7 @@ describe('libp2p.keychain', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await libp2p.keychain.createKey('keyName', 'rsa', 2048)
|
await libp2p.keychain.createKey('keyName', 'rsa', 2048)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
const { expect } = require('aegir/utils/chai')
|
const { expect } = require('aegir/utils/chai')
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
|
|
||||||
|
const { EventEmitter } = require('events')
|
||||||
|
|
||||||
const { randomBytes } = require('libp2p-crypto')
|
const { randomBytes } = require('libp2p-crypto')
|
||||||
const duplexPair = require('it-pair/duplex')
|
const duplexPair = require('it-pair/duplex')
|
||||||
const pipe = require('it-pipe')
|
const pipe = require('it-pipe')
|
||||||
@ -31,7 +34,8 @@ describe('Metrics', () => {
|
|||||||
const [local, remote] = duplexPair()
|
const [local, remote] = duplexPair()
|
||||||
const metrics = new Metrics({
|
const metrics = new Metrics({
|
||||||
computeThrottleMaxQueueSize: 1, // compute after every message
|
computeThrottleMaxQueueSize: 1, // compute after every message
|
||||||
movingAverageIntervals: [10, 100, 1000]
|
movingAverageIntervals: [10, 100, 1000],
|
||||||
|
connectionManager: new EventEmitter()
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics.trackStream({
|
metrics.trackStream({
|
||||||
@ -66,7 +70,8 @@ describe('Metrics', () => {
|
|||||||
const [local, remote] = duplexPair()
|
const [local, remote] = duplexPair()
|
||||||
const metrics = new Metrics({
|
const metrics = new Metrics({
|
||||||
computeThrottleMaxQueueSize: 1, // compute after every message
|
computeThrottleMaxQueueSize: 1, // compute after every message
|
||||||
movingAverageIntervals: [10, 100, 1000]
|
movingAverageIntervals: [10, 100, 1000],
|
||||||
|
connectionManager: new EventEmitter()
|
||||||
})
|
})
|
||||||
|
|
||||||
metrics.trackStream({
|
metrics.trackStream({
|
||||||
@ -114,7 +119,8 @@ describe('Metrics', () => {
|
|||||||
const [local2, remote2] = duplexPair()
|
const [local2, remote2] = duplexPair()
|
||||||
const metrics = new Metrics({
|
const metrics = new Metrics({
|
||||||
computeThrottleMaxQueueSize: 1, // compute after every message
|
computeThrottleMaxQueueSize: 1, // compute after every message
|
||||||
movingAverageIntervals: [10, 100, 1000]
|
movingAverageIntervals: [10, 100, 1000],
|
||||||
|
connectionManager: new EventEmitter()
|
||||||
})
|
})
|
||||||
const protocol = '/echo/1.0.0'
|
const protocol = '/echo/1.0.0'
|
||||||
metrics.start()
|
metrics.start()
|
||||||
@ -169,7 +175,8 @@ describe('Metrics', () => {
|
|||||||
const [local, remote] = duplexPair()
|
const [local, remote] = duplexPair()
|
||||||
const metrics = new Metrics({
|
const metrics = new Metrics({
|
||||||
computeThrottleMaxQueueSize: 1, // compute after every message
|
computeThrottleMaxQueueSize: 1, // compute after every message
|
||||||
movingAverageIntervals: [10, 100, 1000]
|
movingAverageIntervals: [10, 100, 1000],
|
||||||
|
connectionManager: new EventEmitter()
|
||||||
})
|
})
|
||||||
metrics.start()
|
metrics.start()
|
||||||
|
|
||||||
@ -224,7 +231,8 @@ describe('Metrics', () => {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
const metrics = new Metrics({
|
const metrics = new Metrics({
|
||||||
maxOldPeersRetention: 5 // Only keep track of 5
|
maxOldPeersRetention: 5, // Only keep track of 5
|
||||||
|
connectionManager: new EventEmitter()
|
||||||
})
|
})
|
||||||
|
|
||||||
// Clone so trackedPeers isn't modified
|
// Clone so trackedPeers isn't modified
|
||||||
@ -254,22 +262,4 @@ describe('Metrics', () => {
|
|||||||
expect(spy).to.have.property('callCount', 1)
|
expect(spy).to.have.property('callCount', 1)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow components to track metrics', () => {
|
|
||||||
const metrics = new Metrics({
|
|
||||||
maxOldPeersRetention: 5 // Only keep track of 5
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(metrics.getComponentMetrics()).to.be.empty()
|
|
||||||
|
|
||||||
const component = 'my-component'
|
|
||||||
const metric = 'some-metric'
|
|
||||||
const value = 1
|
|
||||||
|
|
||||||
metrics.updateComponentMetric(component, metric, value)
|
|
||||||
|
|
||||||
expect(metrics.getComponentMetrics()).to.have.lengthOf(1)
|
|
||||||
expect(metrics.getComponentMetrics().get(component)).to.have.lengthOf(1)
|
|
||||||
expect(metrics.getComponentMetrics().get(component).get(metric)).to.equal(value)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
@ -244,10 +244,6 @@ describe('Nat Manager (TCP)', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('shuts the nat api down when stopping', async function () {
|
it('shuts the nat api down when stopping', async function () {
|
||||||
if (process.env.CI) {
|
|
||||||
return this.skip('CI environments will not let us map external ports')
|
|
||||||
}
|
|
||||||
|
|
||||||
function findRoutableAddress () {
|
function findRoutableAddress () {
|
||||||
const interfaces = networkInterfaces()
|
const interfaces = networkInterfaces()
|
||||||
|
|
||||||
@ -265,7 +261,7 @@ describe('Nat Manager (TCP)', () => {
|
|||||||
|
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
// skip test if no non-loopback address is found
|
// skip test if no non-loopback address is found
|
||||||
return this.skip()
|
this.skip()
|
||||||
}
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
@ -161,13 +161,20 @@ describe('peer discovery scenarios', () => {
|
|||||||
autoDial: false
|
autoDial: false
|
||||||
},
|
},
|
||||||
dht: {
|
dht: {
|
||||||
|
randomWalk: {
|
||||||
|
enabled: false,
|
||||||
|
delay: 1000, // start the first query quickly
|
||||||
|
interval: 10000,
|
||||||
|
timeout: 5000
|
||||||
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const localConfig = getConfig(peerId)
|
const localConfig = getConfig(peerId)
|
||||||
|
// Only run random walk on our local node
|
||||||
|
localConfig.config.dht.randomWalk.enabled = true
|
||||||
libp2p = new Libp2p(localConfig)
|
libp2p = new Libp2p(localConfig)
|
||||||
|
|
||||||
const remoteLibp2p1 = new Libp2p(getConfig(remotePeerId1))
|
const remoteLibp2p1 = new Libp2p(getConfig(remotePeerId1))
|
||||||
|
@ -36,16 +36,16 @@ describe('peer-routing', () => {
|
|||||||
it('.findPeer should return an error', async () => {
|
it('.findPeer should return an error', async () => {
|
||||||
await expect(node.peerRouting.findPeer('a cid'))
|
await expect(node.peerRouting.findPeer('a cid'))
|
||||||
.to.eventually.be.rejected()
|
.to.eventually.be.rejected()
|
||||||
.and.to.have.property('code', 'ERR_NO_ROUTERS_AVAILABLE')
|
.and.to.have.property('code', 'NO_ROUTERS_AVAILABLE')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('.getClosestPeers should return an error', async () => {
|
it('.getClosestPeers should return an error', async () => {
|
||||||
try {
|
try {
|
||||||
for await (const _ of node.peerRouting.getClosestPeers('a cid')) { } // eslint-disable-line
|
for await (const _ of node.peerRouting.getClosestPeers('a cid')) { } // eslint-disable-line
|
||||||
throw new Error('.getClosestPeers should return an error')
|
throw new Error('.getClosestPeers should return an error')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err.code).to.equal('ERR_NO_ROUTERS_AVAILABLE')
|
expect(err.code).to.equal('NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -72,38 +72,33 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
after(() => Promise.all(nodes.map((n) => n.stop())))
|
after(() => Promise.all(nodes.map((n) => n.stop())))
|
||||||
|
|
||||||
it('should use the nodes dht', async () => {
|
it('should use the nodes dht', () => {
|
||||||
sinon.stub(nodes[0]._dht, 'findPeer').callsFake(async function * () {
|
const deferred = pDefer()
|
||||||
yield {
|
|
||||||
name: 'PEER_RESPONSE',
|
sinon.stub(nodes[0]._dht, 'findPeer').callsFake(() => {
|
||||||
closer: [{
|
deferred.resolve()
|
||||||
id: nodes[1].peerId,
|
return nodes[1].peerId
|
||||||
multiaddrs: []
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(nodes[0]._dht.findPeer.called).to.be.false()
|
nodes[0].peerRouting.findPeer()
|
||||||
await nodes[0].peerRouting.findPeer(nodes[1].peerId)
|
return deferred.promise
|
||||||
expect(nodes[0]._dht.findPeer.called).to.be.true()
|
|
||||||
nodes[0]._dht.findPeer.restore()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use the nodes dht to get the closest peers', async () => {
|
it('should use the nodes dht to get the closest peers', async () => {
|
||||||
sinon.stub(nodes[0]._dht, 'getClosestPeers').callsFake(async function * () {
|
const deferred = pDefer()
|
||||||
|
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
||||||
|
|
||||||
|
sinon.stub(nodes[0]._dht, 'getClosestPeers').callsFake(function * () {
|
||||||
|
deferred.resolve()
|
||||||
yield {
|
yield {
|
||||||
name: 'PEER_RESPONSE',
|
id: remotePeerId,
|
||||||
closer: [{
|
multiaddrs: []
|
||||||
id: nodes[1].peerId,
|
|
||||||
multiaddrs: []
|
|
||||||
}]
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(nodes[0]._dht.getClosestPeers.called).to.be.false()
|
await nodes[0].peerRouting.getClosestPeers().next()
|
||||||
await drain(nodes[0].peerRouting.getClosestPeers(nodes[1].peerId))
|
|
||||||
expect(nodes[0]._dht.getClosestPeers.called).to.be.true()
|
return deferred.promise
|
||||||
nodes[0]._dht.getClosestPeers.restore()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should error when peer tries to find itself', async () => {
|
it('should error when peer tries to find itself', async () => {
|
||||||
@ -111,95 +106,6 @@ describe('peer-routing', () => {
|
|||||||
.to.eventually.be.rejected()
|
.to.eventually.be.rejected()
|
||||||
.and.to.have.property('code', 'ERR_FIND_SELF')
|
.and.to.have.property('code', 'ERR_FIND_SELF')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle error thrown synchronously during find peer', async () => {
|
|
||||||
const unknownPeers = await peerUtils.createPeerId({ number: 1, fixture: false })
|
|
||||||
|
|
||||||
nodes[0].peerRouting._routers = [{
|
|
||||||
findPeer () {
|
|
||||||
throw new Error('Thrown sync')
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
await expect(nodes[0].peerRouting.findPeer(unknownPeers[0]))
|
|
||||||
.to.eventually.be.rejected()
|
|
||||||
.and.to.have.property('code', 'ERR_NOT_FOUND')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle error thrown asynchronously during find peer', async () => {
|
|
||||||
const unknownPeers = await peerUtils.createPeerId({ number: 1, fixture: false })
|
|
||||||
|
|
||||||
nodes[0].peerRouting._routers = [{
|
|
||||||
async findPeer () {
|
|
||||||
throw new Error('Thrown async')
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
await expect(nodes[0].peerRouting.findPeer(unknownPeers[0]))
|
|
||||||
.to.eventually.be.rejected()
|
|
||||||
.and.to.have.property('code', 'ERR_NOT_FOUND')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should handle error thrown asynchronously after delay during find peer', async () => {
|
|
||||||
const unknownPeers = await peerUtils.createPeerId({ number: 1, fixture: false })
|
|
||||||
|
|
||||||
nodes[0].peerRouting._routers = [{
|
|
||||||
async findPeer () {
|
|
||||||
await delay(100)
|
|
||||||
throw new Error('Thrown async after delay')
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
await expect(nodes[0].peerRouting.findPeer(unknownPeers[0]))
|
|
||||||
.to.eventually.be.rejected()
|
|
||||||
.and.to.have.property('code', 'ERR_NOT_FOUND')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return value when one router errors synchronously and another returns a value', async () => {
|
|
||||||
const [peer] = await peerUtils.createPeerId({ number: 1, fixture: false })
|
|
||||||
|
|
||||||
nodes[0].peerRouting._routers = [{
|
|
||||||
findPeer () {
|
|
||||||
throw new Error('Thrown sync')
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
async findPeer () {
|
|
||||||
return Promise.resolve({
|
|
||||||
id: peer,
|
|
||||||
multiaddrs: []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
await expect(nodes[0].peerRouting.findPeer(peer))
|
|
||||||
.to.eventually.deep.equal({
|
|
||||||
id: peer,
|
|
||||||
multiaddrs: []
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return value when one router errors asynchronously and another returns a value', async () => {
|
|
||||||
const [peer] = await peerUtils.createPeerId({ number: 1, fixture: false })
|
|
||||||
|
|
||||||
nodes[0].peerRouting._routers = [{
|
|
||||||
async findPeer () {
|
|
||||||
throw new Error('Thrown sync')
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
async findPeer () {
|
|
||||||
return Promise.resolve({
|
|
||||||
id: peer,
|
|
||||||
multiaddrs: []
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
|
|
||||||
await expect(nodes[0].peerRouting.findPeer(peer))
|
|
||||||
.to.eventually.deep.equal({
|
|
||||||
id: peer,
|
|
||||||
multiaddrs: []
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('via delegate router', () => {
|
describe('via delegate router', () => {
|
||||||
@ -239,35 +145,36 @@ describe('peer-routing', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should use the delegate router to find peers', async () => {
|
it('should use the delegate router to find peers', async () => {
|
||||||
|
const deferred = pDefer()
|
||||||
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
||||||
|
|
||||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||||
|
deferred.resolve()
|
||||||
return {
|
return {
|
||||||
id: remotePeerId,
|
id: remotePeerId,
|
||||||
multiaddrs: []
|
multiaddrs: []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(delegate.findPeer.called).to.be.false()
|
await node.peerRouting.findPeer()
|
||||||
await node.peerRouting.findPeer(remotePeerId)
|
return deferred.promise
|
||||||
expect(delegate.findPeer.called).to.be.true()
|
|
||||||
delegate.findPeer.restore()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use the delegate router to get the closest peers', async () => {
|
it('should use the delegate router to get the closest peers', async () => {
|
||||||
|
const deferred = pDefer()
|
||||||
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
||||||
|
|
||||||
sinon.stub(delegate, 'getClosestPeers').callsFake(function * () {
|
sinon.stub(delegate, 'getClosestPeers').callsFake(function * () {
|
||||||
|
deferred.resolve()
|
||||||
yield {
|
yield {
|
||||||
id: remotePeerId,
|
id: remotePeerId,
|
||||||
multiaddrs: []
|
multiaddrs: []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(delegate.getClosestPeers.called).to.be.false()
|
await node.peerRouting.getClosestPeers().next()
|
||||||
await drain(node.peerRouting.getClosestPeers(remotePeerId))
|
|
||||||
expect(delegate.getClosestPeers.called).to.be.true()
|
return deferred.promise
|
||||||
delegate.getClosestPeers.restore()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to find a peer', async () => {
|
it('should be able to find a peer', async () => {
|
||||||
@ -293,7 +200,7 @@ describe('peer-routing', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should error when a peer cannot be found', async () => {
|
it('should error when a peer cannot be found', async () => {
|
||||||
const peerId = await PeerId.create({ keyType: 'ed25519' })
|
const peerKey = 'key of a peer not on the network'
|
||||||
const mockApi = nock('http://0.0.0.0:60197')
|
const mockApi = nock('http://0.0.0.0:60197')
|
||||||
.post('/api/v0/dht/findpeer')
|
.post('/api/v0/dht/findpeer')
|
||||||
.query(true)
|
.query(true)
|
||||||
@ -302,20 +209,20 @@ describe('peer-routing', () => {
|
|||||||
'X-Chunked-Output', '1'
|
'X-Chunked-Output', '1'
|
||||||
])
|
])
|
||||||
|
|
||||||
await expect(node.peerRouting.findPeer(peerId))
|
await expect(node.peerRouting.findPeer(peerKey))
|
||||||
.to.eventually.be.rejected()
|
.to.eventually.be.rejected()
|
||||||
|
|
||||||
expect(mockApi.isDone()).to.equal(true)
|
expect(mockApi.isDone()).to.equal(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle errors from the api', async () => {
|
it('should handle errors from the api', async () => {
|
||||||
const peerId = await PeerId.create({ keyType: 'ed25519' })
|
const peerKey = 'key of a peer not on the network'
|
||||||
const mockApi = nock('http://0.0.0.0:60197')
|
const mockApi = nock('http://0.0.0.0:60197')
|
||||||
.post('/api/v0/dht/findpeer')
|
.post('/api/v0/dht/findpeer')
|
||||||
.query(true)
|
.query(true)
|
||||||
.reply(502)
|
.reply(502)
|
||||||
|
|
||||||
await expect(node.peerRouting.findPeer(peerId))
|
await expect(node.peerRouting.findPeer(peerKey))
|
||||||
.to.eventually.be.rejected()
|
.to.eventually.be.rejected()
|
||||||
|
|
||||||
expect(mockApi.isDone()).to.equal(true)
|
expect(mockApi.isDone()).to.equal(true)
|
||||||
@ -323,6 +230,7 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
it('should be able to get the closest peers', async () => {
|
it('should be able to get the closest peers', async () => {
|
||||||
const peerId = await PeerId.create({ keyType: 'ed25519' })
|
const peerId = await PeerId.create({ keyType: 'ed25519' })
|
||||||
|
|
||||||
const closest1 = '12D3KooWLewYMMdGWAtuX852n4rgCWkK7EBn4CWbwwBzhsVoKxk3'
|
const closest1 = '12D3KooWLewYMMdGWAtuX852n4rgCWkK7EBn4CWbwwBzhsVoKxk3'
|
||||||
const closest2 = '12D3KooWDtoQbpKhtnWddfj72QmpFvvLDTsBLTFkjvgQm6cde2AK'
|
const closest2 = '12D3KooWDtoQbpKhtnWddfj72QmpFvvLDTsBLTFkjvgQm6cde2AK'
|
||||||
|
|
||||||
@ -341,12 +249,15 @@ describe('peer-routing', () => {
|
|||||||
'X-Chunked-Output', '1'
|
'X-Chunked-Output', '1'
|
||||||
])
|
])
|
||||||
|
|
||||||
const closestPeers = await all(node.peerRouting.getClosestPeers(peerId.id, { timeout: 1000 }))
|
const closestPeers = []
|
||||||
|
for await (const peer of node.peerRouting.getClosestPeers(peerId.id, { timeout: 1000 })) {
|
||||||
|
closestPeers.push(peer)
|
||||||
|
}
|
||||||
|
|
||||||
expect(closestPeers).to.have.length(2)
|
expect(closestPeers).to.have.length(2)
|
||||||
expect(closestPeers[0].id.toB58String()).to.equal(closest1)
|
expect(closestPeers[0].id.toB58String()).to.equal(closest2)
|
||||||
expect(closestPeers[0].multiaddrs).to.have.lengthOf(2)
|
expect(closestPeers[0].multiaddrs).to.have.lengthOf(2)
|
||||||
expect(closestPeers[1].id.toB58String()).to.equal(closest2)
|
expect(closestPeers[1].id.toB58String()).to.equal(closest1)
|
||||||
expect(closestPeers[1].multiaddrs).to.have.lengthOf(2)
|
expect(closestPeers[1].multiaddrs).to.have.lengthOf(2)
|
||||||
expect(mockApi.isDone()).to.equal(true)
|
expect(mockApi.isDone()).to.equal(true)
|
||||||
})
|
})
|
||||||
@ -364,7 +275,7 @@ describe('peer-routing', () => {
|
|||||||
try {
|
try {
|
||||||
for await (const _ of node.peerRouting.getClosestPeers(peerId.id)) { } // eslint-disable-line
|
for await (const _ of node.peerRouting.getClosestPeers(peerId.id)) { } // eslint-disable-line
|
||||||
throw new Error('should handle errors when getting the closest peers')
|
throw new Error('should handle errors when getting the closest peers')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +316,7 @@ describe('peer-routing', () => {
|
|||||||
multiaddrs: []
|
multiaddrs: []
|
||||||
}
|
}
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findPeer').callsFake(async function * () {})
|
sinon.stub(node._dht, 'findPeer').callsFake(() => {})
|
||||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||||
return results
|
return results
|
||||||
})
|
})
|
||||||
@ -423,8 +334,7 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
const defer = pDefer()
|
const defer = pDefer()
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findPeer').callsFake(async function * () {
|
sinon.stub(node._dht, 'findPeer').callsFake(async () => {
|
||||||
yield
|
|
||||||
await defer.promise
|
await defer.promise
|
||||||
})
|
})
|
||||||
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
sinon.stub(delegate, 'findPeer').callsFake(() => {
|
||||||
@ -439,34 +349,29 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
it('should not wait for the delegate to return if the dht does first', async () => {
|
it('should not wait for the delegate to return if the dht does first', async () => {
|
||||||
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
||||||
const result = {
|
const results = {
|
||||||
id: remotePeerId,
|
id: remotePeerId,
|
||||||
multiaddrs: []
|
multiaddrs: []
|
||||||
}
|
}
|
||||||
|
|
||||||
const defer = pDefer()
|
const defer = pDefer()
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findPeer').callsFake(async function * () {
|
sinon.stub(node._dht, 'findPeer').callsFake(() => {
|
||||||
yield {
|
return results
|
||||||
name: 'PEER_RESPONSE',
|
|
||||||
closer: [
|
|
||||||
result
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
sinon.stub(delegate, 'findPeer').callsFake(async () => {
|
sinon.stub(delegate, 'findPeer').callsFake(async () => {
|
||||||
await defer.promise
|
await defer.promise
|
||||||
})
|
})
|
||||||
|
|
||||||
const peer = await node.peerRouting.findPeer(remotePeerId)
|
const peer = await node.peerRouting.findPeer(remotePeerId)
|
||||||
expect(peer).to.eql(result)
|
expect(peer).to.eql(results)
|
||||||
|
|
||||||
defer.resolve()
|
defer.resolve()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should store the addresses of the found peer', async () => {
|
it('should store the addresses of the found peer', async () => {
|
||||||
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
const [remotePeerId] = await peerUtils.createPeerId({ fixture: false })
|
||||||
const result = {
|
const results = {
|
||||||
id: remotePeerId,
|
id: remotePeerId,
|
||||||
multiaddrs: [
|
multiaddrs: [
|
||||||
new Multiaddr('/ip4/123.123.123.123/tcp/38982')
|
new Multiaddr('/ip4/123.123.123.123/tcp/38982')
|
||||||
@ -475,19 +380,14 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
const spy = sinon.spy(node.peerStore.addressBook, 'add')
|
const spy = sinon.spy(node.peerStore.addressBook, 'add')
|
||||||
|
|
||||||
sinon.stub(node._dht, 'findPeer').callsFake(async function * () {
|
sinon.stub(node._dht, 'findPeer').callsFake(() => {
|
||||||
yield {
|
return results
|
||||||
name: 'PEER_RESPONSE',
|
|
||||||
closer: [
|
|
||||||
result
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
sinon.stub(delegate, 'findPeer').callsFake(() => {})
|
sinon.stub(delegate, 'findPeer').callsFake(() => {})
|
||||||
|
|
||||||
await node.peerRouting.findPeer(remotePeerId)
|
await node.peerRouting.findPeer(remotePeerId)
|
||||||
|
|
||||||
expect(spy.calledWith(result.id, result.multiaddrs)).to.be.true()
|
expect(spy.calledWith(results.id, results.multiaddrs)).to.be.true()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should use the delegate if the dht fails to get the closest peer', async () => {
|
it('should use the delegate if the dht fails to get the closest peer', async () => {
|
||||||
@ -587,18 +487,8 @@ describe('peer-routing', () => {
|
|||||||
|
|
||||||
sinon.spy(node.peerStore.addressBook, 'add')
|
sinon.spy(node.peerStore.addressBook, 'add')
|
||||||
sinon.stub(node._dht, 'getClosestPeers').callsFake(function * () {
|
sinon.stub(node._dht, 'getClosestPeers').callsFake(function * () {
|
||||||
yield {
|
yield results[0]
|
||||||
name: 'PEER_RESPONSE',
|
yield results[1]
|
||||||
closer: [
|
|
||||||
results[0]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
yield {
|
|
||||||
name: 'PEER_RESPONSE',
|
|
||||||
closer: [
|
|
||||||
results[1]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await node.start()
|
await node.start()
|
||||||
@ -632,7 +522,7 @@ describe('peer-routing', () => {
|
|||||||
started: false
|
started: false
|
||||||
})
|
})
|
||||||
|
|
||||||
sinon.stub(node._dht, 'getClosestPeers').callsFake(async function * () {
|
sinon.stub(node._dht, 'getClosestPeers').callsFake(function * () {
|
||||||
yield
|
yield
|
||||||
throw new Error('should not be called')
|
throw new Error('should not be called')
|
||||||
})
|
})
|
||||||
|
@ -13,6 +13,9 @@ const routingOptions = mergeOptions(baseOptions, {
|
|||||||
config: {
|
config: {
|
||||||
dht: {
|
dht: {
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
|
randomWalk: {
|
||||||
|
enabled: true
|
||||||
|
},
|
||||||
enabled: true
|
enabled: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.set('invalid peerId')
|
ab.set('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -55,7 +55,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if no addresses provided', () => {
|
it('throwns invalid parameters error if no addresses provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.set(peerId)
|
ab.set(peerId)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -65,7 +65,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid multiaddrs are provided', () => {
|
it('throwns invalid parameters error if invalid multiaddrs are provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.set(peerId, ['invalid multiaddr'])
|
ab.set(peerId, ['invalid multiaddr'])
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -159,7 +159,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.add('invalid peerId')
|
ab.add('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if no addresses provided', () => {
|
it('throwns invalid parameters error if no addresses provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.add(peerId)
|
ab.add(peerId)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -179,7 +179,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid multiaddrs are provided', () => {
|
it('throwns invalid parameters error if invalid multiaddrs are provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.add(peerId, ['invalid multiaddr'])
|
ab.add(peerId, ['invalid multiaddr'])
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.get('invalid peerId')
|
ab.get('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -343,7 +343,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.getMultiaddrsForPeer('invalid peerId')
|
ab.getMultiaddrsForPeer('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -391,7 +391,7 @@ describe('addressBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
ab.delete('invalid peerId')
|
ab.delete('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ describe('keyBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided in set', () => {
|
it('throws invalid parameters error if invalid PeerId is provided in set', () => {
|
||||||
try {
|
try {
|
||||||
kb.set('invalid peerId')
|
kb.set('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ describe('keyBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided in get', () => {
|
it('throws invalid parameters error if invalid PeerId is provided in get', () => {
|
||||||
try {
|
try {
|
||||||
kb.get('invalid peerId')
|
kb.get('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.set('invalid peerId')
|
mb.set('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -44,7 +44,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if no key provided', () => {
|
it('throws invalid parameters error if no key provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.set(peerId)
|
mb.set(peerId)
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if no value provided', () => {
|
it('throws invalid parameters error if no value provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.set(peerId, 'location')
|
mb.set(peerId, 'location')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if value is not a buffer', () => {
|
it('throws invalid parameters error if value is not a buffer', () => {
|
||||||
try {
|
try {
|
||||||
mb.set(peerId, 'location', 'mars')
|
mb.set(peerId, 'location', 'mars')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -163,7 +163,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.get('invalid peerId')
|
mb.get('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -199,7 +199,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.getValue('invalid peerId')
|
mb.getValue('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ describe('metadataBook', () => {
|
|||||||
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
it('throwns invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.delete('invalid peerId')
|
mb.delete('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -305,7 +305,7 @@ describe('metadataBook', () => {
|
|||||||
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
it('throws invalid parameters error if invalid PeerId is provided', () => {
|
||||||
try {
|
try {
|
||||||
mb.deleteValue('invalid peerId')
|
mb.deleteValue('invalid peerId')
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
expect(err.code).to.equal(ERR_INVALID_PARAMETERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@ const { Multiaddr } = require('multiaddr')
|
|||||||
const mockUpgrader = require('../utils/mockUpgrader')
|
const mockUpgrader = require('../utils/mockUpgrader')
|
||||||
const sinon = require('sinon')
|
const sinon = require('sinon')
|
||||||
const Peers = require('../fixtures/peers')
|
const Peers = require('../fixtures/peers')
|
||||||
const pWaitFor = require('p-wait-for')
|
|
||||||
const addrs = [
|
const addrs = [
|
||||||
new Multiaddr('/ip4/127.0.0.1/tcp/0'),
|
new Multiaddr('/ip4/127.0.0.1/tcp/0'),
|
||||||
new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
new Multiaddr('/ip4/127.0.0.1/tcp/0')
|
||||||
@ -73,13 +72,9 @@ describe('Transport Manager (TCP)', () => {
|
|||||||
tm.add(Transport.prototype[Symbol.toStringTag], Transport)
|
tm.add(Transport.prototype[Symbol.toStringTag], Transport)
|
||||||
await tm.listen(addrs)
|
await tm.listen(addrs)
|
||||||
|
|
||||||
// Should created Self Peer record on new listen address, but it is done async
|
// Should created Self Peer record on new listen address
|
||||||
// with no event so we have to wait a bit
|
signedPeerRecord = await tm.libp2p.peerStore.addressBook.getPeerRecord(localPeer)
|
||||||
await pWaitFor(async () => {
|
expect(signedPeerRecord).to.exist()
|
||||||
signedPeerRecord = await tm.libp2p.peerStore.addressBook.getPeerRecord(localPeer)
|
|
||||||
|
|
||||||
return signedPeerRecord != null
|
|
||||||
}, { interval: 100, timeout: 2000 })
|
|
||||||
|
|
||||||
const record = PeerRecord.createFromProtobuf(signedPeerRecord.payload)
|
const record = PeerRecord.createFromProtobuf(signedPeerRecord.payload)
|
||||||
expect(record).to.exist()
|
expect(record).to.exist()
|
||||||
|
@ -201,7 +201,7 @@ describe('libp2p.transportManager (dial only)', () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await libp2p.start()
|
await libp2p.start()
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
expect(err).to.exist()
|
expect(err).to.exist()
|
||||||
expect(err.code).to.equal(ErrorCodes.ERR_NO_VALID_ADDRESSES)
|
expect(err.code).to.equal(ErrorCodes.ERR_NO_VALID_ADDRESSES)
|
||||||
return
|
return
|
||||||
|
@ -7,16 +7,16 @@
|
|||||||
"libp2p": "file:../..",
|
"libp2p": "file:../..",
|
||||||
"libp2p-bootstrap": "^0.13.0",
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
"libp2p-delegated-content-routing": "^0.11.0",
|
"libp2p-delegated-content-routing": "^0.11.0",
|
||||||
"libp2p-delegated-peer-routing": "^0.11.1",
|
"libp2p-delegated-peer-routing": "^0.10.0",
|
||||||
"libp2p-gossipsub": "^0.9.0",
|
"libp2p-gossipsub": "^0.9.0",
|
||||||
"libp2p-interfaces": "^1.0.1",
|
"libp2p-interfaces": "^1.0.1",
|
||||||
"libp2p-kad-dht": "^0.26.5",
|
"libp2p-kad-dht": "^0.23.1",
|
||||||
"libp2p-mplex": "^0.10.4",
|
"libp2p-mplex": "^0.10.4",
|
||||||
"@chainsafe/libp2p-noise": "^4.1.0",
|
"@chainsafe/libp2p-noise": "^4.1.0",
|
||||||
"libp2p-record": "^0.10.4",
|
"libp2p-record": "^0.10.4",
|
||||||
"libp2p-tcp": "^0.17.1",
|
"libp2p-tcp": "^0.17.1",
|
||||||
"libp2p-websockets": "^0.16.1",
|
"libp2p-websockets": "^0.16.1",
|
||||||
"peer-id": "^0.16.0"
|
"peer-id": "^0.15.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "npx tsc",
|
"build": "npx tsc",
|
||||||
|
@ -123,6 +123,11 @@ async function main() {
|
|||||||
dht: {
|
dht: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
kBucketSize: 20,
|
kBucketSize: 20,
|
||||||
|
randomWalk: {
|
||||||
|
enabled: true, // Allows to disable discovery (enabled by default)
|
||||||
|
interval: 300e3,
|
||||||
|
timeout: 10e3
|
||||||
|
},
|
||||||
clientMode: true,
|
clientMode: true,
|
||||||
validators: {
|
validators: {
|
||||||
pk: Libp2pRecord.validator.validators.pk
|
pk: Libp2pRecord.validator.validators.pk
|
||||||
|
@ -108,7 +108,7 @@ function createConnection ({
|
|||||||
// Need to be able to notify a peer of this this._onStream({ connection, stream, protocol })
|
// Need to be able to notify a peer of this this._onStream({ connection, stream, protocol })
|
||||||
const handler = protocols.get(protocol)
|
const handler = protocols.get(protocol)
|
||||||
handler({ connection, stream, protocol })
|
handler({ connection, stream, protocol })
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -124,7 +124,7 @@ function createConnection ({
|
|||||||
try {
|
try {
|
||||||
const { stream, protocol } = await mss.select(protocols)
|
const { stream, protocol } = await mss.select(protocols)
|
||||||
return { stream: { ...muxedStream, ...stream }, protocol }
|
return { stream: { ...muxedStream, ...stream }, protocol }
|
||||||
} catch (/** @type {any} */ err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
throw errCode(err, codes.ERR_UNSUPPORTED_PROTOCOL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"extends": "aegir/src/config/tsconfig.aegir.json",
|
"extends": "./node_modules/aegir/src/config/tsconfig.aegir.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "dist"
|
"outDir": "dist"
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user