mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-10 14:21:33 +00:00
Compare commits
101 Commits
Author | SHA1 | Date | |
---|---|---|---|
d6bb967243 | |||
d48005b8b7 | |||
67b97e32da | |||
664ba2d1e7 | |||
608564b033 | |||
af723b355e | |||
13cf476148 | |||
39b03586e8 | |||
f7183e8afd | |||
b9988adce9 | |||
b291bc06ec | |||
755eb909f2 | |||
afe0f854e8 | |||
50f7f32e53 | |||
052aad4e06 | |||
2c4b567b00 | |||
2a6a635f13 | |||
cd152f122f | |||
2959794796 | |||
2068c845cb | |||
d8ba284883 | |||
869d35d852 | |||
d6540bf01d | |||
478963ad2d | |||
d22ad83890 | |||
538f296b0a | |||
7bac2045cc | |||
818d2b2a98 | |||
d163ffd224 | |||
b29d6c9304 | |||
890dd05941 | |||
a79c6b50d7 | |||
d372a68692 | |||
4e3fc19623 | |||
2fa82b387c | |||
8fc6f8af81 | |||
924585b143 | |||
556f0203db | |||
b5a9eb2087 | |||
e5187d02ba | |||
150e4f97c1 | |||
302bb90058 | |||
f860ffb3e7 | |||
2572f3e034 | |||
d76356e56a | |||
e9543eb2e1 | |||
5282708263 | |||
ed494f03ae | |||
ac370fc967 | |||
ef4393649f | |||
f23fd4b7c7 | |||
5372f7af2f | |||
97da0ba740 | |||
88b04156bf | |||
64f3af897b | |||
54e502afcb | |||
086b0ec0df | |||
cc1f4af879 | |||
6456a0fff8 | |||
44463b9145 | |||
7eb2cea570 | |||
c381be3510 | |||
975e77991e | |||
b043bca607 | |||
3ffeb4ebe6 | |||
06e8f3dd42 | |||
3f7dde3e13 | |||
6f4e7ceeac | |||
2af692fb4d | |||
906315ce73 | |||
49f04cbe70 | |||
3d0a79eff3 | |||
55ee332907 | |||
ffe122d47e | |||
21c9aeecb1 | |||
a93cca9178 | |||
828a32d4f5 | |||
b4fb9b7bf2 | |||
0aed9fe1b3 | |||
9d1b917e8a | |||
8506414ea1 | |||
8e1743cac4 | |||
3ea95ce642 | |||
c4cae29ef3 | |||
a7128f07ec | |||
c3e147df6b | |||
b89445274d | |||
b9e3bcd91e | |||
f5c1cd1fb0 | |||
975e4b0fe0 | |||
9504f1951a | |||
8e1fc78353 | |||
8895a092b6 | |||
f2f361998d | |||
5f702f3481 | |||
03b34cac7d | |||
9c67364caa | |||
a1424826e7 | |||
3d5bba070b | |||
3f314d5e90 | |||
4ee3e1973b |
24
.aegir.js
24
.aegir.js
@ -1,5 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
const Libp2p = require('./src')
|
const Libp2p = require('./src')
|
||||||
const { MULTIADDRS_WEBSOCKETS } = require('./test/fixtures/browser')
|
const { MULTIADDRS_WEBSOCKETS } = require('./test/fixtures/browser')
|
||||||
const Peers = require('./test/fixtures/peers')
|
const Peers = require('./test/fixtures/peers')
|
||||||
@ -47,16 +48,23 @@ const after = async () => {
|
|||||||
await libp2p.stop()
|
await libp2p.stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {import('aegir').Options["build"]["config"]} */
|
||||||
|
const esbuild = {
|
||||||
|
inject: [path.join(__dirname, './scripts/node-globals.js')]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {import('aegir').PartialOptions} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
bundlesize: { maxSize: '220kB' },
|
build: {
|
||||||
hooks: {
|
bundlesizeMax: '253kB'
|
||||||
pre: before,
|
|
||||||
post: after
|
|
||||||
},
|
},
|
||||||
webpack: {
|
test: {
|
||||||
node: {
|
before,
|
||||||
// needed by bcrypto
|
after,
|
||||||
Buffer: true
|
browser: {
|
||||||
|
config: {
|
||||||
|
buildConfig: esbuild
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: libp2p Official Forum
|
||||||
|
url: https://discuss.libp2p.io
|
||||||
|
about: For general questions, support requests and discussions
|
55
.github/ISSUE_TEMPLATE/open_an_issue.md
vendored
Normal file
55
.github/ISSUE_TEMPLATE/open_an_issue.md
vendored
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
---
|
||||||
|
name: Open an issue
|
||||||
|
about: For reporting bugs or errors in the JavaScript libp2p implementation
|
||||||
|
title: ''
|
||||||
|
labels: need/triage
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Thank you for reporting an issue.
|
||||||
|
|
||||||
|
This issue tracker is for bugs found within the JavaScript implementation of libp2p.
|
||||||
|
|
||||||
|
If you are asking a question about how to use libp2p, please ask on https://discuss.libp2p.io
|
||||||
|
|
||||||
|
Otherwise please fill in as much of the template below as possible.
|
||||||
|
-->
|
||||||
|
|
||||||
|
- **Version**:
|
||||||
|
<!--
|
||||||
|
Check package.json version
|
||||||
|
-->
|
||||||
|
|
||||||
|
- **Platform**:
|
||||||
|
<!--
|
||||||
|
Output of `uname -a` (UNIX), or version and 32 or 64-bit (Windows). If using in a Browser, please share the browser version as well
|
||||||
|
-->
|
||||||
|
|
||||||
|
- **Subsystem**:
|
||||||
|
<!--
|
||||||
|
If known, please specify affected core module name (e.g Dialer, Pubsub, Relay etc)
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Severity:
|
||||||
|
<!--
|
||||||
|
One of following:
|
||||||
|
Critical - System crash, application panic.
|
||||||
|
High - The main functionality of the application does not work, API breakage, repo format breakage, etc.
|
||||||
|
Medium - A non-essential functionality does not work, performance issues, etc.
|
||||||
|
Low - An optional functionality does not work.
|
||||||
|
Very Low - Translation or documentation mistake. Something that won't give anyone a bad day.
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Description:
|
||||||
|
<!--
|
||||||
|
- What you did
|
||||||
|
- What happened
|
||||||
|
- What you expected to happen
|
||||||
|
-->
|
||||||
|
|
||||||
|
#### Steps to reproduce the error:
|
||||||
|
<!--
|
||||||
|
If possible, please provide code that demonstrates the problem, keeping it as simple and free of external dependencies as you are able
|
||||||
|
-->
|
||||||
|
|
@ -25,8 +25,6 @@
|
|||||||
- [ ] [js-ipfs](https://github.com/ipfs/js-ipfs)
|
- [ ] [js-ipfs](https://github.com/ipfs/js-ipfs)
|
||||||
- Documentation
|
- Documentation
|
||||||
- [ ] Ensure that README.md is up to date
|
- [ ] Ensure that README.md is up to date
|
||||||
- [ ] Ensure that all the examples run
|
|
||||||
- [ ] Ensure [libp2p/js-libp2p-examples](https://github.com/libp2p/js-libp2p-examples) is updated
|
|
||||||
- [ ] Ensure that [libp2p/docs](https://github.com/libp2p/docs) is updated
|
- [ ] Ensure that [libp2p/docs](https://github.com/libp2p/docs) is updated
|
||||||
- Communication
|
- Communication
|
||||||
- [ ] Create the release issue
|
- [ ] Create the release issue
|
102
.github/workflows/examples.yml
vendored
Normal file
102
.github/workflows/examples.yml
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
name: examples
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: npx aegir lint
|
||||||
|
- run: npx aegir ts -p check
|
||||||
|
- run: npx aegir build
|
||||||
|
test-auto-relay-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- auto-relay
|
||||||
|
test-chat-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- chat
|
||||||
|
test-connection-encryption-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- connection-encryption
|
||||||
|
test-discovery-mechanisms-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- discovery-mechanisms
|
||||||
|
test-echo-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- echo
|
||||||
|
test-libp2p-in-the-browser-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
|
||||||
|
test-peer-and-content-routing-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- peer-and-content-routing
|
||||||
|
test-pnet-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- pnet
|
||||||
|
test-protocol-and-stream-muxing-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- protocol-and-stream-muxing
|
||||||
|
test-pubsub-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- pubsub
|
||||||
|
test-transports-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- transports
|
||||||
|
test-webrtc-direct-example:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: cd examples && yarn && npm run test -- webrtc-direct
|
110
.github/workflows/main.yml
vendored
110
.github/workflows/main.yml
vendored
@ -12,11 +12,15 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: yarn
|
- name: Use Node.js 14
|
||||||
- run: yarn lint
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: 14
|
||||||
|
- run: npm install
|
||||||
|
- run: npx aegir lint
|
||||||
- uses: gozala/typescript-error-reporter-action@v1.0.8
|
- uses: gozala/typescript-error-reporter-action@v1.0.8
|
||||||
- run: yarn build
|
- run: npx aegir build
|
||||||
- run: yarn aegir dep-check
|
- run: npx aegir dep-check
|
||||||
- uses: ipfs/aegir/actions/bundle-size@master
|
- uses: ipfs/aegir/actions/bundle-size@master
|
||||||
name: size
|
name: size
|
||||||
with:
|
with:
|
||||||
@ -27,111 +31,41 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||||
node: [12, 14]
|
node: [14, 16]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
- run: yarn
|
- run: npm install
|
||||||
- run: npx nyc --reporter=lcov aegir test -t node -- --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
|
||||||
- run: yarn
|
- run: npm install
|
||||||
- run: npx aegir test -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
|
||||||
- run: yarn
|
- run: npm install
|
||||||
- run: npx aegir test -t browser -t webworker --bail -- --browsers FirefoxHeadless
|
- run: npx aegir test -t browser -t webworker --bail -- --browser firefox
|
||||||
|
test-ts:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: npm install
|
||||||
|
- run: npm run test:ts
|
||||||
test-interop:
|
test-interop:
|
||||||
needs: check
|
needs: check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: yarn
|
- run: npm install
|
||||||
- run: cd node_modules/interop-libp2p && yarn && LIBP2P_JS=${GITHUB_WORKSPACE}/src/index.js npx aegir test -t node --bail
|
- run: cd node_modules/interop-libp2p && yarn && LIBP2P_JS=${GITHUB_WORKSPACE}/src/index.js npx aegir test -t node --bail
|
||||||
test-auto-relay-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- auto-relay
|
|
||||||
test-chat-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- chat
|
|
||||||
test-connection-encryption-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- connection-encryption
|
|
||||||
test-discovery-mechanisms-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- discovery-mechanisms
|
|
||||||
test-echo-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- echo
|
|
||||||
test-libp2p-in-the-browser-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: macos-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
|
|
||||||
test-peer-and-content-routing-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- peer-and-content-routing
|
|
||||||
test-pnet-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- pnet
|
|
||||||
test-protocol-and-stream-muxing-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- protocol-and-stream-muxing
|
|
||||||
test-pubsub-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- pubsub
|
|
||||||
test-transports-example:
|
|
||||||
needs: check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- run: yarn
|
|
||||||
- run: cd examples && yarn && npm run test -- transports
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,7 @@ docs
|
|||||||
test/repo-tests*
|
test/repo-tests*
|
||||||
**/bundle.js
|
**/bundle.js
|
||||||
.cache
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
|
201
CHANGELOG.md
201
CHANGELOG.md
@ -1,3 +1,204 @@
|
|||||||
|
# [0.32.0](https://github.com/libp2p/js-libp2p/compare/v0.32.0-rc.0...v0.32.0) (2021-07-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.32.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.31.7...v0.32.0-rc.0) (2021-07-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* do not allow dial to large number of multiaddrs ([#954](https://github.com/libp2p/js-libp2p/issues/954)) ([af723b3](https://github.com/libp2p/js-libp2p/commit/af723b355e1ddf4aecf439f81c3aa67613d45fa4))
|
||||||
|
|
||||||
|
|
||||||
|
### chore
|
||||||
|
|
||||||
|
* update to new multiformats ([#948](https://github.com/libp2p/js-libp2p/issues/948)) ([13cf476](https://github.com/libp2p/js-libp2p/commit/13cf4761489d59b22924bb8ec2ec6dbe207b280c))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* uses the CID class from the new multiformats module
|
||||||
|
|
||||||
|
Co-authored-by: Vasco Santos <vasco.santos@moxy.studio>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.7](https://github.com/libp2p/js-libp2p/compare/v0.31.6...v0.31.7) (2021-06-14)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* chat example with new multiaddr ([#946](https://github.com/libp2p/js-libp2p/issues/946)) ([d8ba284](https://github.com/libp2p/js-libp2p/commit/d8ba2848833d9fb8a963d1b7c8d27062c6f829da))
|
||||||
|
* dialer leaking resources after stopping ([#947](https://github.com/libp2p/js-libp2p/issues/947)) ([b291bc0](https://github.com/libp2p/js-libp2p/commit/b291bc06ec13feeb6e010730edfad754a3b2dc1b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.6](https://github.com/libp2p/js-libp2p/compare/v0.31.5...v0.31.6) (2021-05-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* keychain rotate passphrase ([#944](https://github.com/libp2p/js-libp2p/issues/944)) ([478963a](https://github.com/libp2p/js-libp2p/commit/478963ad2d195444494c0acc54cb3847a29e117c))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.5](https://github.com/libp2p/js-libp2p/compare/v0.31.4...v0.31.5) (2021-05-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* store remote agent and protocol version during identify ([#943](https://github.com/libp2p/js-libp2p/issues/943)) ([818d2b2](https://github.com/libp2p/js-libp2p/commit/818d2b2a98736f4242694479089396f6070cdad5))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.4](https://github.com/libp2p/js-libp2p/compare/v0.31.3...v0.31.4) (2021-05-12)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* peerRouting.findPeer() trying to find self ([#941](https://github.com/libp2p/js-libp2p/issues/941)) ([a79c6b5](https://github.com/libp2p/js-libp2p/commit/a79c6b50d7fddbcdb1af53efae922cecad4c9a83))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.3](https://github.com/libp2p/js-libp2p/compare/v0.31.2...v0.31.3) (2021-05-04)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.2](https://github.com/libp2p/js-libp2p/compare/v0.31.1...v0.31.2) (2021-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* moving averages record types ([#935](https://github.com/libp2p/js-libp2p/issues/935)) ([b5a9eb2](https://github.com/libp2p/js-libp2p/commit/b5a9eb208763efa027d0b4caae87c515b6f5869b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.31.1](https://github.com/libp2p/js-libp2p/compare/v0.31.0...v0.31.1) (2021-04-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* event emitter and interfaces types for discovery and routing ([#934](https://github.com/libp2p/js-libp2p/issues/934)) ([302bb90](https://github.com/libp2p/js-libp2p/commit/302bb9005891aa06b70a5f354bfac6b2d5a3c3b8))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.7...v0.31.0) (2021-04-28)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.7](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.6...v0.31.0-rc.7) (2021-04-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* address book guarantees no replicated entries are added ([#927](https://github.com/libp2p/js-libp2p/issues/927)) ([ac370fc](https://github.com/libp2p/js-libp2p/commit/ac370fc9679b51da8cee3791b6dd268d0695d136))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.6](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.5...v0.31.0-rc.6) (2021-04-22)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* keychain optional pw and use interfaces for validators and selectors instead ([#924](https://github.com/libp2p/js-libp2p/issues/924)) ([88b0415](https://github.com/libp2p/js-libp2p/commit/88b04156bf614650c2b14d49b12e969c5eecf04d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.5](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.4...v0.31.0-rc.5) (2021-04-21)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* address book should not emit peer event if no addresses are known ([b4fb9b7](https://github.com/libp2p/js-libp2p/commit/b4fb9b7bf266ba03c4462c0a41b1c2691e4e88d4))
|
||||||
|
* demand pubsub subclass instead of pubsub instance ([#922](https://github.com/libp2p/js-libp2p/issues/922)) ([086b0ec](https://github.com/libp2p/js-libp2p/commit/086b0ec0df2fac93845d0a0a6b2e2464e869afcd))
|
||||||
|
* dht configuration selectors and validators ([#919](https://github.com/libp2p/js-libp2p/issues/919)) ([cc1f4af](https://github.com/libp2p/js-libp2p/commit/cc1f4af879a58e94538591851d0085ff98cd2641))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.4](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.3...v0.31.0-rc.4) (2021-04-20)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* add clientMode dht arg and upgrade interface-datastore ([#918](https://github.com/libp2p/js-libp2p/issues/918)) ([975e779](https://github.com/libp2p/js-libp2p/commit/975e77991e67dd9bff790b83df7bd6fa5ddcfc67))
|
||||||
|
* do not add abort signals to useless addresses ([#913](https://github.com/libp2p/js-libp2p/issues/913)) ([06e8f3d](https://github.com/libp2p/js-libp2p/commit/06e8f3dd42432e4b37ab7904b02abde7d1cadda3))
|
||||||
|
* specify pbjs root ([#917](https://github.com/libp2p/js-libp2p/issues/917)) ([b043bca](https://github.com/libp2p/js-libp2p/commit/b043bca607565cf534771e6cf975288a8ff3030b))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.3](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.2...v0.31.0-rc.3) (2021-04-19)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* remove inline arg types from function definitions ([#916](https://github.com/libp2p/js-libp2p/issues/916)) ([2af692f](https://github.com/libp2p/js-libp2p/commit/2af692fb4de572168524ae684608fc6526de4ef7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.2](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.1...v0.31.0-rc.2) (2021-04-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* metrics stats and moving averages types ([#915](https://github.com/libp2p/js-libp2p/issues/915)) ([3d0a79e](https://github.com/libp2p/js-libp2p/commit/3d0a79eff3bc34a5bdc8ffa31e9b09345a02ad9d))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.1](https://github.com/libp2p/js-libp2p/compare/v0.31.0-rc.0...v0.31.0-rc.1) (2021-04-16)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* dial protocol should throw if no protocol is provided ([#914](https://github.com/libp2p/js-libp2p/issues/914)) ([21c9aee](https://github.com/libp2p/js-libp2p/commit/21c9aeecb13440238aa6b0fb5a6731d2f87d4938))
|
||||||
|
|
||||||
|
|
||||||
|
### BREAKING CHANGES
|
||||||
|
|
||||||
|
* dialProtocol does not return connection when no protocols are provided
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# [0.31.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.30.12...v0.31.0-rc.0) (2021-04-15)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.30.12](https://github.com/libp2p/js-libp2p/compare/v0.30.11...v0.30.12) (2021-03-27)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* the API of es6-promisify is not the same as promisify-es6 ([#905](https://github.com/libp2p/js-libp2p/issues/905)) ([a7128f0](https://github.com/libp2p/js-libp2p/commit/a7128f07ec8d4b729145ecfc6ad1d585ffddea46))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.30.11](https://github.com/libp2p/js-libp2p/compare/v0.30.10...v0.30.11) (2021-03-23)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* connection direction should be only inbound or outbound ([9504f19](https://github.com/libp2p/js-libp2p/commit/9504f1951a3cca55bb7b4e25e4934e4024034ee8))
|
||||||
|
* interface-datastore update ([f5c1cd1](https://github.com/libp2p/js-libp2p/commit/f5c1cd1fb07bc73cf9d9da3c2eb4327bed4279a4))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.30.10](https://github.com/libp2p/js-libp2p/compare/v0.30.9...v0.30.10) (2021-03-09)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* conn mgr access to moving averages record object ([#897](https://github.com/libp2p/js-libp2p/issues/897)) ([5f702f3](https://github.com/libp2p/js-libp2p/commit/5f702f3481afd4ad4fbc89f0e9b75a6d56b03520))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [0.30.9](https://github.com/libp2p/js-libp2p/compare/v0.30.8...v0.30.9) (2021-02-25)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* transport manager fault tolerance should include tolerance to transport listen fail ([#893](https://github.com/libp2p/js-libp2p/issues/893)) ([3f314d5](https://github.com/libp2p/js-libp2p/commit/3f314d5e90f74583b721386d0c9c5d8363cd4de7))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## [0.30.8](https://github.com/libp2p/js-libp2p/compare/v0.30.7...v0.30.8) (2021-02-11)
|
## [0.30.8](https://github.com/libp2p/js-libp2p/compare/v0.30.7...v0.30.8) (2021-02-11)
|
||||||
|
|
||||||
|
|
||||||
|
@ -282,7 +282,7 @@ const node = await Libp2p.create({
|
|||||||
interval: 1000,
|
interval: 1000,
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
[Bootstrap.tag:] {
|
[Bootstrap.tag]: {
|
||||||
list: [ // A list of bootstrap peers to connect to starting up the node
|
list: [ // A list of bootstrap peers to connect to starting up the node
|
||||||
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
|
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
|
||||||
"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
|
"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
|
||||||
@ -373,7 +373,7 @@ const node = await Libp2p.create({
|
|||||||
config: {
|
config: {
|
||||||
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,
|
enabled: true, // This flag is required for DHT to run (disabled by default)
|
||||||
randomWalk: {
|
randomWalk: {
|
||||||
enabled: true, // Allows to disable discovery (enabled by default)
|
enabled: true, // Allows to disable discovery (enabled by default)
|
||||||
interval: 300e3,
|
interval: 300e3,
|
||||||
@ -399,14 +399,14 @@ const PeerId = require('peer-id')
|
|||||||
// create a peerId
|
// create a peerId
|
||||||
const peerId = await PeerId.create()
|
const peerId = await PeerId.create()
|
||||||
|
|
||||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient({
|
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient.create({
|
||||||
host: 'node0.delegate.ipfs.io' // In production you should setup your own delegates
|
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
port: 443
|
port: 443
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient.create({
|
||||||
host: 'node0.delegate.ipfs.io' // In production you should setup your own delegates
|
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||||
protocol: 'https',
|
protocol: 'https',
|
||||||
port: 443
|
port: 443
|
||||||
}))
|
}))
|
||||||
@ -515,7 +515,7 @@ const node = await Libp2p.create({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
await libp2p.loadKeychain()
|
await node.loadKeychain()
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Configuring Dialing
|
#### Configuring Dialing
|
||||||
@ -525,6 +525,7 @@ Dialing in libp2p can be configured to limit the rate of dialing, and how long d
|
|||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
|------|------|-------------|
|
|------|------|-------------|
|
||||||
| maxParallelDials | `number` | How many multiaddrs we can dial in parallel. |
|
| maxParallelDials | `number` | How many multiaddrs we can dial in parallel. |
|
||||||
|
| maxAddrsToDial | `number` | How many multiaddrs is the dial allowed to dial for a single peer. |
|
||||||
| maxDialsPerPeer | `number` | How many multiaddrs we can dial per peer, in parallel. |
|
| maxDialsPerPeer | `number` | How many multiaddrs we can dial per peer, in parallel. |
|
||||||
| dialTimeout | `number` | Second dial timeout per peer in ms. |
|
| dialTimeout | `number` | Second dial timeout per peer in ms. |
|
||||||
| resolvers | `object` | Dial [Resolvers](https://github.com/multiformats/js-multiaddr/blob/master/src/resolvers/index.js) for resolving multiaddrs |
|
| resolvers | `object` | Dial [Resolvers](https://github.com/multiformats/js-multiaddr/blob/master/src/resolvers/index.js) for resolving multiaddrs |
|
||||||
@ -549,6 +550,7 @@ const node = await Libp2p.create({
|
|||||||
},
|
},
|
||||||
dialer: {
|
dialer: {
|
||||||
maxParallelDials: 100,
|
maxParallelDials: 100,
|
||||||
|
maxAddrsToDial: 25,
|
||||||
maxDialsPerPeer: 4,
|
maxDialsPerPeer: 4,
|
||||||
dialTimeout: 30e3,
|
dialTimeout: 30e3,
|
||||||
resolvers: {
|
resolvers: {
|
||||||
@ -599,7 +601,7 @@ 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 { FaultTolerance } = require('libp2p/src/transport-manager')}
|
const { FaultTolerance } = require('libp2p/src/transport-manager')
|
||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
modules: {
|
modules: {
|
||||||
|
123
doc/migrations/v0.30-v0.31.md
Normal file
123
doc/migrations/v0.30-v0.31.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<!--Specify versions for migration below-->
|
||||||
|
# Migrating to libp2p@31
|
||||||
|
|
||||||
|
A migration guide for refactoring your application code from libp2p v0.30.x to v0.31.0.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Types](#types)
|
||||||
|
- [API](#api)
|
||||||
|
- [Module Updates](#module-updates)
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
Most of the type definitions in the libp2p configuration were `any` or were not included before this release. This might cause breaking changes on upstream projects relying on the previous provided types, as well as to libp2p modules implemented by the libp2p community.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Core API
|
||||||
|
|
||||||
|
`libp2p.dialProtocol` does not accept empty or null protocols returning a connection anymore and `dial` must be used instead.
|
||||||
|
|
||||||
|
```js
|
||||||
|
const connection = await libp2p.dialProtocol(peerId)
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const connection = await libp2p.dial(peerId)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection Manager Options
|
||||||
|
|
||||||
|
We updated the connection manager options naming in `libp2p@0.29` but kept it backward compatible until now.
|
||||||
|
|
||||||
|
**Before**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const node = await Libp2p.create({
|
||||||
|
connectionManager: {
|
||||||
|
minPeers: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const node = await Libp2p.create({
|
||||||
|
connectionManager: {
|
||||||
|
minConnections: 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
You can see full details on how to configure the connection manager [here](https://github.com/libp2p/js-libp2p/blob/master/doc/CONFIGURATION.md#configuring-connection-manager).
|
||||||
|
|
||||||
|
### Dialer and Keychain components
|
||||||
|
|
||||||
|
Internal property names to create a libp2p `Dialer` and `Keychain` were updated to reflect the properties naming in the libp2p configuration. These are internal modules of libp2p core and should not impact most of the users, but as it is possible to use them separately here follow the changes:
|
||||||
|
|
||||||
|
***Before**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const dialer = new Dialer({
|
||||||
|
transportManager,
|
||||||
|
peerStore,
|
||||||
|
concurrency,
|
||||||
|
perPeerLimit,
|
||||||
|
timeout,
|
||||||
|
resolvers,
|
||||||
|
addressSorter
|
||||||
|
})
|
||||||
|
|
||||||
|
const keychain = new Keychain(datastore, {
|
||||||
|
passPhrase
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**After**
|
||||||
|
|
||||||
|
```js
|
||||||
|
this.dialer = new Dialer({
|
||||||
|
transportManager,
|
||||||
|
peerStore,
|
||||||
|
maxParallelDials,
|
||||||
|
maxDialsPerPeer,
|
||||||
|
dialTimeout,
|
||||||
|
resolvers,
|
||||||
|
addressSorter
|
||||||
|
})
|
||||||
|
|
||||||
|
const keychain = new Keychain(datastore, {
|
||||||
|
pass
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Module Updates
|
||||||
|
|
||||||
|
With this release you should update the following libp2p modules if you are relying on them:
|
||||||
|
|
||||||
|
<!--Specify module versions in JSON for migration below.
|
||||||
|
It's recommended to check package.json changes for this:
|
||||||
|
`git diff <release> <prev> -- package.json`
|
||||||
|
-->
|
||||||
|
|
||||||
|
```json
|
||||||
|
"libp2p-bootstrap": "^0.12.3",
|
||||||
|
"libp2p-crypto": "^0.19.4",
|
||||||
|
"libp2p-interfaces": "^0.10.0",
|
||||||
|
"libp2p-delegated-content-routing": "^0.10.0",
|
||||||
|
"libp2p-delegated-peer-routing": "^0.9.0",
|
||||||
|
"libp2p-floodsub": "^0.25.1",
|
||||||
|
"libp2p-gossipsub": "^0.9.0",
|
||||||
|
"libp2p-kad-dht": "^0.22.0",
|
||||||
|
"libp2p-mdns": "^0.16.0",
|
||||||
|
"libp2p-noise": "^3.0.0",
|
||||||
|
"libp2p-tcp": "^0.15.4",
|
||||||
|
"libp2p-webrtc-star": "^0.22.2",
|
||||||
|
"libp2p-websockets": "^0.15.6"
|
||||||
|
```
|
||||||
|
|
||||||
|
One of the main changes in this new release is the update to `multiaddr@9.0.0`. This should also be updated in upstream projects to avoid several multiaddr versions in the bundle and to avoid potential problems when libp2p interacts with provided outdated multiaddr instances.
|
36
doc/migrations/v0.31-v0.32.md
Normal file
36
doc/migrations/v0.31-v0.32.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<!--Specify versions for migration below-->
|
||||||
|
# Migrating to libp2p@32
|
||||||
|
|
||||||
|
A migration guide for refactoring your application code from libp2p v0.31.x to v0.32.0.
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Module Updates](#module-updates)
|
||||||
|
|
||||||
|
## Module Updates
|
||||||
|
|
||||||
|
With this release you should update the following libp2p modules if you are relying on them:
|
||||||
|
|
||||||
|
<!--Specify module versions in JSON for migration below.
|
||||||
|
It's recommended to check package.json changes for this:
|
||||||
|
`git diff <release> <prev> -- package.json`
|
||||||
|
-->
|
||||||
|
|
||||||
|
```json
|
||||||
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
|
"libp2p-crypto": "^0.19.4",
|
||||||
|
"libp2p-interfaces": "^1.0.0",
|
||||||
|
"libp2p-delegated-content-routing": "^0.11.0",
|
||||||
|
"libp2p-delegated-peer-routing": "^0.10.0",
|
||||||
|
"libp2p-floodsub": "^0.27.0",
|
||||||
|
"libp2p-gossipsub": "^0.11.0",
|
||||||
|
"libp2p-kad-dht": "^0.23.0",
|
||||||
|
"libp2p-mdns": "^0.17.0",
|
||||||
|
"libp2p-noise": "^4.0.0",
|
||||||
|
"libp2p-tcp": "^0.17.0",
|
||||||
|
"libp2p-webrtc-direct": "^0.7.0",
|
||||||
|
"libp2p-webrtc-star": "^0.23.0",
|
||||||
|
"libp2p-websockets": "^0.16.0"
|
||||||
|
```
|
||||||
|
|
||||||
|
One of the main changes in this new release is the update to `multiaddr@10.0.0`. This should also be updated in upstream projects to avoid several multiaddr versions in the bundle and to avoid potential problems when libp2p interacts with provided outdated multiaddr instances.
|
@ -8,7 +8,7 @@ Let us know if you find any issues, or if you want to contribute and add a new t
|
|||||||
|
|
||||||
- [Transports](./transports)
|
- [Transports](./transports)
|
||||||
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
|
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
|
||||||
- [Encrypted Communications](./encrypted-communications)
|
- [Connection Encryption](./connection-encryption)
|
||||||
- [Discovery Mechanisms](./discovery-mechanisms)
|
- [Discovery Mechanisms](./discovery-mechanisms)
|
||||||
- [Peer and Content Routing](./peer-and-content-routing)
|
- [Peer and Content Routing](./peer-and-content-routing)
|
||||||
- [PubSub](./pubsub)
|
- [PubSub](./pubsub)
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const createLibp2p = require('./libp2p')
|
const createLibp2p = require('./libp2p')
|
||||||
const { stdinToStream, streamToConsole } = require('./stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
|
|
||||||
async function run() {
|
async function run () {
|
||||||
const [idDialer, idListener] = await Promise.all([
|
const [idDialer, idListener] = await Promise.all([
|
||||||
PeerId.createFromJSON(require('./peer-id-dialer')),
|
PeerId.createFromJSON(require('./peer-id-dialer')),
|
||||||
PeerId.createFromJSON(require('./peer-id-listener'))
|
PeerId.createFromJSON(require('./peer-id-listener'))
|
||||||
@ -30,7 +30,7 @@ async function run() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Dial to the remote peer (the "listener")
|
// Dial to the remote peer (the "listener")
|
||||||
const listenerMa = multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toB58String()}`)
|
const listenerMa = new Multiaddr(`/ip4/127.0.0.1/tcp/10333/p2p/${idListener.toB58String()}`)
|
||||||
const { stream } = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0')
|
const { stream } = await nodeDialer.dialProtocol(listenerMa, '/chat/1.0.0')
|
||||||
|
|
||||||
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
|
console.log('Dialer dialed to listener on protocol: /chat/1.0.0')
|
||||||
|
@ -5,7 +5,7 @@ const PeerId = require('peer-id')
|
|||||||
const createLibp2p = require('./libp2p.js')
|
const createLibp2p = require('./libp2p.js')
|
||||||
const { stdinToStream, streamToConsole } = require('./stream')
|
const { stdinToStream, streamToConsole } = require('./stream')
|
||||||
|
|
||||||
async function run() {
|
async function run () {
|
||||||
// Create a new libp2p node with the given multi-address
|
// Create a new libp2p node with the given multi-address
|
||||||
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
|
||||||
const nodeListener = await createLibp2p({
|
const nodeListener = await createLibp2p({
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
A Peer Discovery module enables libp2p to find peers to connect to. Think of these mechanisms as ways to join the rest of the network, as railing points.
|
A Peer Discovery module enables libp2p to find peers to connect to. Think of these mechanisms as ways to join the rest of the network, as railing points.
|
||||||
|
|
||||||
With these system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
|
With this system, a libp2p node can both have a set of nodes to always connect on boot (bootstraper nodes), discover nodes through locality (e.g connected in the same LAN) or through serendipity (random walks on a DHT).
|
||||||
|
|
||||||
These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore.
|
These mechanisms save configuration and enable a node to operate without any explicit dials, it will just work. Once new peers are discovered, their known data is stored in the peer's PeerStore.
|
||||||
|
|
||||||
## 1. Bootstrap list of Peers when booting a node
|
## 1. Bootstrap list of Peers when booting a node
|
||||||
|
|
||||||
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex and NOISE. You can see the complete example at [1.js](./1.js).
|
For this demo, we will connect to IPFS default bootstrapper nodes and so, we will need to support the same set of features those nodes have, that are: TCP, mplex, and NOISE. You can see the complete example at [1.js](./1.js).
|
||||||
|
|
||||||
First, we create our libp2p node.
|
First, we create our libp2p node.
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ First, we create our libp2p node.
|
|||||||
const Libp2p = require('libp2p')
|
const Libp2p = require('libp2p')
|
||||||
const Bootstrap = require('libp2p-bootstrap')
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
|
|
||||||
const node = Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
modules: {
|
modules: {
|
||||||
transport: [ TCP ],
|
transport: [ TCP ],
|
||||||
streamMuxer: [ Mplex ],
|
streamMuxer: [ Mplex ],
|
||||||
@ -203,7 +203,7 @@ const createNode = async (bootstrapers) => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We will use the `libp2p-relay-server` as bootstrap nodes for the libp2p nodes, so that they establish a connection with the relay after starting. As a result, after they establish a connection with the relay, the pubsub discovery will kick in an the relay will advertise them.
|
We will use the `libp2p-relay-server` as bootstrap nodes for the libp2p nodes, so that they establish a connection with the relay after starting. As a result, after they establish a connection with the relay, the pubsub discovery will kick in and the relay will advertise them.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const relay = await createRelayServer({
|
const relay = await createRelayServer({
|
||||||
@ -254,5 +254,5 @@ This is really useful when running libp2p in constrained environments like a bro
|
|||||||
There are plenty more Peer Discovery Mechanisms out there, you can:
|
There are plenty more Peer Discovery Mechanisms out there, you can:
|
||||||
|
|
||||||
- Find one in [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star). Yes, a transport with discovery capabilities! This happens because WebRTC requires a rendezvous point for peers to exchange [SDP](https://tools.ietf.org/html/rfc4317) offer, which means we have one or more points that can introduce peers to each other. Think of it as MulticastDNS for the Web, as in MulticastDNS only works in LAN.
|
- Find one in [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star). Yes, a transport with discovery capabilities! This happens because WebRTC requires a rendezvous point for peers to exchange [SDP](https://tools.ietf.org/html/rfc4317) offer, which means we have one or more points that can introduce peers to each other. Think of it as MulticastDNS for the Web, as in MulticastDNS only works in LAN.
|
||||||
- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht).
|
- Any DHT will offer you a discovery capability. You can simple _random-walk_ the routing tables to find other peers to connect to. For example [libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) can be used for peer discovery. An example of how to configure it to enable random walks can be found [here](https://github.com/libp2p/js-libp2p/blob/v0.28.4/doc/CONFIGURATION.md#customizing-dht).
|
||||||
- You can create your own Discovery service, a registry, a list, a radio beacon, you name it!
|
- You can create your own Discovery service, a registry, a list, a radio beacon, you name it!
|
||||||
|
@ -4,9 +4,13 @@ This example leverages the [Parcel.js bundler](https://parceljs.org/) to compile
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
In order to run the example, first install the dependencies from same directory as this README:
|
In order to run the example:
|
||||||
|
|
||||||
|
- Install dependencey at the root of the js-libp2p repository (if not already done),
|
||||||
|
- then, install the dependencies from same directory as this README:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
npm install
|
||||||
cd ./examples/libp2p-in-the-browser
|
cd ./examples/libp2p-in-the-browser
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"name": "libp2p-in-browser",
|
"name": "libp2p-in-browser",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A libp2p node running in the browser",
|
"description": "A libp2p node running in the browser",
|
||||||
"main": "index.js",
|
"main": "dist/index.html",
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 2 Chrome versions"
|
"last 2 Chrome versions"
|
||||||
],
|
],
|
||||||
@ -15,20 +15,20 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-env": "^7.8.3",
|
"@babel/preset-env": "^7.13.0",
|
||||||
"libp2p": "../../",
|
"libp2p": "../../",
|
||||||
"libp2p-bootstrap": "^0.12.1",
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
"libp2p-mplex": "^0.10.0",
|
"libp2p-mplex": "^0.10.4",
|
||||||
"libp2p-noise": "^2.0.0",
|
"libp2p-noise": "^4.0.0",
|
||||||
"libp2p-webrtc-star": "^0.20.0",
|
"libp2p-webrtc-star": "^0.23.0",
|
||||||
"libp2p-websockets": "^0.14.0"
|
"libp2p-websockets": "^0.16.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.8.3",
|
"@babel/cli": "^7.13.10",
|
||||||
"@babel/core": "^7.8.3",
|
"@babel/core": "^7.13.0",
|
||||||
"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-bundler": "^1.12.4"
|
"parcel": "next"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,10 @@ async function run() {
|
|||||||
const out = chunk.toString()
|
const out = chunk.toString()
|
||||||
|
|
||||||
if (out.includes('Server running at')) {
|
if (out.includes('Server running at')) {
|
||||||
url = out.replace('Server running at ', '')
|
url = out.split('Server running at ')[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out.includes('✨ Built in ')) {
|
if (out.includes('Built in')) {
|
||||||
try {
|
try {
|
||||||
const browser = await chromium.launch();
|
const browser = await chromium.launch();
|
||||||
const page = await browser.newPage();
|
const page = await browser.newPage();
|
||||||
|
@ -10,12 +10,14 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"execa": "^2.1.0",
|
"execa": "^2.1.0",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
"libp2p-pubsub-peer-discovery": "^3.0.0",
|
"libp2p-pubsub-peer-discovery": "^4.0.0",
|
||||||
"libp2p-relay-server": "^0.1.2",
|
"libp2p-relay-server": "^0.2.0",
|
||||||
|
"libp2p-gossipsub": "^0.9.1",
|
||||||
"p-defer": "^3.0.0",
|
"p-defer": "^3.0.0",
|
||||||
"which": "^2.0.1"
|
"which": "^2.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"https": "^1.0.0",
|
||||||
"playwright": "^1.7.1"
|
"playwright": "^1.7.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ const Libp2p = require('../../')
|
|||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const Mplex = require('libp2p-mplex')
|
const Mplex = require('libp2p-mplex')
|
||||||
const { NOISE } = require('libp2p-noise')
|
const { NOISE } = require('libp2p-noise')
|
||||||
const CID = require('cids')
|
const { CID } = require('multiformats/cid')
|
||||||
const KadDHT = require('libp2p-kad-dht')
|
const KadDHT = require('libp2p-kad-dht')
|
||||||
|
|
||||||
const all = require('it-all')
|
const all = require('it-all')
|
||||||
@ -51,10 +51,10 @@ const createNode = async () => {
|
|||||||
// Wait for onConnect handlers in the DHT
|
// Wait for onConnect handlers in the DHT
|
||||||
await delay(100)
|
await delay(100)
|
||||||
|
|
||||||
const cid = new CID('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
|
const cid = CID.parse('QmTp9VkYvnHyrqKQuFPiuZkiX9gPcqj6x5LJ1rmWuSySnL')
|
||||||
await node1.contentRouting.provide(cid)
|
await node1.contentRouting.provide(cid)
|
||||||
|
|
||||||
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toBaseEncodedString())
|
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toString())
|
||||||
|
|
||||||
// wait for propagation
|
// wait for propagation
|
||||||
await delay(300)
|
await delay(300)
|
||||||
|
@ -81,7 +81,7 @@ Instead of calling `peerRouting.findPeer`, we will use `contentRouting.provide`
|
|||||||
|
|
||||||
```JavaScript
|
```JavaScript
|
||||||
await node1.contentRouting.provide(cid)
|
await node1.contentRouting.provide(cid)
|
||||||
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toBaseEncodedString())
|
console.log('Node %s is providing %s', node1.peerId.toB58String(), cid.toString())
|
||||||
|
|
||||||
const provs = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 }))
|
const provs = await all(node3.contentRouting.findProviders(cid, { timeout: 5000 }))
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ We've seen many interesting use cases appear with this, here are some highlights
|
|||||||
- [IPFS PubSub (using libp2p-floodsub) for IoT](https://www.youtube.com/watch?v=qLpM5pBDGiE).
|
- [IPFS PubSub (using libp2p-floodsub) for IoT](https://www.youtube.com/watch?v=qLpM5pBDGiE).
|
||||||
- [Real Time distributed Applications](https://www.youtube.com/watch?v=vQrbxyDPSXg)
|
- [Real Time distributed Applications](https://www.youtube.com/watch?v=vQrbxyDPSXg)
|
||||||
|
|
||||||
|
## 0. Set up the example
|
||||||
|
|
||||||
|
Before moving into the examples, you should run `npm install` on the top level `js-libp2p` folder, in order to install all the dependencies needed for this example. In addition, you will need to install the example related dependencies by doing `cd examples && npm install`. Once the install finishes, you should move into the example folder with `cd pubsub`.
|
||||||
|
|
||||||
## 1. Setting up a simple PubSub network on top of libp2p
|
## 1. Setting up a simple PubSub network on top of libp2p
|
||||||
|
|
||||||
For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
For this example, we will use MulticastDNS for automatic Peer Discovery. This example is based the previous examples found in [Discovery Mechanisms](../discovery-mechanisms). You can find the complete version at [1.js](./1.js).
|
||||||
|
89
examples/transports/4.js
Normal file
89
examples/transports/4.js
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
const Libp2p = require('../..')
|
||||||
|
const TCP = require('libp2p-tcp')
|
||||||
|
const WebSockets = require('libp2p-websockets')
|
||||||
|
const { NOISE } = require('libp2p-noise')
|
||||||
|
const MPLEX = require('libp2p-mplex')
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
|
const pipe = require('it-pipe')
|
||||||
|
|
||||||
|
const transportKey = WebSockets.prototype[Symbol.toStringTag];
|
||||||
|
|
||||||
|
const httpServer = https.createServer({
|
||||||
|
cert: fs.readFileSync('./test_certs/cert.pem'),
|
||||||
|
key: fs.readFileSync('./test_certs/key.pem'),
|
||||||
|
});
|
||||||
|
|
||||||
|
const createNode = async (addresses = []) => {
|
||||||
|
if (!Array.isArray(addresses)) {
|
||||||
|
addresses = [addresses]
|
||||||
|
}
|
||||||
|
|
||||||
|
const node = await Libp2p.create({
|
||||||
|
addresses: {
|
||||||
|
listen: addresses
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
transport: [WebSockets],
|
||||||
|
connEncryption: [NOISE],
|
||||||
|
streamMuxer: [MPLEX]
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
peerDiscovery: {
|
||||||
|
// Disable autoDial as it would fail because we are using a self-signed cert.
|
||||||
|
// `dialProtocol` does not fail because we pass `rejectUnauthorized: false`.
|
||||||
|
autoDial: false
|
||||||
|
},
|
||||||
|
transport: {
|
||||||
|
[transportKey]: {
|
||||||
|
listenerOptions: { server: httpServer },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await node.start()
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
function printAddrs(node, number) {
|
||||||
|
console.log('node %s is listening on:', number)
|
||||||
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
|
}
|
||||||
|
|
||||||
|
function print ({ stream }) {
|
||||||
|
pipe(
|
||||||
|
stream,
|
||||||
|
async function (source) {
|
||||||
|
for await (const msg of source) {
|
||||||
|
console.log(msg.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
const [node1, node2] = await Promise.all([
|
||||||
|
createNode('/ip4/127.0.0.1/tcp/10000/wss'),
|
||||||
|
createNode([])
|
||||||
|
])
|
||||||
|
|
||||||
|
printAddrs(node1, '1')
|
||||||
|
printAddrs(node2, '2')
|
||||||
|
|
||||||
|
node1.handle('/print', print)
|
||||||
|
node2.handle('/print', print)
|
||||||
|
|
||||||
|
const targetAddr = `${node1.multiaddrs[0]}/p2p/${node1.peerId.toB58String()}`;
|
||||||
|
|
||||||
|
// node 2 (Secure WebSockets) dials to node 1 (Secure Websockets)
|
||||||
|
const { stream } = await node2.dialProtocol(targetAddr, '/print', { websocket: { rejectUnauthorized: false } })
|
||||||
|
await pipe(
|
||||||
|
['node 2 dialed to node 1 successfully'],
|
||||||
|
stream
|
||||||
|
)
|
||||||
|
})();
|
33
examples/transports/test-4.js
Normal file
33
examples/transports/test-4.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
const execa = require('execa')
|
||||||
|
const pDefer = require('p-defer')
|
||||||
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
|
|
||||||
|
async function test () {
|
||||||
|
const deferNode1 = pDefer()
|
||||||
|
|
||||||
|
process.stdout.write('4.js\n')
|
||||||
|
|
||||||
|
const proc = execa('node', [path.join(__dirname, '4.js')], {
|
||||||
|
cwd: path.resolve(__dirname),
|
||||||
|
all: true
|
||||||
|
})
|
||||||
|
|
||||||
|
proc.all.on('data', async (data) => {
|
||||||
|
process.stdout.write(data)
|
||||||
|
const line = uint8ArrayToString(data)
|
||||||
|
|
||||||
|
if (line.includes('node 2 dialed to node 1 successfully')) {
|
||||||
|
deferNode1.resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
deferNode1.promise,
|
||||||
|
])
|
||||||
|
proc.kill()
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = test
|
@ -3,11 +3,13 @@
|
|||||||
const test1 = require('./test-1')
|
const test1 = require('./test-1')
|
||||||
const test2 = require('./test-2')
|
const test2 = require('./test-2')
|
||||||
const test3 = require('./test-3')
|
const test3 = require('./test-3')
|
||||||
|
const test4 = require('./test-4')
|
||||||
|
|
||||||
async function test() {
|
async function test() {
|
||||||
await test1()
|
await test1()
|
||||||
await test2()
|
await test2()
|
||||||
await test3()
|
await test3()
|
||||||
|
await test4()
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = test
|
module.exports = test
|
||||||
|
32
examples/transports/test_certs/cert.pem
Normal file
32
examples/transports/test_certs/cert.pem
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFlzCCA3+gAwIBAgIUMYedwb9L/BtvZ7Lhu71iSKrXsa4wDQYJKoZIhvcNAQEL
|
||||||
|
BQAwajELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAlZBMREwDwYDVQQHDAhTb21lQ2l0
|
||||||
|
eTESMBAGA1UECgwJTXlDb21wYW55MRMwEQYDVQQLDApNeURpdmlzaW9uMRIwEAYD
|
||||||
|
VQQDDAkxMjcuMC4wLjEwHhcNMjEwNDI4MDIzMjA5WhcNMjIwNDI4MDIzMjA5WjBq
|
||||||
|
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCVkExETAPBgNVBAcMCFNvbWVDaXR5MRIw
|
||||||
|
EAYDVQQKDAlNeUNvbXBhbnkxEzARBgNVBAsMCk15RGl2aXNpb24xEjAQBgNVBAMM
|
||||||
|
CTEyNy4wLjAuMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANNhXBu0
|
||||||
|
GH1Kzl9iaQxCxEnyyAShS5FYScdKxqpYsgJT4poLWLQBZQEFLEqbdillIlTZqMss
|
||||||
|
jWqkFL2xmjqdcnOKFEZUarntVE2hxFYYQex2Fi8MYwFj+Pvt74d02xPyfzFNFgyX
|
||||||
|
a1EakoGBwClaf3I7jW7raPudjcf4HnwQ7r/NwiO8FqHFZgLcTnwI8bk+cxDoDAqu
|
||||||
|
mhqMB5nnerqvKEyR9Fb2PoL+8PwOPJOOKTDVwLMeMJu2WLR8AU2FzOj5SVI2qsu9
|
||||||
|
Ps5azysD8KQAMcw4y9s6do36SaMQS85fbvXBV7XBqMD34HPBUbFiCoFoaCzK9Zfb
|
||||||
|
pCXyVJMUNmw5hyq9nbjUt4Kvr/58bU2gjUKSdPf6KhBxFnDZwl+2qqPdVIb/qtwz
|
||||||
|
HExtJWq3upklXNOg3HoR6vcr1O9ReJHrzLRMEb51WP1aN/qJ2/lRskcZ4A806qwr
|
||||||
|
W67BvnOg6s3ZtxHN9v3bsyfsvC66w8PEfCnCVxugC7cUW0gtW54AU75T3ukg7X+m
|
||||||
|
vECr/+qIzNEBIxxCPgefCG/JAdJhQ5SCvoARAVPStUIWDmigDeOt7go5nKbdVIJ4
|
||||||
|
7bbBFUhHT2mTHu30fHhRqSDcHzwE7Zz6YJIJmKq29UmzUazFnKlLU67MjLJwiDPm
|
||||||
|
fC3GyOdAWkkZE5hjtkiy+3yWoEHhaJYRI1u3AgMBAAGjNTAzMAsGA1UdDwQEAwIE
|
||||||
|
MDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4ICAQCx/ynu4iCQAK8VId/QQe7GqgOpFgx+6Mce9GQC6ZVEjAPgapsS
|
||||||
|
Pl+l6+11cFjHKv0+Z/iN2JgkFmNXfwJcfYI0tHbMK+0U9hgKb1eFgiIwCqb4cPOz
|
||||||
|
wMwusZ95BjIbtcEbL/+pMUpNhmjPz1fOILJZtDVq++lqJCv7t8+SoAmMVYtlcLNg
|
||||||
|
muuV/UYR3uqvnAJmjgJVWs4otDGrxCYJE48M+9L2Gm05Htpi9WL1bZaQ+fJ85m85
|
||||||
|
daedLc6R1/ZRTIH6i73sD4rYs0bx1fCJvkbcgXtKMHEkiHuG/MzR7Pa4cJAVKCx9
|
||||||
|
lRTgrO7Gkllt2+jp4qg0YhdNq89e0DNA5cyB9H4udRgHQOcrlVRiX9OD/Kz+F5m/
|
||||||
|
fQwMdbnqdg3ar5DSa8Q5g3bdLbNSCcI9sjCLTkNxUC/XTWGdG03RCVIt1qvBvZHk
|
||||||
|
JaG6xGpbRZ5CN0T9eindd38JBrkPAPfgl6qhwvcqh6uVFYua+7KmF9K+mKarlmMw
|
||||||
|
6RWaw2j4sMgUyRIS6fR9vDc20SrtoNvKQM1U6+0VYs1nizfkmsqqqRODmERKbKwc
|
||||||
|
ahKJFubXfr8gz+PipAKFZbxr2EPAyoiNkx+0eM6Eedo55oP2BoGHEfXEoAonyMFM
|
||||||
|
F/xTbpFtdRYE2hwsZCk86fpbcPTmdCY8txeZ7+4Bme2d9XXsTAxF64usqQ==
|
||||||
|
-----END CERTIFICATE-----
|
52
examples/transports/test_certs/key.pem
Normal file
52
examples/transports/test_certs/key.pem
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDTYVwbtBh9Ss5f
|
||||||
|
YmkMQsRJ8sgEoUuRWEnHSsaqWLICU+KaC1i0AWUBBSxKm3YpZSJU2ajLLI1qpBS9
|
||||||
|
sZo6nXJzihRGVGq57VRNocRWGEHsdhYvDGMBY/j77e+HdNsT8n8xTRYMl2tRGpKB
|
||||||
|
gcApWn9yO41u62j7nY3H+B58EO6/zcIjvBahxWYC3E58CPG5PnMQ6AwKrpoajAeZ
|
||||||
|
53q6ryhMkfRW9j6C/vD8DjyTjikw1cCzHjCbtli0fAFNhczo+UlSNqrLvT7OWs8r
|
||||||
|
A/CkADHMOMvbOnaN+kmjEEvOX271wVe1wajA9+BzwVGxYgqBaGgsyvWX26Ql8lST
|
||||||
|
FDZsOYcqvZ241LeCr6/+fG1NoI1CknT3+ioQcRZw2cJftqqj3VSG/6rcMxxMbSVq
|
||||||
|
t7qZJVzToNx6Eer3K9TvUXiR68y0TBG+dVj9Wjf6idv5UbJHGeAPNOqsK1uuwb5z
|
||||||
|
oOrN2bcRzfb927Mn7LwuusPDxHwpwlcboAu3FFtILVueAFO+U97pIO1/prxAq//q
|
||||||
|
iMzRASMcQj4HnwhvyQHSYUOUgr6AEQFT0rVCFg5ooA3jre4KOZym3VSCeO22wRVI
|
||||||
|
R09pkx7t9Hx4Uakg3B88BO2c+mCSCZiqtvVJs1GsxZypS1OuzIyycIgz5nwtxsjn
|
||||||
|
QFpJGROYY7ZIsvt8lqBB4WiWESNbtwIDAQABAoICAQCpGV3iG7Trpohp7gQzdsYo
|
||||||
|
kjxI1+/oGkULVVqQs9vT2N+SdDlF50eyBT1lgfCJNQq97lIGF2IaSaD+D7Jd6c7B
|
||||||
|
d1i42pd2ndGvORYj+cvjKqSchsA9QIjSoYnZRzZrQrdV7WESOZ/0hdlmGTJs4qTJ
|
||||||
|
8bI3ZcPaZjQiIO/iOHmGn0gL5lAEojH1X+C5gT4+/yJ2B+x6LyvAyPzbtj6MUctf
|
||||||
|
VfOuDdf8W47VVV5IfJWfJ6C8qg4gw0M7P2ibZ8qBJcvuJSWFT6OK2UKaGtDLogw0
|
||||||
|
X8tVWfO1qOB3vnWmZtoRZ9aO5JnnpWS9tY1w5gmZdLjB/Kt0DJXIdZALCURwV6U0
|
||||||
|
q5XR0SETEgdRrNX92PA2lmxO9fAgXRSjP/OoeDjAVhnRfYyShDbEIb8GHk7nE+is
|
||||||
|
6ak5ufxKE53S8wB9L7MTPqTvxusBHi8saLevdnPBMQPvtEVkg2Iw/iPBsegUuUjD
|
||||||
|
uzXlq4WUMCUBJEMVPuYEsaQizxpp2oM6AZj/ecuTKFX5CirFFWKOQ4cp+O8lrfI5
|
||||||
|
ruwHrMkfjowDYcQaOLHq13anvt8+8LBlngVw+jiAGB/bGwrAwEZWUc8i1HbH/G8e
|
||||||
|
sm0kMuCqV1GbRyMCUO3pWjzrsz8LEy74Jr0z7KZn52vLWrTkiD4NRXahxTBhHpXb
|
||||||
|
AVclJ+a4BKk2rRJVRFRRQQKCAQEA7+uTl2ZHp1v7A8/I2zPIxoVz0fiwxwAjuv34
|
||||||
|
cV+uxG0n5Tko4PKMxavddRFKNeGvrz0aO/GNX8NIW7pDqZ2CwHyskgUX/bFAqGKF
|
||||||
|
Z/z2DmiZ2rdSUH89O3ysq+OF3RjX/FBNJ0SVdwtrpz3kCSWpa4PnmN7+IevL6zxY
|
||||||
|
8gLrs07Ge+ci94FZaDHBNrkGQ00krbOmwIvnc90hyRPCKfMS+u2/ejKZ5QDyRG+H
|
||||||
|
jbQ008ZV2OqUdS6h1twfoJ1Q4QhHijB6PegRLGdZGuUXIQfFP8dIUsQluKSUFyOy
|
||||||
|
bL9W2yBwtbn3EwYDHLJQnLICxfcTBWg/2vOIucsSjxG7KNY0yQKCAQEA4YwcVpi3
|
||||||
|
D+8OcnbpRBRlHo84DRZorp0RO8vhxevvB1CcBnkLRIYXlS2JIfrnhZAI/5jBk1ei
|
||||||
|
FmgRFyAjZ8gDdkDCiDMQMDUwUhLGSVurI9sk16B4TQKCM+iE0LDrXIy9ezJRJkj0
|
||||||
|
rOt8sqo2/TOttm2KEXY8Cco59tU4bMZg5Tr9l7SMTTj4skTO6Jn6/6hX3XuFkJw7
|
||||||
|
B0DsSzIqXyRHAzOidagIEoIr7k4cEGXsrSWoSiHg/eky1ihCyUw3vDDOmoViBR7s
|
||||||
|
h5nLjQNNAzOtyoKLqST7B7uXkdUo5nV2IUHSGD5LNxlTaNp0XL9Ph3EBtcuwNuB6
|
||||||
|
zyKXc+O5iNfMfwKCAQEA5/RJKCnRgsORxpif5xWEujIRzOHz/yFqagHarbnFHNEv
|
||||||
|
rhT6Kak2YnIL1H/X0IoWsYSQlX2uofQKQ+ysOBM5c2HV8gKMtFAnY+SEeAn/1eRZ
|
||||||
|
QzTTl1G84INj6Xc6V40KXD1CqoFLQ+G9vd4/Vnyb9H99bLXC2wa+ivo4QBqEyEGT
|
||||||
|
8fyAOOxMhUj9NSvjGzQ9DtbOk/9u0PztChtZL/d61TEAW2MKmHW2xGVTl7OvE0QA
|
||||||
|
gYwh5b0k6La+uSj/JeE8USUXOjzgRZ7RbggouV1q3YOMr8BFe+NZ7Zksiqjej1Io
|
||||||
|
xfk6H6FDZv4ao7QSrFR4hlTIz6V9/aqQkdOhsBSQyQKCAQEAzHwz4Qr5xVduGLbY
|
||||||
|
S6HV/7vHDI6Jf+3lBvqUidWa013w5yls3sZXsSckkgshRoVMszayIbystnXJMNcx
|
||||||
|
YlEDWn3iIItzHNHMKkzdOvsCETMIlvnkt6UTmK4xY+dSq4jp7Ty0N+qi8fdaCb2q
|
||||||
|
tyrYTnHHYId6bUHMBY5QZsYAaTNvYNAO96A0UaNyl42q84iTiLkJYg9SsQPad15W
|
||||||
|
7gU84Jk6rEMYdndQDvEAHpnZ1y0yA2vtySZYsbK0wj34tgTl+0/8izn7JgF4ezNH
|
||||||
|
6iQ7Z0OuDT763IrmIxBH0ZEi9YnwSYyIsr6iUYjlQIUuPFRnQYQXEdm5Xfw1pZsL
|
||||||
|
xhYoTwKCAQB9edDe4LX+0z9i4qr0iHV8H/WoyI5UD/Pc217PKkYM3+ewR9SL9D9z
|
||||||
|
TS78Sl7HgRgEmIu+MR/u5B2ePf7jkvB/oxyPwqAzJeJ72mV3Mevm27G/Ndd8lt5W
|
||||||
|
FBCGOx7ZeP4/Cv4mvPD979ix2IalDoWMSWJnpQPN+B1jGeCrUYAXQc1k/vU99gLa
|
||||||
|
8Tuu3WfBpVAsO7hAC9mu6tuLyfKVqiMOVs2aky9xLqiqW/6uIcGu+owrr+gkDDY/
|
||||||
|
JfBSUfxYKcjtJiHOEbFGrrRe93XsngmaTz/Hv9A/QLVCuJgWEHlt4WHSc+BtAtaV
|
||||||
|
9avp6VlyVNfe4KEKW7IekrI0cmfMdXkl
|
||||||
|
-----END PRIVATE KEY-----
|
33
examples/webrtc-direct/README.md
Normal file
33
examples/webrtc-direct/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
### Webrtc-direct example
|
||||||
|
|
||||||
|
An example that uses [js-libp2p-webrtc-direct](https://github.com/libp2p/js-libp2p-webrtc-direct) for connecting
|
||||||
|
nodejs libp2p and browser libp2p clients. To run the example:
|
||||||
|
|
||||||
|
## 0. Run a nodejs libp2p listener
|
||||||
|
|
||||||
|
When in the root folder of this example, type `node listener.js` in terminal. You should see an address that listens for
|
||||||
|
incoming connections. Below is just an example of such address. In your case the suffix hash (`peerId`) will be different.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ node listener.js
|
||||||
|
Listening on:
|
||||||
|
/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. Prepare a browser libp2p dialer
|
||||||
|
Confirm that the above address is the same as the field `list` in `public/dialer.js`:
|
||||||
|
```js
|
||||||
|
peerDiscovery: {
|
||||||
|
[Bootstrap.tag]: {
|
||||||
|
enabled: true,
|
||||||
|
// paste the address into `list`
|
||||||
|
list: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/QmUKQCzEUhhhobcNSrXU5uzxTqbvF1BjMCGNGZzZU14Kgd']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Run a browser libp2p dialer
|
||||||
|
When in the root folder of this example, type `npm run dev` in terminal. You should see an address where you can browse
|
||||||
|
the running client. Open this address in your browser. In console
|
||||||
|
logs you should see logs about successful connection with the node client. In the output of node client you should see
|
||||||
|
a log message about successful connection as well.
|
57
examples/webrtc-direct/dialer.js
Normal file
57
examples/webrtc-direct/dialer.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import 'babel-polyfill'
|
||||||
|
const Libp2p = require('libp2p')
|
||||||
|
const WebRTCDirect = require('libp2p-webrtc-direct')
|
||||||
|
const Mplex = require('libp2p-mplex')
|
||||||
|
const {NOISE} = require('libp2p-noise')
|
||||||
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
// use the same peer id as in `listener.js` to avoid copy-pasting of listener's peer id into `peerDiscovery`
|
||||||
|
const hardcodedPeerId = '12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m'
|
||||||
|
const libp2p = await Libp2p.create({
|
||||||
|
modules: {
|
||||||
|
transport: [WebRTCDirect],
|
||||||
|
streamMuxer: [Mplex],
|
||||||
|
connEncryption: [NOISE],
|
||||||
|
peerDiscovery: [Bootstrap]
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
peerDiscovery: {
|
||||||
|
[Bootstrap.tag]: {
|
||||||
|
enabled: true,
|
||||||
|
list: [`/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct/p2p/${hardcodedPeerId}`]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const status = document.getElementById('status')
|
||||||
|
const output = document.getElementById('output')
|
||||||
|
|
||||||
|
output.textContent = ''
|
||||||
|
|
||||||
|
function log (txt) {
|
||||||
|
console.info(txt)
|
||||||
|
output.textContent += `${txt.trim()}\n`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Listen for new peers
|
||||||
|
libp2p.on('peer:discovery', (peerId) => {
|
||||||
|
log(`Found peer ${peerId.toB58String()}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen for new connections to peers
|
||||||
|
libp2p.connectionManager.on('peer:connect', (connection) => {
|
||||||
|
log(`Connected to ${connection.remotePeer.toB58String()}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Listen for peers disconnecting
|
||||||
|
libp2p.connectionManager.on('peer:disconnect', (connection) => {
|
||||||
|
log(`Disconnected from ${connection.remotePeer.toB58String()}`)
|
||||||
|
})
|
||||||
|
|
||||||
|
await libp2p.start()
|
||||||
|
status.innerText = 'libp2p started!'
|
||||||
|
log(`libp2p id is ${libp2p.peerId.toB58String()}`)
|
||||||
|
|
||||||
|
})
|
17
examples/webrtc-direct/index.html
Normal file
17
examples/webrtc-direct/index.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>js-libp2p parcel.js browser example</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1 id="status">Starting libp2p...</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<pre id="output"></pre>
|
||||||
|
</main>
|
||||||
|
<script src="./dialer.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
44
examples/webrtc-direct/listener.js
Normal file
44
examples/webrtc-direct/listener.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const Libp2p = require('libp2p')
|
||||||
|
const Bootstrap = require('libp2p-bootstrap')
|
||||||
|
const WebRTCDirect = require('libp2p-webrtc-direct')
|
||||||
|
const Mplex = require('libp2p-mplex')
|
||||||
|
const {NOISE} = require('libp2p-noise')
|
||||||
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
|
;(async () => {
|
||||||
|
// hardcoded peer id to avoid copy-pasting of listener's peer id into the dialer's bootstrap list
|
||||||
|
// generated with cmd `peer-id --type=ed25519`
|
||||||
|
const hardcodedPeerId = await PeerId.createFromJSON({
|
||||||
|
"id": "12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m",
|
||||||
|
"privKey": "CAESQAG6Ld7ev6nnD0FKPs033/j0eQpjWilhxnzJ2CCTqT0+LfcWoI2Vr+zdc1vwk7XAVdyoCa2nwUR3RJebPWsF1/I=",
|
||||||
|
"pubKey": "CAESIC33FqCNla/s3XNb8JO1wFXcqAmtp8FEd0SXmz1rBdfy"
|
||||||
|
})
|
||||||
|
const node = await Libp2p.create({
|
||||||
|
peerId: hardcodedPeerId,
|
||||||
|
addresses: {
|
||||||
|
listen: ['/ip4/127.0.0.1/tcp/9090/http/p2p-webrtc-direct']
|
||||||
|
},
|
||||||
|
modules: {
|
||||||
|
transport: [WebRTCDirect],
|
||||||
|
streamMuxer: [Mplex],
|
||||||
|
connEncryption: [NOISE]
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
peerDiscovery: {
|
||||||
|
[Bootstrap.tag]: {
|
||||||
|
enabled: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
node.connectionManager.on('peer:connect', (connection) => {
|
||||||
|
console.info(`Connected to ${connection.remotePeer.toB58String()}!`)
|
||||||
|
})
|
||||||
|
|
||||||
|
await node.start()
|
||||||
|
|
||||||
|
console.log('Listening on:')
|
||||||
|
node.multiaddrs.forEach((ma) => console.log(`${ma.toString()}/p2p/${node.peerId.toB58String()}`))
|
||||||
|
|
||||||
|
})()
|
33
examples/webrtc-direct/package.json
Normal file
33
examples/webrtc-direct/package.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "webrtc-direct",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"private": true,
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/index.html",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "parcel build index.html",
|
||||||
|
"start": "parcel index.html"
|
||||||
|
},
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/cli": "^7.13.10",
|
||||||
|
"@babel/core": "^7.13.10",
|
||||||
|
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||||
|
"babel-plugin-transform-regenerator": "^6.26.0",
|
||||||
|
"babel-polyfill": "^6.26.0",
|
||||||
|
"parcel-bundler": "1.12.3",
|
||||||
|
"util": "^0.12.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"libp2p": "../../",
|
||||||
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
|
"libp2p-mplex": "^0.10.4",
|
||||||
|
"libp2p-noise": "^4.0.0",
|
||||||
|
"libp2p-webrtc-direct": "^0.7.0",
|
||||||
|
"peer-id": "^0.15.0"
|
||||||
|
},
|
||||||
|
"browser": {
|
||||||
|
"ipfs": "ipfs/dist/index.min.js"
|
||||||
|
}
|
||||||
|
}
|
95
examples/webrtc-direct/test.js
Normal file
95
examples/webrtc-direct/test.js
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
const execa = require('execa')
|
||||||
|
const pDefer = require('p-defer')
|
||||||
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
|
const { chromium } = require('playwright');
|
||||||
|
|
||||||
|
function startNode (name, args = []) {
|
||||||
|
return execa('node', [path.join(__dirname, name), ...args], {
|
||||||
|
cwd: path.resolve(__dirname),
|
||||||
|
all: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function startBrowser (name, args = []) {
|
||||||
|
return execa('parcel', [path.join(__dirname, name), ...args], {
|
||||||
|
preferLocal: true,
|
||||||
|
localDir: __dirname,
|
||||||
|
cwd: __dirname,
|
||||||
|
all: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async function test () {
|
||||||
|
// Step 1, listener process
|
||||||
|
const listenerProcReady = pDefer()
|
||||||
|
let listenerOutput = ''
|
||||||
|
process.stdout.write('listener.js\n')
|
||||||
|
const listenerProc = startNode('listener.js')
|
||||||
|
|
||||||
|
listenerProc.all.on('data', async (data) => {
|
||||||
|
process.stdout.write(data)
|
||||||
|
listenerOutput += uint8ArrayToString(data)
|
||||||
|
if (listenerOutput.includes('Listening on:') && listenerOutput.includes('12D3KooWCuo3MdXfMgaqpLC5Houi1TRoFqgK9aoxok4NK5udMu8m')) {
|
||||||
|
listenerProcReady.resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await listenerProcReady.promise
|
||||||
|
process.stdout.write('==================================================================\n')
|
||||||
|
|
||||||
|
// Step 2, dialer process
|
||||||
|
process.stdout.write('dialer.js\n')
|
||||||
|
let dialerUrl = ''
|
||||||
|
const dialerProc = startBrowser('index.html')
|
||||||
|
|
||||||
|
dialerProc.all.on('data', async (chunk) => {
|
||||||
|
/**@type {string} */
|
||||||
|
const out = chunk.toString()
|
||||||
|
|
||||||
|
if (out.includes('Server running at')) {
|
||||||
|
dialerUrl = out.split('Server running at ')[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (out.includes('Built in ')) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const browser = await chromium.launch();
|
||||||
|
const page = await browser.newPage();
|
||||||
|
await page.goto(dialerUrl);
|
||||||
|
await page.waitForFunction(selector => document.querySelector(selector).innerText === 'libp2p started!', '#status')
|
||||||
|
await page.waitForFunction(
|
||||||
|
selector => {
|
||||||
|
const text = document.querySelector(selector).innerText
|
||||||
|
return text.includes('libp2p id is') &&
|
||||||
|
text.includes('Found peer') &&
|
||||||
|
text.includes('Connected to')
|
||||||
|
},
|
||||||
|
'#output',
|
||||||
|
{ timeout: 10000 }
|
||||||
|
)
|
||||||
|
await browser.close();
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
process.exit(1)
|
||||||
|
} finally {
|
||||||
|
dialerProc.cancel()
|
||||||
|
listenerProc.kill()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
listenerProc,
|
||||||
|
dialerProc,
|
||||||
|
]).catch((err) => {
|
||||||
|
if (err.signal !== 'SIGTERM') {
|
||||||
|
throw err
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = test
|
209
package.json
209
package.json
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "libp2p",
|
"name": "libp2p",
|
||||||
"version": "0.30.8",
|
"version": "0.32.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",
|
||||||
@ -20,10 +20,28 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "aegir lint",
|
"lint": "aegir lint",
|
||||||
"build": "aegir build",
|
"build": "aegir build",
|
||||||
"test": "npm run test:node && npm run test:browser",
|
"build:proto": "npm run build:proto:circuit && npm run build:proto:identify && npm run build:proto:plaintext && npm run build:proto:address-book && npm run build:proto:proto-book && npm run build:proto:peer-record && npm run build:proto:envelope",
|
||||||
|
"build:proto:circuit": "pbjs -t static-module -w commonjs -r libp2p-circuit --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/circuit/protocol/index.js ./src/circuit/protocol/index.proto",
|
||||||
|
"build:proto:identify": "pbjs -t static-module -w commonjs -r libp2p-identify --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/identify/message.js ./src/identify/message.proto",
|
||||||
|
"build:proto:plaintext": "pbjs -t static-module -w commonjs -r libp2p-plaintext --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/insecure/proto.js ./src/insecure/proto.proto",
|
||||||
|
"build:proto:address-book": "pbjs -t static-module -w commonjs -r libp2p-address-book --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/peer-store/persistent/pb/address-book.js ./src/peer-store/persistent/pb/address-book.proto",
|
||||||
|
"build:proto:proto-book": "pbjs -t static-module -w commonjs -r libp2p-proto-book --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/peer-store/persistent/pb/proto-book.js ./src/peer-store/persistent/pb/proto-book.proto",
|
||||||
|
"build:proto:peer-record": "pbjs -t static-module -w commonjs -r libp2p-peer-record --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/record/peer-record/peer-record.js ./src/record/peer-record/peer-record.proto",
|
||||||
|
"build:proto:envelope": "pbjs -t static-module -w commonjs -r libp2p-envelope --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/record/envelope/envelope.js ./src/record/envelope/envelope.proto",
|
||||||
|
"build:proto-types": "npm run build:proto-types:circuit && npm run build:proto-types:identify && npm run build:proto-types:plaintext && npm run build:proto-types:address-book && npm run build:proto-types:proto-book && npm run build:proto-types:peer-record && npm run build:proto-types:envelope",
|
||||||
|
"build:proto-types:circuit": "pbts -o src/circuit/protocol/index.d.ts src/circuit/protocol/index.js",
|
||||||
|
"build:proto-types:identify": "pbts -o src/identify/message.d.ts src/identify/message.js",
|
||||||
|
"build:proto-types:plaintext": "pbts -o src/insecure/proto.d.ts src/insecure/proto.js",
|
||||||
|
"build:proto-types:address-book": "pbts -o src/peer-store/persistent/pb/address-book.d.ts src/peer-store/persistent/pb/address-book.js",
|
||||||
|
"build:proto-types:proto-book": "pbts -o src/peer-store/persistent/pb/proto-book.d.ts src/peer-store/persistent/pb/proto-book.js",
|
||||||
|
"build:proto-types:peer-record": "pbts -o src/record/peer-record/peer-record.d.ts src/record/peer-record/peer-record.js",
|
||||||
|
"build:proto-types:envelope": "pbts -o src/record/envelope/envelope.d.ts src/record/envelope/envelope.js",
|
||||||
|
"test": "aegir test",
|
||||||
|
"test:ts": "aegir build --no-bundle && npm run test --prefix test/ts-use",
|
||||||
"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",
|
||||||
|
"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",
|
||||||
"release-major": "aegir release --type major -t node -t browser",
|
"release-major": "aegir release --type major -t node -t browser",
|
||||||
@ -47,152 +65,179 @@
|
|||||||
"homepage": "https://libp2p.io",
|
"homepage": "https://libp2p.io",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0.0",
|
"node": ">=14.0.0"
|
||||||
"npm": ">=6.0.0"
|
|
||||||
},
|
},
|
||||||
"browser": {
|
"browser": {
|
||||||
"@motrix/nat-api": false
|
"@motrix/nat-api": false
|
||||||
},
|
},
|
||||||
|
"eslintConfig": {
|
||||||
|
"extends": "ipfs",
|
||||||
|
"ignorePatterns": [
|
||||||
|
"!.aegir.js",
|
||||||
|
"test/ts-use"
|
||||||
|
]
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@motrix/nat-api": "^0.3.1",
|
"@motrix/nat-api": "^0.3.1",
|
||||||
|
"@vascosantos/moving-average": "^1.1.0",
|
||||||
"abort-controller": "^3.0.0",
|
"abort-controller": "^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",
|
||||||
"cids": "^1.1.5",
|
|
||||||
"class-is": "^1.1.0",
|
"class-is": "^1.1.0",
|
||||||
"debug": "^4.3.1",
|
"debug": "^4.3.1",
|
||||||
"err-code": "^2.0.0",
|
"err-code": "^3.0.0",
|
||||||
"events": "^3.2.0",
|
"es6-promisify": "^6.1.1",
|
||||||
|
"events": "^3.3.0",
|
||||||
"hashlru": "^2.3.0",
|
"hashlru": "^2.3.0",
|
||||||
"interface-datastore": "^3.0.3",
|
"interface-datastore": "^5.1.1",
|
||||||
"ipfs-utils": "^6.0.0",
|
|
||||||
"it-all": "^1.0.4",
|
"it-all": "^1.0.4",
|
||||||
"it-buffer": "^0.1.2",
|
"it-buffer": "^0.1.2",
|
||||||
"it-drain": "^1.0.3",
|
"it-drain": "^1.0.3",
|
||||||
"it-filter": "^1.0.1",
|
"it-filter": "^1.0.1",
|
||||||
"it-first": "^1.0.4",
|
"it-first": "^1.0.4",
|
||||||
"it-handshake": "^1.0.2",
|
"it-handshake": "^2.0.0",
|
||||||
"it-length-prefixed": "^3.1.0",
|
"it-length-prefixed": "^5.0.2",
|
||||||
"it-map": "^1.0.4",
|
"it-map": "^1.0.4",
|
||||||
"it-merge": "1.0.0",
|
"it-merge": "^1.0.0",
|
||||||
"it-pipe": "^1.1.0",
|
"it-pipe": "^1.1.0",
|
||||||
"it-protocol-buffers": "^0.2.0",
|
"it-take": "^1.0.0",
|
||||||
"it-take": "1.0.0",
|
"libp2p-crypto": "^0.19.4",
|
||||||
"libp2p-crypto": "^0.19.0",
|
"libp2p-interfaces": "^1.0.0",
|
||||||
"libp2p-interfaces": "^0.8.1",
|
"libp2p-interfaces-compliance-tests": "^1.0.0",
|
||||||
"libp2p-utils": "^0.2.2",
|
"libp2p-utils": "^0.4.0",
|
||||||
"mafmt": "^8.0.0",
|
"mafmt": "^10.0.0",
|
||||||
"merge-options": "^3.0.4",
|
"merge-options": "^3.0.4",
|
||||||
"moving-average": "^1.0.0",
|
"multiaddr": "^10.0.0",
|
||||||
"multiaddr": "^8.1.0",
|
"multiformats": "^9.0.0",
|
||||||
"multicodec": "^2.1.0",
|
"multistream-select": "^2.0.0",
|
||||||
"multihashing-async": "^2.0.1",
|
|
||||||
"multistream-select": "^1.0.0",
|
|
||||||
"mutable-proxy": "^1.0.0",
|
"mutable-proxy": "^1.0.0",
|
||||||
"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.2.0",
|
"p-retry": "^4.4.0",
|
||||||
"p-settle": "^4.0.1",
|
"p-settle": "^4.1.1",
|
||||||
"peer-id": "^0.14.2",
|
"peer-id": "^0.15.0",
|
||||||
"private-ip": "^2.0.0",
|
"private-ip": "^2.1.0",
|
||||||
"promisify-es6": "^1.0.3",
|
"protobufjs": "^6.10.2",
|
||||||
"protons": "^2.0.0",
|
"retimer": "^3.0.0",
|
||||||
"retimer": "^2.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": "^5.0.2",
|
"streaming-iterables": "^6.0.0",
|
||||||
"timeout-abort-controller": "^1.1.1",
|
"timeout-abort-controller": "^1.1.1",
|
||||||
"varint": "^6.0.0",
|
"varint": "^6.0.0",
|
||||||
"xsalsa20": "^1.0.2"
|
"wherearewe": "^1.0.0",
|
||||||
|
"xsalsa20": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nodeutils/defaults-deep": "^1.1.0",
|
"@nodeutils/defaults-deep": "^1.1.0",
|
||||||
|
"@types/es6-promisify": "^6.0.0",
|
||||||
|
"@types/node": "^16.0.1",
|
||||||
|
"@types/node-forge": "^0.10.1",
|
||||||
|
"@types/varint": "^6.0.0",
|
||||||
"abortable-iterator": "^3.0.0",
|
"abortable-iterator": "^3.0.0",
|
||||||
"aegir": "^29.2.0",
|
"aegir": "^33.1.1",
|
||||||
"chai-bytes": "^0.1.2",
|
"buffer": "^6.0.3",
|
||||||
"chai-string": "^1.5.0",
|
"delay": "^5.0.0",
|
||||||
"delay": "^4.4.0",
|
"interop-libp2p": "^0.4.0",
|
||||||
"interop-libp2p": "^0.3.0",
|
|
||||||
"into-stream": "^6.0.0",
|
"into-stream": "^6.0.0",
|
||||||
"ipfs-http-client": "^48.2.2",
|
"ipfs-http-client": "^50.1.1",
|
||||||
"it-concat": "^1.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.12.0",
|
"libp2p-bootstrap": "^0.13.0",
|
||||||
"libp2p-delegated-content-routing": "^0.9.0",
|
"libp2p-delegated-content-routing": "^0.11.0",
|
||||||
"libp2p-delegated-peer-routing": "^0.8.0",
|
"libp2p-delegated-peer-routing": "^0.10.0",
|
||||||
"libp2p-floodsub": "^0.24.0",
|
"libp2p-floodsub": "^0.27.0",
|
||||||
"libp2p-gossipsub": "^0.8.0",
|
"libp2p-gossipsub": "^0.10.0",
|
||||||
"libp2p-kad-dht": "^0.20.5",
|
"libp2p-kad-dht": "^0.23.0",
|
||||||
"libp2p-mdns": "^0.15.0",
|
"libp2p-mdns": "^0.17.0",
|
||||||
"libp2p-mplex": "^0.10.1",
|
"libp2p-mplex": "^0.10.1",
|
||||||
"libp2p-noise": "^2.0.0",
|
"libp2p-noise": "^4.0.0",
|
||||||
"libp2p-secio": "^0.13.1",
|
"libp2p-tcp": "^0.17.0",
|
||||||
"libp2p-tcp": "^0.15.1",
|
"libp2p-webrtc-star": "^0.23.0",
|
||||||
"libp2p-webrtc-star": "^0.20.0",
|
"libp2p-websockets": "^0.16.0",
|
||||||
"libp2p-websockets": "^0.15.0",
|
"multihashes": "^4.0.2",
|
||||||
"multihashes": "^3.0.1",
|
|
||||||
"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": "^9.2.4",
|
"sinon": "^11.1.1",
|
||||||
"uint8arrays": "^2.0.5"
|
"uint8arrays": "^2.1.3",
|
||||||
|
"util": "^0.12.3"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
|
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||||
"David Dias <daviddias.p@gmail.com>",
|
"David Dias <daviddias.p@gmail.com>",
|
||||||
"Jacob Heun <jacobheun@gmail.com>",
|
"Jacob Heun <jacobheun@gmail.com>",
|
||||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
|
||||||
"Alan Shaw <alan@tableflip.io>",
|
|
||||||
"Alex Potsides <alex@achingbrain.net>",
|
"Alex Potsides <alex@achingbrain.net>",
|
||||||
|
"Alan Shaw <alan@tableflip.io>",
|
||||||
"Cayman <caymannava@gmail.com>",
|
"Cayman <caymannava@gmail.com>",
|
||||||
"Pedro Teixeira <i@pgte.me>",
|
"Pedro Teixeira <i@pgte.me>",
|
||||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||||
"Maciej Krüger <mkg20001@gmail.com>",
|
"Maciej Krüger <mkg20001@gmail.com>",
|
||||||
"Hugo Dias <mail@hugodias.me>",
|
"Hugo Dias <mail@hugodias.me>",
|
||||||
"Volker Mische <volker.mische@gmail.com>",
|
|
||||||
"dirkmc <dirkmdev@gmail.com>",
|
"dirkmc <dirkmdev@gmail.com>",
|
||||||
|
"Chris Dostert <chrisdostert@users.noreply.github.com>",
|
||||||
|
"Volker Mische <volker.mische@gmail.com>",
|
||||||
|
"zeim839 <50573884+zeim839@users.noreply.github.com>",
|
||||||
"Richard Littauer <richard.littauer@gmail.com>",
|
"Richard Littauer <richard.littauer@gmail.com>",
|
||||||
"a1300 <matthias-knopp@gmx.net>",
|
|
||||||
"Ryan Bell <ryan@piing.net>",
|
"Ryan Bell <ryan@piing.net>",
|
||||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
"a1300 <matthias-knopp@gmx.net>",
|
||||||
"Elven <mon.samuel@qq.com>",
|
|
||||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
|
||||||
"Samlior <samlior@foxmail.com>",
|
|
||||||
"Thomas Eizinger <thomas@eizinger.io>",
|
|
||||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||||
"Didrik Nordström <didrik@betamos.se>",
|
"Samlior <samlior@foxmail.com>",
|
||||||
"Irakli Gozalishvili <rfobic@gmail.com>",
|
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||||
"Joel Gustafson <joelg@mit.edu>",
|
"Thomas Eizinger <thomas@eizinger.io>",
|
||||||
"Julien Bouquillon <contact@revolunet.com>",
|
"Franck Royer <franck@royer.one>",
|
||||||
"Kevin Kwok <antimatter15@gmail.com>",
|
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||||
"Kevin Lacker <lacker@gmail.com>",
|
"acolytec3 <17355484+acolytec3@users.noreply.github.com>",
|
||||||
"Ethan Lam <elmemphis2000@gmail.com>",
|
"Elven <mon.samuel@qq.com>",
|
||||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
"Didrik Nordström <didrik.nordstrom@gmail.com>",
|
||||||
"Dmitriy Ryajov <dryajov@gmail.com>",
|
|
||||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||||
"Diogo Silva <fsdiogo@gmail.com>",
|
|
||||||
"Smite Chow <xiaopengyou@live.com>",
|
"Smite Chow <xiaopengyou@live.com>",
|
||||||
"Soeren <nikorpoulsen@gmail.com>",
|
"Soeren <nikorpoulsen@gmail.com>",
|
||||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||||
|
"TJKoury <TJKoury@gmail.com>",
|
||||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||||
"Daijiro Wachi <daijiro.wachi@gmail.com>",
|
|
||||||
"Yusef Napora <yusef@napora.org>",
|
"Yusef Napora <yusef@napora.org>",
|
||||||
"Zane Starr <zcstarr@gmail.com>",
|
"Zane Starr <zcstarr@gmail.com>",
|
||||||
"robertkiel <robert.kiel@validitylabs.org>",
|
|
||||||
"Cindy Wu <ciindy.wu@gmail.com>",
|
|
||||||
"Chris Bratlien <chrisbratlien@gmail.com>",
|
|
||||||
"ebinks <elizabethjbinks@gmail.com>",
|
"ebinks <elizabethjbinks@gmail.com>",
|
||||||
"Francis Gulotta <wizard@roborooter.com>",
|
|
||||||
"Florian-Merle <florian.david.merle@gmail.com>",
|
|
||||||
"Bernd Strehl <bernd.strehl@gmail.com>",
|
|
||||||
"Henrique Dias <hacdias@gmail.com>",
|
|
||||||
"isan_rivkin <isanrivkin@gmail.com>",
|
"isan_rivkin <isanrivkin@gmail.com>",
|
||||||
|
"mayerwin <mayerwin@users.noreply.github.com>",
|
||||||
|
"mcclure <andi.m.mcclure@gmail.com>",
|
||||||
|
"phillmac <phillmac@users.noreply.github.com>",
|
||||||
|
"robertkiel <robert.kiel@validitylabs.org>",
|
||||||
|
"shresthagrawal <34920931+shresthagrawal@users.noreply.github.com>",
|
||||||
|
"swedneck <40505480+swedneck@users.noreply.github.com>",
|
||||||
|
"Marcin Tojek <mtojek@users.noreply.github.com>",
|
||||||
|
"Aleksei <vozhdb@gmail.com>",
|
||||||
|
"Bernd Strehl <bernd.strehl@gmail.com>",
|
||||||
|
"Chris Bratlien <chrisbratlien@gmail.com>",
|
||||||
|
"Cindy Wu <ciindy.wu@gmail.com>",
|
||||||
|
"Daijiro Wachi <daijiro.wachi@gmail.com>",
|
||||||
|
"Diogo Silva <fsdiogo@gmail.com>",
|
||||||
|
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||||
|
"Ethan Lam <elmemphis2000@gmail.com>",
|
||||||
|
"Fei Liu <liu.feiwood@gmail.com>",
|
||||||
"Felipe Martins <felipebrasil93@gmail.com>",
|
"Felipe Martins <felipebrasil93@gmail.com>",
|
||||||
"Fei Liu <liu.feiwood@gmail.com>"
|
"Florian-Merle <florian.david.merle@gmail.com>",
|
||||||
|
"Francis Gulotta <wizard@roborooter.com>",
|
||||||
|
"Guy Sviry <32539816+guysv@users.noreply.github.com>",
|
||||||
|
"Henrique Dias <hacdias@gmail.com>",
|
||||||
|
"Irakli Gozalishvili <rfobic@gmail.com>",
|
||||||
|
"Joel Gustafson <joelg@mit.edu>",
|
||||||
|
"John Rees <johnrees@users.noreply.github.com>",
|
||||||
|
"João Santos <joaosantos15@users.noreply.github.com>",
|
||||||
|
"Julien Bouquillon <contact@revolunet.com>",
|
||||||
|
"Kevin Kwok <antimatter15@gmail.com>",
|
||||||
|
"Kevin Lacker <lacker@gmail.com>",
|
||||||
|
"Lars Gierth <lgierth@users.noreply.github.com>",
|
||||||
|
"Aditya Bose <13054902+adbose@users.noreply.github.com>",
|
||||||
|
"Michael Burns <5170+mburns@users.noreply.github.com>",
|
||||||
|
"Miguel Mota <miguelmota2@gmail.com>",
|
||||||
|
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||||
|
"Philipp Muens <raute1337@gmx.de>"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
2
scripts/node-globals.js
Normal file
2
scripts/node-globals.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
export const { Buffer } = require('buffer')
|
@ -1,15 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
const { Multiaddr } = require('multiaddr')
|
||||||
const EventEmitter = require('events')
|
|
||||||
const multiaddr = require('multiaddr')
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} AddressManagerOptions
|
* @typedef {Object} AddressManagerOptions
|
||||||
* @property {string[]} [listen = []] - list of multiaddrs string representation to listen.
|
* @property {string[]} [listen = []] - list of multiaddrs string representation to listen.
|
||||||
@ -47,7 +41,7 @@ class AddressManager extends EventEmitter {
|
|||||||
* @returns {Multiaddr[]}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
getListenAddrs () {
|
getListenAddrs () {
|
||||||
return Array.from(this.listen).map((a) => multiaddr(a))
|
return Array.from(this.listen).map((a) => new Multiaddr(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +50,7 @@ class AddressManager extends EventEmitter {
|
|||||||
* @returns {Multiaddr[]}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
getAnnounceAddrs () {
|
getAnnounceAddrs () {
|
||||||
return Array.from(this.announce).map((a) => multiaddr(a))
|
return Array.from(this.announce).map((a) => new Multiaddr(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,7 +59,7 @@ class AddressManager extends EventEmitter {
|
|||||||
* @returns {Array<Multiaddr>}
|
* @returns {Array<Multiaddr>}
|
||||||
*/
|
*/
|
||||||
getObservedAddrs () {
|
getObservedAddrs () {
|
||||||
return Array.from(this.observed).map((a) => multiaddr(a))
|
return Array.from(this.observed).map((a) => new Multiaddr(a))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,7 +68,7 @@ class AddressManager extends EventEmitter {
|
|||||||
* @param {string | Multiaddr} addr
|
* @param {string | Multiaddr} addr
|
||||||
*/
|
*/
|
||||||
addObservedAddr (addr) {
|
addObservedAddr (addr) {
|
||||||
let ma = multiaddr(addr)
|
let ma = new Multiaddr(addr)
|
||||||
const remotePeer = ma.getPeerId()
|
const remotePeer = ma.getPeerId()
|
||||||
|
|
||||||
// strip our peer id if it has been passed
|
// strip our peer id if it has been passed
|
||||||
@ -83,7 +77,7 @@ class AddressManager extends EventEmitter {
|
|||||||
|
|
||||||
// use same encoding for comparison
|
// use same encoding for comparison
|
||||||
if (remotePeerId.equals(this.peerId)) {
|
if (remotePeerId.equals(this.peerId)) {
|
||||||
ma = ma.decapsulate(multiaddr(`/p2p/${this.peerId}`))
|
ma = ma.decapsulate(new Multiaddr(`/p2p/${this.peerId}`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ Libp2p circuit configuration can be seen at [Setup with Relay](../../doc/CONFIGU
|
|||||||
Once you have a circuit relay node running, you can configure other nodes to use it as a relay as follows:
|
Once you have a circuit relay node running, you can configure other nodes to use it as a relay as follows:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const Libp2p = require('libp2p')
|
const Libp2p = require('libp2p')
|
||||||
const TCP = require('libp2p-tcp')
|
const TCP = require('libp2p-tcp')
|
||||||
const MPLEX = require('libp2p-mplex')
|
const MPLEX = require('libp2p-mplex')
|
||||||
@ -47,7 +47,7 @@ const relayAddr = ...
|
|||||||
|
|
||||||
const node = await Libp2p.create({
|
const node = await Libp2p.create({
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: [multiaddr(`${relayAddr}/p2p-circuit`)]
|
listen: [new Multiaddr(`${relayAddr}/p2p-circuit`)]
|
||||||
},
|
},
|
||||||
modules: {
|
modules: {
|
||||||
transport: [TCP],
|
transport: [TCP],
|
||||||
|
@ -7,7 +7,7 @@ const log = Object.assign(debug('libp2p:auto-relay'), {
|
|||||||
|
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const { relay: multicodec } = require('./multicodec')
|
const { relay: multicodec } = require('./multicodec')
|
||||||
@ -31,6 +31,7 @@ const {
|
|||||||
*
|
*
|
||||||
* @typedef {Object} AutoRelayOptions
|
* @typedef {Object} AutoRelayOptions
|
||||||
* @property {number} [maxListeners = 1] - maximum number of relays to listen.
|
* @property {number} [maxListeners = 1] - maximum number of relays to listen.
|
||||||
|
* @property {(error: Error, msg?: string) => {}} [onError]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class AutoRelay {
|
class AutoRelay {
|
||||||
@ -40,7 +41,7 @@ class AutoRelay {
|
|||||||
* @class
|
* @class
|
||||||
* @param {AutoRelayProperties & AutoRelayOptions} props
|
* @param {AutoRelayProperties & AutoRelayOptions} props
|
||||||
*/
|
*/
|
||||||
constructor ({ libp2p, maxListeners = 1 }) {
|
constructor ({ libp2p, maxListeners = 1, onError }) {
|
||||||
this._libp2p = libp2p
|
this._libp2p = libp2p
|
||||||
this._peerId = libp2p.peerId
|
this._peerId = libp2p.peerId
|
||||||
this._peerStore = libp2p.peerStore
|
this._peerStore = libp2p.peerStore
|
||||||
@ -60,6 +61,15 @@ class AutoRelay {
|
|||||||
|
|
||||||
this._peerStore.on('change:protocols', this._onProtocolChange)
|
this._peerStore.on('change:protocols', this._onProtocolChange)
|
||||||
this._connectionManager.on('peer:disconnect', this._onPeerDisconnected)
|
this._connectionManager.on('peer:disconnect', this._onPeerDisconnected)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Error} error
|
||||||
|
* @param {string} [msg]
|
||||||
|
*/
|
||||||
|
this._onError = (error, msg) => {
|
||||||
|
log.error(msg || error)
|
||||||
|
onError && onError(error, msg)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,7 +117,7 @@ class AutoRelay {
|
|||||||
await this._addListenRelay(connection, id)
|
await this._addListenRelay(connection, id)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error(err)
|
this._onError(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,10 +167,10 @@ class AutoRelay {
|
|||||||
|
|
||||||
// Attempt to listen on relay
|
// Attempt to listen on relay
|
||||||
try {
|
try {
|
||||||
await this._transportManager.listen([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 (err) {
|
} catch (err) {
|
||||||
log.error(err)
|
this._onError(err)
|
||||||
this._listenRelays.delete(id)
|
this._listenRelays.delete(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,7 +222,7 @@ class AutoRelay {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const peerId = PeerId.createFromCID(id)
|
const peerId = PeerId.createFromB58String(id)
|
||||||
const connection = this._connectionManager.get(peerId)
|
const connection = this._connectionManager.get(peerId)
|
||||||
|
|
||||||
// If not connected, store for possible later use.
|
// If not connected, store for possible later use.
|
||||||
@ -231,8 +241,7 @@ class AutoRelay {
|
|||||||
|
|
||||||
// Try to listen on known peers that are not connected
|
// Try to listen on known peers that are not connected
|
||||||
for (const peerId of knownHopsToDial) {
|
for (const peerId of knownHopsToDial) {
|
||||||
const connection = await this._libp2p.dial(peerId)
|
await this._tryToListenOnRelay(peerId)
|
||||||
await this._addListenRelay(connection, peerId.toB58String())
|
|
||||||
|
|
||||||
// Check if already listening on enough relays
|
// Check if already listening on enough relays
|
||||||
if (this._listenRelays.size >= this.maxListeners) {
|
if (this._listenRelays.size >= this.maxListeners) {
|
||||||
@ -247,12 +256,11 @@ class AutoRelay {
|
|||||||
if (!provider.multiaddrs.length) {
|
if (!provider.multiaddrs.length) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
const peerId = provider.id
|
const peerId = provider.id
|
||||||
|
|
||||||
this._peerStore.addressBook.add(peerId, provider.multiaddrs)
|
this._peerStore.addressBook.add(peerId, provider.multiaddrs)
|
||||||
const connection = await this._libp2p.dial(peerId)
|
|
||||||
|
|
||||||
await this._addListenRelay(connection, peerId.toB58String())
|
await this._tryToListenOnRelay(peerId)
|
||||||
|
|
||||||
// Check if already listening on enough relays
|
// Check if already listening on enough relays
|
||||||
if (this._listenRelays.size >= this.maxListeners) {
|
if (this._listenRelays.size >= this.maxListeners) {
|
||||||
@ -260,7 +268,19 @@ class AutoRelay {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error(err)
|
this._onError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {PeerId} peerId
|
||||||
|
*/
|
||||||
|
async _tryToListenOnRelay (peerId) {
|
||||||
|
try {
|
||||||
|
const connection = await this._libp2p.dial(peerId)
|
||||||
|
await this._addListenRelay(connection, peerId.toB58String())
|
||||||
|
} catch (err) {
|
||||||
|
this._onError(err, `could not connect and listen on known hop relay ${peerId.toB58String()}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,17 @@ const { stop } = require('./stop')
|
|||||||
const multicodec = require('./../multicodec')
|
const multicodec = require('./../multicodec')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
* @typedef {import('../transport')} Transport
|
* @typedef {import('../transport')} Transport
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} HopRequest
|
* @typedef {Object} HopRequest
|
||||||
* @property {Connection} connection
|
* @property {Connection} connection
|
||||||
* @property {CircuitRequest} request
|
* @property {ICircuitRelay} request
|
||||||
* @property {StreamHandlerT} streamHandler
|
* @property {StreamHandler} streamHandler
|
||||||
* @property {Transport} circuit
|
* @property {Transport} circuit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -58,6 +58,11 @@ async function handleHop ({
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!request.dstPeer) {
|
||||||
|
log('HOP request received but we do not receive a dstPeer')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Get the connection to the destination (stop) peer
|
// Get the connection to the destination (stop) peer
|
||||||
const destinationPeer = new PeerId(request.dstPeer.id)
|
const destinationPeer = new PeerId(request.dstPeer.id)
|
||||||
|
|
||||||
@ -113,8 +118,8 @@ async function handleHop ({
|
|||||||
*
|
*
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {Connection} options.connection - Connection to the relay
|
* @param {Connection} options.connection - Connection to the relay
|
||||||
* @param {CircuitRequest} options.request
|
* @param {ICircuitRelay} options.request
|
||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<MuxedStream>}
|
||||||
*/
|
*/
|
||||||
async function hop ({
|
async function hop ({
|
||||||
connection,
|
connection,
|
||||||
@ -128,6 +133,10 @@ async function hop ({
|
|||||||
|
|
||||||
const response = await streamHandler.read()
|
const response = await streamHandler.read()
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
throw errCode(new Error('HOP request had no response'), Errors.ERR_HOP_REQUEST_FAILED)
|
||||||
|
}
|
||||||
|
|
||||||
if (response.code === CircuitPB.Status.SUCCESS) {
|
if (response.code === CircuitPB.Status.SUCCESS) {
|
||||||
log('hop request was successful')
|
log('hop request was successful')
|
||||||
return streamHandler.rest()
|
return streamHandler.rest()
|
||||||
@ -159,7 +168,7 @@ async function canHop ({
|
|||||||
const response = await streamHandler.read()
|
const response = await streamHandler.read()
|
||||||
await streamHandler.close()
|
await streamHandler.close()
|
||||||
|
|
||||||
if (response.code !== CircuitPB.Status.SUCCESS) {
|
if (!response || response.code !== CircuitPB.Status.SUCCESS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +180,7 @@ async function canHop ({
|
|||||||
*
|
*
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {StreamHandlerT} options.streamHandler
|
* @param {StreamHandler} options.streamHandler
|
||||||
* @param {Transport} options.circuit
|
* @param {Transport} options.circuit
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
@ -13,8 +13,7 @@ const { validateAddrs } = require('./utils')
|
|||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||||
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,8 +22,8 @@ const { validateAddrs } = require('./utils')
|
|||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
|
* @param {ICircuitRelay} options.request - The CircuitRelay protobuf request (unencoded)
|
||||||
* @param {StreamHandlerT} options.streamHandler
|
* @param {StreamHandler} options.streamHandler
|
||||||
* @returns {Promise<MuxedStream>|void} Resolves a duplex iterable
|
* @returns {Promise<MuxedStream>|void} Resolves a duplex iterable
|
||||||
*/
|
*/
|
||||||
module.exports.handleStop = function handleStop ({
|
module.exports.handleStop = function handleStop ({
|
||||||
@ -54,7 +53,7 @@ module.exports.handleStop = function handleStop ({
|
|||||||
* @private
|
* @private
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
|
* @param {ICircuitRelay} options.request - The CircuitRelay protobuf request (unencoded)
|
||||||
* @returns {Promise<MuxedStream|void>} Resolves a duplex iterable
|
* @returns {Promise<MuxedStream|void>} Resolves a duplex iterable
|
||||||
*/
|
*/
|
||||||
module.exports.stop = async function stop ({
|
module.exports.stop = async function stop ({
|
||||||
@ -68,6 +67,10 @@ module.exports.stop = async function stop ({
|
|||||||
streamHandler.write(request)
|
streamHandler.write(request)
|
||||||
const response = await streamHandler.read()
|
const response = await streamHandler.read()
|
||||||
|
|
||||||
|
if (!response) {
|
||||||
|
return streamHandler.close()
|
||||||
|
}
|
||||||
|
|
||||||
if (response.code === CircuitPB.Status.SUCCESS) {
|
if (response.code === CircuitPB.Status.SUCCESS) {
|
||||||
log('stop request to %s was successful', connection.remotePeer.toB58String())
|
log('stop request to %s was successful', connection.remotePeer.toB58String())
|
||||||
return streamHandler.rest()
|
return streamHandler.rest()
|
||||||
|
@ -6,16 +6,15 @@ const log = Object.assign(debug('libp2p:circuit:stream-handler'), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
|
// @ts-ignore it-handshake does not export types
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const { CircuitRelay: CircuitPB } = require('../protocol')
|
const { CircuitRelay } = require('../protocol')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
|
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @template T
|
|
||||||
*/
|
|
||||||
class StreamHandler {
|
class StreamHandler {
|
||||||
/**
|
/**
|
||||||
* Create a stream handler for connection
|
* Create a stream handler for connection
|
||||||
@ -29,6 +28,7 @@ class StreamHandler {
|
|||||||
this.stream = stream
|
this.stream = stream
|
||||||
|
|
||||||
this.shake = handshake(this.stream)
|
this.shake = handshake(this.stream)
|
||||||
|
// @ts-ignore options are not optional
|
||||||
this.decoder = lp.decode.fromReader(this.shake.reader, { maxDataLength: maxLength })
|
this.decoder = lp.decode.fromReader(this.shake.reader, { maxDataLength: maxLength })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,12 +36,11 @@ class StreamHandler {
|
|||||||
* Read and decode message
|
* Read and decode message
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @returns {Promise<T|undefined>}
|
|
||||||
*/
|
*/
|
||||||
async read () {
|
async read () {
|
||||||
const msg = await this.decoder.next()
|
const msg = await this.decoder.next()
|
||||||
if (msg.value) {
|
if (msg.value) {
|
||||||
const value = CircuitPB.decode(msg.value.slice())
|
const value = CircuitRelay.decode(msg.value.slice())
|
||||||
log('read message type', value.type)
|
log('read message type', value.type)
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
@ -54,13 +53,13 @@ class StreamHandler {
|
|||||||
/**
|
/**
|
||||||
* Encode and write array of buffers
|
* Encode and write array of buffers
|
||||||
*
|
*
|
||||||
* @param {CircuitPB} msg - An unencoded CircuitRelay protobuf message
|
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
write (msg) {
|
write (msg) {
|
||||||
log('write message type %s', msg.type)
|
log('write message type %s', msg.type)
|
||||||
// @ts-ignore lp.encode expects type type 'Buffer | BufferList', not 'Uint8Array'
|
// @ts-ignore lp.encode expects type type 'Buffer | BufferList', not 'Uint8Array'
|
||||||
this.shake.write(lp.encode.single(CircuitPB.encode(msg)))
|
this.shake.write(lp.encode.single(CircuitRelay.encode(msg).finish()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -73,6 +72,9 @@ class StreamHandler {
|
|||||||
return this.shake.stream
|
return this.shake.stream
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
|
||||||
|
*/
|
||||||
end (msg) {
|
end (msg) {
|
||||||
this.write(msg)
|
this.write(msg)
|
||||||
this.close()
|
this.close()
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const { CircuitRelay } = require('../protocol')
|
const { CircuitRelay } = require('../protocol')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('./stream-handler')} StreamHandler
|
* @typedef {import('./stream-handler')} StreamHandler
|
||||||
* @typedef {import('../../types').CircuitStatus} CircuitStatus
|
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a response
|
* Write a response
|
||||||
*
|
*
|
||||||
* @param {StreamHandler} streamHandler
|
* @param {StreamHandler} streamHandler
|
||||||
* @param {CircuitStatus} status
|
* @param {import('../protocol').CircuitRelay.Status} status
|
||||||
*/
|
*/
|
||||||
function writeResponse (streamHandler, status) {
|
function writeResponse (streamHandler, status) {
|
||||||
streamHandler.write({
|
streamHandler.write({
|
||||||
@ -24,14 +24,16 @@ function writeResponse (streamHandler, status) {
|
|||||||
/**
|
/**
|
||||||
* Validate incomming HOP/STOP message
|
* Validate incomming HOP/STOP message
|
||||||
*
|
*
|
||||||
* @param {*} msg - A CircuitRelay unencoded protobuf message
|
* @param {ICircuitRelay} msg - A CircuitRelay unencoded protobuf message
|
||||||
* @param {StreamHandler} streamHandler
|
* @param {StreamHandler} streamHandler
|
||||||
*/
|
*/
|
||||||
function validateAddrs (msg, streamHandler) {
|
function validateAddrs (msg, streamHandler) {
|
||||||
try {
|
try {
|
||||||
msg.dstPeer.addrs.forEach((addr) => {
|
if (msg.dstPeer && msg.dstPeer.addrs) {
|
||||||
return multiaddr(addr)
|
msg.dstPeer.addrs.forEach((addr) => {
|
||||||
})
|
return new Multiaddr(addr)
|
||||||
|
})
|
||||||
|
}
|
||||||
} catch (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
|
||||||
@ -40,9 +42,11 @@ function validateAddrs (msg, streamHandler) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
msg.srcPeer.addrs.forEach((addr) => {
|
if (msg.srcPeer && msg.srcPeer.addrs) {
|
||||||
return multiaddr(addr)
|
msg.srcPeer.addrs.forEach((addr) => {
|
||||||
})
|
return new Multiaddr(addr)
|
||||||
|
})
|
||||||
|
}
|
||||||
} catch (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
|
||||||
|
@ -8,13 +8,12 @@ const log = Object.assign(debug('libp2p:relay'), {
|
|||||||
const {
|
const {
|
||||||
setDelayedInterval,
|
setDelayedInterval,
|
||||||
clearDelayedInterval
|
clearDelayedInterval
|
||||||
|
// @ts-ignore set-delayed-interval does not export types
|
||||||
} = require('set-delayed-interval')
|
} = require('set-delayed-interval')
|
||||||
|
|
||||||
const AutoRelay = require('./auto-relay')
|
const AutoRelay = require('./auto-relay')
|
||||||
const { namespaceToCid } = require('./utils')
|
const { namespaceToCid } = require('./utils')
|
||||||
const {
|
const {
|
||||||
ADVERTISE_BOOT_DELAY,
|
|
||||||
ADVERTISE_TTL,
|
|
||||||
RELAY_RENDEZVOUS_NS
|
RELAY_RENDEZVOUS_NS
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
|
|
||||||
@ -45,12 +44,6 @@ class Relay {
|
|||||||
constructor (libp2p) {
|
constructor (libp2p) {
|
||||||
this._libp2p = libp2p
|
this._libp2p = libp2p
|
||||||
this._options = {
|
this._options = {
|
||||||
advertise: {
|
|
||||||
bootDelay: ADVERTISE_BOOT_DELAY,
|
|
||||||
enabled: true,
|
|
||||||
ttl: ADVERTISE_TTL,
|
|
||||||
...libp2p._config.relay.advertise
|
|
||||||
},
|
|
||||||
...libp2p._config.relay
|
...libp2p._config.relay
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const { EventEmitter } = require('events')
|
const { EventEmitter } = require('events')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
|
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ module.exports = (libp2p) => {
|
|||||||
async function listen (addr) {
|
async function listen (addr) {
|
||||||
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
|
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
|
||||||
|
|
||||||
const relayConn = await libp2p.dial(multiaddr(addrString))
|
const relayConn = await libp2p.dial(new Multiaddr(addrString))
|
||||||
const relayedAddr = relayConn.remoteAddr.encapsulate('/p2p-circuit')
|
const relayedAddr = relayConn.remoteAddr.encapsulate('/p2p-circuit')
|
||||||
|
|
||||||
listeningAddrs.set(relayConn.remotePeer.toB58String(), relayedAddr)
|
listeningAddrs.set(relayConn.remotePeer.toB58String(), relayedAddr)
|
||||||
|
173
src/circuit/protocol/index.d.ts
vendored
Normal file
173
src/circuit/protocol/index.d.ts
vendored
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of a CircuitRelay. */
|
||||||
|
export interface ICircuitRelay {
|
||||||
|
|
||||||
|
/** CircuitRelay type */
|
||||||
|
type?: (CircuitRelay.Type|null);
|
||||||
|
|
||||||
|
/** CircuitRelay srcPeer */
|
||||||
|
srcPeer?: (CircuitRelay.IPeer|null);
|
||||||
|
|
||||||
|
/** CircuitRelay dstPeer */
|
||||||
|
dstPeer?: (CircuitRelay.IPeer|null);
|
||||||
|
|
||||||
|
/** CircuitRelay code */
|
||||||
|
code?: (CircuitRelay.Status|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a CircuitRelay. */
|
||||||
|
export class CircuitRelay implements ICircuitRelay {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new CircuitRelay.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: ICircuitRelay);
|
||||||
|
|
||||||
|
/** CircuitRelay type. */
|
||||||
|
public type: CircuitRelay.Type;
|
||||||
|
|
||||||
|
/** CircuitRelay srcPeer. */
|
||||||
|
public srcPeer?: (CircuitRelay.IPeer|null);
|
||||||
|
|
||||||
|
/** CircuitRelay dstPeer. */
|
||||||
|
public dstPeer?: (CircuitRelay.IPeer|null);
|
||||||
|
|
||||||
|
/** CircuitRelay code. */
|
||||||
|
public code: CircuitRelay.Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified CircuitRelay message. Does not implicitly {@link CircuitRelay.verify|verify} messages.
|
||||||
|
* @param m CircuitRelay message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: ICircuitRelay, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a CircuitRelay message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns CircuitRelay
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): CircuitRelay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a CircuitRelay message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns CircuitRelay
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): CircuitRelay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a CircuitRelay message. Also converts values to other types if specified.
|
||||||
|
* @param m CircuitRelay
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: CircuitRelay, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this CircuitRelay to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace CircuitRelay {
|
||||||
|
|
||||||
|
/** Status enum. */
|
||||||
|
enum Status {
|
||||||
|
SUCCESS = 100,
|
||||||
|
HOP_SRC_ADDR_TOO_LONG = 220,
|
||||||
|
HOP_DST_ADDR_TOO_LONG = 221,
|
||||||
|
HOP_SRC_MULTIADDR_INVALID = 250,
|
||||||
|
HOP_DST_MULTIADDR_INVALID = 251,
|
||||||
|
HOP_NO_CONN_TO_DST = 260,
|
||||||
|
HOP_CANT_DIAL_DST = 261,
|
||||||
|
HOP_CANT_OPEN_DST_STREAM = 262,
|
||||||
|
HOP_CANT_SPEAK_RELAY = 270,
|
||||||
|
HOP_CANT_RELAY_TO_SELF = 280,
|
||||||
|
STOP_SRC_ADDR_TOO_LONG = 320,
|
||||||
|
STOP_DST_ADDR_TOO_LONG = 321,
|
||||||
|
STOP_SRC_MULTIADDR_INVALID = 350,
|
||||||
|
STOP_DST_MULTIADDR_INVALID = 351,
|
||||||
|
STOP_RELAY_REFUSED = 390,
|
||||||
|
MALFORMED_MESSAGE = 400
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Type enum. */
|
||||||
|
enum Type {
|
||||||
|
HOP = 1,
|
||||||
|
STOP = 2,
|
||||||
|
STATUS = 3,
|
||||||
|
CAN_HOP = 4
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Properties of a Peer. */
|
||||||
|
interface IPeer {
|
||||||
|
|
||||||
|
/** Peer id */
|
||||||
|
id: Uint8Array;
|
||||||
|
|
||||||
|
/** Peer addrs */
|
||||||
|
addrs?: (Uint8Array[]|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a Peer. */
|
||||||
|
class Peer implements IPeer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Peer.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: CircuitRelay.IPeer);
|
||||||
|
|
||||||
|
/** Peer id. */
|
||||||
|
public id: Uint8Array;
|
||||||
|
|
||||||
|
/** Peer addrs. */
|
||||||
|
public addrs: Uint8Array[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Peer message. Does not implicitly {@link CircuitRelay.Peer.verify|verify} messages.
|
||||||
|
* @param m Peer message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: CircuitRelay.IPeer, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a Peer message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Peer
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): CircuitRelay.Peer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Peer message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Peer
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): CircuitRelay.Peer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a Peer message. Also converts values to other types if specified.
|
||||||
|
* @param m Peer
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: CircuitRelay.Peer, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Peer to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
}
|
@ -1,46 +1,530 @@
|
|||||||
'use strict'
|
/*eslint-disable*/
|
||||||
const protobuf = require('protons')
|
"use strict";
|
||||||
|
|
||||||
/** @type {{CircuitRelay: import('../../types').CircuitMessageProto}} */
|
var $protobuf = require("protobufjs/minimal");
|
||||||
module.exports = protobuf(`
|
|
||||||
message CircuitRelay {
|
|
||||||
|
|
||||||
enum Status {
|
// Common aliases
|
||||||
SUCCESS = 100;
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
HOP_SRC_ADDR_TOO_LONG = 220;
|
|
||||||
HOP_DST_ADDR_TOO_LONG = 221;
|
|
||||||
HOP_SRC_MULTIADDR_INVALID = 250;
|
|
||||||
HOP_DST_MULTIADDR_INVALID = 251;
|
|
||||||
HOP_NO_CONN_TO_DST = 260;
|
|
||||||
HOP_CANT_DIAL_DST = 261;
|
|
||||||
HOP_CANT_OPEN_DST_STREAM = 262;
|
|
||||||
HOP_CANT_SPEAK_RELAY = 270;
|
|
||||||
HOP_CANT_RELAY_TO_SELF = 280;
|
|
||||||
STOP_SRC_ADDR_TOO_LONG = 320;
|
|
||||||
STOP_DST_ADDR_TOO_LONG = 321;
|
|
||||||
STOP_SRC_MULTIADDR_INVALID = 350;
|
|
||||||
STOP_DST_MULTIADDR_INVALID = 351;
|
|
||||||
STOP_RELAY_REFUSED = 390;
|
|
||||||
MALFORMED_MESSAGE = 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Type { // RPC identifier, either HOP, STOP or STATUS
|
// Exported root namespace
|
||||||
HOP = 1;
|
var $root = $protobuf.roots["libp2p-circuit"] || ($protobuf.roots["libp2p-circuit"] = {});
|
||||||
STOP = 2;
|
|
||||||
STATUS = 3;
|
|
||||||
CAN_HOP = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Peer {
|
$root.CircuitRelay = (function() {
|
||||||
required bytes id = 1; // peer id
|
|
||||||
repeated bytes addrs = 2; // peer's known addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
optional Type type = 1; // Type of the message
|
/**
|
||||||
|
* Properties of a CircuitRelay.
|
||||||
|
* @exports ICircuitRelay
|
||||||
|
* @interface ICircuitRelay
|
||||||
|
* @property {CircuitRelay.Type|null} [type] CircuitRelay type
|
||||||
|
* @property {CircuitRelay.IPeer|null} [srcPeer] CircuitRelay srcPeer
|
||||||
|
* @property {CircuitRelay.IPeer|null} [dstPeer] CircuitRelay dstPeer
|
||||||
|
* @property {CircuitRelay.Status|null} [code] CircuitRelay code
|
||||||
|
*/
|
||||||
|
|
||||||
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STATUS
|
/**
|
||||||
optional Peer dstPeer = 3;
|
* Constructs a new CircuitRelay.
|
||||||
|
* @exports CircuitRelay
|
||||||
|
* @classdesc Represents a CircuitRelay.
|
||||||
|
* @implements ICircuitRelay
|
||||||
|
* @constructor
|
||||||
|
* @param {ICircuitRelay=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function CircuitRelay(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
optional Status code = 4; // Status code, used when Type is STATUS
|
/**
|
||||||
}
|
* CircuitRelay type.
|
||||||
`)
|
* @member {CircuitRelay.Type} type
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CircuitRelay.prototype.type = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CircuitRelay srcPeer.
|
||||||
|
* @member {CircuitRelay.IPeer|null|undefined} srcPeer
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CircuitRelay.prototype.srcPeer = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CircuitRelay dstPeer.
|
||||||
|
* @member {CircuitRelay.IPeer|null|undefined} dstPeer
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CircuitRelay.prototype.dstPeer = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CircuitRelay code.
|
||||||
|
* @member {CircuitRelay.Status} code
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CircuitRelay.prototype.code = 100;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified CircuitRelay message. Does not implicitly {@link CircuitRelay.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @static
|
||||||
|
* @param {ICircuitRelay} m CircuitRelay message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
CircuitRelay.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.type != null && Object.hasOwnProperty.call(m, "type"))
|
||||||
|
w.uint32(8).int32(m.type);
|
||||||
|
if (m.srcPeer != null && Object.hasOwnProperty.call(m, "srcPeer"))
|
||||||
|
$root.CircuitRelay.Peer.encode(m.srcPeer, w.uint32(18).fork()).ldelim();
|
||||||
|
if (m.dstPeer != null && Object.hasOwnProperty.call(m, "dstPeer"))
|
||||||
|
$root.CircuitRelay.Peer.encode(m.dstPeer, w.uint32(26).fork()).ldelim();
|
||||||
|
if (m.code != null && Object.hasOwnProperty.call(m, "code"))
|
||||||
|
w.uint32(32).int32(m.code);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a CircuitRelay message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {CircuitRelay} CircuitRelay
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
CircuitRelay.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.CircuitRelay();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.type = r.int32();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.srcPeer = $root.CircuitRelay.Peer.decode(r, r.uint32());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
m.dstPeer = $root.CircuitRelay.Peer.decode(r, r.uint32());
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
m.code = r.int32();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a CircuitRelay message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {CircuitRelay} CircuitRelay
|
||||||
|
*/
|
||||||
|
CircuitRelay.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.CircuitRelay)
|
||||||
|
return d;
|
||||||
|
var m = new $root.CircuitRelay();
|
||||||
|
switch (d.type) {
|
||||||
|
case "HOP":
|
||||||
|
case 1:
|
||||||
|
m.type = 1;
|
||||||
|
break;
|
||||||
|
case "STOP":
|
||||||
|
case 2:
|
||||||
|
m.type = 2;
|
||||||
|
break;
|
||||||
|
case "STATUS":
|
||||||
|
case 3:
|
||||||
|
m.type = 3;
|
||||||
|
break;
|
||||||
|
case "CAN_HOP":
|
||||||
|
case 4:
|
||||||
|
m.type = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (d.srcPeer != null) {
|
||||||
|
if (typeof d.srcPeer !== "object")
|
||||||
|
throw TypeError(".CircuitRelay.srcPeer: object expected");
|
||||||
|
m.srcPeer = $root.CircuitRelay.Peer.fromObject(d.srcPeer);
|
||||||
|
}
|
||||||
|
if (d.dstPeer != null) {
|
||||||
|
if (typeof d.dstPeer !== "object")
|
||||||
|
throw TypeError(".CircuitRelay.dstPeer: object expected");
|
||||||
|
m.dstPeer = $root.CircuitRelay.Peer.fromObject(d.dstPeer);
|
||||||
|
}
|
||||||
|
switch (d.code) {
|
||||||
|
case "SUCCESS":
|
||||||
|
case 100:
|
||||||
|
m.code = 100;
|
||||||
|
break;
|
||||||
|
case "HOP_SRC_ADDR_TOO_LONG":
|
||||||
|
case 220:
|
||||||
|
m.code = 220;
|
||||||
|
break;
|
||||||
|
case "HOP_DST_ADDR_TOO_LONG":
|
||||||
|
case 221:
|
||||||
|
m.code = 221;
|
||||||
|
break;
|
||||||
|
case "HOP_SRC_MULTIADDR_INVALID":
|
||||||
|
case 250:
|
||||||
|
m.code = 250;
|
||||||
|
break;
|
||||||
|
case "HOP_DST_MULTIADDR_INVALID":
|
||||||
|
case 251:
|
||||||
|
m.code = 251;
|
||||||
|
break;
|
||||||
|
case "HOP_NO_CONN_TO_DST":
|
||||||
|
case 260:
|
||||||
|
m.code = 260;
|
||||||
|
break;
|
||||||
|
case "HOP_CANT_DIAL_DST":
|
||||||
|
case 261:
|
||||||
|
m.code = 261;
|
||||||
|
break;
|
||||||
|
case "HOP_CANT_OPEN_DST_STREAM":
|
||||||
|
case 262:
|
||||||
|
m.code = 262;
|
||||||
|
break;
|
||||||
|
case "HOP_CANT_SPEAK_RELAY":
|
||||||
|
case 270:
|
||||||
|
m.code = 270;
|
||||||
|
break;
|
||||||
|
case "HOP_CANT_RELAY_TO_SELF":
|
||||||
|
case 280:
|
||||||
|
m.code = 280;
|
||||||
|
break;
|
||||||
|
case "STOP_SRC_ADDR_TOO_LONG":
|
||||||
|
case 320:
|
||||||
|
m.code = 320;
|
||||||
|
break;
|
||||||
|
case "STOP_DST_ADDR_TOO_LONG":
|
||||||
|
case 321:
|
||||||
|
m.code = 321;
|
||||||
|
break;
|
||||||
|
case "STOP_SRC_MULTIADDR_INVALID":
|
||||||
|
case 350:
|
||||||
|
m.code = 350;
|
||||||
|
break;
|
||||||
|
case "STOP_DST_MULTIADDR_INVALID":
|
||||||
|
case 351:
|
||||||
|
m.code = 351;
|
||||||
|
break;
|
||||||
|
case "STOP_RELAY_REFUSED":
|
||||||
|
case 390:
|
||||||
|
m.code = 390;
|
||||||
|
break;
|
||||||
|
case "MALFORMED_MESSAGE":
|
||||||
|
case 400:
|
||||||
|
m.code = 400;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a CircuitRelay message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @static
|
||||||
|
* @param {CircuitRelay} m CircuitRelay
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
CircuitRelay.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
d.type = o.enums === String ? "HOP" : 1;
|
||||||
|
d.srcPeer = null;
|
||||||
|
d.dstPeer = null;
|
||||||
|
d.code = o.enums === String ? "SUCCESS" : 100;
|
||||||
|
}
|
||||||
|
if (m.type != null && m.hasOwnProperty("type")) {
|
||||||
|
d.type = o.enums === String ? $root.CircuitRelay.Type[m.type] : m.type;
|
||||||
|
}
|
||||||
|
if (m.srcPeer != null && m.hasOwnProperty("srcPeer")) {
|
||||||
|
d.srcPeer = $root.CircuitRelay.Peer.toObject(m.srcPeer, o);
|
||||||
|
}
|
||||||
|
if (m.dstPeer != null && m.hasOwnProperty("dstPeer")) {
|
||||||
|
d.dstPeer = $root.CircuitRelay.Peer.toObject(m.dstPeer, o);
|
||||||
|
}
|
||||||
|
if (m.code != null && m.hasOwnProperty("code")) {
|
||||||
|
d.code = o.enums === String ? $root.CircuitRelay.Status[m.code] : m.code;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this CircuitRelay to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
CircuitRelay.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status enum.
|
||||||
|
* @name CircuitRelay.Status
|
||||||
|
* @enum {number}
|
||||||
|
* @property {number} SUCCESS=100 SUCCESS value
|
||||||
|
* @property {number} HOP_SRC_ADDR_TOO_LONG=220 HOP_SRC_ADDR_TOO_LONG value
|
||||||
|
* @property {number} HOP_DST_ADDR_TOO_LONG=221 HOP_DST_ADDR_TOO_LONG value
|
||||||
|
* @property {number} HOP_SRC_MULTIADDR_INVALID=250 HOP_SRC_MULTIADDR_INVALID value
|
||||||
|
* @property {number} HOP_DST_MULTIADDR_INVALID=251 HOP_DST_MULTIADDR_INVALID value
|
||||||
|
* @property {number} HOP_NO_CONN_TO_DST=260 HOP_NO_CONN_TO_DST value
|
||||||
|
* @property {number} HOP_CANT_DIAL_DST=261 HOP_CANT_DIAL_DST value
|
||||||
|
* @property {number} HOP_CANT_OPEN_DST_STREAM=262 HOP_CANT_OPEN_DST_STREAM value
|
||||||
|
* @property {number} HOP_CANT_SPEAK_RELAY=270 HOP_CANT_SPEAK_RELAY value
|
||||||
|
* @property {number} HOP_CANT_RELAY_TO_SELF=280 HOP_CANT_RELAY_TO_SELF value
|
||||||
|
* @property {number} STOP_SRC_ADDR_TOO_LONG=320 STOP_SRC_ADDR_TOO_LONG value
|
||||||
|
* @property {number} STOP_DST_ADDR_TOO_LONG=321 STOP_DST_ADDR_TOO_LONG value
|
||||||
|
* @property {number} STOP_SRC_MULTIADDR_INVALID=350 STOP_SRC_MULTIADDR_INVALID value
|
||||||
|
* @property {number} STOP_DST_MULTIADDR_INVALID=351 STOP_DST_MULTIADDR_INVALID value
|
||||||
|
* @property {number} STOP_RELAY_REFUSED=390 STOP_RELAY_REFUSED value
|
||||||
|
* @property {number} MALFORMED_MESSAGE=400 MALFORMED_MESSAGE value
|
||||||
|
*/
|
||||||
|
CircuitRelay.Status = (function() {
|
||||||
|
var valuesById = {}, values = Object.create(valuesById);
|
||||||
|
values[valuesById[100] = "SUCCESS"] = 100;
|
||||||
|
values[valuesById[220] = "HOP_SRC_ADDR_TOO_LONG"] = 220;
|
||||||
|
values[valuesById[221] = "HOP_DST_ADDR_TOO_LONG"] = 221;
|
||||||
|
values[valuesById[250] = "HOP_SRC_MULTIADDR_INVALID"] = 250;
|
||||||
|
values[valuesById[251] = "HOP_DST_MULTIADDR_INVALID"] = 251;
|
||||||
|
values[valuesById[260] = "HOP_NO_CONN_TO_DST"] = 260;
|
||||||
|
values[valuesById[261] = "HOP_CANT_DIAL_DST"] = 261;
|
||||||
|
values[valuesById[262] = "HOP_CANT_OPEN_DST_STREAM"] = 262;
|
||||||
|
values[valuesById[270] = "HOP_CANT_SPEAK_RELAY"] = 270;
|
||||||
|
values[valuesById[280] = "HOP_CANT_RELAY_TO_SELF"] = 280;
|
||||||
|
values[valuesById[320] = "STOP_SRC_ADDR_TOO_LONG"] = 320;
|
||||||
|
values[valuesById[321] = "STOP_DST_ADDR_TOO_LONG"] = 321;
|
||||||
|
values[valuesById[350] = "STOP_SRC_MULTIADDR_INVALID"] = 350;
|
||||||
|
values[valuesById[351] = "STOP_DST_MULTIADDR_INVALID"] = 351;
|
||||||
|
values[valuesById[390] = "STOP_RELAY_REFUSED"] = 390;
|
||||||
|
values[valuesById[400] = "MALFORMED_MESSAGE"] = 400;
|
||||||
|
return values;
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type enum.
|
||||||
|
* @name CircuitRelay.Type
|
||||||
|
* @enum {number}
|
||||||
|
* @property {number} HOP=1 HOP value
|
||||||
|
* @property {number} STOP=2 STOP value
|
||||||
|
* @property {number} STATUS=3 STATUS value
|
||||||
|
* @property {number} CAN_HOP=4 CAN_HOP value
|
||||||
|
*/
|
||||||
|
CircuitRelay.Type = (function() {
|
||||||
|
var valuesById = {}, values = Object.create(valuesById);
|
||||||
|
values[valuesById[1] = "HOP"] = 1;
|
||||||
|
values[valuesById[2] = "STOP"] = 2;
|
||||||
|
values[valuesById[3] = "STATUS"] = 3;
|
||||||
|
values[valuesById[4] = "CAN_HOP"] = 4;
|
||||||
|
return values;
|
||||||
|
})();
|
||||||
|
|
||||||
|
CircuitRelay.Peer = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of a Peer.
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @interface IPeer
|
||||||
|
* @property {Uint8Array} id Peer id
|
||||||
|
* @property {Array.<Uint8Array>|null} [addrs] Peer addrs
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Peer.
|
||||||
|
* @memberof CircuitRelay
|
||||||
|
* @classdesc Represents a Peer.
|
||||||
|
* @implements IPeer
|
||||||
|
* @constructor
|
||||||
|
* @param {CircuitRelay.IPeer=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Peer(p) {
|
||||||
|
this.addrs = [];
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peer id.
|
||||||
|
* @member {Uint8Array} id
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Peer.prototype.id = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Peer addrs.
|
||||||
|
* @member {Array.<Uint8Array>} addrs
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Peer.prototype.addrs = $util.emptyArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Peer message. Does not implicitly {@link CircuitRelay.Peer.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @static
|
||||||
|
* @param {CircuitRelay.IPeer} m Peer message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Peer.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
w.uint32(10).bytes(m.id);
|
||||||
|
if (m.addrs != null && m.addrs.length) {
|
||||||
|
for (var i = 0; i < m.addrs.length; ++i)
|
||||||
|
w.uint32(18).bytes(m.addrs[i]);
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a Peer message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {CircuitRelay.Peer} Peer
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Peer.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.CircuitRelay.Peer();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.id = r.bytes();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!(m.addrs && m.addrs.length))
|
||||||
|
m.addrs = [];
|
||||||
|
m.addrs.push(r.bytes());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!m.hasOwnProperty("id"))
|
||||||
|
throw $util.ProtocolError("missing required 'id'", { instance: m });
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Peer message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {CircuitRelay.Peer} Peer
|
||||||
|
*/
|
||||||
|
Peer.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.CircuitRelay.Peer)
|
||||||
|
return d;
|
||||||
|
var m = new $root.CircuitRelay.Peer();
|
||||||
|
if (d.id != null) {
|
||||||
|
if (typeof d.id === "string")
|
||||||
|
$util.base64.decode(d.id, m.id = $util.newBuffer($util.base64.length(d.id)), 0);
|
||||||
|
else if (d.id.length)
|
||||||
|
m.id = d.id;
|
||||||
|
}
|
||||||
|
if (d.addrs) {
|
||||||
|
if (!Array.isArray(d.addrs))
|
||||||
|
throw TypeError(".CircuitRelay.Peer.addrs: array expected");
|
||||||
|
m.addrs = [];
|
||||||
|
for (var i = 0; i < d.addrs.length; ++i) {
|
||||||
|
if (typeof d.addrs[i] === "string")
|
||||||
|
$util.base64.decode(d.addrs[i], m.addrs[i] = $util.newBuffer($util.base64.length(d.addrs[i])), 0);
|
||||||
|
else if (d.addrs[i].length)
|
||||||
|
m.addrs[i] = d.addrs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a Peer message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @static
|
||||||
|
* @param {CircuitRelay.Peer} m Peer
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Peer.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.arrays || o.defaults) {
|
||||||
|
d.addrs = [];
|
||||||
|
}
|
||||||
|
if (o.defaults) {
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.id = "";
|
||||||
|
else {
|
||||||
|
d.id = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.id = $util.newBuffer(d.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.id != null && m.hasOwnProperty("id")) {
|
||||||
|
d.id = o.bytes === String ? $util.base64.encode(m.id, 0, m.id.length) : o.bytes === Array ? Array.prototype.slice.call(m.id) : m.id;
|
||||||
|
}
|
||||||
|
if (m.addrs && m.addrs.length) {
|
||||||
|
d.addrs = [];
|
||||||
|
for (var j = 0; j < m.addrs.length; ++j) {
|
||||||
|
d.addrs[j] = o.bytes === String ? $util.base64.encode(m.addrs[j], 0, m.addrs[j].length) : o.bytes === Array ? Array.prototype.slice.call(m.addrs[j]) : m.addrs[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Peer to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof CircuitRelay.Peer
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Peer.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Peer;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return CircuitRelay;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
||||||
|
42
src/circuit/protocol/index.proto
Normal file
42
src/circuit/protocol/index.proto
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
syntax = "proto2";
|
||||||
|
|
||||||
|
message CircuitRelay {
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
SUCCESS = 100;
|
||||||
|
HOP_SRC_ADDR_TOO_LONG = 220;
|
||||||
|
HOP_DST_ADDR_TOO_LONG = 221;
|
||||||
|
HOP_SRC_MULTIADDR_INVALID = 250;
|
||||||
|
HOP_DST_MULTIADDR_INVALID = 251;
|
||||||
|
HOP_NO_CONN_TO_DST = 260;
|
||||||
|
HOP_CANT_DIAL_DST = 261;
|
||||||
|
HOP_CANT_OPEN_DST_STREAM = 262;
|
||||||
|
HOP_CANT_SPEAK_RELAY = 270;
|
||||||
|
HOP_CANT_RELAY_TO_SELF = 280;
|
||||||
|
STOP_SRC_ADDR_TOO_LONG = 320;
|
||||||
|
STOP_DST_ADDR_TOO_LONG = 321;
|
||||||
|
STOP_SRC_MULTIADDR_INVALID = 350;
|
||||||
|
STOP_DST_MULTIADDR_INVALID = 351;
|
||||||
|
STOP_RELAY_REFUSED = 390;
|
||||||
|
MALFORMED_MESSAGE = 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Type { // RPC identifier, either HOP, STOP or STATUS
|
||||||
|
HOP = 1;
|
||||||
|
STOP = 2;
|
||||||
|
STATUS = 3;
|
||||||
|
CAN_HOP = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Peer {
|
||||||
|
required bytes id = 1; // peer id
|
||||||
|
repeated bytes addrs = 2; // peer's known addresses
|
||||||
|
}
|
||||||
|
|
||||||
|
optional Type type = 1; // Type of the message
|
||||||
|
|
||||||
|
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STATUS
|
||||||
|
optional Peer dstPeer = 3;
|
||||||
|
|
||||||
|
optional Status code = 4; // Status code, used when Type is STATUS
|
||||||
|
}
|
@ -5,10 +5,12 @@ const log = Object.assign(debug('libp2p:circuit'), {
|
|||||||
error: debug('libp2p:circuit:err')
|
error: debug('libp2p:circuit:err')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const errCode = require('err-code')
|
||||||
const mafmt = require('mafmt')
|
const mafmt = require('mafmt')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const { CircuitRelay: CircuitPB } = require('./protocol')
|
const { CircuitRelay: CircuitPB } = require('./protocol')
|
||||||
|
const { codes } = require('../errors')
|
||||||
|
|
||||||
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
|
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
|
||||||
|
|
||||||
@ -21,10 +23,8 @@ const StreamHandler = require('./circuit/stream-handler')
|
|||||||
const transportSymbol = Symbol.for('@libp2p/js-libp2p-circuit/circuit')
|
const transportSymbol = Symbol.for('@libp2p/js-libp2p-circuit/circuit')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
* @typedef {import('../types').CircuitRequest} CircuitRequest
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Circuit {
|
class Circuit {
|
||||||
@ -54,7 +54,7 @@ class Circuit {
|
|||||||
* @param {MuxedStream} props.stream
|
* @param {MuxedStream} props.stream
|
||||||
*/
|
*/
|
||||||
async _onProtocol ({ connection, stream }) {
|
async _onProtocol ({ connection, stream }) {
|
||||||
/** @type {import('./circuit/stream-handler')<CircuitRequest>} */
|
/** @type {import('./circuit/stream-handler')} */
|
||||||
const streamHandler = new StreamHandler({ stream })
|
const streamHandler = new StreamHandler({ stream })
|
||||||
const request = await streamHandler.read()
|
const request = await streamHandler.read()
|
||||||
|
|
||||||
@ -96,8 +96,10 @@ class Circuit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (virtualConnection) {
|
if (virtualConnection) {
|
||||||
const remoteAddr = multiaddr(request.dstPeer.addrs[0])
|
// @ts-ignore dst peer will not be undefined
|
||||||
const localAddr = multiaddr(request.srcPeer.addrs[0])
|
const remoteAddr = new Multiaddr(request.dstPeer.addrs[0])
|
||||||
|
// @ts-ignore src peer will not be undefined
|
||||||
|
const localAddr = new Multiaddr(request.srcPeer.addrs[0])
|
||||||
const maConn = toConnection({
|
const maConn = toConnection({
|
||||||
stream: virtualConnection,
|
stream: virtualConnection,
|
||||||
remoteAddr,
|
remoteAddr,
|
||||||
@ -123,10 +125,19 @@ class Circuit {
|
|||||||
async dial (ma, options) {
|
async dial (ma, options) {
|
||||||
// Check the multiaddr to see if it contains a relay and a destination peer
|
// Check the multiaddr to see if it contains a relay and a destination peer
|
||||||
const addrs = ma.toString().split('/p2p-circuit')
|
const addrs = ma.toString().split('/p2p-circuit')
|
||||||
const relayAddr = multiaddr(addrs[0])
|
const relayAddr = new Multiaddr(addrs[0])
|
||||||
const destinationAddr = multiaddr(addrs[addrs.length - 1])
|
const destinationAddr = new Multiaddr(addrs[addrs.length - 1])
|
||||||
const relayPeer = PeerId.createFromCID(relayAddr.getPeerId())
|
const relayId = relayAddr.getPeerId()
|
||||||
const destinationPeer = PeerId.createFromCID(destinationAddr.getPeerId())
|
const destinationId = destinationAddr.getPeerId()
|
||||||
|
|
||||||
|
if (!relayId || !destinationId) {
|
||||||
|
const errMsg = 'Circuit relay dial failed as addresses did not have peer id'
|
||||||
|
log.error(errMsg)
|
||||||
|
throw errCode(new Error(errMsg), codes.ERR_RELAYED_DIAL)
|
||||||
|
}
|
||||||
|
|
||||||
|
const relayPeer = PeerId.createFromB58String(relayId)
|
||||||
|
const destinationPeer = PeerId.createFromB58String(destinationId)
|
||||||
|
|
||||||
let disconnectOnFailure = false
|
let disconnectOnFailure = false
|
||||||
let relayConnection = this._connectionManager.get(relayPeer)
|
let relayConnection = this._connectionManager.get(relayPeer)
|
||||||
@ -146,7 +157,7 @@ class Circuit {
|
|||||||
},
|
},
|
||||||
dstPeer: {
|
dstPeer: {
|
||||||
id: destinationPeer.toBytes(),
|
id: destinationPeer.toBytes(),
|
||||||
addrs: [multiaddr(destinationAddr).bytes]
|
addrs: [new Multiaddr(destinationAddr).bytes]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const CID = require('cids')
|
const { CID } = require('multiformats/cid')
|
||||||
const multihashing = require('multihashing-async')
|
const { sha256 } = require('multiformats/hashes/sha2')
|
||||||
|
|
||||||
const TextEncoder = require('ipfs-utils/src/text-encoder')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a namespace string into a cid.
|
* Convert a namespace string into a cid.
|
||||||
@ -13,7 +11,7 @@ const TextEncoder = require('ipfs-utils/src/text-encoder')
|
|||||||
*/
|
*/
|
||||||
module.exports.namespaceToCid = async (namespace) => {
|
module.exports.namespaceToCid = async (namespace) => {
|
||||||
const bytes = new TextEncoder().encode(namespace)
|
const bytes = new TextEncoder().encode(namespace)
|
||||||
const hash = await multihashing(bytes, 'sha2-256')
|
const hash = await sha256.digest(bytes)
|
||||||
|
|
||||||
return new CID(hash)
|
return CID.createV0(hash)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
|
// @ts-ignore no types in multiaddr path
|
||||||
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
|
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
|
||||||
|
|
||||||
const Constants = require('./constants')
|
const Constants = require('./constants')
|
||||||
@ -10,11 +11,18 @@ const RelayConstants = require('./circuit/constants')
|
|||||||
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
||||||
const { FaultTolerance } = require('./transport-manager')
|
const { FaultTolerance } = require('./transport-manager')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
|
* @typedef {import('.').Libp2pOptions} Libp2pOptions
|
||||||
|
* @typedef {import('.').constructorOptions} constructorOptions
|
||||||
|
*/
|
||||||
|
|
||||||
const DefaultConfig = {
|
const DefaultConfig = {
|
||||||
addresses: {
|
addresses: {
|
||||||
listen: [],
|
listen: [],
|
||||||
announce: [],
|
announce: [],
|
||||||
noAnnounce: []
|
noAnnounce: [],
|
||||||
|
announceFilter: (/** @type {Multiaddr[]} */ multiaddrs) => multiaddrs
|
||||||
},
|
},
|
||||||
connectionManager: {
|
connectionManager: {
|
||||||
minConnections: 25
|
minConnections: 25
|
||||||
@ -95,10 +103,15 @@ const DefaultConfig = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Libp2pOptions} opts
|
||||||
|
* @returns {DefaultConfig & Libp2pOptions & constructorOptions}
|
||||||
|
*/
|
||||||
module.exports.validate = (opts) => {
|
module.exports.validate = (opts) => {
|
||||||
opts = mergeOptions(DefaultConfig, opts)
|
/** @type {DefaultConfig & Libp2pOptions & constructorOptions} */
|
||||||
|
const resultingOptions = mergeOptions(DefaultConfig, opts)
|
||||||
|
|
||||||
if (opts.modules.transport.length < 1) throw new Error("'options.modules.transport' must contain at least 1 transport")
|
if (resultingOptions.modules.transport.length < 1) throw new Error("'options.modules.transport' must contain at least 1 transport")
|
||||||
|
|
||||||
return opts
|
return resultingOptions
|
||||||
}
|
}
|
||||||
|
@ -8,11 +8,10 @@ const log = Object.assign(debug('libp2p:connection-manager'), {
|
|||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
const LatencyMonitor = require('./latency-monitor')
|
const LatencyMonitor = require('./latency-monitor')
|
||||||
|
// @ts-ignore retimer does not have types
|
||||||
const retimer = require('retimer')
|
const retimer = require('retimer')
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
|
||||||
const EventEmitter = require('events')
|
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
@ -98,6 +97,11 @@ class ConnectionManager extends EventEmitter {
|
|||||||
this._autoDialTimeout = null
|
this._autoDialTimeout = null
|
||||||
this._checkMetrics = this._checkMetrics.bind(this)
|
this._checkMetrics = this._checkMetrics.bind(this)
|
||||||
this._autoDial = this._autoDial.bind(this)
|
this._autoDial = this._autoDial.bind(this)
|
||||||
|
|
||||||
|
this._latencyMonitor = new LatencyMonitor({
|
||||||
|
latencyCheckIntervalMs: this._options.pollInterval,
|
||||||
|
dataEmitIntervalMs: this._options.pollInterval
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,10 +122,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// latency monitor
|
// latency monitor
|
||||||
this._latencyMonitor = new LatencyMonitor({
|
this._latencyMonitor.start()
|
||||||
latencyCheckIntervalMs: this._options.pollInterval,
|
|
||||||
dataEmitIntervalMs: this._options.pollInterval
|
|
||||||
})
|
|
||||||
this._onLatencyMeasure = this._onLatencyMeasure.bind(this)
|
this._onLatencyMeasure = this._onLatencyMeasure.bind(this)
|
||||||
this._latencyMonitor.on('data', this._onLatencyMeasure)
|
this._latencyMonitor.on('data', this._onLatencyMeasure)
|
||||||
|
|
||||||
@ -139,7 +140,9 @@ class ConnectionManager extends EventEmitter {
|
|||||||
async stop () {
|
async stop () {
|
||||||
this._autoDialTimeout && this._autoDialTimeout.clear()
|
this._autoDialTimeout && this._autoDialTimeout.clear()
|
||||||
this._timer && this._timer.clear()
|
this._timer && this._timer.clear()
|
||||||
this._latencyMonitor && this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
|
||||||
|
this._latencyMonitor.removeListener('data', this._onLatencyMeasure)
|
||||||
|
this._latencyMonitor.stop()
|
||||||
|
|
||||||
this._started = false
|
this._started = false
|
||||||
await this._close()
|
await this._close()
|
||||||
@ -188,8 +191,10 @@ class ConnectionManager extends EventEmitter {
|
|||||||
_checkMetrics () {
|
_checkMetrics () {
|
||||||
if (this._libp2p.metrics) {
|
if (this._libp2p.metrics) {
|
||||||
const movingAverages = this._libp2p.metrics.global.movingAverages
|
const movingAverages = this._libp2p.metrics.global.movingAverages
|
||||||
|
// @ts-ignore moving averages object types
|
||||||
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
|
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
|
||||||
this._checkMaxLimit('maxReceivedData', received)
|
this._checkMaxLimit('maxReceivedData', received)
|
||||||
|
// @ts-ignore moving averages object types
|
||||||
const sent = movingAverages.dataSent[this._options.movingAverageInterval].movingAverage()
|
const sent = movingAverages.dataSent[this._options.movingAverageInterval].movingAverage()
|
||||||
this._checkMaxLimit('maxSentData', sent)
|
this._checkMaxLimit('maxSentData', sent)
|
||||||
const total = received + sent
|
const total = received + sent
|
||||||
@ -362,7 +367,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
*/
|
*/
|
||||||
_maybeDisconnectOne () {
|
_maybeDisconnectOne () {
|
||||||
if (this._options.minConnections < this.connections.size) {
|
if (this._options.minConnections < this.connections.size) {
|
||||||
const peerValues = Array.from(this._peerValues).sort(byPeerValue)
|
const peerValues = Array.from(new Map([...this._peerValues.entries()].sort((a, b) => a[1] - b[1])))
|
||||||
log('%s: sorted peer values: %j', this._peerId, peerValues)
|
log('%s: sorted peer values: %j', this._peerId, peerValues)
|
||||||
const disconnectPeer = peerValues[0]
|
const disconnectPeer = peerValues[0]
|
||||||
if (disconnectPeer) {
|
if (disconnectPeer) {
|
||||||
@ -381,7 +386,3 @@ class ConnectionManager extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ConnectionManager
|
module.exports = ConnectionManager
|
||||||
|
|
||||||
function byPeerValue (peerValueEntryA, peerValueEntryB) {
|
|
||||||
return peerValueEntryA[1] - peerValueEntryB[1]
|
|
||||||
}
|
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
|
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
|
||||||
const EventEmitter = require('events')
|
|
||||||
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
||||||
const debug = require('debug')('latency-monitor:LatencyMonitor')
|
const debug = require('debug')('latency-monitor:LatencyMonitor')
|
||||||
|
|
||||||
@ -59,7 +57,8 @@ class LatencyMonitor extends EventEmitter {
|
|||||||
that._latecyCheckMultiply = 2 * (that.latencyRandomPercentage / 100.0) * that.latencyCheckIntervalMs
|
that._latecyCheckMultiply = 2 * (that.latencyRandomPercentage / 100.0) * that.latencyCheckIntervalMs
|
||||||
that._latecyCheckSubtract = that._latecyCheckMultiply / 2
|
that._latecyCheckSubtract = that._latecyCheckMultiply / 2
|
||||||
|
|
||||||
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0) ? undefined
|
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0)
|
||||||
|
? undefined
|
||||||
: dataEmitIntervalMs || 5 * 1000 // 5s
|
: dataEmitIntervalMs || 5 * 1000 // 5s
|
||||||
debug('latencyCheckIntervalMs: %s dataEmitIntervalMs: %s',
|
debug('latencyCheckIntervalMs: %s dataEmitIntervalMs: %s',
|
||||||
that.latencyCheckIntervalMs, that.dataEmitIntervalMs)
|
that.latencyCheckIntervalMs, that.dataEmitIntervalMs)
|
||||||
@ -70,49 +69,55 @@ class LatencyMonitor extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
that.asyncTestFn = asyncTestFn // If there is no asyncFn, we measure latency
|
that.asyncTestFn = asyncTestFn // If there is no asyncFn, we measure latency
|
||||||
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
// If process: use high resolution timer
|
// If process: use high resolution timer
|
||||||
if (globalThis.process && globalThis.process.hrtime) { // eslint-disable-line no-undef
|
if (globalThis.process && globalThis.process.hrtime) { // eslint-disable-line no-undef
|
||||||
debug('Using process.hrtime for timing')
|
debug('Using process.hrtime for timing')
|
||||||
that.now = globalThis.process.hrtime // eslint-disable-line no-undef
|
this.now = globalThis.process.hrtime // eslint-disable-line no-undef
|
||||||
that.getDeltaMS = (startTime) => {
|
this.getDeltaMS = (startTime) => {
|
||||||
const hrtime = that.now(startTime)
|
const hrtime = this.now(startTime)
|
||||||
return (hrtime[0] * 1000) + (hrtime[1] / 1000000)
|
return (hrtime[0] * 1000) + (hrtime[1] / 1000000)
|
||||||
}
|
}
|
||||||
// Let's try for a timer that only monotonically increases
|
// Let's try for a timer that only monotonically increases
|
||||||
} else if (typeof window !== 'undefined' && window.performance && window.performance.now) {
|
} else if (typeof window !== 'undefined' && window.performance && window.performance.now) {
|
||||||
debug('Using performance.now for timing')
|
debug('Using performance.now for timing')
|
||||||
that.now = window.performance.now.bind(window.performance)
|
this.now = window.performance.now.bind(window.performance)
|
||||||
that.getDeltaMS = (startTime) => Math.round(that.now() - startTime)
|
this.getDeltaMS = (startTime) => Math.round(this.now() - startTime)
|
||||||
} else {
|
} else {
|
||||||
debug('Using Date.now for timing')
|
debug('Using Date.now for timing')
|
||||||
that.now = Date.now
|
this.now = Date.now
|
||||||
that.getDeltaMS = (startTime) => that.now() - startTime
|
this.getDeltaMS = (startTime) => this.now() - startTime
|
||||||
}
|
}
|
||||||
|
|
||||||
that._latencyData = that._initLatencyData()
|
this._latencyData = this._initLatencyData()
|
||||||
|
|
||||||
// We check for isBrowser because of browsers set max rates of timeouts when a page is hidden,
|
// We check for isBrowser because of browsers set max rates of timeouts when a page is hidden,
|
||||||
// so we fall back to another library
|
// so we fall back to another library
|
||||||
// See: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs
|
// See: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
that._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
this._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
||||||
|
|
||||||
that._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
this._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
||||||
if (pageInFocus) {
|
if (pageInFocus) {
|
||||||
that._startTimers()
|
this._startTimers()
|
||||||
} else {
|
} else {
|
||||||
that._emitSummary()
|
this._emitSummary()
|
||||||
that._stopTimers()
|
this._stopTimers()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!that._visibilityChangeEmitter || that._visibilityChangeEmitter.isVisible()) {
|
if (!this._visibilityChangeEmitter || this._visibilityChangeEmitter.isVisible()) {
|
||||||
that._startTimers()
|
this._startTimers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
this._stopTimers()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start internal timers
|
* Start internal timers
|
||||||
*
|
*
|
||||||
@ -174,7 +179,8 @@ class LatencyMonitor extends EventEmitter {
|
|||||||
events: this._latencyData.events,
|
events: this._latencyData.events,
|
||||||
minMs: this._latencyData.minMs,
|
minMs: this._latencyData.minMs,
|
||||||
maxMs: this._latencyData.maxMs,
|
maxMs: this._latencyData.maxMs,
|
||||||
avgMs: this._latencyData.events ? this._latencyData.totalMs / this._latencyData.events
|
avgMs: this._latencyData.events
|
||||||
|
? this._latencyData.totalMs / this._latencyData.events
|
||||||
: Number.POSITIVE_INFINITY,
|
: Number.POSITIVE_INFINITY,
|
||||||
lengthMs: this.getDeltaMS(this._latencyData.startTime)
|
lengthMs: this.getDeltaMS(this._latencyData.startTime)
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
|
||||||
const EventEmitter = require('events')
|
|
||||||
|
|
||||||
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ module.exports = {
|
|||||||
DIAL_TIMEOUT: 30e3, // How long in ms a dial attempt is allowed to take
|
DIAL_TIMEOUT: 30e3, // How long in ms a dial attempt is allowed to take
|
||||||
MAX_PARALLEL_DIALS: 100, // Maximum allowed concurrent dials
|
MAX_PARALLEL_DIALS: 100, // Maximum allowed concurrent dials
|
||||||
MAX_PER_PEER_DIALS: 4, // Allowed parallel dials per DialRequest
|
MAX_PER_PEER_DIALS: 4, // Allowed parallel dials per DialRequest
|
||||||
|
MAX_ADDRS_TO_DIAL: 25, // Maximum number of allowed addresses to attempt to dial
|
||||||
METRICS: {
|
METRICS: {
|
||||||
computeThrottleMaxQueueSize: 1000,
|
computeThrottleMaxQueueSize: 1000,
|
||||||
computeThrottleTimeout: 2000,
|
computeThrottleTimeout: 2000,
|
||||||
|
@ -14,8 +14,9 @@ const { pipe } = require('it-pipe')
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
* @typedef {import('cids')} CID
|
* @typedef {import('multiformats/cid').CID} CID
|
||||||
|
* @typedef {import('libp2p-interfaces/src/content-routing/types').ContentRouting} ContentRoutingModule
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,6 +32,7 @@ class ContentRouting {
|
|||||||
*/
|
*/
|
||||||
constructor (libp2p) {
|
constructor (libp2p) {
|
||||||
this.libp2p = libp2p
|
this.libp2p = libp2p
|
||||||
|
/** @type {ContentRoutingModule[]} */
|
||||||
this.routers = libp2p._modules.contentRouting || []
|
this.routers = libp2p._modules.contentRouting || []
|
||||||
this.dht = libp2p._dht
|
this.dht = libp2p._dht
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ const take = require('it-take')
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,13 +3,14 @@
|
|||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const AbortController = require('abort-controller').default
|
const AbortController = require('abort-controller').default
|
||||||
const { anySignal } = require('any-signal')
|
const { anySignal } = require('any-signal')
|
||||||
|
// @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')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('./')} Dialer
|
* @typedef {import('./')} Dialer
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,8 +5,10 @@ const log = Object.assign(debug('libp2p:dialer'), {
|
|||||||
error: debug('libp2p:dialer:err')
|
error: debug('libp2p:dialer:err')
|
||||||
})
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
|
// @ts-ignore timeout-abourt-controles does not export types
|
||||||
const TimeoutController = require('timeout-abort-controller')
|
const TimeoutController = require('timeout-abort-controller')
|
||||||
|
const { AbortError } = require('abortable-iterator')
|
||||||
const { anySignal } = require('any-signal')
|
const { anySignal } = require('any-signal')
|
||||||
|
|
||||||
const DialRequest = require('./dial-request')
|
const DialRequest = require('./dial-request')
|
||||||
@ -17,12 +19,12 @@ const { codes } = require('../errors')
|
|||||||
const {
|
const {
|
||||||
DIAL_TIMEOUT,
|
DIAL_TIMEOUT,
|
||||||
MAX_PARALLEL_DIALS,
|
MAX_PARALLEL_DIALS,
|
||||||
MAX_PER_PEER_DIALS
|
MAX_PER_PEER_DIALS,
|
||||||
|
MAX_ADDRS_TO_DIAL
|
||||||
} = require('../constants')
|
} = require('../constants')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
* @typedef {import('../peer-store')} PeerStore
|
* @typedef {import('../peer-store')} PeerStore
|
||||||
* @typedef {import('../peer-store/address-book').Address} Address
|
* @typedef {import('../peer-store/address-book').Address} Address
|
||||||
@ -38,9 +40,10 @@ const {
|
|||||||
*
|
*
|
||||||
* @typedef {Object} DialerOptions
|
* @typedef {Object} DialerOptions
|
||||||
* @property {(addresses: Address[]) => Address[]} [options.addressSorter = publicAddressesFirst] - Sort the known addresses of a peer before trying to dial.
|
* @property {(addresses: Address[]) => Address[]} [options.addressSorter = publicAddressesFirst] - Sort the known addresses of a peer before trying to dial.
|
||||||
* @property {number} [concurrency = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
|
* @property {number} [maxParallelDials = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
|
||||||
* @property {number} [perPeerLimit = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
|
* @property {number} [maxAddrsToDial = MAX_ADDRS_TO_DIAL] - Number of max addresses to dial for a given peer.
|
||||||
* @property {number} [timeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
|
* @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 {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
|
* @property {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
|
||||||
*
|
*
|
||||||
* @typedef DialTarget
|
* @typedef DialTarget
|
||||||
@ -50,7 +53,7 @@ const {
|
|||||||
* @typedef PendingDial
|
* @typedef PendingDial
|
||||||
* @property {DialRequest} dialRequest
|
* @property {DialRequest} dialRequest
|
||||||
* @property {TimeoutController} controller
|
* @property {TimeoutController} controller
|
||||||
* @property {Promise} promise
|
* @property {Promise<Connection>} promise
|
||||||
* @property {function():void} destroy
|
* @property {function():void} destroy
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -63,22 +66,25 @@ class Dialer {
|
|||||||
transportManager,
|
transportManager,
|
||||||
peerStore,
|
peerStore,
|
||||||
addressSorter = publicAddressesFirst,
|
addressSorter = publicAddressesFirst,
|
||||||
concurrency = MAX_PARALLEL_DIALS,
|
maxParallelDials = MAX_PARALLEL_DIALS,
|
||||||
timeout = DIAL_TIMEOUT,
|
maxAddrsToDial = MAX_ADDRS_TO_DIAL,
|
||||||
perPeerLimit = MAX_PER_PEER_DIALS,
|
dialTimeout = DIAL_TIMEOUT,
|
||||||
|
maxDialsPerPeer = MAX_PER_PEER_DIALS,
|
||||||
resolvers = {}
|
resolvers = {}
|
||||||
}) {
|
}) {
|
||||||
this.transportManager = transportManager
|
this.transportManager = transportManager
|
||||||
this.peerStore = peerStore
|
this.peerStore = peerStore
|
||||||
this.addressSorter = addressSorter
|
this.addressSorter = addressSorter
|
||||||
this.concurrency = concurrency
|
this.maxParallelDials = maxParallelDials
|
||||||
this.timeout = timeout
|
this.maxAddrsToDial = maxAddrsToDial
|
||||||
this.perPeerLimit = perPeerLimit
|
this.timeout = dialTimeout
|
||||||
this.tokens = [...new Array(concurrency)].map((_, index) => index)
|
this.maxDialsPerPeer = maxDialsPerPeer
|
||||||
|
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
|
||||||
this._pendingDials = new Map()
|
this._pendingDials = new Map()
|
||||||
|
this._pendingDialTargets = new Map()
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +100,11 @@ class Dialer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this._pendingDials.clear()
|
this._pendingDials.clear()
|
||||||
|
|
||||||
|
for (const pendingTarget of this._pendingDialTargets.values()) {
|
||||||
|
pendingTarget.reject(new AbortError('Dialer was destroyed'))
|
||||||
|
}
|
||||||
|
this._pendingDialTargets.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,10 +118,10 @@ class Dialer {
|
|||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
async connectToPeer (peer, options = {}) {
|
async connectToPeer (peer, options = {}) {
|
||||||
const dialTarget = await this._createDialTarget(peer)
|
const dialTarget = await this._createCancellableDialTarget(peer)
|
||||||
|
|
||||||
if (!dialTarget.addrs.length) {
|
if (!dialTarget.addrs.length) {
|
||||||
throw errCode(new Error('The dial request has no addresses'), codes.ERR_NO_VALID_ADDRESSES)
|
throw errCode(new Error('The dial request has no valid addresses'), codes.ERR_NO_VALID_ADDRESSES)
|
||||||
}
|
}
|
||||||
const pendingDial = this._pendingDials.get(dialTarget.id) || this._createPendingDial(dialTarget, options)
|
const pendingDial = this._pendingDials.get(dialTarget.id) || this._createPendingDial(dialTarget, options)
|
||||||
|
|
||||||
@ -130,10 +141,36 @@ class Dialer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to a given `peer` by dialing all of its known addresses.
|
||||||
|
* The dial to the first address that is successfully able to upgrade a connection
|
||||||
|
* will be used.
|
||||||
|
*
|
||||||
|
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||||
|
* @returns {Promise<DialTarget>}
|
||||||
|
*/
|
||||||
|
async _createCancellableDialTarget (peer) {
|
||||||
|
// Make dial target promise cancellable
|
||||||
|
const id = `${(parseInt(String(Math.random() * 1e9), 10)).toString() + Date.now()}`
|
||||||
|
const cancellablePromise = new Promise((resolve, reject) => {
|
||||||
|
this._pendingDialTargets.set(id, { resolve, reject })
|
||||||
|
})
|
||||||
|
|
||||||
|
const dialTarget = await Promise.race([
|
||||||
|
this._createDialTarget(peer),
|
||||||
|
cancellablePromise
|
||||||
|
])
|
||||||
|
|
||||||
|
this._pendingDialTargets.delete(id)
|
||||||
|
|
||||||
|
return dialTarget
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DialTarget. The DialTarget is used to create and track
|
* Creates a DialTarget. The DialTarget is used to create and track
|
||||||
* the DialRequest to a given peer.
|
* the DialRequest to a given peer.
|
||||||
* If a multiaddr is received it should be the first address attempted.
|
* If a multiaddr is received it should be the first address attempted.
|
||||||
|
* Multiaddrs not supported by the available transports will be filtered out.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerId|Multiaddr|string} peer - A PeerId or Multiaddr
|
* @param {PeerId|Multiaddr|string} peer - A PeerId or Multiaddr
|
||||||
@ -150,20 +187,29 @@ class Dialer {
|
|||||||
|
|
||||||
// If received a multiaddr to dial, it should be the first to use
|
// If received a multiaddr to dial, it should be the first to use
|
||||||
// But, if we know other multiaddrs for the peer, we should try them too.
|
// But, if we know other multiaddrs for the peer, we should try them too.
|
||||||
if (multiaddr.isMultiaddr(peer)) {
|
if (Multiaddr.isMultiaddr(peer)) {
|
||||||
knownAddrs = knownAddrs.filter((addr) => !peer.equals(addr))
|
knownAddrs = knownAddrs.filter((addr) => !peer.equals(addr))
|
||||||
knownAddrs.unshift(peer)
|
knownAddrs.unshift(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type {Multiaddr[]} */
|
||||||
const addrs = []
|
const addrs = []
|
||||||
for (const a of knownAddrs) {
|
for (const a of knownAddrs) {
|
||||||
const resolvedAddrs = await this._resolve(a)
|
const resolvedAddrs = await this._resolve(a)
|
||||||
resolvedAddrs.forEach(ra => addrs.push(ra))
|
resolvedAddrs.forEach(ra => addrs.push(ra))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Multiaddrs not supported by the available transports will be filtered out.
|
||||||
|
const supportedAddrs = addrs.filter(a => this.transportManager.transportForMultiaddr(a))
|
||||||
|
|
||||||
|
if (supportedAddrs.length > this.maxAddrsToDial) {
|
||||||
|
this.peerStore.delete(id)
|
||||||
|
throw errCode(new Error('dial with more addresses than allowed'), codes.ERR_TOO_MANY_ADDRESSES)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: id.toB58String(),
|
id: id.toB58String(),
|
||||||
addrs
|
addrs: supportedAddrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +223,10 @@ class Dialer {
|
|||||||
* @returns {PendingDial}
|
* @returns {PendingDial}
|
||||||
*/
|
*/
|
||||||
_createPendingDial (dialTarget, options = {}) {
|
_createPendingDial (dialTarget, options = {}) {
|
||||||
|
/**
|
||||||
|
* @param {Multiaddr} addr
|
||||||
|
* @param {{ signal: { aborted: any; }; }} options
|
||||||
|
*/
|
||||||
const dialAction = (addr, options) => {
|
const dialAction = (addr, options) => {
|
||||||
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
|
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
|
||||||
return this.transportManager.dial(addr, options)
|
return this.transportManager.dial(addr, options)
|
||||||
@ -207,13 +257,19 @@ class Dialer {
|
|||||||
return pendingDial
|
return pendingDial
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} num
|
||||||
|
*/
|
||||||
getTokens (num) {
|
getTokens (num) {
|
||||||
const total = Math.min(num, this.perPeerLimit, this.tokens.length)
|
const total = Math.min(num, this.maxDialsPerPeer, this.tokens.length)
|
||||||
const tokens = this.tokens.splice(0, total)
|
const tokens = this.tokens.splice(0, total)
|
||||||
log('%d tokens request, returning %d, %d remaining', num, total, this.tokens.length)
|
log('%d tokens request, returning %d, %d remaining', num, total, this.tokens.length)
|
||||||
return tokens
|
return tokens
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {number} token
|
||||||
|
*/
|
||||||
releaseToken (token) {
|
releaseToken (token) {
|
||||||
// Guard against duplicate releases
|
// Guard against duplicate releases
|
||||||
if (this.tokens.indexOf(token) > -1) return
|
if (this.tokens.indexOf(token) > -1) return
|
||||||
@ -259,7 +315,7 @@ class Dialer {
|
|||||||
*/
|
*/
|
||||||
async _resolveRecord (ma) {
|
async _resolveRecord (ma) {
|
||||||
try {
|
try {
|
||||||
ma = multiaddr(ma.toString()) // Use current multiaddr module
|
ma = new Multiaddr(ma.toString()) // Use current multiaddr module
|
||||||
const multiaddrs = await ma.resolve()
|
const multiaddrs = await ma.resolve()
|
||||||
return multiaddrs
|
return multiaddrs
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
|
@ -11,11 +11,14 @@ exports.codes = {
|
|||||||
PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED',
|
PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED',
|
||||||
DHT_NOT_STARTED: 'ERR_DHT_NOT_STARTED',
|
DHT_NOT_STARTED: 'ERR_DHT_NOT_STARTED',
|
||||||
CONN_ENCRYPTION_REQUIRED: 'ERR_CONN_ENCRYPTION_REQUIRED',
|
CONN_ENCRYPTION_REQUIRED: 'ERR_CONN_ENCRYPTION_REQUIRED',
|
||||||
|
ERR_INVALID_PROTOCOLS_FOR_STREAM: 'ERR_INVALID_PROTOCOLS_FOR_STREAM',
|
||||||
ERR_CONNECTION_ENDED: 'ERR_CONNECTION_ENDED',
|
ERR_CONNECTION_ENDED: 'ERR_CONNECTION_ENDED',
|
||||||
ERR_CONNECTION_FAILED: 'ERR_CONNECTION_FAILED',
|
ERR_CONNECTION_FAILED: 'ERR_CONNECTION_FAILED',
|
||||||
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
|
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
|
||||||
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
|
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
|
||||||
|
ERR_TOO_MANY_ADDRESSES: 'ERR_TOO_MANY_ADDRESSES',
|
||||||
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
|
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
|
||||||
|
ERR_RELAYED_DIAL: 'ERR_RELAYED_DIAL',
|
||||||
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
|
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
|
||||||
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
|
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
|
||||||
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
|
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
|
|
||||||
const { codes } = require('./errors')
|
const { codes } = require('./errors')
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given `peer` to a `Peer` object.
|
* Converts the given `peer` to a `Peer` object.
|
||||||
* If a multiaddr is received, the addressBook is updated.
|
* If a multiaddr is received, the addressBook is updated.
|
||||||
@ -19,14 +15,23 @@ const { codes } = require('./errors')
|
|||||||
*/
|
*/
|
||||||
function getPeer (peer) {
|
function getPeer (peer) {
|
||||||
if (typeof peer === 'string') {
|
if (typeof peer === 'string') {
|
||||||
peer = multiaddr(peer)
|
peer = new Multiaddr(peer)
|
||||||
}
|
}
|
||||||
|
|
||||||
let addr
|
let addr
|
||||||
if (multiaddr.isMultiaddr(peer)) {
|
if (Multiaddr.isMultiaddr(peer)) {
|
||||||
addr = peer
|
addr = peer
|
||||||
|
const idStr = peer.getPeerId()
|
||||||
|
|
||||||
|
if (!idStr) {
|
||||||
|
throw errCode(
|
||||||
|
new Error(`${peer} does not have a valid peer type`),
|
||||||
|
codes.ERR_INVALID_MULTIADDR
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
peer = PeerId.createFromB58String(peer.getPeerId())
|
peer = PeerId.createFromB58String(idStr)
|
||||||
} catch (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`),
|
||||||
|
@ -5,14 +5,14 @@ const log = Object.assign(debug('libp2p:identify'), {
|
|||||||
error: debug('libp2p:identify:err')
|
error: debug('libp2p:identify:err')
|
||||||
})
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const pb = require('it-protocol-buffers')
|
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
const { pipe } = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const { collect, take, consume } = require('streaming-iterables')
|
const { collect, take, consume } = require('streaming-iterables')
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
|
// @ts-ignore it-buffer does not have types
|
||||||
const { toBuffer } = require('it-buffer')
|
const { toBuffer } = require('it-buffer')
|
||||||
|
|
||||||
const Message = require('./message')
|
const Message = require('./message')
|
||||||
@ -23,7 +23,6 @@ const PeerRecord = require('../record/peer-record')
|
|||||||
const {
|
const {
|
||||||
MULTICODEC_IDENTIFY,
|
MULTICODEC_IDENTIFY,
|
||||||
MULTICODEC_IDENTIFY_PUSH,
|
MULTICODEC_IDENTIFY_PUSH,
|
||||||
AGENT_VERSION,
|
|
||||||
PROTOCOL_VERSION
|
PROTOCOL_VERSION
|
||||||
} = require('./consts')
|
} = require('./consts')
|
||||||
|
|
||||||
@ -34,6 +33,11 @@ const { codes } = require('../errors')
|
|||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} HostProperties
|
||||||
|
* @property {string} agentVersion
|
||||||
|
*/
|
||||||
|
|
||||||
class IdentifyService {
|
class IdentifyService {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
@ -51,7 +55,6 @@ class IdentifyService {
|
|||||||
|
|
||||||
// Store self host metadata
|
// Store self host metadata
|
||||||
this._host = {
|
this._host = {
|
||||||
agentVersion: AGENT_VERSION,
|
|
||||||
protocolVersion: PROTOCOL_VERSION,
|
protocolVersion: PROTOCOL_VERSION,
|
||||||
...libp2p._options.host
|
...libp2p._options.host
|
||||||
}
|
}
|
||||||
@ -94,12 +97,12 @@ class IdentifyService {
|
|||||||
const { stream } = await connection.newStream(MULTICODEC_IDENTIFY_PUSH)
|
const { stream } = await connection.newStream(MULTICODEC_IDENTIFY_PUSH)
|
||||||
|
|
||||||
await pipe(
|
await pipe(
|
||||||
[{
|
[Message.Identify.encode({
|
||||||
listenAddrs,
|
listenAddrs,
|
||||||
signedPeerRecord,
|
signedPeerRecord,
|
||||||
protocols
|
protocols
|
||||||
}],
|
}).finish()],
|
||||||
pb.encode(Message),
|
lp.encode(),
|
||||||
stream,
|
stream,
|
||||||
consume
|
consume
|
||||||
)
|
)
|
||||||
@ -160,12 +163,12 @@ class IdentifyService {
|
|||||||
|
|
||||||
let message
|
let message
|
||||||
try {
|
try {
|
||||||
message = Message.decode(data)
|
message = Message.Identify.decode(data)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
const {
|
||||||
publicKey,
|
publicKey,
|
||||||
listenAddrs,
|
listenAddrs,
|
||||||
protocols,
|
protocols,
|
||||||
@ -180,12 +183,14 @@ class IdentifyService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the observedAddr if there is one
|
// Get the observedAddr if there is one
|
||||||
observedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
|
const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
|
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
|
||||||
if (this.peerStore.addressBook.consumePeerRecord(envelope)) {
|
if (this.peerStore.addressBook.consumePeerRecord(envelope)) {
|
||||||
this.peerStore.protoBook.set(id, protocols)
|
this.peerStore.protoBook.set(id, protocols)
|
||||||
|
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
||||||
|
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -194,16 +199,17 @@ class IdentifyService {
|
|||||||
|
|
||||||
// LEGACY: Update peers data in PeerStore
|
// LEGACY: Update peers data in PeerStore
|
||||||
try {
|
try {
|
||||||
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
|
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => new Multiaddr(addr)))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('received invalid addrs', err)
|
log.error('received invalid addrs', err)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.peerStore.protoBook.set(id, protocols)
|
this.peerStore.protoBook.set(id, protocols)
|
||||||
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
||||||
|
this.peerStore.metadataBook.set(id, 'ProtocolVersion', uint8ArrayFromString(message.protocolVersion))
|
||||||
|
|
||||||
// TODO: Add and score our observed addr
|
// TODO: Add and score our observed addr
|
||||||
log('received observed address of %s', observedAddr)
|
log('received observed address of %s', cleanObservedAddr)
|
||||||
// this.addressManager.addObservedAddr(observedAddr)
|
// this.addressManager.addObservedAddr(observedAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +252,7 @@ class IdentifyService {
|
|||||||
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
|
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
|
||||||
const protocols = this.peerStore.protoBook.get(this.peerId) || []
|
const protocols = this.peerStore.protoBook.get(this.peerId) || []
|
||||||
|
|
||||||
const message = Message.encode({
|
const message = Message.Identify.encode({
|
||||||
protocolVersion: this._host.protocolVersion,
|
protocolVersion: this._host.protocolVersion,
|
||||||
agentVersion: this._host.agentVersion,
|
agentVersion: this._host.agentVersion,
|
||||||
publicKey,
|
publicKey,
|
||||||
@ -254,7 +260,7 @@ class IdentifyService {
|
|||||||
signedPeerRecord,
|
signedPeerRecord,
|
||||||
observedAddr: connection.remoteAddr.bytes,
|
observedAddr: connection.remoteAddr.bytes,
|
||||||
protocols
|
protocols
|
||||||
})
|
}).finish()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await pipe(
|
await pipe(
|
||||||
@ -288,7 +294,7 @@ class IdentifyService {
|
|||||||
toBuffer,
|
toBuffer,
|
||||||
collect
|
collect
|
||||||
)
|
)
|
||||||
message = Message.decode(data)
|
message = Message.Identify.decode(data)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return log.error('received invalid message', err)
|
return log.error('received invalid message', err)
|
||||||
}
|
}
|
||||||
@ -307,7 +313,8 @@ class IdentifyService {
|
|||||||
|
|
||||||
// LEGACY: Update peers data in PeerStore
|
// LEGACY: Update peers data in PeerStore
|
||||||
try {
|
try {
|
||||||
this.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
|
this.peerStore.addressBook.set(id,
|
||||||
|
message.listenAddrs.map((addr) => new Multiaddr(addr)))
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('received invalid addrs', err)
|
log.error('received invalid addrs', err)
|
||||||
}
|
}
|
||||||
@ -320,12 +327,12 @@ class IdentifyService {
|
|||||||
* Takes the `addr` and converts it to a Multiaddr if possible
|
* Takes the `addr` and converts it to a Multiaddr if possible
|
||||||
*
|
*
|
||||||
* @param {Uint8Array | string} addr
|
* @param {Uint8Array | string} addr
|
||||||
* @returns {multiaddr|null}
|
* @returns {Multiaddr|null}
|
||||||
*/
|
*/
|
||||||
static getCleanMultiaddr (addr) {
|
static getCleanMultiaddr (addr) {
|
||||||
if (addr && addr.length > 0) {
|
if (addr && addr.length > 0) {
|
||||||
try {
|
try {
|
||||||
return multiaddr(addr)
|
return new Multiaddr(addr)
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
95
src/identify/message.d.ts
vendored
Normal file
95
src/identify/message.d.ts
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of an Identify. */
|
||||||
|
export interface IIdentify {
|
||||||
|
|
||||||
|
/** Identify protocolVersion */
|
||||||
|
protocolVersion?: (string|null);
|
||||||
|
|
||||||
|
/** Identify agentVersion */
|
||||||
|
agentVersion?: (string|null);
|
||||||
|
|
||||||
|
/** Identify publicKey */
|
||||||
|
publicKey?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Identify listenAddrs */
|
||||||
|
listenAddrs?: (Uint8Array[]|null);
|
||||||
|
|
||||||
|
/** Identify observedAddr */
|
||||||
|
observedAddr?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Identify protocols */
|
||||||
|
protocols?: (string[]|null);
|
||||||
|
|
||||||
|
/** Identify signedPeerRecord */
|
||||||
|
signedPeerRecord?: (Uint8Array|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents an Identify. */
|
||||||
|
export class Identify implements IIdentify {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Identify.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IIdentify);
|
||||||
|
|
||||||
|
/** Identify protocolVersion. */
|
||||||
|
public protocolVersion: string;
|
||||||
|
|
||||||
|
/** Identify agentVersion. */
|
||||||
|
public agentVersion: string;
|
||||||
|
|
||||||
|
/** Identify publicKey. */
|
||||||
|
public publicKey: Uint8Array;
|
||||||
|
|
||||||
|
/** Identify listenAddrs. */
|
||||||
|
public listenAddrs: Uint8Array[];
|
||||||
|
|
||||||
|
/** Identify observedAddr. */
|
||||||
|
public observedAddr: Uint8Array;
|
||||||
|
|
||||||
|
/** Identify protocols. */
|
||||||
|
public protocols: string[];
|
||||||
|
|
||||||
|
/** Identify signedPeerRecord. */
|
||||||
|
public signedPeerRecord: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Identify message. Does not implicitly {@link Identify.verify|verify} messages.
|
||||||
|
* @param m Identify message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IIdentify, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Identify message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Identify
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Identify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Identify message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Identify
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Identify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Identify message. Also converts values to other types if specified.
|
||||||
|
* @param m Identify
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Identify, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Identify to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
@ -1,35 +1,328 @@
|
|||||||
'use strict'
|
/*eslint-disable*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const protons = require('protons')
|
var $protobuf = require("protobufjs/minimal");
|
||||||
const schema = `
|
|
||||||
message Identify {
|
|
||||||
// protocolVersion determines compatibility between peers
|
|
||||||
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
|
|
||||||
|
|
||||||
// agentVersion is like a UserAgent string in browsers, or client version in bittorrent
|
// Common aliases
|
||||||
// includes the client name and client.
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
optional string agentVersion = 6; // e.g. go-ipfs/0.1.0
|
|
||||||
|
|
||||||
// publicKey is this node's public key (which also gives its node.ID)
|
// Exported root namespace
|
||||||
// - may not need to be sent, as secure channel implies it has been sent.
|
var $root = $protobuf.roots["libp2p-identify"] || ($protobuf.roots["libp2p-identify"] = {});
|
||||||
// - then again, if we change / disable secure channel, may still want it.
|
|
||||||
optional bytes publicKey = 1;
|
|
||||||
|
|
||||||
// listenAddrs are the multiaddrs the sender node listens for open connections on
|
$root.Identify = (function() {
|
||||||
repeated bytes listenAddrs = 2;
|
|
||||||
|
|
||||||
// oservedAddr is the multiaddr of the remote endpoint that the sender node perceives
|
/**
|
||||||
// this is useful information to convey to the other side, as it helps the remote endpoint
|
* Properties of an Identify.
|
||||||
// determine whether its connection to the local peer goes through NAT.
|
* @exports IIdentify
|
||||||
optional bytes observedAddr = 4;
|
* @interface IIdentify
|
||||||
|
* @property {string|null} [protocolVersion] Identify protocolVersion
|
||||||
|
* @property {string|null} [agentVersion] Identify agentVersion
|
||||||
|
* @property {Uint8Array|null} [publicKey] Identify publicKey
|
||||||
|
* @property {Array.<Uint8Array>|null} [listenAddrs] Identify listenAddrs
|
||||||
|
* @property {Uint8Array|null} [observedAddr] Identify observedAddr
|
||||||
|
* @property {Array.<string>|null} [protocols] Identify protocols
|
||||||
|
* @property {Uint8Array|null} [signedPeerRecord] Identify signedPeerRecord
|
||||||
|
*/
|
||||||
|
|
||||||
repeated string protocols = 3;
|
/**
|
||||||
|
* Constructs a new Identify.
|
||||||
|
* @exports Identify
|
||||||
|
* @classdesc Represents an Identify.
|
||||||
|
* @implements IIdentify
|
||||||
|
* @constructor
|
||||||
|
* @param {IIdentify=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Identify(p) {
|
||||||
|
this.listenAddrs = [];
|
||||||
|
this.protocols = [];
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
// signedPeerRecord contains a serialized SignedEnvelope containing a PeerRecord,
|
/**
|
||||||
// signed by the sending node. It contains the same addresses as the listenAddrs field, but
|
* Identify protocolVersion.
|
||||||
// in a form that lets us share authenticated addrs with other peers.
|
* @member {string} protocolVersion
|
||||||
optional bytes signedPeerRecord = 8;
|
* @memberof Identify
|
||||||
}
|
* @instance
|
||||||
`
|
*/
|
||||||
|
Identify.prototype.protocolVersion = "";
|
||||||
|
|
||||||
module.exports = protons(schema).Identify
|
/**
|
||||||
|
* Identify agentVersion.
|
||||||
|
* @member {string} agentVersion
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.agentVersion = "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify publicKey.
|
||||||
|
* @member {Uint8Array} publicKey
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.publicKey = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify listenAddrs.
|
||||||
|
* @member {Array.<Uint8Array>} listenAddrs
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.listenAddrs = $util.emptyArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify observedAddr.
|
||||||
|
* @member {Uint8Array} observedAddr
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.observedAddr = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify protocols.
|
||||||
|
* @member {Array.<string>} protocols
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.protocols = $util.emptyArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify signedPeerRecord.
|
||||||
|
* @member {Uint8Array} signedPeerRecord
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Identify.prototype.signedPeerRecord = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Identify message. Does not implicitly {@link Identify.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Identify
|
||||||
|
* @static
|
||||||
|
* @param {IIdentify} m Identify message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Identify.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey"))
|
||||||
|
w.uint32(10).bytes(m.publicKey);
|
||||||
|
if (m.listenAddrs != null && m.listenAddrs.length) {
|
||||||
|
for (var i = 0; i < m.listenAddrs.length; ++i)
|
||||||
|
w.uint32(18).bytes(m.listenAddrs[i]);
|
||||||
|
}
|
||||||
|
if (m.protocols != null && m.protocols.length) {
|
||||||
|
for (var i = 0; i < m.protocols.length; ++i)
|
||||||
|
w.uint32(26).string(m.protocols[i]);
|
||||||
|
}
|
||||||
|
if (m.observedAddr != null && Object.hasOwnProperty.call(m, "observedAddr"))
|
||||||
|
w.uint32(34).bytes(m.observedAddr);
|
||||||
|
if (m.protocolVersion != null && Object.hasOwnProperty.call(m, "protocolVersion"))
|
||||||
|
w.uint32(42).string(m.protocolVersion);
|
||||||
|
if (m.agentVersion != null && Object.hasOwnProperty.call(m, "agentVersion"))
|
||||||
|
w.uint32(50).string(m.agentVersion);
|
||||||
|
if (m.signedPeerRecord != null && Object.hasOwnProperty.call(m, "signedPeerRecord"))
|
||||||
|
w.uint32(66).bytes(m.signedPeerRecord);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Identify message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Identify
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Identify} Identify
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Identify.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Identify();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 5:
|
||||||
|
m.protocolVersion = r.string();
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
m.agentVersion = r.string();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m.publicKey = r.bytes();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (!(m.listenAddrs && m.listenAddrs.length))
|
||||||
|
m.listenAddrs = [];
|
||||||
|
m.listenAddrs.push(r.bytes());
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
m.observedAddr = r.bytes();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (!(m.protocols && m.protocols.length))
|
||||||
|
m.protocols = [];
|
||||||
|
m.protocols.push(r.string());
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
m.signedPeerRecord = r.bytes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Identify message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Identify
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Identify} Identify
|
||||||
|
*/
|
||||||
|
Identify.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Identify)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Identify();
|
||||||
|
if (d.protocolVersion != null) {
|
||||||
|
m.protocolVersion = String(d.protocolVersion);
|
||||||
|
}
|
||||||
|
if (d.agentVersion != null) {
|
||||||
|
m.agentVersion = String(d.agentVersion);
|
||||||
|
}
|
||||||
|
if (d.publicKey != null) {
|
||||||
|
if (typeof d.publicKey === "string")
|
||||||
|
$util.base64.decode(d.publicKey, m.publicKey = $util.newBuffer($util.base64.length(d.publicKey)), 0);
|
||||||
|
else if (d.publicKey.length)
|
||||||
|
m.publicKey = d.publicKey;
|
||||||
|
}
|
||||||
|
if (d.listenAddrs) {
|
||||||
|
if (!Array.isArray(d.listenAddrs))
|
||||||
|
throw TypeError(".Identify.listenAddrs: array expected");
|
||||||
|
m.listenAddrs = [];
|
||||||
|
for (var i = 0; i < d.listenAddrs.length; ++i) {
|
||||||
|
if (typeof d.listenAddrs[i] === "string")
|
||||||
|
$util.base64.decode(d.listenAddrs[i], m.listenAddrs[i] = $util.newBuffer($util.base64.length(d.listenAddrs[i])), 0);
|
||||||
|
else if (d.listenAddrs[i].length)
|
||||||
|
m.listenAddrs[i] = d.listenAddrs[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d.observedAddr != null) {
|
||||||
|
if (typeof d.observedAddr === "string")
|
||||||
|
$util.base64.decode(d.observedAddr, m.observedAddr = $util.newBuffer($util.base64.length(d.observedAddr)), 0);
|
||||||
|
else if (d.observedAddr.length)
|
||||||
|
m.observedAddr = d.observedAddr;
|
||||||
|
}
|
||||||
|
if (d.protocols) {
|
||||||
|
if (!Array.isArray(d.protocols))
|
||||||
|
throw TypeError(".Identify.protocols: array expected");
|
||||||
|
m.protocols = [];
|
||||||
|
for (var i = 0; i < d.protocols.length; ++i) {
|
||||||
|
m.protocols[i] = String(d.protocols[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d.signedPeerRecord != null) {
|
||||||
|
if (typeof d.signedPeerRecord === "string")
|
||||||
|
$util.base64.decode(d.signedPeerRecord, m.signedPeerRecord = $util.newBuffer($util.base64.length(d.signedPeerRecord)), 0);
|
||||||
|
else if (d.signedPeerRecord.length)
|
||||||
|
m.signedPeerRecord = d.signedPeerRecord;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Identify message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Identify
|
||||||
|
* @static
|
||||||
|
* @param {Identify} m Identify
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Identify.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.arrays || o.defaults) {
|
||||||
|
d.listenAddrs = [];
|
||||||
|
d.protocols = [];
|
||||||
|
}
|
||||||
|
if (o.defaults) {
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.publicKey = "";
|
||||||
|
else {
|
||||||
|
d.publicKey = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.publicKey = $util.newBuffer(d.publicKey);
|
||||||
|
}
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.observedAddr = "";
|
||||||
|
else {
|
||||||
|
d.observedAddr = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.observedAddr = $util.newBuffer(d.observedAddr);
|
||||||
|
}
|
||||||
|
d.protocolVersion = "";
|
||||||
|
d.agentVersion = "";
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.signedPeerRecord = "";
|
||||||
|
else {
|
||||||
|
d.signedPeerRecord = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.signedPeerRecord = $util.newBuffer(d.signedPeerRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.publicKey != null && m.hasOwnProperty("publicKey")) {
|
||||||
|
d.publicKey = o.bytes === String ? $util.base64.encode(m.publicKey, 0, m.publicKey.length) : o.bytes === Array ? Array.prototype.slice.call(m.publicKey) : m.publicKey;
|
||||||
|
}
|
||||||
|
if (m.listenAddrs && m.listenAddrs.length) {
|
||||||
|
d.listenAddrs = [];
|
||||||
|
for (var j = 0; j < m.listenAddrs.length; ++j) {
|
||||||
|
d.listenAddrs[j] = o.bytes === String ? $util.base64.encode(m.listenAddrs[j], 0, m.listenAddrs[j].length) : o.bytes === Array ? Array.prototype.slice.call(m.listenAddrs[j]) : m.listenAddrs[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.protocols && m.protocols.length) {
|
||||||
|
d.protocols = [];
|
||||||
|
for (var j = 0; j < m.protocols.length; ++j) {
|
||||||
|
d.protocols[j] = m.protocols[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.observedAddr != null && m.hasOwnProperty("observedAddr")) {
|
||||||
|
d.observedAddr = o.bytes === String ? $util.base64.encode(m.observedAddr, 0, m.observedAddr.length) : o.bytes === Array ? Array.prototype.slice.call(m.observedAddr) : m.observedAddr;
|
||||||
|
}
|
||||||
|
if (m.protocolVersion != null && m.hasOwnProperty("protocolVersion")) {
|
||||||
|
d.protocolVersion = m.protocolVersion;
|
||||||
|
}
|
||||||
|
if (m.agentVersion != null && m.hasOwnProperty("agentVersion")) {
|
||||||
|
d.agentVersion = m.agentVersion;
|
||||||
|
}
|
||||||
|
if (m.signedPeerRecord != null && m.hasOwnProperty("signedPeerRecord")) {
|
||||||
|
d.signedPeerRecord = o.bytes === String ? $util.base64.encode(m.signedPeerRecord, 0, m.signedPeerRecord.length) : o.bytes === Array ? Array.prototype.slice.call(m.signedPeerRecord) : m.signedPeerRecord;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Identify to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Identify
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Identify.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Identify;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
||||||
|
30
src/identify/message.proto
Normal file
30
src/identify/message.proto
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message Identify {
|
||||||
|
// protocolVersion determines compatibility between peers
|
||||||
|
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
|
||||||
|
|
||||||
|
// agentVersion is like a UserAgent string in browsers, or client version in bittorrent
|
||||||
|
// includes the client name and client.
|
||||||
|
optional string agentVersion = 6; // e.g. go-ipfs/0.1.0
|
||||||
|
|
||||||
|
// publicKey is this node's public key (which also gives its node.ID)
|
||||||
|
// - may not need to be sent, as secure channel implies it has been sent.
|
||||||
|
// - then again, if we change / disable secure channel, may still want it.
|
||||||
|
optional bytes publicKey = 1;
|
||||||
|
|
||||||
|
// listenAddrs are the multiaddrs the sender node listens for open connections on
|
||||||
|
repeated bytes listenAddrs = 2;
|
||||||
|
|
||||||
|
// oservedAddr is the multiaddr of the remote endpoint that the sender node perceives
|
||||||
|
// this is useful information to convey to the other side, as it helps the remote endpoint
|
||||||
|
// determine whether its connection to the local peer goes through NAT.
|
||||||
|
optional bytes observedAddr = 4;
|
||||||
|
|
||||||
|
repeated string protocols = 3;
|
||||||
|
|
||||||
|
// signedPeerRecord contains a serialized SignedEnvelope containing a PeerRecord,
|
||||||
|
// signed by the sending node. It contains the same addresses as the listenAddrs field, but
|
||||||
|
// in a form that lets us share authenticated addrs with other peers.
|
||||||
|
optional bytes signedPeerRecord = 8;
|
||||||
|
}
|
125
src/index.js
125
src/index.js
@ -4,13 +4,11 @@ const debug = require('debug')
|
|||||||
const log = Object.assign(debug('libp2p'), {
|
const log = Object.assign(debug('libp2p'), {
|
||||||
error: debug('libp2p:err')
|
error: debug('libp2p:err')
|
||||||
})
|
})
|
||||||
/** @typedef {import('./types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
|
||||||
const EventEmitter = require('events')
|
|
||||||
|
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
|
|
||||||
const PeerRouting = require('./peer-routing')
|
const PeerRouting = require('./peer-routing')
|
||||||
const ContentRouting = require('./content-routing')
|
const ContentRouting = require('./content-routing')
|
||||||
@ -38,29 +36,63 @@ const NatManager = require('./nat-manager')
|
|||||||
const { updateSelfPeerRecord } = require('./record/utils')
|
const { updateSelfPeerRecord } = require('./record/utils')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory} TransportFactory
|
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory<any, any>} TransportFactory
|
||||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxerFactory} MuxerFactory
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxerFactory} MuxerFactory
|
||||||
|
* @typedef {import('libp2p-interfaces/src/content-routing/types').ContentRouting} ContentRoutingModule
|
||||||
|
* @typedef {import('libp2p-interfaces/src/peer-discovery/types').PeerDiscoveryFactory} PeerDiscoveryFactory
|
||||||
|
* @typedef {import('libp2p-interfaces/src/peer-routing/types').PeerRouting} PeerRoutingModule
|
||||||
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
||||||
* @typedef {import('libp2p-interfaces/src/pubsub')} Pubsub
|
* @typedef {import('libp2p-interfaces/src/pubsub')} Pubsub
|
||||||
|
* @typedef {import('libp2p-interfaces/src/pubsub').PubsubOptions} PubsubOptions
|
||||||
|
* @typedef {import('interface-datastore').Datastore} Datastore
|
||||||
|
* @typedef {import('./pnet')} Protector
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {Object} HandlerProps
|
||||||
|
* @property {Connection} connection
|
||||||
|
* @property {MuxedStream} stream
|
||||||
|
* @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
|
||||||
|
* @property {boolean} [enabled = false]
|
||||||
|
* @property {number} [kBucketSize = 20]
|
||||||
|
* @property {RandomWalkOptions} [randomWalk]
|
||||||
|
* @property {boolean} [clientMode]
|
||||||
|
* @property {import('libp2p-interfaces/src/types').DhtSelectors} [selectors]
|
||||||
|
* @property {import('libp2p-interfaces/src/types').DhtValidators} [validators]
|
||||||
|
*
|
||||||
|
* @typedef {Object} KeychainOptions
|
||||||
|
* @property {Datastore} [datastore]
|
||||||
|
*
|
||||||
* @typedef {Object} PeerStoreOptions
|
* @typedef {Object} PeerStoreOptions
|
||||||
* @property {boolean} persistence
|
* @property {boolean} persistence
|
||||||
*
|
*
|
||||||
* @typedef {Object} RelayOptions
|
* @typedef {Object} PubsubLocalOptions
|
||||||
* @property {boolean} enabled
|
* @property {boolean} enabled
|
||||||
* @property {import('./circuit').RelayAdvertiseOptions} advertise
|
*
|
||||||
* @property {import('./circuit').HopOptions} hop
|
* @typedef {Object} MetricsOptions
|
||||||
* @property {import('./circuit').AutoRelayOptions} autoRelay
|
* @property {boolean} enabled
|
||||||
|
*
|
||||||
|
* @typedef {Object} RelayOptions
|
||||||
|
* @property {boolean} [enabled = true]
|
||||||
|
* @property {import('./circuit').RelayAdvertiseOptions} [advertise]
|
||||||
|
* @property {import('./circuit').HopOptions} [hop]
|
||||||
|
* @property {import('./circuit').AutoRelayOptions} [autoRelay]
|
||||||
*
|
*
|
||||||
* @typedef {Object} Libp2pConfig
|
* @typedef {Object} Libp2pConfig
|
||||||
* @property {Object} [dht] dht module options
|
* @property {DhtOptions} [dht] dht module options
|
||||||
* @property {Object} [peerDiscovery]
|
* @property {import('./nat-manager').NatManagerOptions} [nat]
|
||||||
* @property {Pubsub} [pubsub] pubsub module options
|
* @property {Record<string, Object|boolean>} [peerDiscovery]
|
||||||
|
* @property {PubsubLocalOptions & PubsubOptions} [pubsub] pubsub module options
|
||||||
* @property {RelayOptions} [relay]
|
* @property {RelayOptions} [relay]
|
||||||
* @property {Record<string, Object>} [transport] transport options indexed by transport key
|
* @property {Record<string, Object>} [transport] transport options indexed by transport key
|
||||||
*
|
*
|
||||||
@ -68,16 +100,25 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
|||||||
* @property {TransportFactory[]} transport
|
* @property {TransportFactory[]} transport
|
||||||
* @property {MuxerFactory[]} streamMuxer
|
* @property {MuxerFactory[]} streamMuxer
|
||||||
* @property {Crypto[]} connEncryption
|
* @property {Crypto[]} connEncryption
|
||||||
|
* @property {PeerDiscoveryFactory[]} [peerDiscovery]
|
||||||
|
* @property {PeerRoutingModule[]} [peerRouting]
|
||||||
|
* @property {ContentRoutingModule[]} [contentRouting]
|
||||||
|
* @property {Object} [dht]
|
||||||
|
* @property {{new(...args: any[]): Pubsub}} [pubsub]
|
||||||
|
* @property {Protector} [connProtector]
|
||||||
*
|
*
|
||||||
* @typedef {Object} Libp2pOptions
|
* @typedef {Object} Libp2pOptions
|
||||||
* @property {Libp2pModules} modules libp2p modules to use
|
* @property {Libp2pModules} modules libp2p modules to use
|
||||||
* @property {import('./address-manager').AddressManagerOptions} [addresses]
|
* @property {import('./address-manager').AddressManagerOptions} [addresses]
|
||||||
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
|
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
|
||||||
|
* @property {Datastore} [datastore]
|
||||||
* @property {import('./dialer').DialerOptions} [dialer]
|
* @property {import('./dialer').DialerOptions} [dialer]
|
||||||
* @property {import('./metrics').MetricsOptions} [metrics]
|
* @property {import('./identify/index').HostProperties} [host] libp2p host
|
||||||
* @property {Object} [keychain]
|
* @property {KeychainOptions & import('./keychain/index').KeychainOptions} [keychain]
|
||||||
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
|
* @property {MetricsOptions & import('./metrics').MetricsOptions} [metrics]
|
||||||
|
* @property {import('./peer-routing').PeerRoutingOptions} [peerRouting]
|
||||||
* @property {PeerStoreOptions & import('./peer-store/persistent').PersistentPeerStoreOptions} [peerStore]
|
* @property {PeerStoreOptions & import('./peer-store/persistent').PersistentPeerStoreOptions} [peerStore]
|
||||||
|
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
|
||||||
* @property {Libp2pConfig} [config]
|
* @property {Libp2pConfig} [config]
|
||||||
*
|
*
|
||||||
* @typedef {Object} constructorOptions
|
* @typedef {Object} constructorOptions
|
||||||
@ -152,9 +193,6 @@ class Libp2p extends EventEmitter {
|
|||||||
this._discovery = new Map() // Discovery service instances/references
|
this._discovery = new Map() // Discovery service instances/references
|
||||||
|
|
||||||
// Create the Connection Manager
|
// Create the Connection Manager
|
||||||
if (this._options.connectionManager.minPeers) { // Remove in 0.29
|
|
||||||
this._options.connectionManager.minConnections = this._options.connectionManager.minPeers
|
|
||||||
}
|
|
||||||
this.connectionManager = new ConnectionManager(this, {
|
this.connectionManager = new ConnectionManager(this, {
|
||||||
autoDial: this._config.peerDiscovery.autoDial,
|
autoDial: this._config.peerDiscovery.autoDial,
|
||||||
...this._options.connectionManager
|
...this._options.connectionManager
|
||||||
@ -175,7 +213,6 @@ class Libp2p extends EventEmitter {
|
|||||||
const keychainOpts = Keychain.generateOptions()
|
const keychainOpts = Keychain.generateOptions()
|
||||||
|
|
||||||
this.keychain = new Keychain(this._options.keychain.datastore, {
|
this.keychain = new Keychain(this._options.keychain.datastore, {
|
||||||
passPhrase: this._options.keychain.pass,
|
|
||||||
...keychainOpts,
|
...keychainOpts,
|
||||||
...this._options.keychain
|
...this._options.keychain
|
||||||
})
|
})
|
||||||
@ -203,6 +240,7 @@ class Libp2p extends EventEmitter {
|
|||||||
peerId: this.peerId,
|
peerId: this.peerId,
|
||||||
addressManager: this.addressManager,
|
addressManager: this.addressManager,
|
||||||
transportManager: this.transportManager,
|
transportManager: this.transportManager,
|
||||||
|
// @ts-ignore Nat typedef is not understood as Object
|
||||||
...this._options.config.nat
|
...this._options.config.nat
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -227,11 +265,7 @@ class Libp2p extends EventEmitter {
|
|||||||
this.dialer = new Dialer({
|
this.dialer = new Dialer({
|
||||||
transportManager: this.transportManager,
|
transportManager: this.transportManager,
|
||||||
peerStore: this.peerStore,
|
peerStore: this.peerStore,
|
||||||
concurrency: this._options.dialer.maxParallelDials,
|
...this._options.dialer
|
||||||
perPeerLimit: this._options.dialer.maxDialsPerPeer,
|
|
||||||
timeout: this._options.dialer.dialTimeout,
|
|
||||||
resolvers: this._options.dialer.resolvers,
|
|
||||||
addressSorter: this._options.dialer.addressSorter
|
|
||||||
})
|
})
|
||||||
|
|
||||||
this._modules.transport.forEach((Transport) => {
|
this._modules.transport.forEach((Transport) => {
|
||||||
@ -268,6 +302,7 @@ 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 Object is not constructable
|
||||||
this._dht = new DHT({
|
this._dht = new DHT({
|
||||||
libp2p: this,
|
libp2p: this,
|
||||||
dialer: this.dialer,
|
dialer: this.dialer,
|
||||||
@ -426,22 +461,36 @@ class Libp2p extends EventEmitter {
|
|||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
dial (peer, options) {
|
dial (peer, options) {
|
||||||
return this.dialProtocol(peer, [], options)
|
return this._dial(peer, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dials to the provided peer and handshakes with the given protocol.
|
* Dials to the provided peer and tries to handshake with the given protocols in order.
|
||||||
* If successful, the known metadata of the peer will be added to the nodes `peerStore`,
|
* If successful, the known metadata of the peer will be added to the nodes `peerStore`,
|
||||||
* and the `Connection` will be returned
|
* and the `MuxedStream` will be returned together with the successful negotiated protocol.
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||||
* @param {string[]|string} protocols
|
* @param {string[]|string} protocols
|
||||||
* @param {object} [options]
|
* @param {object} [options]
|
||||||
* @param {AbortSignal} [options.signal]
|
* @param {AbortSignal} [options.signal]
|
||||||
* @returns {Promise<Connection|*>}
|
|
||||||
*/
|
*/
|
||||||
async dialProtocol (peer, protocols, options) {
|
async dialProtocol (peer, protocols, options) {
|
||||||
|
if (!protocols || !protocols.length) {
|
||||||
|
throw errCode(new Error('no protocols were provided to open a stream'), codes.ERR_INVALID_PROTOCOLS_FOR_STREAM)
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = await this._dial(peer, options)
|
||||||
|
return connection.newStream(protocols)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||||
|
* @param {object} [options]
|
||||||
|
* @returns {Promise<Connection>}
|
||||||
|
*/
|
||||||
|
async _dial (peer, options) {
|
||||||
const { id, multiaddrs } = getPeer(peer)
|
const { id, multiaddrs } = getPeer(peer)
|
||||||
|
|
||||||
if (id.equals(this.peerId)) {
|
if (id.equals(this.peerId)) {
|
||||||
@ -456,11 +505,6 @@ class Libp2p extends EventEmitter {
|
|||||||
this.peerStore.addressBook.add(id, multiaddrs)
|
this.peerStore.addressBook.add(id, multiaddrs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a protocol was provided, create a new stream
|
|
||||||
if (protocols && protocols.length) {
|
|
||||||
return connection.newStream(protocols)
|
|
||||||
}
|
|
||||||
|
|
||||||
return connection
|
return connection
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,13 +528,13 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
addrs = addrs.concat(this.addressManager.getObservedAddrs().map(ma => ma.toString()))
|
addrs = addrs.concat(this.addressManager.getObservedAddrs().map(ma => ma.toString()))
|
||||||
|
|
||||||
const announceFilter = this._options.addresses.announceFilter || ((multiaddrs) => multiaddrs)
|
const announceFilter = this._options.addresses.announceFilter
|
||||||
|
|
||||||
// dedupe multiaddrs
|
// dedupe multiaddrs
|
||||||
const addrSet = new Set(addrs)
|
const addrSet = new Set(addrs)
|
||||||
|
|
||||||
// Create advertising list
|
// Create advertising list
|
||||||
return announceFilter(Array.from(addrSet).map(str => multiaddr(str)))
|
return announceFilter(Array.from(addrSet).map(str => new Multiaddr(str)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -536,7 +580,7 @@ class Libp2p extends EventEmitter {
|
|||||||
* Registers the `handler` for each protocol
|
* Registers the `handler` for each protocol
|
||||||
*
|
*
|
||||||
* @param {string[]|string} protocols
|
* @param {string[]|string} protocols
|
||||||
* @param {({ connection: Connection, stream: MuxedStream, protocol: string }) => void} handler
|
* @param {(props: HandlerProps) => void} handler
|
||||||
*/
|
*/
|
||||||
handle (protocols, handler) {
|
handle (protocols, handler) {
|
||||||
protocols = Array.isArray(protocols) ? protocols : [protocols]
|
protocols = Array.isArray(protocols) ? protocols : [protocols]
|
||||||
@ -656,7 +700,7 @@ class Libp2p extends EventEmitter {
|
|||||||
try {
|
try {
|
||||||
await this.dialer.connectToPeer(peerId)
|
await this.dialer.connectToPeer(peerId)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log.error('could not connect to discovered peer', err)
|
log.error(`could not connect to discovered peer ${peerId.toB58String()} with ${err}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,6 +713,9 @@ class Libp2p extends EventEmitter {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
async _setupPeerDiscovery () {
|
async _setupPeerDiscovery () {
|
||||||
|
/**
|
||||||
|
* @param {PeerDiscoveryFactory} DiscoveryService
|
||||||
|
*/
|
||||||
const setupService = (DiscoveryService) => {
|
const setupService = (DiscoveryService) => {
|
||||||
let config = {
|
let config = {
|
||||||
enabled: true // on by default
|
enabled: true // on by default
|
||||||
@ -677,6 +724,7 @@ class Libp2p extends EventEmitter {
|
|||||||
if (DiscoveryService.tag &&
|
if (DiscoveryService.tag &&
|
||||||
this._config.peerDiscovery &&
|
this._config.peerDiscovery &&
|
||||||
this._config.peerDiscovery[DiscoveryService.tag]) {
|
this._config.peerDiscovery[DiscoveryService.tag]) {
|
||||||
|
// @ts-ignore PeerDiscovery not understood as an Object for spread
|
||||||
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
|
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -685,6 +733,7 @@ class Libp2p extends EventEmitter {
|
|||||||
let discoveryService
|
let discoveryService
|
||||||
|
|
||||||
if (typeof DiscoveryService === 'function') {
|
if (typeof DiscoveryService === 'function') {
|
||||||
|
// @ts-ignore DiscoveryService has no constructor type inferred
|
||||||
discoveryService = new DiscoveryService(Object.assign({}, config, {
|
discoveryService = new DiscoveryService(Object.assign({}, config, {
|
||||||
peerId: this.peerId,
|
peerId: this.peerId,
|
||||||
libp2p: this
|
libp2p: this
|
||||||
|
@ -4,6 +4,7 @@ const debug = require('debug')
|
|||||||
const log = Object.assign(debug('libp2p:plaintext'), {
|
const log = Object.assign(debug('libp2p:plaintext'), {
|
||||||
error: debug('libp2p:plaintext:err')
|
error: debug('libp2p:plaintext:err')
|
||||||
})
|
})
|
||||||
|
// @ts-ignore it-handshake do not export types
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
@ -16,8 +17,12 @@ const protocol = '/plaintext/2.0.0'
|
|||||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import('./proto').IExchange} exchange
|
||||||
|
*/
|
||||||
function lpEncodeExchange (exchange) {
|
function lpEncodeExchange (exchange) {
|
||||||
const pb = Exchange.encode(exchange)
|
const pb = Exchange.encode(exchange).finish()
|
||||||
|
// @ts-ignore TODO: Uint8Array not assignable to Buffer
|
||||||
return lp.encode.single(pb)
|
return lp.encode.single(pb)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,12 +73,23 @@ async function encrypt (localId, conn, remoteId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports =
|
||||||
protocol,
|
{
|
||||||
secureInbound: (localId, conn, remoteId) => {
|
protocol,
|
||||||
return encrypt(localId, conn, remoteId)
|
/**
|
||||||
},
|
* @param {PeerId} localId
|
||||||
secureOutbound: (localId, conn, remoteId) => {
|
* @param {Connection} conn
|
||||||
return encrypt(localId, conn, remoteId)
|
* @param {PeerId | undefined} remoteId
|
||||||
}
|
*/
|
||||||
}
|
secureInbound: (localId, conn, remoteId) => {
|
||||||
|
return encrypt(localId, conn, remoteId)
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @param {PeerId} localId
|
||||||
|
* @param {Connection} conn
|
||||||
|
* @param {PeerId | undefined} remoteId
|
||||||
|
*/
|
||||||
|
secureOutbound: (localId, conn, remoteId) => {
|
||||||
|
return encrypt(localId, conn, remoteId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
128
src/insecure/proto.d.ts
vendored
Normal file
128
src/insecure/proto.d.ts
vendored
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of an Exchange. */
|
||||||
|
export interface IExchange {
|
||||||
|
|
||||||
|
/** Exchange id */
|
||||||
|
id?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Exchange pubkey */
|
||||||
|
pubkey?: (IPublicKey|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents an Exchange. */
|
||||||
|
export class Exchange implements IExchange {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Exchange.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IExchange);
|
||||||
|
|
||||||
|
/** Exchange id. */
|
||||||
|
public id: Uint8Array;
|
||||||
|
|
||||||
|
/** Exchange pubkey. */
|
||||||
|
public pubkey?: (IPublicKey|null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Exchange message. Does not implicitly {@link Exchange.verify|verify} messages.
|
||||||
|
* @param m Exchange message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IExchange, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Exchange message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Exchange
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Exchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Exchange message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Exchange
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Exchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Exchange message. Also converts values to other types if specified.
|
||||||
|
* @param m Exchange
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Exchange, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Exchange to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** KeyType enum. */
|
||||||
|
export enum KeyType {
|
||||||
|
RSA = 0,
|
||||||
|
Ed25519 = 1,
|
||||||
|
Secp256k1 = 2,
|
||||||
|
ECDSA = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a PublicKey. */
|
||||||
|
export class PublicKey implements IPublicKey {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new PublicKey.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IPublicKey);
|
||||||
|
|
||||||
|
/** PublicKey Type. */
|
||||||
|
public Type: KeyType;
|
||||||
|
|
||||||
|
/** PublicKey Data. */
|
||||||
|
public Data: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified PublicKey message. Does not implicitly {@link PublicKey.verify|verify} messages.
|
||||||
|
* @param m PublicKey message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IPublicKey, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a PublicKey message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns PublicKey
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): PublicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PublicKey message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns PublicKey
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): PublicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a PublicKey message. Also converts values to other types if specified.
|
||||||
|
* @param m PublicKey
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: PublicKey, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this PublicKey to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
@ -1,22 +1,371 @@
|
|||||||
'use strict'
|
/*eslint-disable*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
const protobuf = require('protons')
|
var $protobuf = require("protobufjs/minimal");
|
||||||
|
|
||||||
module.exports = protobuf(`
|
// Common aliases
|
||||||
message Exchange {
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
optional bytes id = 1;
|
|
||||||
optional PublicKey pubkey = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum KeyType {
|
// Exported root namespace
|
||||||
RSA = 0;
|
var $root = $protobuf.roots["libp2p-plaintext"] || ($protobuf.roots["libp2p-plaintext"] = {});
|
||||||
Ed25519 = 1;
|
|
||||||
Secp256k1 = 2;
|
|
||||||
ECDSA = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PublicKey {
|
$root.Exchange = (function() {
|
||||||
required KeyType Type = 1;
|
|
||||||
required bytes Data = 2;
|
/**
|
||||||
}
|
* Properties of an Exchange.
|
||||||
`)
|
* @exports IExchange
|
||||||
|
* @interface IExchange
|
||||||
|
* @property {Uint8Array|null} [id] Exchange id
|
||||||
|
* @property {IPublicKey|null} [pubkey] Exchange pubkey
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Exchange.
|
||||||
|
* @exports Exchange
|
||||||
|
* @classdesc Represents an Exchange.
|
||||||
|
* @implements IExchange
|
||||||
|
* @constructor
|
||||||
|
* @param {IExchange=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Exchange(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchange id.
|
||||||
|
* @member {Uint8Array} id
|
||||||
|
* @memberof Exchange
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Exchange.prototype.id = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exchange pubkey.
|
||||||
|
* @member {IPublicKey|null|undefined} pubkey
|
||||||
|
* @memberof Exchange
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Exchange.prototype.pubkey = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Exchange message. Does not implicitly {@link Exchange.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Exchange
|
||||||
|
* @static
|
||||||
|
* @param {IExchange} m Exchange message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Exchange.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.id != null && Object.hasOwnProperty.call(m, "id"))
|
||||||
|
w.uint32(10).bytes(m.id);
|
||||||
|
if (m.pubkey != null && Object.hasOwnProperty.call(m, "pubkey"))
|
||||||
|
$root.PublicKey.encode(m.pubkey, w.uint32(18).fork()).ldelim();
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Exchange message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Exchange
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Exchange} Exchange
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Exchange.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Exchange();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.id = r.bytes();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.pubkey = $root.PublicKey.decode(r, r.uint32());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Exchange message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Exchange
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Exchange} Exchange
|
||||||
|
*/
|
||||||
|
Exchange.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Exchange)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Exchange();
|
||||||
|
if (d.id != null) {
|
||||||
|
if (typeof d.id === "string")
|
||||||
|
$util.base64.decode(d.id, m.id = $util.newBuffer($util.base64.length(d.id)), 0);
|
||||||
|
else if (d.id.length)
|
||||||
|
m.id = d.id;
|
||||||
|
}
|
||||||
|
if (d.pubkey != null) {
|
||||||
|
if (typeof d.pubkey !== "object")
|
||||||
|
throw TypeError(".Exchange.pubkey: object expected");
|
||||||
|
m.pubkey = $root.PublicKey.fromObject(d.pubkey);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Exchange message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Exchange
|
||||||
|
* @static
|
||||||
|
* @param {Exchange} m Exchange
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Exchange.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.id = "";
|
||||||
|
else {
|
||||||
|
d.id = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.id = $util.newBuffer(d.id);
|
||||||
|
}
|
||||||
|
d.pubkey = null;
|
||||||
|
}
|
||||||
|
if (m.id != null && m.hasOwnProperty("id")) {
|
||||||
|
d.id = o.bytes === String ? $util.base64.encode(m.id, 0, m.id.length) : o.bytes === Array ? Array.prototype.slice.call(m.id) : m.id;
|
||||||
|
}
|
||||||
|
if (m.pubkey != null && m.hasOwnProperty("pubkey")) {
|
||||||
|
d.pubkey = $root.PublicKey.toObject(m.pubkey, o);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Exchange to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Exchange
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Exchange.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Exchange;
|
||||||
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KeyType enum.
|
||||||
|
* @exports KeyType
|
||||||
|
* @enum {number}
|
||||||
|
* @property {number} RSA=0 RSA value
|
||||||
|
* @property {number} Ed25519=1 Ed25519 value
|
||||||
|
* @property {number} Secp256k1=2 Secp256k1 value
|
||||||
|
* @property {number} ECDSA=3 ECDSA value
|
||||||
|
*/
|
||||||
|
$root.KeyType = (function() {
|
||||||
|
var valuesById = {}, values = Object.create(valuesById);
|
||||||
|
values[valuesById[0] = "RSA"] = 0;
|
||||||
|
values[valuesById[1] = "Ed25519"] = 1;
|
||||||
|
values[valuesById[2] = "Secp256k1"] = 2;
|
||||||
|
values[valuesById[3] = "ECDSA"] = 3;
|
||||||
|
return values;
|
||||||
|
})();
|
||||||
|
|
||||||
|
$root.PublicKey = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of a PublicKey.
|
||||||
|
* @exports IPublicKey
|
||||||
|
* @interface IPublicKey
|
||||||
|
* @property {KeyType|null} [Type] PublicKey Type
|
||||||
|
* @property {Uint8Array|null} [Data] PublicKey Data
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new PublicKey.
|
||||||
|
* @exports PublicKey
|
||||||
|
* @classdesc Represents a PublicKey.
|
||||||
|
* @implements IPublicKey
|
||||||
|
* @constructor
|
||||||
|
* @param {IPublicKey=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function PublicKey(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PublicKey Type.
|
||||||
|
* @member {KeyType} Type
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
PublicKey.prototype.Type = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PublicKey Data.
|
||||||
|
* @member {Uint8Array} Data
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
PublicKey.prototype.Data = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified PublicKey message. Does not implicitly {@link PublicKey.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @static
|
||||||
|
* @param {IPublicKey} m PublicKey message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
PublicKey.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.Type != null && Object.hasOwnProperty.call(m, "Type"))
|
||||||
|
w.uint32(8).int32(m.Type);
|
||||||
|
if (m.Data != null && Object.hasOwnProperty.call(m, "Data"))
|
||||||
|
w.uint32(18).bytes(m.Data);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a PublicKey message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {PublicKey} PublicKey
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
PublicKey.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.PublicKey();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.Type = r.int32();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.Data = r.bytes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a PublicKey message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {PublicKey} PublicKey
|
||||||
|
*/
|
||||||
|
PublicKey.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.PublicKey)
|
||||||
|
return d;
|
||||||
|
var m = new $root.PublicKey();
|
||||||
|
switch (d.Type) {
|
||||||
|
case "RSA":
|
||||||
|
case 0:
|
||||||
|
m.Type = 0;
|
||||||
|
break;
|
||||||
|
case "Ed25519":
|
||||||
|
case 1:
|
||||||
|
m.Type = 1;
|
||||||
|
break;
|
||||||
|
case "Secp256k1":
|
||||||
|
case 2:
|
||||||
|
m.Type = 2;
|
||||||
|
break;
|
||||||
|
case "ECDSA":
|
||||||
|
case 3:
|
||||||
|
m.Type = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (d.Data != null) {
|
||||||
|
if (typeof d.Data === "string")
|
||||||
|
$util.base64.decode(d.Data, m.Data = $util.newBuffer($util.base64.length(d.Data)), 0);
|
||||||
|
else if (d.Data.length)
|
||||||
|
m.Data = d.Data;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a PublicKey message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @static
|
||||||
|
* @param {PublicKey} m PublicKey
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
PublicKey.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
d.Type = o.enums === String ? "RSA" : 0;
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.Data = "";
|
||||||
|
else {
|
||||||
|
d.Data = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.Data = $util.newBuffer(d.Data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.Type != null && m.hasOwnProperty("Type")) {
|
||||||
|
d.Type = o.enums === String ? $root.KeyType[m.Type] : m.Type;
|
||||||
|
}
|
||||||
|
if (m.Data != null && m.hasOwnProperty("Data")) {
|
||||||
|
d.Data = o.bytes === String ? $util.base64.encode(m.Data, 0, m.Data.length) : o.bytes === Array ? Array.prototype.slice.call(m.Data) : m.Data;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this PublicKey to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof PublicKey
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
PublicKey.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return PublicKey;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
||||||
|
18
src/insecure/proto.proto
Normal file
18
src/insecure/proto.proto
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message Exchange {
|
||||||
|
optional bytes id = 1;
|
||||||
|
optional PublicKey pubkey = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum KeyType {
|
||||||
|
RSA = 0;
|
||||||
|
Ed25519 = 1;
|
||||||
|
Secp256k1 = 2;
|
||||||
|
ECDSA = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PublicKey {
|
||||||
|
KeyType Type = 1;
|
||||||
|
bytes Data = 2;
|
||||||
|
}
|
@ -1,7 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
// @ts-ignore node-forge types not exported
|
||||||
require('node-forge/lib/pkcs7')
|
require('node-forge/lib/pkcs7')
|
||||||
|
// @ts-ignore node-forge types not exported
|
||||||
require('node-forge/lib/pbe')
|
require('node-forge/lib/pbe')
|
||||||
|
// @ts-ignore node-forge types not exported
|
||||||
const forge = require('node-forge/lib/forge')
|
const forge = require('node-forge/lib/forge')
|
||||||
const { certificateForKey, findAsync } = require('./util')
|
const { certificateForKey, findAsync } = require('./util')
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
@ -85,6 +88,7 @@ class CMS {
|
|||||||
try {
|
try {
|
||||||
const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'))
|
const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'))
|
||||||
const obj = forge.asn1.fromDer(buf)
|
const obj = forge.asn1.fromDer(buf)
|
||||||
|
// @ts-ignore not defined
|
||||||
cms = forge.pkcs7.messageFromAsn1(obj)
|
cms = forge.pkcs7.messageFromAsn1(obj)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
|
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
|
||||||
@ -93,11 +97,15 @@ class 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
|
||||||
// issued by ipfs (O=ipfs).
|
// issued by ipfs (O=ipfs).
|
||||||
const recipients = cms.recipients
|
const recipients = cms.recipients
|
||||||
|
// @ts-ignore cms types not defined
|
||||||
.filter(r => r.issuer.find(a => a.shortName === 'O' && a.value === 'ipfs'))
|
.filter(r => r.issuer.find(a => a.shortName === 'O' && a.value === 'ipfs'))
|
||||||
|
// @ts-ignore cms types not defined
|
||||||
.filter(r => r.issuer.find(a => a.shortName === 'CN'))
|
.filter(r => r.issuer.find(a => a.shortName === 'CN'))
|
||||||
|
// @ts-ignore cms types not defined
|
||||||
.map(r => {
|
.map(r => {
|
||||||
return {
|
return {
|
||||||
recipient: r,
|
recipient: r,
|
||||||
|
// @ts-ignore cms types not defined
|
||||||
keyId: r.issuer.find(a => a.shortName === 'CN').value
|
keyId: r.issuer.find(a => a.shortName === 'CN').value
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -113,6 +121,7 @@ class CMS {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
|
// @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(', ')), 'ERR_MISSING_KEYS', {
|
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
|
||||||
missingKeys
|
missingKeys
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
/* eslint max-nested-callbacks: ["error", 5] */
|
/* eslint max-nested-callbacks: ["error", 5] */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:keychain'), {
|
||||||
|
error: debug('libp2p:keychain:err')
|
||||||
|
})
|
||||||
const sanitize = require('sanitize-filename')
|
const sanitize = require('sanitize-filename')
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
@ -10,11 +13,32 @@ const errcode = require('err-code')
|
|||||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
|
|
||||||
|
// @ts-ignore node-forge sha512 types not exported
|
||||||
require('node-forge/lib/sha512')
|
require('node-forge/lib/sha512')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
* @typedef {import('interface-datastore/src/types').Datastore} Datastore
|
* @typedef {import('interface-datastore').Datastore} Datastore
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DekOptions
|
||||||
|
* @property {string} hash
|
||||||
|
* @property {string} salt
|
||||||
|
* @property {number} iterationCount
|
||||||
|
* @property {number} keyLength
|
||||||
|
*
|
||||||
|
* @typedef {Object} KeychainOptions
|
||||||
|
* @property {string} [pass]
|
||||||
|
* @property {DekOptions} [dek]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Information about a key.
|
||||||
|
*
|
||||||
|
* @typedef {Object} KeyInfo
|
||||||
|
* @property {string} id - The universally unique key id.
|
||||||
|
* @property {string} name - The local key name.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const keyPrefix = '/pkcs8/'
|
const keyPrefix = '/pkcs8/'
|
||||||
@ -38,6 +62,9 @@ const defaultOptions = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} name
|
||||||
|
*/
|
||||||
function validateKeyName (name) {
|
function validateKeyName (name) {
|
||||||
if (!name) return false
|
if (!name) return false
|
||||||
if (typeof name !== 'string') return false
|
if (typeof name !== 'string') return false
|
||||||
@ -85,14 +112,6 @@ function DsInfoName (name) {
|
|||||||
return new Key(infoPrefix + name)
|
return new Key(infoPrefix + name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about a key.
|
|
||||||
*
|
|
||||||
* @typedef {Object} KeyInfo
|
|
||||||
* @property {string} id - The universally unique key id.
|
|
||||||
* @property {string} name - The local key name.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages the lifecycle of a key. Keys are encrypted at rest using PKCS #8.
|
* Manages the lifecycle of a key. Keys are encrypted at rest using PKCS #8.
|
||||||
*
|
*
|
||||||
@ -106,7 +125,7 @@ class Keychain {
|
|||||||
* Creates a new instance of a key chain.
|
* Creates a new instance of a key chain.
|
||||||
*
|
*
|
||||||
* @param {Datastore} store - where the key are.
|
* @param {Datastore} store - where the key are.
|
||||||
* @param {object} options
|
* @param {KeychainOptions} options
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
constructor (store, options) {
|
constructor (store, options) {
|
||||||
@ -118,8 +137,8 @@ class Keychain {
|
|||||||
this.opts = mergeOptions(defaultOptions, options)
|
this.opts = mergeOptions(defaultOptions, options)
|
||||||
|
|
||||||
// Enforce NIST SP 800-132
|
// Enforce NIST SP 800-132
|
||||||
if (this.opts.passPhrase && this.opts.passPhrase.length < 20) {
|
if (this.opts.pass && this.opts.pass.length < 20) {
|
||||||
throw new Error('passPhrase must be least 20 characters')
|
throw new Error('pass must be least 20 characters')
|
||||||
}
|
}
|
||||||
if (this.opts.dek.keyLength < NIST.minKeyLength) {
|
if (this.opts.dek.keyLength < NIST.minKeyLength) {
|
||||||
throw new Error(`dek.keyLength must be least ${NIST.minKeyLength} bytes`)
|
throw new Error(`dek.keyLength must be least ${NIST.minKeyLength} bytes`)
|
||||||
@ -131,12 +150,14 @@ class Keychain {
|
|||||||
throw new Error(`dek.iterationCount must be least ${NIST.minIterationCount}`)
|
throw new Error(`dek.iterationCount must be least ${NIST.minIterationCount}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const dek = this.opts.passPhrase ? crypto.pbkdf2(
|
const dek = this.opts.pass
|
||||||
this.opts.passPhrase,
|
? crypto.pbkdf2(
|
||||||
this.opts.dek.salt,
|
this.opts.pass,
|
||||||
this.opts.dek.iterationCount,
|
this.opts.dek.salt,
|
||||||
this.opts.dek.keyLength,
|
this.opts.dek.iterationCount,
|
||||||
this.opts.dek.hash) : ''
|
this.opts.dek.keyLength,
|
||||||
|
this.opts.dek.hash)
|
||||||
|
: ''
|
||||||
|
|
||||||
privates.set(this, { dek })
|
privates.set(this, { dek })
|
||||||
}
|
}
|
||||||
@ -485,6 +506,55 @@ class Keychain {
|
|||||||
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
|
return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate keychain password and re-encrypt all assosciated keys
|
||||||
|
*
|
||||||
|
* @param {string} oldPass - The old local keychain password
|
||||||
|
* @param {string} newPass - The new local keychain password
|
||||||
|
*/
|
||||||
|
async rotateKeychainPass (oldPass, newPass) {
|
||||||
|
if (typeof oldPass !== 'string') {
|
||||||
|
return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE'))
|
||||||
|
}
|
||||||
|
if (typeof newPass !== 'string') {
|
||||||
|
return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE'))
|
||||||
|
}
|
||||||
|
if (newPass.length < 20) {
|
||||||
|
return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH'))
|
||||||
|
}
|
||||||
|
log('recreating keychain')
|
||||||
|
const oldDek = privates.get(this).dek
|
||||||
|
this.opts.pass = newPass
|
||||||
|
const newDek = newPass
|
||||||
|
? crypto.pbkdf2(
|
||||||
|
newPass,
|
||||||
|
this.opts.dek.salt,
|
||||||
|
this.opts.dek.iterationCount,
|
||||||
|
this.opts.dek.keyLength,
|
||||||
|
this.opts.dek.hash)
|
||||||
|
: ''
|
||||||
|
privates.set(this, { dek: newDek })
|
||||||
|
const keys = await this.listKeys()
|
||||||
|
for (const key of keys) {
|
||||||
|
const res = await this.store.get(DsName(key.name))
|
||||||
|
const pem = uint8ArrayToString(res)
|
||||||
|
const privateKey = await crypto.keys.import(pem, oldDek)
|
||||||
|
const password = newDek.toString()
|
||||||
|
const keyAsPEM = await privateKey.export(password)
|
||||||
|
|
||||||
|
// Update stored key
|
||||||
|
const batch = this.store.batch()
|
||||||
|
const keyInfo = {
|
||||||
|
name: key.name,
|
||||||
|
id: key.id
|
||||||
|
}
|
||||||
|
batch.put(DsName(key.name), uint8ArrayFromString(keyAsPEM))
|
||||||
|
batch.put(DsInfoName(key.name), uint8ArrayFromString(JSON.stringify(keyInfo)))
|
||||||
|
await batch.commit()
|
||||||
|
}
|
||||||
|
log('keychain reconstructed')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Keychain
|
module.exports = Keychain
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
require('node-forge/lib/x509')
|
require('node-forge/lib/x509')
|
||||||
const forge = require('node-forge/lib/forge')
|
const forge = require('node-forge/lib/forge')
|
||||||
const pki = forge.pki
|
const pki = forge.pki
|
||||||
exports = module.exports
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a self-signed X.509 certificate for the key.
|
* Gets a self-signed X.509 certificate for the key.
|
||||||
@ -17,7 +16,7 @@ exports = module.exports
|
|||||||
* @param {RsaPrivateKey} privateKey - The naked key
|
* @param {RsaPrivateKey} privateKey - The naked key
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
exports.certificateForKey = (key, privateKey) => {
|
const certificateForKey = (key, privateKey) => {
|
||||||
const publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
const publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
||||||
const cert = pki.createCertificate()
|
const cert = pki.createCertificate()
|
||||||
cert.publicKey = publicKey
|
cert.publicKey = publicKey
|
||||||
@ -87,4 +86,7 @@ async function findAsync (array, asyncCompare) {
|
|||||||
return array[index]
|
return array[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.findAsync = findAsync
|
module.exports = {
|
||||||
|
certificateForKey,
|
||||||
|
findAsync
|
||||||
|
}
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
// @ts-nocheck
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
const { BigNumber: Big } = require('bignumber.js')
|
||||||
const EventEmitter = require('events')
|
const MovingAverage = require('@vascosantos/moving-average')
|
||||||
const Big = require('bignumber.js')
|
|
||||||
const MovingAverage = require('moving-average')
|
|
||||||
const retimer = require('retimer')
|
const retimer = require('retimer')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('@vascosantos/moving-average').IMovingAverage} IMovingAverage
|
||||||
|
*/
|
||||||
|
|
||||||
class Stats extends EventEmitter {
|
class Stats extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* A queue based manager for stat processing
|
* A queue based manager for stat processing
|
||||||
@ -21,24 +23,30 @@ class Stats extends EventEmitter {
|
|||||||
|
|
||||||
this._options = options
|
this._options = options
|
||||||
this._queue = []
|
this._queue = []
|
||||||
this._stats = {}
|
|
||||||
|
/** @type {{ dataReceived: Big, dataSent: Big }} */
|
||||||
|
this._stats = {
|
||||||
|
dataReceived: Big(0),
|
||||||
|
dataSent: Big(0)
|
||||||
|
}
|
||||||
|
|
||||||
this._frequencyLastTime = Date.now()
|
this._frequencyLastTime = Date.now()
|
||||||
this._frequencyAccumulators = {}
|
this._frequencyAccumulators = {}
|
||||||
|
|
||||||
|
/** @type {{ dataReceived: IMovingAverage[], dataSent: IMovingAverage[] }} */
|
||||||
this._movingAverages = {}
|
this._movingAverages = {}
|
||||||
|
|
||||||
this._update = this._update.bind(this)
|
this._update = this._update.bind(this)
|
||||||
|
|
||||||
const intervals = this._options.movingAverageIntervals
|
const intervals = this._options.movingAverageIntervals
|
||||||
|
|
||||||
for (var i = 0; i < initialCounters.length; i++) {
|
for (let i = 0; i < initialCounters.length; i++) {
|
||||||
var key = initialCounters[i]
|
const key = initialCounters[i]
|
||||||
this._stats[key] = Big(0)
|
this._stats[key] = Big(0)
|
||||||
this._movingAverages[key] = {}
|
this._movingAverages[key] = {}
|
||||||
for (var k = 0; k < intervals.length; k++) {
|
for (let k = 0; k < intervals.length; k++) {
|
||||||
var interval = intervals[k]
|
const interval = intervals[k]
|
||||||
var ma = this._movingAverages[key][interval] = MovingAverage(interval)
|
const ma = this._movingAverages[key][interval] = MovingAverage(interval)
|
||||||
ma.push(this._frequencyLastTime, 0)
|
ma.push(this._frequencyLastTime, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,8 +80,6 @@ class Stats extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a clone of the current stats.
|
* Returns a clone of the current stats.
|
||||||
*
|
|
||||||
* @returns {Object}
|
|
||||||
*/
|
*/
|
||||||
get snapshot () {
|
get snapshot () {
|
||||||
return Object.assign({}, this._stats)
|
return Object.assign({}, this._stats)
|
||||||
@ -81,8 +87,6 @@ class Stats extends EventEmitter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a clone of the internal movingAverages
|
* Returns a clone of the internal movingAverages
|
||||||
*
|
|
||||||
* @returns {MovingAverage}
|
|
||||||
*/
|
*/
|
||||||
get movingAverages () {
|
get movingAverages () {
|
||||||
return Object.assign({}, this._movingAverages)
|
return Object.assign({}, this._movingAverages)
|
||||||
@ -219,9 +223,9 @@ class Stats extends EventEmitter {
|
|||||||
|
|
||||||
const intervals = this._options.movingAverageIntervals
|
const intervals = this._options.movingAverageIntervals
|
||||||
|
|
||||||
for (var i = 0; i < intervals.length; i++) {
|
for (let i = 0; i < intervals.length; i++) {
|
||||||
var movingAverageInterval = intervals[i]
|
const movingAverageInterval = intervals[i]
|
||||||
var movingAverage = movingAverages[movingAverageInterval]
|
let movingAverage = movingAverages[movingAverageInterval]
|
||||||
if (!movingAverage) {
|
if (!movingAverage) {
|
||||||
movingAverage = movingAverages[movingAverageInterval] = MovingAverage(movingAverageInterval)
|
movingAverage = movingAverages[movingAverageInterval] = MovingAverage(movingAverageInterval)
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,16 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
// @ts-ignore nat-api does not export types
|
||||||
const NatAPI = require('@motrix/nat-api')
|
const NatAPI = require('@motrix/nat-api')
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const promisify = require('promisify-es6')
|
const { promisify } = require('es6-promisify')
|
||||||
const Multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const log = Object.assign(debug('libp2p:nat'), {
|
const log = Object.assign(debug('libp2p:nat'), {
|
||||||
error: debug('libp2p:nat:err')
|
error: debug('libp2p:nat:err')
|
||||||
})
|
})
|
||||||
const { isBrowser } = require('ipfs-utils/src/env')
|
const { isBrowser } = require('wherearewe')
|
||||||
const retry = require('p-retry')
|
const retry = require('p-retry')
|
||||||
|
// @ts-ignore private-api does not export types
|
||||||
const isPrivateIp = require('private-ip')
|
const isPrivateIp = require('private-ip')
|
||||||
const pkg = require('../package.json')
|
const pkg = require('../package.json')
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
@ -17,33 +19,39 @@ const {
|
|||||||
} = require('./errors')
|
} = require('./errors')
|
||||||
const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback')
|
const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback')
|
||||||
|
|
||||||
|
const DEFAULT_TTL = 7200
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
* @typedef {import('./transport-manager')} TransportManager
|
* @typedef {import('./transport-manager')} TransportManager
|
||||||
* @typedef {import('./address-manager')} AddressManager
|
* @typedef {import('./address-manager')} AddressManager
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} NatManagerProperties
|
||||||
|
* @property {PeerId} peerId - The peer ID of the current node
|
||||||
|
* @property {TransportManager} transportManager - A transport manager
|
||||||
|
* @property {AddressManager} addressManager - An address manager
|
||||||
|
*
|
||||||
|
* @typedef {Object} NatManagerOptions
|
||||||
|
* @property {boolean} enabled - Whether to enable the NAT manager
|
||||||
|
* @property {string} [externalIp] - Pass a value to use instead of auto-detection
|
||||||
|
* @property {string} [description] - A string value to use for the port mapping description on the gateway
|
||||||
|
* @property {number} [ttl = DEFAULT_TTL] - How long UPnP port mappings should last for in seconds (minimum 1200)
|
||||||
|
* @property {boolean} [keepAlive] - Whether to automatically refresh UPnP port mappings when their TTL is reached
|
||||||
|
* @property {string} [gateway] - Pass a value to use instead of auto-detection
|
||||||
|
* @property {object} [pmp] - PMP options
|
||||||
|
* @property {boolean} [pmp.enabled] - Whether to enable PMP as well as UPnP
|
||||||
|
*/
|
||||||
|
|
||||||
function highPort (min = 1024, max = 65535) {
|
function highPort (min = 1024, max = 65535) {
|
||||||
return Math.floor(Math.random() * (max - min + 1) + min)
|
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_TTL = 7200
|
|
||||||
|
|
||||||
class NatManager {
|
class NatManager {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {object} options
|
* @param {NatManagerProperties & NatManagerOptions} options
|
||||||
* @param {PeerId} options.peerId - The peer ID of the current node
|
|
||||||
* @param {TransportManager} options.transportManager - A transport manager
|
|
||||||
* @param {AddressManager} options.addressManager - An address manager
|
|
||||||
* @param {boolean} options.enabled - Whether to enable the NAT manager
|
|
||||||
* @param {string} [options.externalIp] - Pass a value to use instead of auto-detection
|
|
||||||
* @param {string} [options.description] - A string value to use for the port mapping description on the gateway
|
|
||||||
* @param {number} [options.ttl] - How long UPnP port mappings should last for in seconds (minimum 1200)
|
|
||||||
* @param {boolean} [options.keepAlive] - Whether to automatically refresh UPnP port mappings when their TTL is reached
|
|
||||||
* @param {string} [options.gateway] - Pass a value to use instead of auto-detection
|
|
||||||
* @param {object} [options.pmp] - PMP options
|
|
||||||
* @param {boolean} [options.pmp.enabled] - Whether to enable PMP as well as UPnP
|
|
||||||
*/
|
*/
|
||||||
constructor ({ peerId, addressManager, transportManager, ...options }) {
|
constructor ({ peerId, addressManager, transportManager, ...options }) {
|
||||||
this._peerId = peerId
|
this._peerId = peerId
|
||||||
@ -89,15 +97,18 @@ class NatManager {
|
|||||||
|
|
||||||
if (!addr.isThinWaistAddress() || transport !== 'tcp') {
|
if (!addr.isThinWaistAddress() || transport !== 'tcp') {
|
||||||
// only bare tcp addresses
|
// only bare tcp addresses
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isLoopback(addr)) {
|
if (isLoopback(addr)) {
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if (family !== 'ipv4') {
|
if (family !== 4) {
|
||||||
// ignore ipv6
|
// ignore ipv6
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,9 +130,9 @@ class NatManager {
|
|||||||
})
|
})
|
||||||
|
|
||||||
this._addressManager.addObservedAddr(Multiaddr.fromNodeAddress({
|
this._addressManager.addObservedAddr(Multiaddr.fromNodeAddress({
|
||||||
family: 'IPv4',
|
family: 4,
|
||||||
address: publicIp,
|
address: publicIp,
|
||||||
port: `${publicPort}`
|
port: publicPort
|
||||||
}, transport))
|
}, transport))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -132,14 +143,32 @@ class NatManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const client = new NatAPI(this._options)
|
const client = new NatAPI(this._options)
|
||||||
const map = promisify(client.map, { context: client })
|
|
||||||
const destroy = promisify(client.destroy, { context: client })
|
|
||||||
const externalIp = promisify(client.externalIp, { context: client })
|
|
||||||
|
|
||||||
|
/** @type {(...any: any) => any} */
|
||||||
|
const map = promisify(client.map.bind(client))
|
||||||
|
/** @type {(...any: any) => any} */
|
||||||
|
const destroy = promisify(client.destroy.bind(client))
|
||||||
|
/** @type {(...any: any) => any} */
|
||||||
|
const externalIp = promisify(client.externalIp.bind(client))
|
||||||
|
|
||||||
|
// these are all network operations so add a retry
|
||||||
this._client = {
|
this._client = {
|
||||||
// these are all network operations so add a retry
|
/**
|
||||||
|
* @param {...any} args
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
map: (...args) => retry(() => map(...args), { onFailedAttempt: log.error, unref: true }),
|
map: (...args) => retry(() => map(...args), { onFailedAttempt: log.error, unref: true }),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {...any} args
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
destroy: (...args) => retry(() => destroy(...args), { onFailedAttempt: log.error, unref: true }),
|
destroy: (...args) => retry(() => destroy(...args), { onFailedAttempt: log.error, unref: true }),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {...any} args
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
*/
|
||||||
externalIp: (...args) => retry(() => externalIp(...args), { onFailedAttempt: log.error, unref: true })
|
externalIp: (...args) => retry(() => externalIp(...args), { onFailedAttempt: log.error, unref: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,12 +19,25 @@ const filter = require('it-filter')
|
|||||||
const {
|
const {
|
||||||
setDelayedInterval,
|
setDelayedInterval,
|
||||||
clearDelayedInterval
|
clearDelayedInterval
|
||||||
|
// @ts-ignore module with no types
|
||||||
} = require('set-delayed-interval')
|
} = require('set-delayed-interval')
|
||||||
const PeerId = require('peer-id')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
|
* @typedef {import('libp2p-interfaces/src/peer-routing/types').PeerRouting} PeerRoutingModule
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} RefreshManagerOptions
|
||||||
|
* @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} [interval = 10e3] - Interval between each Refresh Manager run (in ms)
|
||||||
|
*
|
||||||
|
* @typedef {Object} PeerRoutingOptions
|
||||||
|
* @property {RefreshManagerOptions} [refreshManager]
|
||||||
|
*/
|
||||||
|
|
||||||
class PeerRouting {
|
class PeerRouting {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
@ -33,6 +46,7 @@ class PeerRouting {
|
|||||||
constructor (libp2p) {
|
constructor (libp2p) {
|
||||||
this._peerId = libp2p.peerId
|
this._peerId = libp2p.peerId
|
||||||
this._peerStore = libp2p.peerStore
|
this._peerStore = libp2p.peerStore
|
||||||
|
/** @type {PeerRoutingModule[]} */
|
||||||
this._routers = libp2p._modules.peerRouting || []
|
this._routers = libp2p._modules.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
|
||||||
@ -90,11 +104,16 @@ class PeerRouting {
|
|||||||
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id.toB58String() === this._peerId.toB58String()) {
|
||||||
|
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 => [router.findPeer(id, options)])
|
...this._routers.map(router => [router.findPeer(id, options)])
|
||||||
),
|
),
|
||||||
(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)
|
||||||
)
|
)
|
||||||
|
@ -6,7 +6,7 @@ const log = Object.assign(debug('libp2p:peer-store:address-book'), {
|
|||||||
})
|
})
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const Book = require('./book')
|
const Book = require('./book')
|
||||||
@ -18,7 +18,6 @@ const {
|
|||||||
const Envelope = require('../record/envelope')
|
const Envelope = require('../record/envelope')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('./')} PeerStore
|
* @typedef {import('./')} PeerStore
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -60,7 +59,7 @@ class AddressBook extends Book {
|
|||||||
if (!data.addresses) {
|
if (!data.addresses) {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
return data.addresses.map((address) => address.multiaddr)
|
return data.addresses.map((/** @type {Address} */ address) => address.multiaddr)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -230,6 +229,11 @@ class AddressBook extends Book {
|
|||||||
const addresses = this._toAddresses(multiaddrs)
|
const addresses = this._toAddresses(multiaddrs)
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
|
|
||||||
|
// No addresses to be added
|
||||||
|
if (!addresses.length) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
const entry = this.data.get(id)
|
const entry = this.data.get(id)
|
||||||
|
|
||||||
if (entry && entry.addresses) {
|
if (entry && entry.addresses) {
|
||||||
@ -295,17 +299,21 @@ class AddressBook extends Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create Address for each address
|
// create Address for each address
|
||||||
|
/** @type {Address[]} */
|
||||||
const addresses = []
|
const addresses = []
|
||||||
multiaddrs.forEach((addr) => {
|
multiaddrs.forEach((addr) => {
|
||||||
if (!multiaddr.isMultiaddr(addr)) {
|
if (!Multiaddr.isMultiaddr(addr)) {
|
||||||
log.error(`multiaddr ${addr} must be an instance of multiaddr`)
|
log.error(`multiaddr ${addr} must be an instance of multiaddr`)
|
||||||
throw errcode(new Error(`multiaddr ${addr} must be an instance of multiaddr`), ERR_INVALID_PARAMETERS)
|
throw errcode(new Error(`multiaddr ${addr} must be an instance of multiaddr`), ERR_INVALID_PARAMETERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
addresses.push({
|
// Guarantee no replicates
|
||||||
multiaddr: addr,
|
if (!addresses.find((a) => a.multiaddr.equals(addr))) {
|
||||||
isCertified
|
addresses.push({
|
||||||
})
|
multiaddr: addr,
|
||||||
|
isCertified
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return addresses
|
return addresses
|
||||||
|
@ -7,6 +7,9 @@ const {
|
|||||||
codes: { ERR_INVALID_PARAMETERS }
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} data
|
||||||
|
*/
|
||||||
const passthrough = data => data
|
const passthrough = data => data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
|
|
||||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
const { EventEmitter } = require('events')
|
||||||
/** @type Events */
|
|
||||||
const EventEmitter = require('events')
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const AddressBook = require('./address-book')
|
const AddressBook = require('./address-book')
|
||||||
@ -101,7 +99,7 @@ class PeerStore extends EventEmitter {
|
|||||||
|
|
||||||
const peersData = new Map()
|
const peersData = new Map()
|
||||||
storedPeers.forEach((idStr) => {
|
storedPeers.forEach((idStr) => {
|
||||||
peersData.set(idStr, this.get(PeerId.createFromCID(idStr)))
|
peersData.set(idStr, this.get(PeerId.createFromB58String(idStr)))
|
||||||
})
|
})
|
||||||
|
|
||||||
return peersData
|
return peersData
|
||||||
|
@ -81,6 +81,9 @@ class MetadataBook extends Book {
|
|||||||
* Set data into the datastructure
|
* Set data into the datastructure
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
|
* @param {PeerId} peerId
|
||||||
|
* @param {string} key
|
||||||
|
* @param {Uint8Array} value
|
||||||
*/
|
*/
|
||||||
_setValue (peerId, key, value, { emit = true } = {}) {
|
_setValue (peerId, key, value, { emit = true } = {}) {
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
|
@ -5,8 +5,9 @@ const log = Object.assign(debug('libp2p:persistent-peer-store'), {
|
|||||||
error: debug('libp2p:persistent-peer-store:err')
|
error: debug('libp2p:persistent-peer-store:err')
|
||||||
})
|
})
|
||||||
const { Key } = require('interface-datastore')
|
const { Key } = require('interface-datastore')
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
const { base32 } = require('multiformats/bases/base32')
|
||||||
|
|
||||||
const PeerStore = require('..')
|
const PeerStore = require('..')
|
||||||
|
|
||||||
@ -18,13 +19,18 @@ const {
|
|||||||
NAMESPACE_PROTOCOL
|
NAMESPACE_PROTOCOL
|
||||||
} = require('./consts')
|
} = require('./consts')
|
||||||
|
|
||||||
const Addresses = require('./pb/address-book.proto')
|
const { Addresses } = require('./pb/address-book')
|
||||||
const Protocols = require('./pb/proto-book.proto')
|
const { Protocols } = require('./pb/proto-book')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('interface-datastore').Batch} Batch
|
||||||
|
* @typedef {import('../address-book.js').Address} Address
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PersistentPeerStoreProperties
|
* @typedef {Object} PersistentPeerStoreProperties
|
||||||
* @property {PeerId} peerId
|
* @property {PeerId} peerId
|
||||||
* @property {any} datastore
|
* @property {import('interface-datastore').Datastore} datastore
|
||||||
*
|
*
|
||||||
* @typedef {Object} PersistentPeerStoreOptions
|
* @typedef {Object} PersistentPeerStoreOptions
|
||||||
* @property {number} [threshold = 5] - Number of dirty peers allowed before commit data.
|
* @property {number} [threshold = 5] - Number of dirty peers allowed before commit data.
|
||||||
@ -190,7 +196,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
const batch = this._datastore.batch()
|
const batch = this._datastore.batch()
|
||||||
for (const peerIdStr of commitPeers) {
|
for (const peerIdStr of commitPeers) {
|
||||||
// PeerId
|
// PeerId
|
||||||
const peerId = this.keyBook.data.get(peerIdStr) || PeerId.createFromCID(peerIdStr)
|
const peerId = this.keyBook.data.get(peerIdStr) || PeerId.createFromB58String(peerIdStr)
|
||||||
|
|
||||||
// Address Book
|
// Address Book
|
||||||
this._batchAddressBook(peerId, batch)
|
this._batchAddressBook(peerId, batch)
|
||||||
@ -214,7 +220,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Object} batch
|
* @param {Batch} batch
|
||||||
*/
|
*/
|
||||||
_batchAddressBook (peerId, batch) {
|
_batchAddressBook (peerId, batch) {
|
||||||
const b32key = peerId.toString()
|
const b32key = peerId.toString()
|
||||||
@ -234,11 +240,13 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
multiaddr: address.multiaddr.bytes,
|
multiaddr: address.multiaddr.bytes,
|
||||||
isCertified: address.isCertified
|
isCertified: address.isCertified
|
||||||
})),
|
})),
|
||||||
certified_record: entry.record ? {
|
certifiedRecord: entry.record
|
||||||
seq: entry.record.seqNumber,
|
? {
|
||||||
raw: entry.record.raw
|
seq: entry.record.seqNumber,
|
||||||
} : undefined
|
raw: entry.record.raw
|
||||||
})
|
}
|
||||||
|
: undefined
|
||||||
|
}).finish()
|
||||||
|
|
||||||
batch.put(key, encodedData)
|
batch.put(key, encodedData)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -251,7 +259,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Object} batch
|
* @param {Batch} batch
|
||||||
*/
|
*/
|
||||||
_batchKeyBook (peerId, batch) {
|
_batchKeyBook (peerId, batch) {
|
||||||
const b32key = peerId.toString()
|
const b32key = peerId.toString()
|
||||||
@ -277,14 +285,14 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Object} batch
|
* @param {Batch} batch
|
||||||
*/
|
*/
|
||||||
_batchMetadataBook (peerId, batch) {
|
_batchMetadataBook (peerId, batch) {
|
||||||
const b32key = peerId.toString()
|
const b32key = peerId.toString()
|
||||||
const dirtyMetada = this._dirtyMetadata.get(peerId.toB58String()) || []
|
const dirtyMetada = this._dirtyMetadata.get(peerId.toB58String()) || []
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dirtyMetada.forEach((dirtyKey) => {
|
dirtyMetada.forEach((/** @type {string} */ dirtyKey) => {
|
||||||
const key = new Key(`${NAMESPACE_METADATA}${b32key}/${dirtyKey}`)
|
const key = new Key(`${NAMESPACE_METADATA}${b32key}/${dirtyKey}`)
|
||||||
const dirtyValue = this.metadataBook.getValue(peerId, dirtyKey)
|
const dirtyValue = this.metadataBook.getValue(peerId, dirtyKey)
|
||||||
|
|
||||||
@ -304,7 +312,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Object} batch
|
* @param {Batch} batch
|
||||||
*/
|
*/
|
||||||
_batchProtoBook (peerId, batch) {
|
_batchProtoBook (peerId, batch) {
|
||||||
const b32key = peerId.toString()
|
const b32key = peerId.toString()
|
||||||
@ -319,7 +327,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const encodedData = Protocols.encode({ protocols })
|
const encodedData = Protocols.encode({ protocols }).finish()
|
||||||
|
|
||||||
batch.put(key, encodedData)
|
batch.put(key, encodedData)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -339,7 +347,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
async _processDatastoreEntry ({ key, value }) {
|
async _processDatastoreEntry ({ key, value }) {
|
||||||
try {
|
try {
|
||||||
const keyParts = key.toString().split('/')
|
const keyParts = key.toString().split('/')
|
||||||
const peerId = PeerId.createFromCID(keyParts[3])
|
const peerId = PeerId.createFromBytes(base32.decode(keyParts[3]))
|
||||||
|
|
||||||
let decoded
|
let decoded
|
||||||
switch (keyParts[2]) {
|
switch (keyParts[2]) {
|
||||||
@ -351,13 +359,15 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
peerId,
|
peerId,
|
||||||
{
|
{
|
||||||
addresses: decoded.addrs.map((address) => ({
|
addresses: decoded.addrs.map((address) => ({
|
||||||
multiaddr: multiaddr(address.multiaddr),
|
multiaddr: new Multiaddr(address.multiaddr),
|
||||||
isCertified: Boolean(address.isCertified)
|
isCertified: Boolean(address.isCertified)
|
||||||
})),
|
})),
|
||||||
record: decoded.certified_record ? {
|
record: decoded.certifiedRecord
|
||||||
raw: decoded.certified_record.raw,
|
? {
|
||||||
seqNumber: decoded.certified_record.seq
|
raw: decoded.certifiedRecord.raw,
|
||||||
} : undefined
|
seqNumber: decoded.certifiedRecord.seq
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
},
|
},
|
||||||
{ emit: false })
|
{ emit: false })
|
||||||
break
|
break
|
||||||
|
198
src/peer-store/persistent/pb/address-book.d.ts
vendored
Normal file
198
src/peer-store/persistent/pb/address-book.d.ts
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of an Addresses. */
|
||||||
|
export interface IAddresses {
|
||||||
|
|
||||||
|
/** Addresses addrs */
|
||||||
|
addrs?: (Addresses.IAddress[]|null);
|
||||||
|
|
||||||
|
/** Addresses certifiedRecord */
|
||||||
|
certifiedRecord?: (Addresses.ICertifiedRecord|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents an Addresses. */
|
||||||
|
export class Addresses implements IAddresses {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Addresses.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IAddresses);
|
||||||
|
|
||||||
|
/** Addresses addrs. */
|
||||||
|
public addrs: Addresses.IAddress[];
|
||||||
|
|
||||||
|
/** Addresses certifiedRecord. */
|
||||||
|
public certifiedRecord?: (Addresses.ICertifiedRecord|null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Addresses message. Does not implicitly {@link Addresses.verify|verify} messages.
|
||||||
|
* @param m Addresses message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IAddresses, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Addresses message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Addresses
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Addresses message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Addresses
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Addresses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Addresses message. Also converts values to other types if specified.
|
||||||
|
* @param m Addresses
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Addresses, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Addresses to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Addresses {
|
||||||
|
|
||||||
|
/** Properties of an Address. */
|
||||||
|
interface IAddress {
|
||||||
|
|
||||||
|
/** Address multiaddr */
|
||||||
|
multiaddr?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Address isCertified */
|
||||||
|
isCertified?: (boolean|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents an Address. */
|
||||||
|
class Address implements IAddress {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Address.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: Addresses.IAddress);
|
||||||
|
|
||||||
|
/** Address multiaddr. */
|
||||||
|
public multiaddr: Uint8Array;
|
||||||
|
|
||||||
|
/** Address isCertified. */
|
||||||
|
public isCertified: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Address message. Does not implicitly {@link Addresses.Address.verify|verify} messages.
|
||||||
|
* @param m Address message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: Addresses.IAddress, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Address message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Address
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses.Address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Address message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Address
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Addresses.Address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Address message. Also converts values to other types if specified.
|
||||||
|
* @param m Address
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Addresses.Address, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Address to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Properties of a CertifiedRecord. */
|
||||||
|
interface ICertifiedRecord {
|
||||||
|
|
||||||
|
/** CertifiedRecord seq */
|
||||||
|
seq?: (number|null);
|
||||||
|
|
||||||
|
/** CertifiedRecord raw */
|
||||||
|
raw?: (Uint8Array|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a CertifiedRecord. */
|
||||||
|
class CertifiedRecord implements ICertifiedRecord {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new CertifiedRecord.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: Addresses.ICertifiedRecord);
|
||||||
|
|
||||||
|
/** CertifiedRecord seq. */
|
||||||
|
public seq: number;
|
||||||
|
|
||||||
|
/** CertifiedRecord raw. */
|
||||||
|
public raw: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified CertifiedRecord message. Does not implicitly {@link Addresses.CertifiedRecord.verify|verify} messages.
|
||||||
|
* @param m CertifiedRecord message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: Addresses.ICertifiedRecord, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a CertifiedRecord message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns CertifiedRecord
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses.CertifiedRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a CertifiedRecord message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns CertifiedRecord
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Addresses.CertifiedRecord;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a CertifiedRecord message. Also converts values to other types if specified.
|
||||||
|
* @param m CertifiedRecord
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Addresses.CertifiedRecord, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this CertifiedRecord to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
||||||
|
}
|
522
src/peer-store/persistent/pb/address-book.js
Normal file
522
src/peer-store/persistent/pb/address-book.js
Normal file
@ -0,0 +1,522 @@
|
|||||||
|
/*eslint-disable*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var $protobuf = require("protobufjs/minimal");
|
||||||
|
|
||||||
|
// Common aliases
|
||||||
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
|
|
||||||
|
// Exported root namespace
|
||||||
|
var $root = $protobuf.roots["libp2p-address-book"] || ($protobuf.roots["libp2p-address-book"] = {});
|
||||||
|
|
||||||
|
$root.Addresses = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of an Addresses.
|
||||||
|
* @exports IAddresses
|
||||||
|
* @interface IAddresses
|
||||||
|
* @property {Array.<Addresses.IAddress>|null} [addrs] Addresses addrs
|
||||||
|
* @property {Addresses.ICertifiedRecord|null} [certifiedRecord] Addresses certifiedRecord
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Addresses.
|
||||||
|
* @exports Addresses
|
||||||
|
* @classdesc Represents an Addresses.
|
||||||
|
* @implements IAddresses
|
||||||
|
* @constructor
|
||||||
|
* @param {IAddresses=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Addresses(p) {
|
||||||
|
this.addrs = [];
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addresses addrs.
|
||||||
|
* @member {Array.<Addresses.IAddress>} addrs
|
||||||
|
* @memberof Addresses
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Addresses.prototype.addrs = $util.emptyArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Addresses certifiedRecord.
|
||||||
|
* @member {Addresses.ICertifiedRecord|null|undefined} certifiedRecord
|
||||||
|
* @memberof Addresses
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Addresses.prototype.certifiedRecord = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Addresses message. Does not implicitly {@link Addresses.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Addresses
|
||||||
|
* @static
|
||||||
|
* @param {IAddresses} m Addresses message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Addresses.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.addrs != null && m.addrs.length) {
|
||||||
|
for (var i = 0; i < m.addrs.length; ++i)
|
||||||
|
$root.Addresses.Address.encode(m.addrs[i], w.uint32(10).fork()).ldelim();
|
||||||
|
}
|
||||||
|
if (m.certifiedRecord != null && Object.hasOwnProperty.call(m, "certifiedRecord"))
|
||||||
|
$root.Addresses.CertifiedRecord.encode(m.certifiedRecord, w.uint32(18).fork()).ldelim();
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Addresses message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Addresses
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Addresses} Addresses
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Addresses.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (!(m.addrs && m.addrs.length))
|
||||||
|
m.addrs = [];
|
||||||
|
m.addrs.push($root.Addresses.Address.decode(r, r.uint32()));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.certifiedRecord = $root.Addresses.CertifiedRecord.decode(r, r.uint32());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Addresses message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Addresses
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Addresses} Addresses
|
||||||
|
*/
|
||||||
|
Addresses.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Addresses)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Addresses();
|
||||||
|
if (d.addrs) {
|
||||||
|
if (!Array.isArray(d.addrs))
|
||||||
|
throw TypeError(".Addresses.addrs: array expected");
|
||||||
|
m.addrs = [];
|
||||||
|
for (var i = 0; i < d.addrs.length; ++i) {
|
||||||
|
if (typeof d.addrs[i] !== "object")
|
||||||
|
throw TypeError(".Addresses.addrs: object expected");
|
||||||
|
m.addrs[i] = $root.Addresses.Address.fromObject(d.addrs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d.certifiedRecord != null) {
|
||||||
|
if (typeof d.certifiedRecord !== "object")
|
||||||
|
throw TypeError(".Addresses.certifiedRecord: object expected");
|
||||||
|
m.certifiedRecord = $root.Addresses.CertifiedRecord.fromObject(d.certifiedRecord);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Addresses message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Addresses
|
||||||
|
* @static
|
||||||
|
* @param {Addresses} m Addresses
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Addresses.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.arrays || o.defaults) {
|
||||||
|
d.addrs = [];
|
||||||
|
}
|
||||||
|
if (o.defaults) {
|
||||||
|
d.certifiedRecord = null;
|
||||||
|
}
|
||||||
|
if (m.addrs && m.addrs.length) {
|
||||||
|
d.addrs = [];
|
||||||
|
for (var j = 0; j < m.addrs.length; ++j) {
|
||||||
|
d.addrs[j] = $root.Addresses.Address.toObject(m.addrs[j], o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.certifiedRecord != null && m.hasOwnProperty("certifiedRecord")) {
|
||||||
|
d.certifiedRecord = $root.Addresses.CertifiedRecord.toObject(m.certifiedRecord, o);
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Addresses to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Addresses
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Addresses.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
Addresses.Address = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of an Address.
|
||||||
|
* @memberof Addresses
|
||||||
|
* @interface IAddress
|
||||||
|
* @property {Uint8Array|null} [multiaddr] Address multiaddr
|
||||||
|
* @property {boolean|null} [isCertified] Address isCertified
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Address.
|
||||||
|
* @memberof Addresses
|
||||||
|
* @classdesc Represents an Address.
|
||||||
|
* @implements IAddress
|
||||||
|
* @constructor
|
||||||
|
* @param {Addresses.IAddress=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Address(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address multiaddr.
|
||||||
|
* @member {Uint8Array} multiaddr
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Address.prototype.multiaddr = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Address isCertified.
|
||||||
|
* @member {boolean} isCertified
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Address.prototype.isCertified = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Address message. Does not implicitly {@link Addresses.Address.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @static
|
||||||
|
* @param {Addresses.IAddress} m Address message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Address.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.multiaddr != null && Object.hasOwnProperty.call(m, "multiaddr"))
|
||||||
|
w.uint32(10).bytes(m.multiaddr);
|
||||||
|
if (m.isCertified != null && Object.hasOwnProperty.call(m, "isCertified"))
|
||||||
|
w.uint32(16).bool(m.isCertified);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Address message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Addresses.Address} Address
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Address.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses.Address();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.multiaddr = r.bytes();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.isCertified = r.bool();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Address message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Addresses.Address} Address
|
||||||
|
*/
|
||||||
|
Address.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Addresses.Address)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Addresses.Address();
|
||||||
|
if (d.multiaddr != null) {
|
||||||
|
if (typeof d.multiaddr === "string")
|
||||||
|
$util.base64.decode(d.multiaddr, m.multiaddr = $util.newBuffer($util.base64.length(d.multiaddr)), 0);
|
||||||
|
else if (d.multiaddr.length)
|
||||||
|
m.multiaddr = d.multiaddr;
|
||||||
|
}
|
||||||
|
if (d.isCertified != null) {
|
||||||
|
m.isCertified = Boolean(d.isCertified);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Address message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @static
|
||||||
|
* @param {Addresses.Address} m Address
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Address.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.multiaddr = "";
|
||||||
|
else {
|
||||||
|
d.multiaddr = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.multiaddr = $util.newBuffer(d.multiaddr);
|
||||||
|
}
|
||||||
|
d.isCertified = false;
|
||||||
|
}
|
||||||
|
if (m.multiaddr != null && m.hasOwnProperty("multiaddr")) {
|
||||||
|
d.multiaddr = o.bytes === String ? $util.base64.encode(m.multiaddr, 0, m.multiaddr.length) : o.bytes === Array ? Array.prototype.slice.call(m.multiaddr) : m.multiaddr;
|
||||||
|
}
|
||||||
|
if (m.isCertified != null && m.hasOwnProperty("isCertified")) {
|
||||||
|
d.isCertified = m.isCertified;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Address to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Addresses.Address
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Address.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Address;
|
||||||
|
})();
|
||||||
|
|
||||||
|
Addresses.CertifiedRecord = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of a CertifiedRecord.
|
||||||
|
* @memberof Addresses
|
||||||
|
* @interface ICertifiedRecord
|
||||||
|
* @property {number|null} [seq] CertifiedRecord seq
|
||||||
|
* @property {Uint8Array|null} [raw] CertifiedRecord raw
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new CertifiedRecord.
|
||||||
|
* @memberof Addresses
|
||||||
|
* @classdesc Represents a CertifiedRecord.
|
||||||
|
* @implements ICertifiedRecord
|
||||||
|
* @constructor
|
||||||
|
* @param {Addresses.ICertifiedRecord=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function CertifiedRecord(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CertifiedRecord seq.
|
||||||
|
* @member {number} seq
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CertifiedRecord.prototype.seq = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CertifiedRecord raw.
|
||||||
|
* @member {Uint8Array} raw
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
CertifiedRecord.prototype.raw = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified CertifiedRecord message. Does not implicitly {@link Addresses.CertifiedRecord.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @static
|
||||||
|
* @param {Addresses.ICertifiedRecord} m CertifiedRecord message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
CertifiedRecord.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.seq != null && Object.hasOwnProperty.call(m, "seq"))
|
||||||
|
w.uint32(8).uint64(m.seq);
|
||||||
|
if (m.raw != null && Object.hasOwnProperty.call(m, "raw"))
|
||||||
|
w.uint32(18).bytes(m.raw);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a CertifiedRecord message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Addresses.CertifiedRecord} CertifiedRecord
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
CertifiedRecord.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses.CertifiedRecord();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.seq = r.uint64();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.raw = r.bytes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a CertifiedRecord message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Addresses.CertifiedRecord} CertifiedRecord
|
||||||
|
*/
|
||||||
|
CertifiedRecord.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Addresses.CertifiedRecord)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Addresses.CertifiedRecord();
|
||||||
|
if (d.seq != null) {
|
||||||
|
if ($util.Long)
|
||||||
|
(m.seq = $util.Long.fromValue(d.seq)).unsigned = true;
|
||||||
|
else if (typeof d.seq === "string")
|
||||||
|
m.seq = parseInt(d.seq, 10);
|
||||||
|
else if (typeof d.seq === "number")
|
||||||
|
m.seq = d.seq;
|
||||||
|
else if (typeof d.seq === "object")
|
||||||
|
m.seq = new $util.LongBits(d.seq.low >>> 0, d.seq.high >>> 0).toNumber(true);
|
||||||
|
}
|
||||||
|
if (d.raw != null) {
|
||||||
|
if (typeof d.raw === "string")
|
||||||
|
$util.base64.decode(d.raw, m.raw = $util.newBuffer($util.base64.length(d.raw)), 0);
|
||||||
|
else if (d.raw.length)
|
||||||
|
m.raw = d.raw;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a CertifiedRecord message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @static
|
||||||
|
* @param {Addresses.CertifiedRecord} m CertifiedRecord
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
CertifiedRecord.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
if ($util.Long) {
|
||||||
|
var n = new $util.Long(0, 0, true);
|
||||||
|
d.seq = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n;
|
||||||
|
} else
|
||||||
|
d.seq = o.longs === String ? "0" : 0;
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.raw = "";
|
||||||
|
else {
|
||||||
|
d.raw = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.raw = $util.newBuffer(d.raw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.seq != null && m.hasOwnProperty("seq")) {
|
||||||
|
if (typeof m.seq === "number")
|
||||||
|
d.seq = o.longs === String ? String(m.seq) : m.seq;
|
||||||
|
else
|
||||||
|
d.seq = o.longs === String ? $util.Long.prototype.toString.call(m.seq) : o.longs === Number ? new $util.LongBits(m.seq.low >>> 0, m.seq.high >>> 0).toNumber(true) : m.seq;
|
||||||
|
}
|
||||||
|
if (m.raw != null && m.hasOwnProperty("raw")) {
|
||||||
|
d.raw = o.bytes === String ? $util.base64.encode(m.raw, 0, m.raw.length) : o.bytes === Array ? Array.prototype.slice.call(m.raw) : m.raw;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this CertifiedRecord to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Addresses.CertifiedRecord
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
CertifiedRecord.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return CertifiedRecord;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return Addresses;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
@ -1,12 +1,9 @@
|
|||||||
'use strict'
|
syntax = "proto3";
|
||||||
|
|
||||||
const protons = require('protons')
|
|
||||||
|
|
||||||
const message = `
|
|
||||||
message Addresses {
|
message Addresses {
|
||||||
// Address represents a single multiaddr.
|
// Address represents a single multiaddr.
|
||||||
message Address {
|
message Address {
|
||||||
required bytes multiaddr = 1;
|
bytes multiaddr = 1;
|
||||||
|
|
||||||
// Flag to indicate if the address comes from a certified source.
|
// Flag to indicate if the address comes from a certified source.
|
||||||
optional bool isCertified = 2;
|
optional bool isCertified = 2;
|
||||||
@ -27,7 +24,4 @@ message Addresses {
|
|||||||
|
|
||||||
// The most recently received signed PeerRecord.
|
// The most recently received signed PeerRecord.
|
||||||
CertifiedRecord certified_record = 2;
|
CertifiedRecord certified_record = 2;
|
||||||
}
|
}
|
||||||
`
|
|
||||||
|
|
||||||
module.exports = protons(message).Addresses
|
|
59
src/peer-store/persistent/pb/proto-book.d.ts
vendored
Normal file
59
src/peer-store/persistent/pb/proto-book.d.ts
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of a Protocols. */
|
||||||
|
export interface IProtocols {
|
||||||
|
|
||||||
|
/** Protocols protocols */
|
||||||
|
protocols?: (string[]|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents a Protocols. */
|
||||||
|
export class Protocols implements IProtocols {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Protocols.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IProtocols);
|
||||||
|
|
||||||
|
/** Protocols protocols. */
|
||||||
|
public protocols: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Protocols message. Does not implicitly {@link Protocols.verify|verify} messages.
|
||||||
|
* @param m Protocols message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IProtocols, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a Protocols message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Protocols
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Protocols;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Protocols message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Protocols
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Protocols;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a Protocols message. Also converts values to other types if specified.
|
||||||
|
* @param m Protocols
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Protocols, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Protocols to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
157
src/peer-store/persistent/pb/proto-book.js
Normal file
157
src/peer-store/persistent/pb/proto-book.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*eslint-disable*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var $protobuf = require("protobufjs/minimal");
|
||||||
|
|
||||||
|
// Common aliases
|
||||||
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
|
|
||||||
|
// Exported root namespace
|
||||||
|
var $root = $protobuf.roots["libp2p-proto-book"] || ($protobuf.roots["libp2p-proto-book"] = {});
|
||||||
|
|
||||||
|
$root.Protocols = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of a Protocols.
|
||||||
|
* @exports IProtocols
|
||||||
|
* @interface IProtocols
|
||||||
|
* @property {Array.<string>|null} [protocols] Protocols protocols
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Protocols.
|
||||||
|
* @exports Protocols
|
||||||
|
* @classdesc Represents a Protocols.
|
||||||
|
* @implements IProtocols
|
||||||
|
* @constructor
|
||||||
|
* @param {IProtocols=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Protocols(p) {
|
||||||
|
this.protocols = [];
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protocols protocols.
|
||||||
|
* @member {Array.<string>} protocols
|
||||||
|
* @memberof Protocols
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Protocols.prototype.protocols = $util.emptyArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Protocols message. Does not implicitly {@link Protocols.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Protocols
|
||||||
|
* @static
|
||||||
|
* @param {IProtocols} m Protocols message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Protocols.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.protocols != null && m.protocols.length) {
|
||||||
|
for (var i = 0; i < m.protocols.length; ++i)
|
||||||
|
w.uint32(10).string(m.protocols[i]);
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a Protocols message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Protocols
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Protocols} Protocols
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Protocols.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Protocols();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
if (!(m.protocols && m.protocols.length))
|
||||||
|
m.protocols = [];
|
||||||
|
m.protocols.push(r.string());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Protocols message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Protocols
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Protocols} Protocols
|
||||||
|
*/
|
||||||
|
Protocols.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Protocols)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Protocols();
|
||||||
|
if (d.protocols) {
|
||||||
|
if (!Array.isArray(d.protocols))
|
||||||
|
throw TypeError(".Protocols.protocols: array expected");
|
||||||
|
m.protocols = [];
|
||||||
|
for (var i = 0; i < d.protocols.length; ++i) {
|
||||||
|
m.protocols[i] = String(d.protocols[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from a Protocols message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Protocols
|
||||||
|
* @static
|
||||||
|
* @param {Protocols} m Protocols
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Protocols.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.arrays || o.defaults) {
|
||||||
|
d.protocols = [];
|
||||||
|
}
|
||||||
|
if (m.protocols && m.protocols.length) {
|
||||||
|
d.protocols = [];
|
||||||
|
for (var j = 0; j < m.protocols.length; ++j) {
|
||||||
|
d.protocols[j] = m.protocols[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Protocols to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Protocols
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Protocols.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Protocols;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
5
src/peer-store/persistent/pb/proto-book.proto
Normal file
5
src/peer-store/persistent/pb/proto-book.proto
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
message Protocols {
|
||||||
|
repeated string protocols = 1;
|
||||||
|
}
|
@ -1,12 +0,0 @@
|
|||||||
'use strict'
|
|
||||||
|
|
||||||
const protons = require('protons')
|
|
||||||
|
|
||||||
/* eslint-disable no-tabs */
|
|
||||||
const message = `
|
|
||||||
message Protocols {
|
|
||||||
repeated string protocols = 1;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
module.exports = protons(message).Protocols
|
|
@ -74,6 +74,10 @@ class ProtoBook extends Book {
|
|||||||
const recSet = this.data.get(id)
|
const recSet = this.data.get(id)
|
||||||
const newSet = new Set(protocols)
|
const newSet = new Set(protocols)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Set<string>} a
|
||||||
|
* @param {Set<string>} b
|
||||||
|
*/
|
||||||
const isSetEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value))
|
const isSetEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value))
|
||||||
|
|
||||||
// Already knows the peer and the recorded protocols are the same?
|
// Already knows the peer and the recorded protocols are the same?
|
||||||
|
@ -8,6 +8,7 @@ const errCode = require('err-code')
|
|||||||
|
|
||||||
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
|
||||||
const { toBuffer } = require('it-buffer')
|
const { toBuffer } = require('it-buffer')
|
||||||
const { collect, take } = require('streaming-iterables')
|
const { collect, take } = require('streaming-iterables')
|
||||||
const equals = require('uint8arrays/equals')
|
const equals = require('uint8arrays/equals')
|
||||||
@ -16,8 +17,9 @@ const { PROTOCOL, PING_LENGTH } = require('./constants')
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('../')} Libp2p
|
* @typedef {import('../')} Libp2p
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +33,8 @@ async function ping (node, peer) {
|
|||||||
// @ts-ignore multiaddr might not have toB58String
|
// @ts-ignore multiaddr might not have toB58String
|
||||||
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
|
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
|
||||||
|
|
||||||
const { stream } = await node.dialProtocol(peer, PROTOCOL)
|
const connection = await node.dial(peer)
|
||||||
|
const { stream } = await connection.newStream(PROTOCOL)
|
||||||
|
|
||||||
const start = Date.now()
|
const start = Date.now()
|
||||||
const data = crypto.randomBytes(PING_LENGTH)
|
const data = crypto.randomBytes(PING_LENGTH)
|
||||||
@ -39,7 +42,7 @@ async function ping (node, peer) {
|
|||||||
const [result] = await pipe(
|
const [result] = await pipe(
|
||||||
[data],
|
[data],
|
||||||
stream,
|
stream,
|
||||||
stream => take(1, stream),
|
(/** @type {MuxedStream} */ stream) => take(1, stream),
|
||||||
toBuffer,
|
toBuffer,
|
||||||
collect
|
collect
|
||||||
)
|
)
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
const constants = require('./constants')
|
const constants = require('./constants')
|
||||||
|
|
||||||
exports = module.exports
|
/**
|
||||||
|
* @param {number} length
|
||||||
exports.rnd = (length) => {
|
*/
|
||||||
|
function rnd (length) {
|
||||||
if (!length) {
|
if (!length) {
|
||||||
length = constants.PING_LENGTH
|
length = constants.PING_LENGTH
|
||||||
}
|
}
|
||||||
return crypto.randomBytes(length)
|
return crypto.randomBytes(length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
rnd
|
||||||
|
}
|
||||||
|
@ -7,6 +7,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const Errors = require('./errors')
|
const Errors = require('./errors')
|
||||||
|
// @ts-ignore xsalsa20 has no types exported
|
||||||
const xsalsa20 = require('xsalsa20')
|
const xsalsa20 = require('xsalsa20')
|
||||||
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
|
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
@ -21,7 +22,8 @@ const uint8ArrayToString = require('uint8arrays/to-string')
|
|||||||
*/
|
*/
|
||||||
module.exports.createBoxStream = (nonce, psk) => {
|
module.exports.createBoxStream = (nonce, psk) => {
|
||||||
const xor = xsalsa20(nonce, psk)
|
const xor = xsalsa20(nonce, psk)
|
||||||
return (source) => (async function * () {
|
|
||||||
|
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
|
||||||
for await (const chunk of source) {
|
for await (const chunk of source) {
|
||||||
yield Uint8Array.from(xor.update(chunk.slice()))
|
yield Uint8Array.from(xor.update(chunk.slice()))
|
||||||
}
|
}
|
||||||
@ -36,7 +38,7 @@ module.exports.createBoxStream = (nonce, psk) => {
|
|||||||
* @returns {*} a through iterable
|
* @returns {*} a through iterable
|
||||||
*/
|
*/
|
||||||
module.exports.createUnboxStream = (nonce, psk) => {
|
module.exports.createUnboxStream = (nonce, psk) => {
|
||||||
return (source) => (async function * () {
|
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
|
||||||
const xor = xsalsa20(nonce, psk)
|
const xor = xsalsa20(nonce, psk)
|
||||||
log.trace('Decryption enabled')
|
log.trace('Decryption enabled')
|
||||||
|
|
||||||
@ -51,7 +53,7 @@ module.exports.createUnboxStream = (nonce, psk) => {
|
|||||||
*
|
*
|
||||||
* @param {Uint8Array} pskBuffer
|
* @param {Uint8Array} pskBuffer
|
||||||
* @throws {INVALID_PSK}
|
* @throws {INVALID_PSK}
|
||||||
* @returns {Object} The PSK metadata (tag, codecName, psk)
|
* @returns {{ tag?: string, codecName?: string, psk: Uint8Array }} The PSK metadata (tag, codecName, psk)
|
||||||
*/
|
*/
|
||||||
module.exports.decodeV1PSK = (pskBuffer) => {
|
module.exports.decodeV1PSK = (pskBuffer) => {
|
||||||
try {
|
try {
|
||||||
|
@ -6,6 +6,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
|
|||||||
})
|
})
|
||||||
const { pipe } = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
|
// @ts-ignore it-pair has no types exported
|
||||||
const duplexPair = require('it-pair/duplex')
|
const duplexPair = require('it-pair/duplex')
|
||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
const Errors = require('./errors')
|
const Errors = require('./errors')
|
||||||
@ -17,6 +18,7 @@ const {
|
|||||||
createUnboxStream,
|
createUnboxStream,
|
||||||
decodeV1PSK
|
decodeV1PSK
|
||||||
} = require('./crypto')
|
} = require('./crypto')
|
||||||
|
// @ts-ignore it-handshake has no types exported
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const { NONCE_LENGTH } = require('./key-generator')
|
const { NONCE_LENGTH } = require('./key-generator')
|
||||||
|
|
||||||
|
@ -22,8 +22,12 @@ module.exports = generate
|
|||||||
module.exports.NONCE_LENGTH = 24
|
module.exports.NONCE_LENGTH = 24
|
||||||
module.exports.KEY_LENGTH = KEY_LENGTH
|
module.exports.KEY_LENGTH = KEY_LENGTH
|
||||||
|
|
||||||
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
|
try {
|
||||||
if (require.main === module) {
|
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
|
||||||
// @ts-ignore
|
if (require.main === module) {
|
||||||
generate(process.stdout)
|
// @ts-ignore
|
||||||
|
generate(process.stdout)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
// Pubsub adapter to keep API with handlers while not removed.
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/pubsub').InMessage} InMessage
|
* @typedef {import('libp2p-interfaces/src/pubsub').InMessage} InMessage
|
||||||
* @typedef {import('libp2p-interfaces/src/pubsub')} PubsubRouter
|
* @typedef {import('libp2p-interfaces/src/pubsub')} PubsubRouter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Pubsub adapter to keep API with handlers while not removed.
|
/**
|
||||||
|
* @param {{new(...args: any[]): PubsubRouter}} PubsubRouter
|
||||||
|
* @param {import('.')} libp2p
|
||||||
|
* @param {{ enabled: boolean; } & import(".").PubsubLocalOptions & import("libp2p-interfaces/src/pubsub").PubsubOptions} options
|
||||||
|
*/
|
||||||
function pubsubAdapter (PubsubRouter, libp2p, options) {
|
function pubsubAdapter (PubsubRouter, libp2p, options) {
|
||||||
|
/** @type {PubsubRouter & { _subscribeAdapter: PubsubRouter['subscribe'], _unsubscribeAdapter: PubsubRouter['unsubscribe'] }} */
|
||||||
|
// @ts-ignore we set the extra _subscribeAdapter and _unsubscribeAdapter properties afterwards
|
||||||
const pubsub = new PubsubRouter(libp2p, options)
|
const pubsub = new PubsubRouter(libp2p, options)
|
||||||
pubsub._subscribeAdapter = pubsub.subscribe
|
pubsub._subscribeAdapter = pubsub.subscribe
|
||||||
pubsub._unsubscribeAdapter = pubsub.unsubscribe
|
pubsub._unsubscribeAdapter = pubsub.unsubscribe
|
||||||
|
77
src/record/envelope/envelope.d.ts
vendored
Normal file
77
src/record/envelope/envelope.d.ts
vendored
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
import * as $protobuf from "protobufjs";
|
||||||
|
/** Properties of an Envelope. */
|
||||||
|
export interface IEnvelope {
|
||||||
|
|
||||||
|
/** Envelope publicKey */
|
||||||
|
publicKey?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Envelope payloadType */
|
||||||
|
payloadType?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Envelope payload */
|
||||||
|
payload?: (Uint8Array|null);
|
||||||
|
|
||||||
|
/** Envelope signature */
|
||||||
|
signature?: (Uint8Array|null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Represents an Envelope. */
|
||||||
|
export class Envelope implements IEnvelope {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Envelope.
|
||||||
|
* @param [p] Properties to set
|
||||||
|
*/
|
||||||
|
constructor(p?: IEnvelope);
|
||||||
|
|
||||||
|
/** Envelope publicKey. */
|
||||||
|
public publicKey: Uint8Array;
|
||||||
|
|
||||||
|
/** Envelope payloadType. */
|
||||||
|
public payloadType: Uint8Array;
|
||||||
|
|
||||||
|
/** Envelope payload. */
|
||||||
|
public payload: Uint8Array;
|
||||||
|
|
||||||
|
/** Envelope signature. */
|
||||||
|
public signature: Uint8Array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
|
||||||
|
* @param m Envelope message or plain object to encode
|
||||||
|
* @param [w] Writer to encode to
|
||||||
|
* @returns Writer
|
||||||
|
*/
|
||||||
|
public static encode(m: IEnvelope, w?: $protobuf.Writer): $protobuf.Writer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Envelope message from the specified reader or buffer.
|
||||||
|
* @param r Reader or buffer to decode from
|
||||||
|
* @param [l] Message length if known beforehand
|
||||||
|
* @returns Envelope
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Envelope message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @param d Plain object
|
||||||
|
* @returns Envelope
|
||||||
|
*/
|
||||||
|
public static fromObject(d: { [k: string]: any }): Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Envelope message. Also converts values to other types if specified.
|
||||||
|
* @param m Envelope
|
||||||
|
* @param [o] Conversion options
|
||||||
|
* @returns Plain object
|
||||||
|
*/
|
||||||
|
public static toObject(m: Envelope, o?: $protobuf.IConversionOptions): { [k: string]: any };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Envelope to JSON.
|
||||||
|
* @returns JSON object
|
||||||
|
*/
|
||||||
|
public toJSON(): { [k: string]: any };
|
||||||
|
}
|
243
src/record/envelope/envelope.js
Normal file
243
src/record/envelope/envelope.js
Normal file
@ -0,0 +1,243 @@
|
|||||||
|
/*eslint-disable*/
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var $protobuf = require("protobufjs/minimal");
|
||||||
|
|
||||||
|
// Common aliases
|
||||||
|
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||||
|
|
||||||
|
// Exported root namespace
|
||||||
|
var $root = $protobuf.roots["libp2p-envelope"] || ($protobuf.roots["libp2p-envelope"] = {});
|
||||||
|
|
||||||
|
$root.Envelope = (function() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properties of an Envelope.
|
||||||
|
* @exports IEnvelope
|
||||||
|
* @interface IEnvelope
|
||||||
|
* @property {Uint8Array|null} [publicKey] Envelope publicKey
|
||||||
|
* @property {Uint8Array|null} [payloadType] Envelope payloadType
|
||||||
|
* @property {Uint8Array|null} [payload] Envelope payload
|
||||||
|
* @property {Uint8Array|null} [signature] Envelope signature
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new Envelope.
|
||||||
|
* @exports Envelope
|
||||||
|
* @classdesc Represents an Envelope.
|
||||||
|
* @implements IEnvelope
|
||||||
|
* @constructor
|
||||||
|
* @param {IEnvelope=} [p] Properties to set
|
||||||
|
*/
|
||||||
|
function Envelope(p) {
|
||||||
|
if (p)
|
||||||
|
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
|
||||||
|
if (p[ks[i]] != null)
|
||||||
|
this[ks[i]] = p[ks[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envelope publicKey.
|
||||||
|
* @member {Uint8Array} publicKey
|
||||||
|
* @memberof Envelope
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Envelope.prototype.publicKey = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envelope payloadType.
|
||||||
|
* @member {Uint8Array} payloadType
|
||||||
|
* @memberof Envelope
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Envelope.prototype.payloadType = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envelope payload.
|
||||||
|
* @member {Uint8Array} payload
|
||||||
|
* @memberof Envelope
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Envelope.prototype.payload = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envelope signature.
|
||||||
|
* @member {Uint8Array} signature
|
||||||
|
* @memberof Envelope
|
||||||
|
* @instance
|
||||||
|
*/
|
||||||
|
Envelope.prototype.signature = $util.newBuffer([]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
|
||||||
|
* @function encode
|
||||||
|
* @memberof Envelope
|
||||||
|
* @static
|
||||||
|
* @param {IEnvelope} m Envelope message or plain object to encode
|
||||||
|
* @param {$protobuf.Writer} [w] Writer to encode to
|
||||||
|
* @returns {$protobuf.Writer} Writer
|
||||||
|
*/
|
||||||
|
Envelope.encode = function encode(m, w) {
|
||||||
|
if (!w)
|
||||||
|
w = $Writer.create();
|
||||||
|
if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey"))
|
||||||
|
w.uint32(10).bytes(m.publicKey);
|
||||||
|
if (m.payloadType != null && Object.hasOwnProperty.call(m, "payloadType"))
|
||||||
|
w.uint32(18).bytes(m.payloadType);
|
||||||
|
if (m.payload != null && Object.hasOwnProperty.call(m, "payload"))
|
||||||
|
w.uint32(26).bytes(m.payload);
|
||||||
|
if (m.signature != null && Object.hasOwnProperty.call(m, "signature"))
|
||||||
|
w.uint32(42).bytes(m.signature);
|
||||||
|
return w;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes an Envelope message from the specified reader or buffer.
|
||||||
|
* @function decode
|
||||||
|
* @memberof Envelope
|
||||||
|
* @static
|
||||||
|
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
|
||||||
|
* @param {number} [l] Message length if known beforehand
|
||||||
|
* @returns {Envelope} Envelope
|
||||||
|
* @throws {Error} If the payload is not a reader or valid buffer
|
||||||
|
* @throws {$protobuf.util.ProtocolError} If required fields are missing
|
||||||
|
*/
|
||||||
|
Envelope.decode = function decode(r, l) {
|
||||||
|
if (!(r instanceof $Reader))
|
||||||
|
r = $Reader.create(r);
|
||||||
|
var c = l === undefined ? r.len : r.pos + l, m = new $root.Envelope();
|
||||||
|
while (r.pos < c) {
|
||||||
|
var t = r.uint32();
|
||||||
|
switch (t >>> 3) {
|
||||||
|
case 1:
|
||||||
|
m.publicKey = r.bytes();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
m.payloadType = r.bytes();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
m.payload = r.bytes();
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
m.signature = r.bytes();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
r.skipType(t & 7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an Envelope message from a plain object. Also converts values to their respective internal types.
|
||||||
|
* @function fromObject
|
||||||
|
* @memberof Envelope
|
||||||
|
* @static
|
||||||
|
* @param {Object.<string,*>} d Plain object
|
||||||
|
* @returns {Envelope} Envelope
|
||||||
|
*/
|
||||||
|
Envelope.fromObject = function fromObject(d) {
|
||||||
|
if (d instanceof $root.Envelope)
|
||||||
|
return d;
|
||||||
|
var m = new $root.Envelope();
|
||||||
|
if (d.publicKey != null) {
|
||||||
|
if (typeof d.publicKey === "string")
|
||||||
|
$util.base64.decode(d.publicKey, m.publicKey = $util.newBuffer($util.base64.length(d.publicKey)), 0);
|
||||||
|
else if (d.publicKey.length)
|
||||||
|
m.publicKey = d.publicKey;
|
||||||
|
}
|
||||||
|
if (d.payloadType != null) {
|
||||||
|
if (typeof d.payloadType === "string")
|
||||||
|
$util.base64.decode(d.payloadType, m.payloadType = $util.newBuffer($util.base64.length(d.payloadType)), 0);
|
||||||
|
else if (d.payloadType.length)
|
||||||
|
m.payloadType = d.payloadType;
|
||||||
|
}
|
||||||
|
if (d.payload != null) {
|
||||||
|
if (typeof d.payload === "string")
|
||||||
|
$util.base64.decode(d.payload, m.payload = $util.newBuffer($util.base64.length(d.payload)), 0);
|
||||||
|
else if (d.payload.length)
|
||||||
|
m.payload = d.payload;
|
||||||
|
}
|
||||||
|
if (d.signature != null) {
|
||||||
|
if (typeof d.signature === "string")
|
||||||
|
$util.base64.decode(d.signature, m.signature = $util.newBuffer($util.base64.length(d.signature)), 0);
|
||||||
|
else if (d.signature.length)
|
||||||
|
m.signature = d.signature;
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a plain object from an Envelope message. Also converts values to other types if specified.
|
||||||
|
* @function toObject
|
||||||
|
* @memberof Envelope
|
||||||
|
* @static
|
||||||
|
* @param {Envelope} m Envelope
|
||||||
|
* @param {$protobuf.IConversionOptions} [o] Conversion options
|
||||||
|
* @returns {Object.<string,*>} Plain object
|
||||||
|
*/
|
||||||
|
Envelope.toObject = function toObject(m, o) {
|
||||||
|
if (!o)
|
||||||
|
o = {};
|
||||||
|
var d = {};
|
||||||
|
if (o.defaults) {
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.publicKey = "";
|
||||||
|
else {
|
||||||
|
d.publicKey = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.publicKey = $util.newBuffer(d.publicKey);
|
||||||
|
}
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.payloadType = "";
|
||||||
|
else {
|
||||||
|
d.payloadType = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.payloadType = $util.newBuffer(d.payloadType);
|
||||||
|
}
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.payload = "";
|
||||||
|
else {
|
||||||
|
d.payload = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.payload = $util.newBuffer(d.payload);
|
||||||
|
}
|
||||||
|
if (o.bytes === String)
|
||||||
|
d.signature = "";
|
||||||
|
else {
|
||||||
|
d.signature = [];
|
||||||
|
if (o.bytes !== Array)
|
||||||
|
d.signature = $util.newBuffer(d.signature);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.publicKey != null && m.hasOwnProperty("publicKey")) {
|
||||||
|
d.publicKey = o.bytes === String ? $util.base64.encode(m.publicKey, 0, m.publicKey.length) : o.bytes === Array ? Array.prototype.slice.call(m.publicKey) : m.publicKey;
|
||||||
|
}
|
||||||
|
if (m.payloadType != null && m.hasOwnProperty("payloadType")) {
|
||||||
|
d.payloadType = o.bytes === String ? $util.base64.encode(m.payloadType, 0, m.payloadType.length) : o.bytes === Array ? Array.prototype.slice.call(m.payloadType) : m.payloadType;
|
||||||
|
}
|
||||||
|
if (m.payload != null && m.hasOwnProperty("payload")) {
|
||||||
|
d.payload = o.bytes === String ? $util.base64.encode(m.payload, 0, m.payload.length) : o.bytes === Array ? Array.prototype.slice.call(m.payload) : m.payload;
|
||||||
|
}
|
||||||
|
if (m.signature != null && m.hasOwnProperty("signature")) {
|
||||||
|
d.signature = o.bytes === String ? $util.base64.encode(m.signature, 0, m.signature.length) : o.bytes === Array ? Array.prototype.slice.call(m.signature) : m.signature;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts this Envelope to JSON.
|
||||||
|
* @function toJSON
|
||||||
|
* @memberof Envelope
|
||||||
|
* @instance
|
||||||
|
* @returns {Object.<string,*>} JSON object
|
||||||
|
*/
|
||||||
|
Envelope.prototype.toJSON = function toJSON() {
|
||||||
|
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
|
||||||
|
};
|
||||||
|
|
||||||
|
return Envelope;
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = $root;
|
@ -1,9 +1,5 @@
|
|||||||
'use strict'
|
syntax = "proto3";
|
||||||
|
|
||||||
const protons = require('protons')
|
|
||||||
|
|
||||||
/** @type {{Envelope: import('../../types').MessageProto}} */
|
|
||||||
module.exports = protons(`
|
|
||||||
message Envelope {
|
message Envelope {
|
||||||
// public_key is the public key of the keypair the enclosed payload was
|
// public_key is the public key of the keypair the enclosed payload was
|
||||||
// signed with.
|
// signed with.
|
||||||
@ -20,5 +16,4 @@ message Envelope {
|
|||||||
// the enclosed public key, over the payload, prefixing a domain string for
|
// the enclosed public key, over the payload, prefixing a domain string for
|
||||||
// additional security.
|
// additional security.
|
||||||
bytes signature = 5;
|
bytes signature = 5;
|
||||||
}
|
}
|
||||||
`)
|
|
@ -3,13 +3,14 @@
|
|||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const uint8arraysConcat = require('uint8arrays/concat')
|
const uint8arraysConcat = require('uint8arrays/concat')
|
||||||
const uint8arraysFromString = require('uint8arrays/from-string')
|
const uint8arraysFromString = require('uint8arrays/from-string')
|
||||||
|
// @ts-ignore libp2p-crypto does not support types
|
||||||
const cryptoKeys = require('libp2p-crypto/src/keys')
|
const cryptoKeys = require('libp2p-crypto/src/keys')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const varint = require('varint')
|
const varint = require('varint')
|
||||||
const uint8arraysEquals = require('uint8arrays/equals')
|
const uint8arraysEquals = require('uint8arrays/equals')
|
||||||
|
|
||||||
const { codes } = require('../../errors')
|
const { codes } = require('../../errors')
|
||||||
const Protobuf = require('./envelope.proto')
|
const { Envelope: Protobuf } = require('./envelope')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||||
@ -49,12 +50,12 @@ class Envelope {
|
|||||||
|
|
||||||
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
|
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
|
||||||
|
|
||||||
this._marshal = Protobuf.Envelope.encode({
|
this._marshal = Protobuf.encode({
|
||||||
public_key: publicKey,
|
publicKey: publicKey,
|
||||||
payload_type: this.payloadType,
|
payloadType: this.payloadType,
|
||||||
payload: this.payload,
|
payload: this.payload,
|
||||||
signature: this.signature
|
signature: this.signature
|
||||||
})
|
}).finish()
|
||||||
|
|
||||||
return this._marshal
|
return this._marshal
|
||||||
}
|
}
|
||||||
@ -124,12 +125,12 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
|
|||||||
* @returns {Promise<Envelope>}
|
* @returns {Promise<Envelope>}
|
||||||
*/
|
*/
|
||||||
Envelope.createFromProtobuf = async (data) => {
|
Envelope.createFromProtobuf = async (data) => {
|
||||||
const envelopeData = Protobuf.Envelope.decode(data)
|
const envelopeData = Protobuf.decode(data)
|
||||||
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
const peerId = await PeerId.createFromPubKey(envelopeData.publicKey)
|
||||||
|
|
||||||
return new Envelope({
|
return new Envelope({
|
||||||
peerId,
|
peerId,
|
||||||
payloadType: envelopeData.payload_type,
|
payloadType: envelopeData.payloadType,
|
||||||
payload: envelopeData.payload,
|
payload: envelopeData.payload,
|
||||||
signature: envelopeData.signature
|
signature: envelopeData.signature
|
||||||
})
|
})
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multicodec = require('multicodec')
|
|
||||||
|
|
||||||
// The domain string used for peer records contained in a Envelope.
|
// The domain string used for peer records contained in a Envelope.
|
||||||
const domain = multicodec.getName(multicodec.LIBP2P_PEER_RECORD) || 'libp2p-peer-record'
|
const domain = 'libp2p-peer-record'
|
||||||
|
|
||||||
// The type hint used to identify peer records in a Envelope.
|
// The type hint used to identify peer records in a Envelope.
|
||||||
// Defined in https://github.com/multiformats/multicodec/blob/master/table.csv
|
// Defined in https://github.com/multiformats/multicodec/blob/master/table.csv
|
||||||
|
@ -1,18 +1,17 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const { Multiaddr } = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const arrayEquals = require('libp2p-utils/src/array-equals')
|
const arrayEquals = require('libp2p-utils/src/array-equals')
|
||||||
|
|
||||||
const Protobuf = require('./peer-record.proto')
|
const { PeerRecord: Protobuf } = require('./peer-record')
|
||||||
const {
|
const {
|
||||||
ENVELOPE_DOMAIN_PEER_RECORD,
|
ENVELOPE_DOMAIN_PEER_RECORD,
|
||||||
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
|
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
|
||||||
} = require('./consts')
|
} = require('./consts')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {import('peer-id')} PeerId
|
* @typedef {import('../../peer-store/address-book.js').Address} Address
|
||||||
* @typedef {import('multiaddr')} Multiaddr
|
|
||||||
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -52,13 +51,13 @@ class PeerRecord {
|
|||||||
return this._marshal
|
return this._marshal
|
||||||
}
|
}
|
||||||
|
|
||||||
this._marshal = Protobuf.PeerRecord.encode({
|
this._marshal = Protobuf.encode({
|
||||||
peer_id: this.peerId.toBytes(),
|
peerId: this.peerId.toBytes(),
|
||||||
seq: this.seqNumber,
|
seq: this.seqNumber,
|
||||||
addresses: this.multiaddrs.map((m) => ({
|
addresses: this.multiaddrs.map((m) => ({
|
||||||
multiaddr: m.bytes
|
multiaddr: m.bytes
|
||||||
}))
|
}))
|
||||||
})
|
}).finish()
|
||||||
|
|
||||||
return this._marshal
|
return this._marshal
|
||||||
}
|
}
|
||||||
@ -100,12 +99,11 @@ class PeerRecord {
|
|||||||
* @returns {PeerRecord}
|
* @returns {PeerRecord}
|
||||||
*/
|
*/
|
||||||
PeerRecord.createFromProtobuf = (buf) => {
|
PeerRecord.createFromProtobuf = (buf) => {
|
||||||
// Decode
|
const peerRecord = Protobuf.decode(buf)
|
||||||
const peerRecord = Protobuf.PeerRecord.decode(buf)
|
|
||||||
|
|
||||||
const peerId = PeerId.createFromBytes(peerRecord.peer_id)
|
const peerId = PeerId.createFromBytes(peerRecord.peerId)
|
||||||
const multiaddrs = (peerRecord.addresses || []).map((a) => multiaddr(a.multiaddr))
|
const multiaddrs = (peerRecord.addresses || []).map((a) => new Multiaddr(a.multiaddr))
|
||||||
const seqNumber = peerRecord.seq
|
const seqNumber = Number(peerRecord.seq)
|
||||||
|
|
||||||
return new PeerRecord({ peerId, multiaddrs, seqNumber })
|
return new PeerRecord({ peerId, multiaddrs, seqNumber })
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user