mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-16 00:51:57 +00:00
Compare commits
69 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
fc6558b897 | ||
|
3e302570e5 | ||
|
a34d2bbcc3 | ||
|
9941414a91 | ||
|
46cb46188a | ||
|
1af8472dc6 | ||
|
f6a4cad827 | ||
|
b1079474de | ||
|
a150ea60c5 | ||
|
aec8e3d3bb | ||
|
3abf4aeb35 | ||
|
a36b2112aa |
24
.aegir.js
24
.aegir.js
@@ -1,5 +1,6 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const Libp2p = require('./src')
|
||||
const { MULTIADDRS_WEBSOCKETS } = require('./test/fixtures/browser')
|
||||
const Peers = require('./test/fixtures/peers')
|
||||
@@ -47,16 +48,23 @@ const after = async () => {
|
||||
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 = {
|
||||
bundlesize: { maxSize: '215kB' },
|
||||
hooks: {
|
||||
pre: before,
|
||||
post: after
|
||||
build: {
|
||||
bundlesizeMax: '253kB'
|
||||
},
|
||||
webpack: {
|
||||
node: {
|
||||
// needed by bcrypto
|
||||
Buffer: true
|
||||
test: {
|
||||
before,
|
||||
after,
|
||||
browser: {
|
||||
config: {
|
||||
buildConfig: esbuild
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
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
|
78
.github/workflows/main.yml
vendored
78
.github/workflows/main.yml
vendored
@@ -12,11 +12,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: yarn lint
|
||||
- run: npm install
|
||||
- run: npx aegir lint
|
||||
- uses: gozala/typescript-error-reporter-action@v1.0.8
|
||||
- run: yarn build
|
||||
- run: yarn aegir dep-check
|
||||
- run: npx aegir build
|
||||
- run: npx aegir dep-check
|
||||
- uses: ipfs/aegir/actions/bundle-size@master
|
||||
name: size
|
||||
with:
|
||||
@@ -27,83 +27,41 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
node: [12, 14]
|
||||
node: [14]
|
||||
fail-fast: true
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
- run: yarn
|
||||
- run: npx nyc --reporter=lcov aegir test -t node -- --bail
|
||||
- run: npm install
|
||||
- run: npx aegir test -t node --cov --bail
|
||||
- uses: codecov/codecov-action@v1
|
||||
test-chrome:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: npm install
|
||||
- run: npx aegir test -t browser -t webworker --bail
|
||||
test-firefox:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: npx aegir test -t browser -t webworker --bail -- --browsers FirefoxHeadless
|
||||
- run: npm install
|
||||
- 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:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- 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
|
||||
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-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-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-pnet-example:
|
||||
needs: check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: yarn
|
||||
- run: cd examples && yarn && npm run test -- pnet
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@ docs
|
||||
test/repo-tests*
|
||||
**/bundle.js
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Logs
|
||||
logs
|
||||
|
135
CHANGELOG.md
135
CHANGELOG.md
@@ -1,3 +1,138 @@
|
||||
# [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)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* routers should only use dht if enabled ([#885](https://github.com/libp2p/js-libp2p/issues/885)) ([a34d2bb](https://github.com/libp2p/js-libp2p/commit/a34d2bbcc3d69ec3006137a909a7e8c53b9d378e))
|
||||
|
||||
|
||||
|
||||
## [0.30.7](https://github.com/libp2p/js-libp2p/compare/v0.30.6...v0.30.7) (2021-02-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not add observed address received from peers ([#882](https://github.com/libp2p/js-libp2p/issues/882)) ([a36b211](https://github.com/libp2p/js-libp2p/commit/a36b2112aafcee309a02de0cff5440cf69cd53a7))
|
||||
|
||||
|
||||
|
||||
## [0.30.6](https://github.com/libp2p/js-libp2p/compare/v0.30.5...v0.30.6) (2021-01-29)
|
||||
|
||||
|
||||
|
@@ -25,7 +25,6 @@
|
||||
- [ ] [js-ipfs](https://github.com/ipfs/js-ipfs)
|
||||
- Documentation
|
||||
- [ ] 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
|
||||
- Communication
|
||||
|
@@ -391,6 +391,7 @@ const Libp2p = require('libp2p')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
const { NOISE } = require('libp2p-noise')
|
||||
const ipfsHttpClient = require('ipfs-http-client')
|
||||
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
|
||||
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
|
||||
const PeerId = require('peer-id')
|
||||
@@ -398,17 +399,25 @@ const PeerId = require('peer-id')
|
||||
// create a peerId
|
||||
const peerId = await PeerId.create()
|
||||
|
||||
const delegatedPeerRouting = new DelegatedPeerRouter(ipfsHttpClient({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
}))
|
||||
|
||||
const delegatedContentRouting = new DelegatedContentRouter(peerId, ipfsHttpClient({
|
||||
host: 'node0.delegate.ipfs.io', // In production you should setup your own delegates
|
||||
protocol: 'https',
|
||||
port: 443
|
||||
}))
|
||||
|
||||
const node = await Libp2p.create({
|
||||
modules: {
|
||||
transport: [TCP],
|
||||
streamMuxer: [MPLEX],
|
||||
connEncryption: [NOISE],
|
||||
contentRouting: [
|
||||
new DelegatedContentRouter(peerId)
|
||||
],
|
||||
peerRouting: [
|
||||
new DelegatedPeerRouter()
|
||||
],
|
||||
contentRouting: [delegatedContentRouting],
|
||||
peerRouting: [delegatedPeerRouting],
|
||||
},
|
||||
peerId,
|
||||
peerRouting: { // Peer routing configuration
|
||||
@@ -590,7 +599,7 @@ const TCP = require('libp2p-tcp')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
const { NOISE } = require('libp2p-noise')
|
||||
|
||||
const { FaultTolerance } = require('libp2p/src/transport-manager')}
|
||||
const { FaultTolerance } = require('libp2p/src/transport-manager')
|
||||
|
||||
const node = await Libp2p.create({
|
||||
modules: {
|
||||
|
@@ -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)
|
||||
- [Protocol and Stream Muxing](./protocol-and-stream-muxing)
|
||||
- [Encrypted Communications](./encrypted-communications)
|
||||
- [Connection Encryption](./connection-encryption)
|
||||
- [Discovery Mechanisms](./discovery-mechanisms)
|
||||
- [Peer and Content Routing](./peer-and-content-routing)
|
||||
- [PubSub](./pubsub)
|
||||
|
68
examples/discovery-mechanisms/3.js
Normal file
68
examples/discovery-mechanisms/3.js
Normal file
@@ -0,0 +1,68 @@
|
||||
/* eslint-disable no-console */
|
||||
'use strict'
|
||||
|
||||
const Libp2p = require('../../')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const Mplex = require('libp2p-mplex')
|
||||
const { NOISE } = require('libp2p-noise')
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
|
||||
|
||||
const createRelayServer = require('libp2p-relay-server')
|
||||
|
||||
const createNode = async (bootstrapers) => {
|
||||
const node = await Libp2p.create({
|
||||
addresses: {
|
||||
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||
},
|
||||
modules: {
|
||||
transport: [TCP],
|
||||
streamMuxer: [Mplex],
|
||||
connEncryption: [NOISE],
|
||||
pubsub: Gossipsub,
|
||||
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
[PubsubPeerDiscovery.tag]: {
|
||||
interval: 1000,
|
||||
enabled: true
|
||||
},
|
||||
[Bootstrap.tag]: {
|
||||
enabled: true,
|
||||
list: bootstrapers
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
;(async () => {
|
||||
const relay = await createRelayServer({
|
||||
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
|
||||
})
|
||||
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
|
||||
await relay.start()
|
||||
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
|
||||
|
||||
const [node1, node2] = await Promise.all([
|
||||
createNode(relayMultiaddrs),
|
||||
createNode(relayMultiaddrs)
|
||||
])
|
||||
|
||||
node1.on('peer:discovery', (peerId) => {
|
||||
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
|
||||
})
|
||||
node2.on('peer:discovery', (peerId) => {
|
||||
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
|
||||
})
|
||||
|
||||
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
|
||||
await Promise.all([
|
||||
node1.start(),
|
||||
node2.start()
|
||||
])
|
||||
})();
|
@@ -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.
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
@@ -16,7 +16,7 @@ First, we create our libp2p node.
|
||||
const Libp2p = require('libp2p')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
|
||||
const node = Libp2p.create({
|
||||
const node = await Libp2p.create({
|
||||
modules: {
|
||||
transport: [ TCP ],
|
||||
streamMuxer: [ Mplex ],
|
||||
@@ -156,10 +156,103 @@ Discovered: QmSSbQpuKrxkoXHm1v4Pi35hPN5hUHMZoBoawEs2Nhvi8m
|
||||
Discovered: QmRcXXhtG8vTqwVBRonKWtV4ovDoC1Fe56WYtcrw694eiJ
|
||||
```
|
||||
|
||||
## 3. Where to find other Peer Discovery Mechanisms
|
||||
## 3. Pubsub based Peer Discovery
|
||||
|
||||
For this example, we need [`libp2p-pubsub-peer-discovery`](https://github.com/libp2p/js-libp2p-pubsub-peer-discovery/), go ahead and `npm install` it. You also need to spin up a set of [`libp2p-relay-servers`](https://github.com/libp2p/js-libp2p-relay-server). These servers act as relay servers and a peer discovery source.
|
||||
|
||||
In the context of this example, we will create and run the `libp2p-relay-server` in the same code snippet. You can find the complete solution at [3.js](./3.js).
|
||||
|
||||
You can create your libp2p nodes as follows:
|
||||
|
||||
```js
|
||||
const Libp2p = require('libp2p')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const Mplex = require('libp2p-mplex')
|
||||
const { NOISE } = require('libp2p-noise')
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const Bootstrap = require('libp2p-bootstrap')
|
||||
const PubsubPeerDiscovery = require('libp2p-pubsub-peer-discovery')
|
||||
|
||||
const createNode = async (bootstrapers) => {
|
||||
const node = await Libp2p.create({
|
||||
addresses: {
|
||||
listen: ['/ip4/0.0.0.0/tcp/0']
|
||||
},
|
||||
modules: {
|
||||
transport: [TCP],
|
||||
streamMuxer: [Mplex],
|
||||
connEncryption: [NOISE],
|
||||
pubsub: Gossipsub,
|
||||
peerDiscovery: [Bootstrap, PubsubPeerDiscovery]
|
||||
},
|
||||
config: {
|
||||
peerDiscovery: {
|
||||
[PubsubPeerDiscovery.tag]: {
|
||||
interval: 1000,
|
||||
enabled: true
|
||||
},
|
||||
[Bootstrap.tag]: {
|
||||
enabled: true,
|
||||
list: bootstrapers
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return node
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
const relay = await createRelayServer({
|
||||
listenAddresses: ['/ip4/0.0.0.0/tcp/0']
|
||||
})
|
||||
console.log(`libp2p relay starting with id: ${relay.peerId.toB58String()}`)
|
||||
await relay.start()
|
||||
const relayMultiaddrs = relay.multiaddrs.map((m) => `${m.toString()}/p2p/${relay.peerId.toB58String()}`)
|
||||
|
||||
const [node1, node2] = await Promise.all([
|
||||
createNode(relayMultiaddrs),
|
||||
createNode(relayMultiaddrs)
|
||||
])
|
||||
|
||||
node1.on('peer:discovery', (peerId) => {
|
||||
console.log(`Peer ${node1.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
|
||||
})
|
||||
node2.on('peer:discovery', (peerId) => {
|
||||
console.log(`Peer ${node2.peerId.toB58String()} discovered: ${peerId.toB58String()}`)
|
||||
})
|
||||
|
||||
;[node1, node2].forEach((node, index) => console.log(`Node ${index} starting with id: ${node.peerId.toB58String()}`))
|
||||
await Promise.all([
|
||||
node1.start(),
|
||||
node2.start()
|
||||
])
|
||||
```
|
||||
|
||||
If you run this example, you will see the other peers being discovered.
|
||||
|
||||
```bash
|
||||
> node 3.js
|
||||
libp2p relay starting with id: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
|
||||
Node 0 starting with id: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
|
||||
Node 1 starting with id: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
|
||||
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
|
||||
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmW6FqVV6RsyoGC5zaeFGW9gSWA3LcBRVZrjkKMruh38Bo
|
||||
Peer QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv discovered: QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N
|
||||
Peer QmezqDTmEjZ5BfMgVqjSpLY19mVVLTQ9bE9mRpZwtGxL8N discovered: QmYWeom2odTkm79DzB68NHULqVHDaNDqHhoyqLdcV1fqdv
|
||||
```
|
||||
|
||||
Taking into account the output, after the relay and both libp2p nodes start, both libp2p nodes will discover the bootstrap node (relay) and connect with it. After establishing a connection with the relay, they will discover each other.
|
||||
|
||||
This is really useful when running libp2p in constrained environments like a browser. You can run a set of `libp2p-relay-server` nodes that will be responsible for both relaying websocket connections between browser nodes and for discovering other browser peers.
|
||||
|
||||
## 4. Where to find other Peer Discovery Mechanisms
|
||||
|
||||
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.
|
||||
- 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!
|
||||
|
35
examples/discovery-mechanisms/test-3.js
Normal file
35
examples/discovery-mechanisms/test-3.js
Normal file
@@ -0,0 +1,35 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const discoveredCopy = 'discovered:'
|
||||
|
||||
async function test() {
|
||||
let discoverCount = 0
|
||||
|
||||
process.stdout.write('3.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '3.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
// Discovered or Connected
|
||||
if (line.includes(discoveredCopy)) {
|
||||
discoverCount++
|
||||
}
|
||||
})
|
||||
|
||||
await pWaitFor(() => discoverCount === 4)
|
||||
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
@@ -2,10 +2,12 @@
|
||||
|
||||
const test1 = require('./test-1')
|
||||
const test2 = require('./test-2')
|
||||
const test3 = require('./test-3')
|
||||
|
||||
async function test () {
|
||||
await test1()
|
||||
await test2()
|
||||
await test3()
|
||||
}
|
||||
|
||||
module.exports = test
|
||||
|
@@ -4,9 +4,13 @@ This example leverages the [Parcel.js bundler](https://parceljs.org/) to compile
|
||||
|
||||
## 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
|
||||
npm install
|
||||
```
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"name": "libp2p-in-browser",
|
||||
"version": "1.0.0",
|
||||
"description": "A libp2p node running in the browser",
|
||||
"main": "index.js",
|
||||
"main": "dist/index.html",
|
||||
"browserslist": [
|
||||
"last 2 Chrome versions"
|
||||
],
|
||||
@@ -15,20 +15,20 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/preset-env": "^7.8.3",
|
||||
"@babel/preset-env": "^7.13.0",
|
||||
"libp2p": "../../",
|
||||
"libp2p-bootstrap": "^0.12.1",
|
||||
"libp2p-mplex": "^0.10.0",
|
||||
"libp2p-noise": "^2.0.0",
|
||||
"libp2p-webrtc-star": "^0.20.0",
|
||||
"libp2p-websockets": "^0.14.0"
|
||||
"libp2p-webrtc-star": "^0.22.0",
|
||||
"libp2p-websockets": "^0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.3",
|
||||
"@babel/core": "^7.8.3",
|
||||
"@babel/cli": "^7.13.10",
|
||||
"@babel/core": "^7.13.0",
|
||||
"babel-plugin-syntax-async-functions": "^6.13.0",
|
||||
"babel-plugin-transform-regenerator": "^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()
|
||||
|
||||
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 {
|
||||
const browser = await chromium.launch();
|
||||
const page = await browser.newPage();
|
||||
|
@@ -10,6 +10,8 @@
|
||||
"dependencies": {
|
||||
"execa": "^2.1.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"libp2p-pubsub-peer-discovery": "^3.0.0",
|
||||
"libp2p-relay-server": "^0.1.2",
|
||||
"p-defer": "^3.0.0",
|
||||
"which": "^2.0.1"
|
||||
},
|
||||
|
36
examples/peer-and-content-routing/test-1.js
Normal file
36
examples/peer-and-content-routing/test-1.js
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
async function test() {
|
||||
process.stdout.write('1.js\n')
|
||||
|
||||
const addrs = []
|
||||
let foundIt = false
|
||||
const proc = execa('node', [path.join(__dirname, '1.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
// Discovered peer
|
||||
if (!foundIt && line.includes('Found it, multiaddrs are:')) {
|
||||
foundIt = true
|
||||
}
|
||||
|
||||
addrs.push(line)
|
||||
})
|
||||
|
||||
await pWaitFor(() => addrs.length === 2)
|
||||
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
40
examples/peer-and-content-routing/test-2.js
Normal file
40
examples/peer-and-content-routing/test-2.js
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pDefer = require('p-defer')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const providedCopy = 'is providing'
|
||||
const foundCopy = 'Found provider:'
|
||||
|
||||
async function test() {
|
||||
process.stdout.write('2.js\n')
|
||||
const providedDefer = pDefer()
|
||||
const foundDefer = pDefer()
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '2.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (line.includes(providedCopy)) {
|
||||
providedDefer.resolve()
|
||||
} else if (line.includes(foundCopy)) {
|
||||
foundDefer.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
providedDefer.promise,
|
||||
foundDefer.promise
|
||||
])
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
11
examples/peer-and-content-routing/test.js
Normal file
11
examples/peer-and-content-routing/test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const test1 = require('./test-1')
|
||||
const test2 = require('./test-2')
|
||||
|
||||
async function test() {
|
||||
await test1()
|
||||
await test2()
|
||||
}
|
||||
|
||||
module.exports = test
|
31
examples/protocol-and-stream-muxing/test-1.js
Normal file
31
examples/protocol-and-stream-muxing/test-1.js
Normal file
@@ -0,0 +1,31 @@
|
||||
'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 messageDefer = pDefer()
|
||||
process.stdout.write('1.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '1.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (line.includes('my own protocol, wow!')) {
|
||||
messageDefer.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await messageDefer.promise
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
38
examples/protocol-and-stream-muxing/test-2.js
Normal file
38
examples/protocol-and-stream-muxing/test-2.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const messages = [
|
||||
'protocol (a)',
|
||||
'protocol (b)',
|
||||
'another stream on protocol (b)'
|
||||
]
|
||||
|
||||
async function test() {
|
||||
process.stdout.write('2.js\n')
|
||||
|
||||
let count = 0
|
||||
const proc = execa('node', [path.join(__dirname, '2.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (messages.find((m) => line.includes(m))) {
|
||||
count += 1
|
||||
}
|
||||
})
|
||||
|
||||
await pWaitFor(() => count === messages.length)
|
||||
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
37
examples/protocol-and-stream-muxing/test-3.js
Normal file
37
examples/protocol-and-stream-muxing/test-3.js
Normal file
@@ -0,0 +1,37 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pWaitFor = require('p-wait-for')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const messages = [
|
||||
'from 1 to 2',
|
||||
'from 2 to 1'
|
||||
]
|
||||
|
||||
async function test() {
|
||||
process.stdout.write('3.js\n')
|
||||
|
||||
let count = 0
|
||||
const proc = execa('node', [path.join(__dirname, '3.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (messages.find((m) => line.includes(m))) {
|
||||
count += 1
|
||||
}
|
||||
})
|
||||
|
||||
await pWaitFor(() => count === messages.length)
|
||||
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
13
examples/protocol-and-stream-muxing/test.js
Normal file
13
examples/protocol-and-stream-muxing/test.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
const test1 = require('./test-1')
|
||||
const test2 = require('./test-2')
|
||||
const test3 = require('./test-3')
|
||||
|
||||
async function test() {
|
||||
await test1()
|
||||
await test2()
|
||||
await test3()
|
||||
}
|
||||
|
||||
module.exports = test
|
67
examples/pubsub/message-filtering/test.js
Normal file
67
examples/pubsub/message-filtering/test.js
Normal file
@@ -0,0 +1,67 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
const execa = require('execa')
|
||||
const pDefer = require('p-defer')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const stdout = [
|
||||
{
|
||||
topic: 'banana',
|
||||
messageCount: 2
|
||||
},
|
||||
{
|
||||
topic: 'apple',
|
||||
messageCount: 2
|
||||
},
|
||||
{
|
||||
topic: 'car',
|
||||
messageCount: 0
|
||||
},
|
||||
{
|
||||
topic: 'orange',
|
||||
messageCount: 2
|
||||
},
|
||||
]
|
||||
|
||||
async function test () {
|
||||
const defer = pDefer()
|
||||
let topicCount = 0
|
||||
let topicMessageCount = 0
|
||||
|
||||
process.stdout.write('message-filtering/1.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '1.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
// End
|
||||
if (topicCount === stdout.length) {
|
||||
defer.resolve()
|
||||
proc.all.removeAllListeners('data')
|
||||
}
|
||||
|
||||
process.stdout.write(data)
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (stdout[topicCount] && line.includes(stdout[topicCount].topic)) {
|
||||
// Validate previous number of messages
|
||||
if (topicCount > 0 && topicMessageCount > stdout[topicCount - 1].messageCount) {
|
||||
defer.reject()
|
||||
throw new Error(`topic ${stdout[topicCount - 1].topic} had ${topicMessageCount} messages instead of ${stdout[topicCount - 1].messageCount}`)
|
||||
}
|
||||
|
||||
topicCount++
|
||||
topicMessageCount = 0
|
||||
} else {
|
||||
topicMessageCount++
|
||||
}
|
||||
})
|
||||
|
||||
await defer.promise
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
30
examples/pubsub/test-1.js
Normal file
30
examples/pubsub/test-1.js
Normal file
@@ -0,0 +1,30 @@
|
||||
'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 defer = pDefer()
|
||||
process.stdout.write('1.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '1.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (line.includes('node1 received: Bird bird bird, bird is the word!')) {
|
||||
defer.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await defer.promise
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
11
examples/pubsub/test.js
Normal file
11
examples/pubsub/test.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const test1 = require('./test-1')
|
||||
const testMessageFiltering = require('./message-filtering/test')
|
||||
|
||||
async function test() {
|
||||
await test1()
|
||||
await testMessageFiltering()
|
||||
}
|
||||
|
||||
module.exports = test
|
38
examples/transports/test-1.js
Normal file
38
examples/transports/test-1.js
Normal file
@@ -0,0 +1,38 @@
|
||||
'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 deferStarted = pDefer()
|
||||
const deferListen = pDefer()
|
||||
|
||||
process.stdout.write('1.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '1.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 has started (true/false): true')) {
|
||||
deferStarted.resolve()
|
||||
} else if (line.includes('p2p')) {
|
||||
deferListen.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
deferStarted.promise,
|
||||
deferListen.promise
|
||||
])
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
30
examples/transports/test-2.js
Normal file
30
examples/transports/test-2.js
Normal file
@@ -0,0 +1,30 @@
|
||||
'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 defer = pDefer()
|
||||
process.stdout.write('2.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '2.js')], {
|
||||
cwd: path.resolve(__dirname),
|
||||
all: true
|
||||
})
|
||||
|
||||
proc.all.on('data', async (data) => {
|
||||
process.stdout.write(data)
|
||||
const line = uint8ArrayToString(data)
|
||||
|
||||
if (line.includes('Hello p2p world!')) {
|
||||
defer.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await defer.promise
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
41
examples/transports/test-3.js
Normal file
41
examples/transports/test-3.js
Normal file
@@ -0,0 +1,41 @@
|
||||
'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()
|
||||
const deferNode2 = pDefer()
|
||||
const deferNode3 = pDefer()
|
||||
|
||||
process.stdout.write('3.js\n')
|
||||
|
||||
const proc = execa('node', [path.join(__dirname, '3.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 1 dialed to node 2 successfully')) {
|
||||
deferNode1.resolve()
|
||||
} else if (line.includes('node 2 dialed to node 3 successfully')) {
|
||||
deferNode2.resolve()
|
||||
} else if (line.includes('node 3 failed to dial to node 1 with:')) {
|
||||
deferNode3.resolve()
|
||||
}
|
||||
})
|
||||
|
||||
await Promise.all([
|
||||
deferNode1.promise,
|
||||
deferNode2.promise,
|
||||
deferNode3.promise
|
||||
])
|
||||
proc.kill()
|
||||
}
|
||||
|
||||
module.exports = test
|
13
examples/transports/test.js
Normal file
13
examples/transports/test.js
Normal file
@@ -0,0 +1,13 @@
|
||||
'use strict'
|
||||
|
||||
const test1 = require('./test-1')
|
||||
const test2 = require('./test-2')
|
||||
const test3 = require('./test-3')
|
||||
|
||||
async function test() {
|
||||
await test1()
|
||||
await test2()
|
||||
await test3()
|
||||
}
|
||||
|
||||
module.exports = test
|
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.12.1",
|
||||
"libp2p-mplex": "^0.10.1",
|
||||
"libp2p-noise": "^2.0.1",
|
||||
"libp2p-webrtc-direct": "^0.6.0",
|
||||
"peer-id": "^0.14.3"
|
||||
},
|
||||
"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
|
174
package.json
174
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libp2p",
|
||||
"version": "0.30.6",
|
||||
"version": "0.31.0",
|
||||
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||
"main": "src/index.js",
|
||||
@@ -20,10 +20,28 @@
|
||||
"scripts": {
|
||||
"lint": "aegir lint",
|
||||
"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:browser": "aegir test -t browser",
|
||||
"test:examples": "cd examples && npm run test:all",
|
||||
"prepare": "aegir build --no-bundle",
|
||||
"release": "aegir release -t node -t browser",
|
||||
"release-minor": "aegir release --type minor -t node -t browser",
|
||||
"release-major": "aegir release --type major -t node -t browser",
|
||||
@@ -47,12 +65,18 @@
|
||||
"homepage": "https://libp2p.io",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0",
|
||||
"npm": ">=6.0.0"
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"browser": {
|
||||
"@motrix/nat-api": false
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "ipfs",
|
||||
"ignorePatterns": [
|
||||
"!.aegir.js",
|
||||
"test/ts-use"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@motrix/nat-api": "^0.3.1",
|
||||
"abort-controller": "^3.0.0",
|
||||
@@ -62,137 +86,143 @@
|
||||
"cids": "^1.1.5",
|
||||
"class-is": "^1.1.0",
|
||||
"debug": "^4.3.1",
|
||||
"err-code": "^2.0.0",
|
||||
"events": "^3.2.0",
|
||||
"err-code": "^3.0.0",
|
||||
"es6-promisify": "^6.1.1",
|
||||
"events": "^3.3.0",
|
||||
"hashlru": "^2.3.0",
|
||||
"interface-datastore": "^3.0.3",
|
||||
"interface-datastore": "^4.0.0",
|
||||
"ipfs-utils": "^6.0.0",
|
||||
"it-all": "^1.0.4",
|
||||
"it-buffer": "^0.1.2",
|
||||
"it-drain": "^1.0.3",
|
||||
"it-filter": "^1.0.1",
|
||||
"it-first": "^1.0.4",
|
||||
"it-handshake": "^1.0.2",
|
||||
"it-length-prefixed": "^3.1.0",
|
||||
"it-handshake": "^2.0.0",
|
||||
"it-length-prefixed": "^5.0.2",
|
||||
"it-map": "^1.0.4",
|
||||
"it-merge": "1.0.0",
|
||||
"it-pipe": "^1.1.0",
|
||||
"it-protocol-buffers": "^0.2.0",
|
||||
"it-take": "1.0.0",
|
||||
"libp2p-crypto": "^0.19.0",
|
||||
"libp2p-interfaces": "^0.8.1",
|
||||
"libp2p-utils": "^0.2.2",
|
||||
"mafmt": "^8.0.0",
|
||||
"libp2p-interfaces": "^0.10.3",
|
||||
"libp2p-utils": "^0.3.1",
|
||||
"mafmt": "^9.0.0",
|
||||
"merge-options": "^3.0.4",
|
||||
"moving-average": "^1.0.0",
|
||||
"multiaddr": "^8.1.0",
|
||||
"multicodec": "^2.1.0",
|
||||
"multihashing-async": "^2.0.1",
|
||||
"multistream-select": "^1.0.0",
|
||||
"multiaddr": "^9.0.1",
|
||||
"multicodec": "^3.0.1",
|
||||
"multihashing-async": "^2.1.2",
|
||||
"multistream-select": "^2.0.0",
|
||||
"mutable-proxy": "^1.0.0",
|
||||
"node-forge": "^0.10.0",
|
||||
"p-any": "^3.0.0",
|
||||
"p-fifo": "^1.0.0",
|
||||
"p-retry": "^4.2.0",
|
||||
"p-settle": "^4.0.1",
|
||||
"p-retry": "^4.4.0",
|
||||
"p-settle": "^4.1.1",
|
||||
"peer-id": "^0.14.2",
|
||||
"private-ip": "^2.0.0",
|
||||
"promisify-es6": "^1.0.3",
|
||||
"protons": "^2.0.0",
|
||||
"retimer": "^2.0.0",
|
||||
"private-ip": "^2.1.0",
|
||||
"protobufjs": "^6.10.2",
|
||||
"retimer": "^3.0.0",
|
||||
"sanitize-filename": "^1.6.3",
|
||||
"set-delayed-interval": "^1.0.0",
|
||||
"streaming-iterables": "^5.0.2",
|
||||
"timeout-abort-controller": "^1.1.1",
|
||||
"varint": "^6.0.0",
|
||||
"xsalsa20": "^1.0.2"
|
||||
"xsalsa20": "^1.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nodeutils/defaults-deep": "^1.1.0",
|
||||
"@types/es6-promisify": "^6.0.0",
|
||||
"@types/node-forge": "^0.9.7",
|
||||
"@types/varint": "^6.0.0",
|
||||
"abortable-iterator": "^3.0.0",
|
||||
"aegir": "^29.2.0",
|
||||
"chai-bytes": "^0.1.2",
|
||||
"chai-string": "^1.5.0",
|
||||
"delay": "^4.4.0",
|
||||
"aegir": "^33.1.1",
|
||||
"buffer": "^6.0.3",
|
||||
"delay": "^5.0.0",
|
||||
"interop-libp2p": "^0.3.0",
|
||||
"into-stream": "^6.0.0",
|
||||
"ipfs-http-client": "^48.2.2",
|
||||
"ipfs-http-client": "^49.0.4",
|
||||
"it-concat": "^1.0.0",
|
||||
"it-pair": "^1.0.0",
|
||||
"it-pushable": "^1.4.0",
|
||||
"libp2p": ".",
|
||||
"libp2p-bootstrap": "^0.12.0",
|
||||
"libp2p-delegated-content-routing": "^0.9.0",
|
||||
"libp2p-delegated-peer-routing": "^0.8.0",
|
||||
"libp2p-floodsub": "^0.24.0",
|
||||
"libp2p-bootstrap": "^0.12.3",
|
||||
"libp2p-delegated-content-routing": "^0.10.0",
|
||||
"libp2p-delegated-peer-routing": "^0.9.0",
|
||||
"libp2p-floodsub": "^0.25.0",
|
||||
"libp2p-gossipsub": "^0.8.0",
|
||||
"libp2p-kad-dht": "^0.20.5",
|
||||
"libp2p-mdns": "^0.15.0",
|
||||
"libp2p-kad-dht": "^0.21.0",
|
||||
"libp2p-mdns": "^0.16.0",
|
||||
"libp2p-mplex": "^0.10.1",
|
||||
"libp2p-noise": "^2.0.0",
|
||||
"libp2p-secio": "^0.13.1",
|
||||
"libp2p-noise": "^3.0.0",
|
||||
"libp2p-tcp": "^0.15.1",
|
||||
"libp2p-webrtc-star": "^0.20.0",
|
||||
"libp2p-webrtc-star": "^0.22.0",
|
||||
"libp2p-websockets": "^0.15.0",
|
||||
"multihashes": "^3.0.1",
|
||||
"multihashes": "^4.0.2",
|
||||
"nock": "^13.0.3",
|
||||
"p-defer": "^3.0.0",
|
||||
"p-times": "^3.0.0",
|
||||
"p-wait-for": "^3.2.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"sinon": "^9.2.4",
|
||||
"uint8arrays": "^2.0.5"
|
||||
"sinon": "^10.0.0",
|
||||
"uint8arrays": "^2.1.3",
|
||||
"util": "^0.12.3"
|
||||
},
|
||||
"contributors": [
|
||||
"David Dias <daviddias.p@gmail.com>",
|
||||
"Jacob Heun <jacobheun@gmail.com>",
|
||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||
"Alan Shaw <alan@tableflip.io>",
|
||||
"Jacob Heun <jacobheun@gmail.com>",
|
||||
"Alex Potsides <alex@achingbrain.net>",
|
||||
"Alan Shaw <alan@tableflip.io>",
|
||||
"Cayman <caymannava@gmail.com>",
|
||||
"Pedro Teixeira <i@pgte.me>",
|
||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"Maciej Krüger <mkg20001@gmail.com>",
|
||||
"Hugo Dias <mail@hugodias.me>",
|
||||
"Volker Mische <volker.mische@gmail.com>",
|
||||
"dirkmc <dirkmdev@gmail.com>",
|
||||
"Volker Mische <volker.mische@gmail.com>",
|
||||
"Richard Littauer <richard.littauer@gmail.com>",
|
||||
"a1300 <matthias-knopp@gmx.net>",
|
||||
"Ryan Bell <ryan@piing.net>",
|
||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||
"Elven <mon.samuel@qq.com>",
|
||||
"Giovanni T. Parra <fiatjaf@gmail.com>",
|
||||
"Samlior <samlior@foxmail.com>",
|
||||
"Thomas Eizinger <thomas@eizinger.io>",
|
||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||
"Didrik Nordström <didrik@betamos.se>",
|
||||
"Thomas Eizinger <thomas@eizinger.io>",
|
||||
"Samlior <samlior@foxmail.com>",
|
||||
"Ryan Bell <ryan@piing.net>",
|
||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||
"Didrik Nordström <didrik.nordstrom@gmail.com>",
|
||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||
"Philipp Muens <raute1337@gmx.de>",
|
||||
"Smite Chow <xiaopengyou@live.com>",
|
||||
"Soeren <nikorpoulsen@gmail.com>",
|
||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||
"TJKoury <TJKoury@gmail.com>",
|
||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||
"Yusef Napora <yusef@napora.org>",
|
||||
"Zane Starr <zcstarr@gmail.com>",
|
||||
"ebinks <elizabethjbinks@gmail.com>",
|
||||
"isan_rivkin <isanrivkin@gmail.com>",
|
||||
"robertkiel <robert.kiel@validitylabs.org>",
|
||||
"RasmusErik Voel Jensen <github@solsort.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>",
|
||||
"Florian-Merle <florian.david.merle@gmail.com>",
|
||||
"Francis Gulotta <wizard@roborooter.com>",
|
||||
"Franck Royer <franck@royer.one>",
|
||||
"Henrique Dias <hacdias@gmail.com>",
|
||||
"Irakli Gozalishvili <rfobic@gmail.com>",
|
||||
"Joel Gustafson <joelg@mit.edu>",
|
||||
"Julien Bouquillon <contact@revolunet.com>",
|
||||
"Kevin Kwok <antimatter15@gmail.com>",
|
||||
"Kevin Lacker <lacker@gmail.com>",
|
||||
"Ethan Lam <elmemphis2000@gmail.com>",
|
||||
"Nuno Nogueira <nunofmn@gmail.com>",
|
||||
"Dmitriy Ryajov <dryajov@gmail.com>",
|
||||
"RasmusErik Voel Jensen <github@solsort.com>",
|
||||
"Diogo Silva <fsdiogo@gmail.com>",
|
||||
"Smite Chow <xiaopengyou@live.com>",
|
||||
"Soeren <nikorpoulsen@gmail.com>",
|
||||
"Sönke Hahn <soenkehahn@gmail.com>",
|
||||
"Tiago Alves <alvesjtiago@gmail.com>",
|
||||
"Daijiro Wachi <daijiro.wachi@gmail.com>",
|
||||
"Yusef Napora <yusef@napora.org>",
|
||||
"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>",
|
||||
"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>",
|
||||
"Felipe Martins <felipebrasil93@gmail.com>",
|
||||
"Fei Liu <liu.feiwood@gmail.com>"
|
||||
"Miguel Mota <miguelmota2@gmail.com>"
|
||||
]
|
||||
}
|
||||
|
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'
|
||||
|
||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} AddressManagerOptions
|
||||
* @property {string[]} [listen = []] - list of multiaddrs string representation to listen.
|
||||
@@ -47,7 +41,7 @@ class AddressManager extends EventEmitter {
|
||||
* @returns {Multiaddr[]}
|
||||
*/
|
||||
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[]}
|
||||
*/
|
||||
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>}
|
||||
*/
|
||||
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
|
||||
*/
|
||||
addObservedAddr (addr) {
|
||||
let ma = multiaddr(addr)
|
||||
let ma = new Multiaddr(addr)
|
||||
const remotePeer = ma.getPeerId()
|
||||
|
||||
// strip our peer id if it has been passed
|
||||
@@ -83,7 +77,7 @@ class AddressManager extends EventEmitter {
|
||||
|
||||
// use same encoding for comparison
|
||||
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:
|
||||
|
||||
```js
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const Libp2p = require('libp2p')
|
||||
const TCP = require('libp2p-tcp')
|
||||
const MPLEX = require('libp2p-mplex')
|
||||
@@ -47,7 +47,7 @@ const relayAddr = ...
|
||||
|
||||
const node = await Libp2p.create({
|
||||
addresses: {
|
||||
listen: [multiaddr(`${relayAddr}/p2p-circuit`)]
|
||||
listen: [new Multiaddr(`${relayAddr}/p2p-circuit`)]
|
||||
},
|
||||
modules: {
|
||||
transport: [TCP],
|
||||
|
@@ -7,7 +7,7 @@ const log = Object.assign(debug('libp2p:auto-relay'), {
|
||||
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
const { relay: multicodec } = require('./multicodec')
|
||||
@@ -31,6 +31,7 @@ const {
|
||||
*
|
||||
* @typedef {Object} AutoRelayOptions
|
||||
* @property {number} [maxListeners = 1] - maximum number of relays to listen.
|
||||
* @property {(error: Error, msg?: string) => {}} [onError]
|
||||
*/
|
||||
|
||||
class AutoRelay {
|
||||
@@ -40,7 +41,7 @@ class AutoRelay {
|
||||
* @class
|
||||
* @param {AutoRelayProperties & AutoRelayOptions} props
|
||||
*/
|
||||
constructor ({ libp2p, maxListeners = 1 }) {
|
||||
constructor ({ libp2p, maxListeners = 1, onError }) {
|
||||
this._libp2p = libp2p
|
||||
this._peerId = libp2p.peerId
|
||||
this._peerStore = libp2p.peerStore
|
||||
@@ -60,6 +61,15 @@ class AutoRelay {
|
||||
|
||||
this._peerStore.on('change:protocols', this._onProtocolChange)
|
||||
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)
|
||||
}
|
||||
} catch (err) {
|
||||
log.error(err)
|
||||
this._onError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,10 +167,10 @@ class AutoRelay {
|
||||
|
||||
// Attempt to listen on relay
|
||||
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
|
||||
} catch (err) {
|
||||
log.error(err)
|
||||
this._onError(err)
|
||||
this._listenRelays.delete(id)
|
||||
}
|
||||
}
|
||||
@@ -231,8 +241,7 @@ class AutoRelay {
|
||||
|
||||
// Try to listen on known peers that are not connected
|
||||
for (const peerId of knownHopsToDial) {
|
||||
const connection = await this._libp2p.dial(peerId)
|
||||
await this._addListenRelay(connection, peerId.toB58String())
|
||||
await this._tryToListenOnRelay(peerId)
|
||||
|
||||
// Check if already listening on enough relays
|
||||
if (this._listenRelays.size >= this.maxListeners) {
|
||||
@@ -247,12 +256,11 @@ class AutoRelay {
|
||||
if (!provider.multiaddrs.length) {
|
||||
continue
|
||||
}
|
||||
|
||||
const peerId = provider.id
|
||||
|
||||
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
|
||||
if (this._listenRelays.size >= this.maxListeners) {
|
||||
@@ -260,7 +268,19 @@ class AutoRelay {
|
||||
}
|
||||
}
|
||||
} 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')
|
||||
|
||||
/**
|
||||
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
||||
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||
* @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 {Object} HopRequest
|
||||
* @property {Connection} connection
|
||||
* @property {CircuitRequest} request
|
||||
* @property {StreamHandlerT} streamHandler
|
||||
* @property {ICircuitRelay} request
|
||||
* @property {StreamHandler} streamHandler
|
||||
* @property {Transport} circuit
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,11 @@ async function handleHop ({
|
||||
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
|
||||
const destinationPeer = new PeerId(request.dstPeer.id)
|
||||
|
||||
@@ -113,8 +118,8 @@ async function handleHop ({
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {Connection} options.connection - Connection to the relay
|
||||
* @param {CircuitRequest} options.request
|
||||
* @returns {Promise<Connection>}
|
||||
* @param {ICircuitRelay} options.request
|
||||
* @returns {Promise<MuxedStream>}
|
||||
*/
|
||||
async function hop ({
|
||||
connection,
|
||||
@@ -128,6 +133,10 @@ async function hop ({
|
||||
|
||||
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) {
|
||||
log('hop request was successful')
|
||||
return streamHandler.rest()
|
||||
@@ -159,7 +168,7 @@ async function canHop ({
|
||||
const response = await streamHandler.read()
|
||||
await streamHandler.close()
|
||||
|
||||
if (response.code !== CircuitPB.Status.SUCCESS) {
|
||||
if (!response || response.code !== CircuitPB.Status.SUCCESS) {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -171,7 +180,7 @@ async function canHop ({
|
||||
*
|
||||
* @param {Object} options
|
||||
* @param {Connection} options.connection
|
||||
* @param {StreamHandlerT} options.streamHandler
|
||||
* @param {StreamHandler} options.streamHandler
|
||||
* @param {Transport} options.circuit
|
||||
* @private
|
||||
*/
|
||||
|
@@ -13,8 +13,7 @@ const { validateAddrs } = require('./utils')
|
||||
/**
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
||||
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
|
||||
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -23,8 +22,8 @@ const { validateAddrs } = require('./utils')
|
||||
* @private
|
||||
* @param {Object} options
|
||||
* @param {Connection} options.connection
|
||||
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
|
||||
* @param {StreamHandlerT} options.streamHandler
|
||||
* @param {ICircuitRelay} options.request - The CircuitRelay protobuf request (unencoded)
|
||||
* @param {StreamHandler} options.streamHandler
|
||||
* @returns {Promise<MuxedStream>|void} Resolves a duplex iterable
|
||||
*/
|
||||
module.exports.handleStop = function handleStop ({
|
||||
@@ -54,7 +53,7 @@ module.exports.handleStop = function handleStop ({
|
||||
* @private
|
||||
* @param {Object} options
|
||||
* @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
|
||||
*/
|
||||
module.exports.stop = async function stop ({
|
||||
@@ -68,6 +67,10 @@ module.exports.stop = async function stop ({
|
||||
streamHandler.write(request)
|
||||
const response = await streamHandler.read()
|
||||
|
||||
if (!response) {
|
||||
return streamHandler.close()
|
||||
}
|
||||
|
||||
if (response.code === CircuitPB.Status.SUCCESS) {
|
||||
log('stop request to %s was successful', connection.remotePeer.toB58String())
|
||||
return streamHandler.rest()
|
||||
|
@@ -6,16 +6,15 @@ const log = Object.assign(debug('libp2p:circuit:stream-handler'), {
|
||||
})
|
||||
|
||||
const lp = require('it-length-prefixed')
|
||||
// @ts-ignore it-handshake does not export types
|
||||
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('../protocol').ICircuitRelay} ICircuitRelay
|
||||
*/
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*/
|
||||
class StreamHandler {
|
||||
/**
|
||||
* Create a stream handler for connection
|
||||
@@ -29,6 +28,7 @@ class StreamHandler {
|
||||
this.stream = stream
|
||||
|
||||
this.shake = handshake(this.stream)
|
||||
// @ts-ignore options are not optional
|
||||
this.decoder = lp.decode.fromReader(this.shake.reader, { maxDataLength: maxLength })
|
||||
}
|
||||
|
||||
@@ -36,12 +36,11 @@ class StreamHandler {
|
||||
* Read and decode message
|
||||
*
|
||||
* @async
|
||||
* @returns {Promise<T|undefined>}
|
||||
*/
|
||||
async read () {
|
||||
const msg = await this.decoder.next()
|
||||
if (msg.value) {
|
||||
const value = CircuitPB.decode(msg.value.slice())
|
||||
const value = CircuitRelay.decode(msg.value.slice())
|
||||
log('read message type', value.type)
|
||||
return value
|
||||
}
|
||||
@@ -54,13 +53,13 @@ class StreamHandler {
|
||||
/**
|
||||
* Encode and write array of buffers
|
||||
*
|
||||
* @param {CircuitPB} msg - An unencoded CircuitRelay protobuf message
|
||||
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
|
||||
* @returns {void}
|
||||
*/
|
||||
write (msg) {
|
||||
log('write message type %s', msg.type)
|
||||
// @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
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
|
||||
*/
|
||||
end (msg) {
|
||||
this.write(msg)
|
||||
this.close()
|
||||
|
@@ -1,18 +1,18 @@
|
||||
'use strict'
|
||||
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const { CircuitRelay } = require('../protocol')
|
||||
|
||||
/**
|
||||
* @typedef {import('./stream-handler')} StreamHandler
|
||||
* @typedef {import('../../types').CircuitStatus} CircuitStatus
|
||||
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
|
||||
*/
|
||||
|
||||
/**
|
||||
* Write a response
|
||||
*
|
||||
* @param {StreamHandler} streamHandler
|
||||
* @param {CircuitStatus} status
|
||||
* @param {import('../protocol').CircuitRelay.Status} status
|
||||
*/
|
||||
function writeResponse (streamHandler, status) {
|
||||
streamHandler.write({
|
||||
@@ -24,14 +24,16 @@ function writeResponse (streamHandler, status) {
|
||||
/**
|
||||
* Validate incomming HOP/STOP message
|
||||
*
|
||||
* @param {*} msg - A CircuitRelay unencoded protobuf message
|
||||
* @param {ICircuitRelay} msg - A CircuitRelay unencoded protobuf message
|
||||
* @param {StreamHandler} streamHandler
|
||||
*/
|
||||
function validateAddrs (msg, streamHandler) {
|
||||
try {
|
||||
msg.dstPeer.addrs.forEach((addr) => {
|
||||
return multiaddr(addr)
|
||||
})
|
||||
if (msg.dstPeer && msg.dstPeer.addrs) {
|
||||
msg.dstPeer.addrs.forEach((addr) => {
|
||||
return new Multiaddr(addr)
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
||||
? CircuitRelay.Status.HOP_DST_MULTIADDR_INVALID
|
||||
@@ -40,9 +42,11 @@ function validateAddrs (msg, streamHandler) {
|
||||
}
|
||||
|
||||
try {
|
||||
msg.srcPeer.addrs.forEach((addr) => {
|
||||
return multiaddr(addr)
|
||||
})
|
||||
if (msg.srcPeer && msg.srcPeer.addrs) {
|
||||
msg.srcPeer.addrs.forEach((addr) => {
|
||||
return new Multiaddr(addr)
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
|
||||
? CircuitRelay.Status.HOP_SRC_MULTIADDR_INVALID
|
||||
|
@@ -8,13 +8,12 @@ const log = Object.assign(debug('libp2p:relay'), {
|
||||
const {
|
||||
setDelayedInterval,
|
||||
clearDelayedInterval
|
||||
// @ts-ignore set-delayed-interval does not export types
|
||||
} = require('set-delayed-interval')
|
||||
|
||||
const AutoRelay = require('./auto-relay')
|
||||
const { namespaceToCid } = require('./utils')
|
||||
const {
|
||||
ADVERTISE_BOOT_DELAY,
|
||||
ADVERTISE_TTL,
|
||||
RELAY_RENDEZVOUS_NS
|
||||
} = require('./constants')
|
||||
|
||||
@@ -45,12 +44,6 @@ class Relay {
|
||||
constructor (libp2p) {
|
||||
this._libp2p = libp2p
|
||||
this._options = {
|
||||
advertise: {
|
||||
bootDelay: ADVERTISE_BOOT_DELAY,
|
||||
enabled: true,
|
||||
ttl: ADVERTISE_TTL,
|
||||
...libp2p._config.relay.advertise
|
||||
},
|
||||
...libp2p._config.relay
|
||||
}
|
||||
|
||||
|
@@ -1,10 +1,9 @@
|
||||
'use strict'
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
@@ -24,7 +23,7 @@ module.exports = (libp2p) => {
|
||||
async function listen (addr) {
|
||||
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')
|
||||
|
||||
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'
|
||||
const protobuf = require('protons')
|
||||
/*eslint-disable*/
|
||||
"use strict";
|
||||
|
||||
/** @type {{CircuitRelay: import('../../types').CircuitMessageProto}} */
|
||||
module.exports = protobuf(`
|
||||
message CircuitRelay {
|
||||
var $protobuf = require("protobufjs/minimal");
|
||||
|
||||
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;
|
||||
}
|
||||
// Common aliases
|
||||
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||
|
||||
enum Type { // RPC identifier, either HOP, STOP or STATUS
|
||||
HOP = 1;
|
||||
STOP = 2;
|
||||
STATUS = 3;
|
||||
CAN_HOP = 4;
|
||||
}
|
||||
// Exported root namespace
|
||||
var $root = $protobuf.roots["libp2p-circuit"] || ($protobuf.roots["libp2p-circuit"] = {});
|
||||
|
||||
message Peer {
|
||||
required bytes id = 1; // peer id
|
||||
repeated bytes addrs = 2; // peer's known addresses
|
||||
}
|
||||
$root.CircuitRelay = (function() {
|
||||
|
||||
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')
|
||||
})
|
||||
|
||||
const errCode = require('err-code')
|
||||
const mafmt = require('mafmt')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
const { CircuitRelay: CircuitPB } = require('./protocol')
|
||||
const { codes } = require('../errors')
|
||||
|
||||
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')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||
* @typedef {import('../types').CircuitRequest} CircuitRequest
|
||||
*/
|
||||
|
||||
class Circuit {
|
||||
@@ -54,7 +54,7 @@ class Circuit {
|
||||
* @param {MuxedStream} props.stream
|
||||
*/
|
||||
async _onProtocol ({ connection, stream }) {
|
||||
/** @type {import('./circuit/stream-handler')<CircuitRequest>} */
|
||||
/** @type {import('./circuit/stream-handler')} */
|
||||
const streamHandler = new StreamHandler({ stream })
|
||||
const request = await streamHandler.read()
|
||||
|
||||
@@ -96,8 +96,10 @@ class Circuit {
|
||||
}
|
||||
|
||||
if (virtualConnection) {
|
||||
const remoteAddr = multiaddr(request.dstPeer.addrs[0])
|
||||
const localAddr = multiaddr(request.srcPeer.addrs[0])
|
||||
// @ts-ignore dst peer will not be undefined
|
||||
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({
|
||||
stream: virtualConnection,
|
||||
remoteAddr,
|
||||
@@ -123,10 +125,19 @@ class Circuit {
|
||||
async dial (ma, options) {
|
||||
// Check the multiaddr to see if it contains a relay and a destination peer
|
||||
const addrs = ma.toString().split('/p2p-circuit')
|
||||
const relayAddr = multiaddr(addrs[0])
|
||||
const destinationAddr = multiaddr(addrs[addrs.length - 1])
|
||||
const relayPeer = PeerId.createFromCID(relayAddr.getPeerId())
|
||||
const destinationPeer = PeerId.createFromCID(destinationAddr.getPeerId())
|
||||
const relayAddr = new Multiaddr(addrs[0])
|
||||
const destinationAddr = new Multiaddr(addrs[addrs.length - 1])
|
||||
const relayId = relayAddr.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.createFromCID(relayId)
|
||||
const destinationPeer = PeerId.createFromCID(destinationId)
|
||||
|
||||
let disconnectOnFailure = false
|
||||
let relayConnection = this._connectionManager.get(relayPeer)
|
||||
@@ -146,7 +157,7 @@ class Circuit {
|
||||
},
|
||||
dstPeer: {
|
||||
id: destinationPeer.toBytes(),
|
||||
addrs: [multiaddr(destinationAddr).bytes]
|
||||
addrs: [new Multiaddr(destinationAddr).bytes]
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -1,6 +1,7 @@
|
||||
'use strict'
|
||||
|
||||
const mergeOptions = require('merge-options')
|
||||
// @ts-ignore no types in multiaddr path
|
||||
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
|
||||
|
||||
const Constants = require('./constants')
|
||||
@@ -10,11 +11,18 @@ const RelayConstants = require('./circuit/constants')
|
||||
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
||||
const { FaultTolerance } = require('./transport-manager')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
* @typedef {import('.').Libp2pOptions} Libp2pOptions
|
||||
* @typedef {import('.').constructorOptions} constructorOptions
|
||||
*/
|
||||
|
||||
const DefaultConfig = {
|
||||
addresses: {
|
||||
listen: [],
|
||||
announce: [],
|
||||
noAnnounce: []
|
||||
noAnnounce: [],
|
||||
announceFilter: (/** @type {Multiaddr[]} */ multiaddrs) => multiaddrs
|
||||
},
|
||||
connectionManager: {
|
||||
minConnections: 25
|
||||
@@ -95,10 +103,15 @@ const DefaultConfig = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Libp2pOptions} opts
|
||||
* @returns {DefaultConfig & Libp2pOptions & constructorOptions}
|
||||
*/
|
||||
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,10 +8,9 @@ const log = Object.assign(debug('libp2p:connection-manager'), {
|
||||
const errcode = require('err-code')
|
||||
const mergeOptions = require('merge-options')
|
||||
const LatencyMonitor = require('./latency-monitor')
|
||||
// @ts-ignore retimer does not have types
|
||||
const retimer = require('retimer')
|
||||
|
||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
|
||||
const PeerId = require('peer-id')
|
||||
@@ -188,8 +187,10 @@ class ConnectionManager extends EventEmitter {
|
||||
_checkMetrics () {
|
||||
if (this._libp2p.metrics) {
|
||||
const movingAverages = this._libp2p.metrics.global.movingAverages
|
||||
// @ts-ignore moving averages object types
|
||||
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
|
||||
this._checkMaxLimit('maxReceivedData', received)
|
||||
// @ts-ignore moving averages object types
|
||||
const sent = movingAverages.dataSent[this._options.movingAverageInterval].movingAverage()
|
||||
this._checkMaxLimit('maxSentData', sent)
|
||||
const total = received + sent
|
||||
@@ -362,7 +363,7 @@ class ConnectionManager extends EventEmitter {
|
||||
*/
|
||||
_maybeDisconnectOne () {
|
||||
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)
|
||||
const disconnectPeer = peerValues[0]
|
||||
if (disconnectPeer) {
|
||||
@@ -381,7 +382,3 @@ class ConnectionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
module.exports = ConnectionManager
|
||||
|
||||
function byPeerValue (peerValueEntryA, peerValueEntryB) {
|
||||
return peerValueEntryA[1] - peerValueEntryB[1]
|
||||
}
|
||||
|
@@ -5,8 +5,6 @@
|
||||
* 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 */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
||||
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._latecyCheckSubtract = that._latecyCheckMultiply / 2
|
||||
|
||||
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0) ? undefined
|
||||
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0)
|
||||
? undefined
|
||||
: dataEmitIntervalMs || 5 * 1000 // 5s
|
||||
debug('latencyCheckIntervalMs: %s dataEmitIntervalMs: %s',
|
||||
that.latencyCheckIntervalMs, that.dataEmitIntervalMs)
|
||||
@@ -174,7 +173,8 @@ class LatencyMonitor extends EventEmitter {
|
||||
events: this._latencyData.events,
|
||||
minMs: this._latencyData.minMs,
|
||||
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,
|
||||
lengthMs: this.getDeltaMS(this._latencyData.startTime)
|
||||
}
|
||||
|
@@ -6,8 +6,6 @@
|
||||
*/
|
||||
'use strict'
|
||||
|
||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
|
||||
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
||||
|
@@ -14,8 +14,9 @@ const { pipe } = require('it-pipe')
|
||||
|
||||
/**
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
* @typedef {import('cids')} CID
|
||||
* @typedef {import('libp2p-interfaces/src/content-routing/types')} ContentRoutingModule
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -31,11 +32,12 @@ class ContentRouting {
|
||||
*/
|
||||
constructor (libp2p) {
|
||||
this.libp2p = libp2p
|
||||
/** @type {ContentRoutingModule[]} */
|
||||
this.routers = libp2p._modules.contentRouting || []
|
||||
this.dht = libp2p._dht
|
||||
|
||||
// If we have the dht, add it to the available content routers
|
||||
if (this.dht) {
|
||||
if (this.dht && libp2p._config.dht.enabled) {
|
||||
this.routers.push(this.dht)
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ const take = require('it-take')
|
||||
|
||||
/**
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -3,13 +3,14 @@
|
||||
const errCode = require('err-code')
|
||||
const AbortController = require('abort-controller').default
|
||||
const { anySignal } = require('any-signal')
|
||||
// @ts-ignore p-fifo does not export types
|
||||
const FIFO = require('p-fifo')
|
||||
const pAny = require('p-any')
|
||||
|
||||
/**
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
* @typedef {import('./')} Dialer
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@@ -5,7 +5,8 @@ const log = Object.assign(debug('libp2p:dialer'), {
|
||||
error: debug('libp2p:dialer:err')
|
||||
})
|
||||
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 { anySignal } = require('any-signal')
|
||||
|
||||
@@ -22,7 +23,6 @@ const {
|
||||
|
||||
/**
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('../peer-store')} PeerStore
|
||||
* @typedef {import('../peer-store/address-book').Address} Address
|
||||
@@ -38,9 +38,9 @@ const {
|
||||
*
|
||||
* @typedef {Object} DialerOptions
|
||||
* @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} [perPeerLimit = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
|
||||
* @property {number} [timeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
|
||||
* @property {number} [maxParallelDials = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
|
||||
* @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
|
||||
*
|
||||
* @typedef DialTarget
|
||||
@@ -50,7 +50,7 @@ const {
|
||||
* @typedef PendingDial
|
||||
* @property {DialRequest} dialRequest
|
||||
* @property {TimeoutController} controller
|
||||
* @property {Promise} promise
|
||||
* @property {Promise<Connection>} promise
|
||||
* @property {function():void} destroy
|
||||
*/
|
||||
|
||||
@@ -63,22 +63,22 @@ class Dialer {
|
||||
transportManager,
|
||||
peerStore,
|
||||
addressSorter = publicAddressesFirst,
|
||||
concurrency = MAX_PARALLEL_DIALS,
|
||||
timeout = DIAL_TIMEOUT,
|
||||
perPeerLimit = MAX_PER_PEER_DIALS,
|
||||
maxParallelDials = MAX_PARALLEL_DIALS,
|
||||
dialTimeout = DIAL_TIMEOUT,
|
||||
maxDialsPerPeer = MAX_PER_PEER_DIALS,
|
||||
resolvers = {}
|
||||
}) {
|
||||
this.transportManager = transportManager
|
||||
this.peerStore = peerStore
|
||||
this.addressSorter = addressSorter
|
||||
this.concurrency = concurrency
|
||||
this.timeout = timeout
|
||||
this.perPeerLimit = perPeerLimit
|
||||
this.tokens = [...new Array(concurrency)].map((_, index) => index)
|
||||
this.maxParallelDials = maxParallelDials
|
||||
this.timeout = dialTimeout
|
||||
this.maxDialsPerPeer = maxDialsPerPeer
|
||||
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
|
||||
this._pendingDials = new Map()
|
||||
|
||||
for (const [key, value] of Object.entries(resolvers)) {
|
||||
multiaddr.resolvers.set(key, value)
|
||||
Multiaddr.resolvers.set(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ class Dialer {
|
||||
const dialTarget = await this._createDialTarget(peer)
|
||||
|
||||
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)
|
||||
|
||||
@@ -134,6 +134,7 @@ class Dialer {
|
||||
* Creates a DialTarget. The DialTarget is used to create and track
|
||||
* the DialRequest to a given peer.
|
||||
* If a multiaddr is received it should be the first address attempted.
|
||||
* Multiaddrs not supported by the available transports will be filtered out.
|
||||
*
|
||||
* @private
|
||||
* @param {PeerId|Multiaddr|string} peer - A PeerId or Multiaddr
|
||||
@@ -150,20 +151,24 @@ class Dialer {
|
||||
|
||||
// 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.
|
||||
if (multiaddr.isMultiaddr(peer)) {
|
||||
if (Multiaddr.isMultiaddr(peer)) {
|
||||
knownAddrs = knownAddrs.filter((addr) => !peer.equals(addr))
|
||||
knownAddrs.unshift(peer)
|
||||
}
|
||||
|
||||
/** @type {Multiaddr[]} */
|
||||
const addrs = []
|
||||
for (const a of knownAddrs) {
|
||||
const resolvedAddrs = await this._resolve(a)
|
||||
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))
|
||||
|
||||
return {
|
||||
id: id.toB58String(),
|
||||
addrs
|
||||
addrs: supportedAddrs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +182,10 @@ class Dialer {
|
||||
* @returns {PendingDial}
|
||||
*/
|
||||
_createPendingDial (dialTarget, options = {}) {
|
||||
/**
|
||||
* @param {Multiaddr} addr
|
||||
* @param {{ signal: { aborted: any; }; }} options
|
||||
*/
|
||||
const dialAction = (addr, options) => {
|
||||
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
|
||||
return this.transportManager.dial(addr, options)
|
||||
@@ -207,13 +216,19 @@ class Dialer {
|
||||
return pendingDial
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} 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)
|
||||
log('%d tokens request, returning %d, %d remaining', num, total, this.tokens.length)
|
||||
return tokens
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} token
|
||||
*/
|
||||
releaseToken (token) {
|
||||
// Guard against duplicate releases
|
||||
if (this.tokens.indexOf(token) > -1) return
|
||||
@@ -259,7 +274,7 @@ class Dialer {
|
||||
*/
|
||||
async _resolveRecord (ma) {
|
||||
try {
|
||||
ma = multiaddr(ma.toString()) // Use current multiaddr module
|
||||
ma = new Multiaddr(ma.toString()) // Use current multiaddr module
|
||||
const multiaddrs = await ma.resolve()
|
||||
return multiaddrs
|
||||
} catch (_) {
|
||||
|
@@ -11,11 +11,13 @@ exports.codes = {
|
||||
PUBSUB_NOT_STARTED: 'ERR_PUBSUB_NOT_STARTED',
|
||||
DHT_NOT_STARTED: 'ERR_DHT_NOT_STARTED',
|
||||
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_FAILED: 'ERR_CONNECTION_FAILED',
|
||||
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
|
||||
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
|
||||
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
|
||||
ERR_RELAYED_DIAL: 'ERR_RELAYED_DIAL',
|
||||
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
|
||||
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
|
||||
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
|
||||
|
@@ -1,15 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const PeerId = require('peer-id')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const errCode = require('err-code')
|
||||
|
||||
const { codes } = require('./errors')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
*/
|
||||
|
||||
/**
|
||||
* Converts the given `peer` to a `Peer` object.
|
||||
* If a multiaddr is received, the addressBook is updated.
|
||||
@@ -19,14 +15,23 @@ const { codes } = require('./errors')
|
||||
*/
|
||||
function getPeer (peer) {
|
||||
if (typeof peer === 'string') {
|
||||
peer = multiaddr(peer)
|
||||
peer = new Multiaddr(peer)
|
||||
}
|
||||
|
||||
let addr
|
||||
if (multiaddr.isMultiaddr(peer)) {
|
||||
if (Multiaddr.isMultiaddr(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 {
|
||||
peer = PeerId.createFromB58String(peer.getPeerId())
|
||||
peer = PeerId.createFromB58String(idStr)
|
||||
} catch (err) {
|
||||
throw errCode(
|
||||
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')
|
||||
})
|
||||
const errCode = require('err-code')
|
||||
const pb = require('it-protocol-buffers')
|
||||
const lp = require('it-length-prefixed')
|
||||
const { pipe } = require('it-pipe')
|
||||
const { collect, take, consume } = require('streaming-iterables')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
|
||||
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 Message = require('./message')
|
||||
@@ -23,7 +23,6 @@ const PeerRecord = require('../record/peer-record')
|
||||
const {
|
||||
MULTICODEC_IDENTIFY,
|
||||
MULTICODEC_IDENTIFY_PUSH,
|
||||
AGENT_VERSION,
|
||||
PROTOCOL_VERSION
|
||||
} = require('./consts')
|
||||
|
||||
@@ -34,6 +33,11 @@ const { codes } = require('../errors')
|
||||
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} HostProperties
|
||||
* @property {string} agentVersion
|
||||
*/
|
||||
|
||||
class IdentifyService {
|
||||
/**
|
||||
* @class
|
||||
@@ -51,7 +55,6 @@ class IdentifyService {
|
||||
|
||||
// Store self host metadata
|
||||
this._host = {
|
||||
agentVersion: AGENT_VERSION,
|
||||
protocolVersion: PROTOCOL_VERSION,
|
||||
...libp2p._options.host
|
||||
}
|
||||
@@ -94,12 +97,12 @@ class IdentifyService {
|
||||
const { stream } = await connection.newStream(MULTICODEC_IDENTIFY_PUSH)
|
||||
|
||||
await pipe(
|
||||
[{
|
||||
[Message.Identify.encode({
|
||||
listenAddrs,
|
||||
signedPeerRecord,
|
||||
protocols
|
||||
}],
|
||||
pb.encode(Message),
|
||||
}).finish()],
|
||||
lp.encode(),
|
||||
stream,
|
||||
consume
|
||||
)
|
||||
@@ -160,12 +163,12 @@ class IdentifyService {
|
||||
|
||||
let message
|
||||
try {
|
||||
message = Message.decode(data)
|
||||
message = Message.Identify.decode(data)
|
||||
} catch (err) {
|
||||
throw errCode(err, codes.ERR_INVALID_MESSAGE)
|
||||
}
|
||||
|
||||
let {
|
||||
const {
|
||||
publicKey,
|
||||
listenAddrs,
|
||||
protocols,
|
||||
@@ -180,7 +183,7 @@ class IdentifyService {
|
||||
}
|
||||
|
||||
// Get the observedAddr if there is one
|
||||
observedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
|
||||
const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
|
||||
|
||||
try {
|
||||
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
|
||||
@@ -194,7 +197,7 @@ class IdentifyService {
|
||||
|
||||
// LEGACY: Update peers data in PeerStore
|
||||
try {
|
||||
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
|
||||
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => new Multiaddr(addr)))
|
||||
} catch (err) {
|
||||
log.error('received invalid addrs', err)
|
||||
}
|
||||
@@ -202,9 +205,9 @@ class IdentifyService {
|
||||
this.peerStore.protoBook.set(id, protocols)
|
||||
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
|
||||
|
||||
// TODO: Score our observed addr
|
||||
log('received observed address of %s', observedAddr)
|
||||
this.addressManager.addObservedAddr(observedAddr)
|
||||
// TODO: Add and score our observed addr
|
||||
log('received observed address of %s', cleanObservedAddr)
|
||||
// this.addressManager.addObservedAddr(observedAddr)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,7 +249,7 @@ class IdentifyService {
|
||||
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
|
||||
const protocols = this.peerStore.protoBook.get(this.peerId) || []
|
||||
|
||||
const message = Message.encode({
|
||||
const message = Message.Identify.encode({
|
||||
protocolVersion: this._host.protocolVersion,
|
||||
agentVersion: this._host.agentVersion,
|
||||
publicKey,
|
||||
@@ -254,7 +257,7 @@ class IdentifyService {
|
||||
signedPeerRecord,
|
||||
observedAddr: connection.remoteAddr.bytes,
|
||||
protocols
|
||||
})
|
||||
}).finish()
|
||||
|
||||
try {
|
||||
await pipe(
|
||||
@@ -288,7 +291,7 @@ class IdentifyService {
|
||||
toBuffer,
|
||||
collect
|
||||
)
|
||||
message = Message.decode(data)
|
||||
message = Message.Identify.decode(data)
|
||||
} catch (err) {
|
||||
return log.error('received invalid message', err)
|
||||
}
|
||||
@@ -307,7 +310,8 @@ class IdentifyService {
|
||||
|
||||
// LEGACY: Update peers data in PeerStore
|
||||
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) {
|
||||
log.error('received invalid addrs', err)
|
||||
}
|
||||
@@ -320,12 +324,12 @@ class IdentifyService {
|
||||
* Takes the `addr` and converts it to a Multiaddr if possible
|
||||
*
|
||||
* @param {Uint8Array | string} addr
|
||||
* @returns {multiaddr|null}
|
||||
* @returns {Multiaddr|null}
|
||||
*/
|
||||
static getCleanMultiaddr (addr) {
|
||||
if (addr && addr.length > 0) {
|
||||
try {
|
||||
return multiaddr(addr)
|
||||
return new Multiaddr(addr)
|
||||
} catch (_) {
|
||||
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')
|
||||
const schema = `
|
||||
message Identify {
|
||||
// protocolVersion determines compatibility between peers
|
||||
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
|
||||
var $protobuf = require("protobufjs/minimal");
|
||||
|
||||
// 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
|
||||
// Common aliases
|
||||
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||
|
||||
// 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;
|
||||
// Exported root namespace
|
||||
var $root = $protobuf.roots["libp2p-identify"] || ($protobuf.roots["libp2p-identify"] = {});
|
||||
|
||||
// listenAddrs are the multiaddrs the sender node listens for open connections on
|
||||
repeated bytes listenAddrs = 2;
|
||||
$root.Identify = (function() {
|
||||
|
||||
// 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;
|
||||
/**
|
||||
* Properties of an Identify.
|
||||
* @exports IIdentify
|
||||
* @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
|
||||
// in a form that lets us share authenticated addrs with other peers.
|
||||
optional bytes signedPeerRecord = 8;
|
||||
}
|
||||
`
|
||||
/**
|
||||
* Identify protocolVersion.
|
||||
* @member {string} protocolVersion
|
||||
* @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;
|
||||
}
|
123
src/index.js
123
src/index.js
@@ -4,13 +4,11 @@ const debug = require('debug')
|
||||
const log = Object.assign(debug('libp2p'), {
|
||||
error: debug('libp2p:err')
|
||||
})
|
||||
/** @typedef {import('./types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
|
||||
const errCode = require('err-code')
|
||||
const PeerId = require('peer-id')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
|
||||
const PeerRouting = require('./peer-routing')
|
||||
const ContentRouting = require('./content-routing')
|
||||
@@ -38,29 +36,63 @@ const NatManager = require('./nat-manager')
|
||||
const { updateSelfPeerRecord } = require('./record/utils')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
* @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/content-routing/types')} ContentRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-discovery/types')} PeerDiscoveryModule
|
||||
* @typedef {import('libp2p-interfaces/src/peer-routing/types')} PeerRoutingModule
|
||||
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
||||
* @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
|
||||
* @property {boolean} persistence
|
||||
*
|
||||
* @typedef {Object} RelayOptions
|
||||
* @typedef {Object} PubsubLocalOptions
|
||||
* @property {boolean} enabled
|
||||
* @property {import('./circuit').RelayAdvertiseOptions} advertise
|
||||
* @property {import('./circuit').HopOptions} hop
|
||||
* @property {import('./circuit').AutoRelayOptions} autoRelay
|
||||
*
|
||||
* @typedef {Object} MetricsOptions
|
||||
* @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
|
||||
* @property {Object} [dht] dht module options
|
||||
* @property {Object} [peerDiscovery]
|
||||
* @property {Pubsub} [pubsub] pubsub module options
|
||||
* @property {DhtOptions} [dht] dht module options
|
||||
* @property {import('./nat-manager').NatManagerOptions} [nat]
|
||||
* @property {Record<string, Object|boolean>} [peerDiscovery]
|
||||
* @property {PubsubLocalOptions & PubsubOptions} [pubsub] pubsub module options
|
||||
* @property {RelayOptions} [relay]
|
||||
* @property {Record<string, Object>} [transport] transport options indexed by transport key
|
||||
*
|
||||
@@ -68,16 +100,25 @@ const { updateSelfPeerRecord } = require('./record/utils')
|
||||
* @property {TransportFactory[]} transport
|
||||
* @property {MuxerFactory[]} streamMuxer
|
||||
* @property {Crypto[]} connEncryption
|
||||
* @property {PeerDiscoveryModule[]} [peerDiscovery]
|
||||
* @property {PeerRoutingModule[]} [peerRouting]
|
||||
* @property {ContentRoutingModule[]} [contentRouting]
|
||||
* @property {Object} [dht]
|
||||
* @property {{new(...args: any[]): Pubsub}} [pubsub]
|
||||
* @property {Protector} [connProtector]
|
||||
*
|
||||
* @typedef {Object} Libp2pOptions
|
||||
* @property {Libp2pModules} modules libp2p modules to use
|
||||
* @property {import('./address-manager').AddressManagerOptions} [addresses]
|
||||
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
|
||||
* @property {Datastore} [datastore]
|
||||
* @property {import('./dialer').DialerOptions} [dialer]
|
||||
* @property {import('./metrics').MetricsOptions} [metrics]
|
||||
* @property {Object} [keychain]
|
||||
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
|
||||
* @property {import('./identify/index').HostProperties} [host] libp2p host
|
||||
* @property {KeychainOptions & import('./keychain/index').KeychainOptions} [keychain]
|
||||
* @property {MetricsOptions & import('./metrics').MetricsOptions} [metrics]
|
||||
* @property {import('./peer-routing').PeerRoutingOptions} [peerRouting]
|
||||
* @property {PeerStoreOptions & import('./peer-store/persistent').PersistentPeerStoreOptions} [peerStore]
|
||||
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
|
||||
* @property {Libp2pConfig} [config]
|
||||
*
|
||||
* @typedef {Object} constructorOptions
|
||||
@@ -152,9 +193,6 @@ class Libp2p extends EventEmitter {
|
||||
this._discovery = new Map() // Discovery service instances/references
|
||||
|
||||
// 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, {
|
||||
autoDial: this._config.peerDiscovery.autoDial,
|
||||
...this._options.connectionManager
|
||||
@@ -175,7 +213,6 @@ class Libp2p extends EventEmitter {
|
||||
const keychainOpts = Keychain.generateOptions()
|
||||
|
||||
this.keychain = new Keychain(this._options.keychain.datastore, {
|
||||
passPhrase: this._options.keychain.pass,
|
||||
...keychainOpts,
|
||||
...this._options.keychain
|
||||
})
|
||||
@@ -203,6 +240,7 @@ class Libp2p extends EventEmitter {
|
||||
peerId: this.peerId,
|
||||
addressManager: this.addressManager,
|
||||
transportManager: this.transportManager,
|
||||
// @ts-ignore Nat typedef is not understood as Object
|
||||
...this._options.config.nat
|
||||
})
|
||||
|
||||
@@ -227,11 +265,7 @@ class Libp2p extends EventEmitter {
|
||||
this.dialer = new Dialer({
|
||||
transportManager: this.transportManager,
|
||||
peerStore: this.peerStore,
|
||||
concurrency: this._options.dialer.maxParallelDials,
|
||||
perPeerLimit: this._options.dialer.maxDialsPerPeer,
|
||||
timeout: this._options.dialer.dialTimeout,
|
||||
resolvers: this._options.dialer.resolvers,
|
||||
addressSorter: this._options.dialer.addressSorter
|
||||
...this._options.dialer
|
||||
})
|
||||
|
||||
this._modules.transport.forEach((Transport) => {
|
||||
@@ -268,6 +302,7 @@ class Libp2p extends EventEmitter {
|
||||
// dht provided components (peerRouting, contentRouting, dht)
|
||||
if (this._modules.dht) {
|
||||
const DHT = this._modules.dht
|
||||
// @ts-ignore Object is not constructable
|
||||
this._dht = new DHT({
|
||||
libp2p: this,
|
||||
dialer: this.dialer,
|
||||
@@ -426,22 +461,36 @@ class Libp2p extends EventEmitter {
|
||||
* @returns {Promise<Connection>}
|
||||
*/
|
||||
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`,
|
||||
* and the `Connection` will be returned
|
||||
* and the `MuxedStream` will be returned together with the successful negotiated protocol.
|
||||
*
|
||||
* @async
|
||||
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||
* @param {string[]|string} protocols
|
||||
* @param {object} [options]
|
||||
* @param {AbortSignal} [options.signal]
|
||||
* @returns {Promise<Connection|*>}
|
||||
*/
|
||||
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)
|
||||
|
||||
if (id.equals(this.peerId)) {
|
||||
@@ -456,11 +505,6 @@ class Libp2p extends EventEmitter {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -484,13 +528,13 @@ class Libp2p extends EventEmitter {
|
||||
|
||||
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
|
||||
const addrSet = new Set(addrs)
|
||||
|
||||
// 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
|
||||
*
|
||||
* @param {string[]|string} protocols
|
||||
* @param {({ connection: Connection, stream: MuxedStream, protocol: string }) => void} handler
|
||||
* @param {(props: HandlerProps) => void} handler
|
||||
*/
|
||||
handle (protocols, handler) {
|
||||
protocols = Array.isArray(protocols) ? protocols : [protocols]
|
||||
@@ -656,7 +700,7 @@ class Libp2p extends EventEmitter {
|
||||
try {
|
||||
await this.dialer.connectToPeer(peerId)
|
||||
} 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
|
||||
*/
|
||||
async _setupPeerDiscovery () {
|
||||
/**
|
||||
* @param {PeerDiscoveryModule} DiscoveryService
|
||||
*/
|
||||
const setupService = (DiscoveryService) => {
|
||||
let config = {
|
||||
enabled: true // on by default
|
||||
@@ -677,6 +724,7 @@ class Libp2p extends EventEmitter {
|
||||
if (DiscoveryService.tag &&
|
||||
this._config.peerDiscovery &&
|
||||
this._config.peerDiscovery[DiscoveryService.tag]) {
|
||||
// @ts-ignore PeerDiscovery not understood as an Object for spread
|
||||
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
|
||||
}
|
||||
|
||||
@@ -685,6 +733,7 @@ class Libp2p extends EventEmitter {
|
||||
let discoveryService
|
||||
|
||||
if (typeof DiscoveryService === 'function') {
|
||||
// @ts-ignore DiscoveryService has no constructor type inferred
|
||||
discoveryService = new DiscoveryService(Object.assign({}, config, {
|
||||
peerId: this.peerId,
|
||||
libp2p: this
|
||||
|
@@ -4,6 +4,7 @@ const debug = require('debug')
|
||||
const log = Object.assign(debug('libp2p:plaintext'), {
|
||||
error: debug('libp2p:plaintext:err')
|
||||
})
|
||||
// @ts-ignore it-handshake do not export types
|
||||
const handshake = require('it-handshake')
|
||||
const lp = require('it-length-prefixed')
|
||||
const PeerId = require('peer-id')
|
||||
@@ -16,8 +17,12 @@ const protocol = '/plaintext/2.0.0'
|
||||
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {import('./proto').IExchange} 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)
|
||||
}
|
||||
|
||||
@@ -68,12 +73,23 @@ async function encrypt (localId, conn, remoteId) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
protocol,
|
||||
secureInbound: (localId, conn, remoteId) => {
|
||||
return encrypt(localId, conn, remoteId)
|
||||
},
|
||||
secureOutbound: (localId, conn, remoteId) => {
|
||||
return encrypt(localId, conn, remoteId)
|
||||
}
|
||||
}
|
||||
module.exports =
|
||||
{
|
||||
protocol,
|
||||
/**
|
||||
* @param {PeerId} localId
|
||||
* @param {Connection} conn
|
||||
* @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(`
|
||||
message Exchange {
|
||||
optional bytes id = 1;
|
||||
optional PublicKey pubkey = 2;
|
||||
}
|
||||
// Common aliases
|
||||
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
|
||||
|
||||
enum KeyType {
|
||||
RSA = 0;
|
||||
Ed25519 = 1;
|
||||
Secp256k1 = 2;
|
||||
ECDSA = 3;
|
||||
}
|
||||
// Exported root namespace
|
||||
var $root = $protobuf.roots["libp2p-plaintext"] || ($protobuf.roots["libp2p-plaintext"] = {});
|
||||
|
||||
message PublicKey {
|
||||
required KeyType Type = 1;
|
||||
required bytes Data = 2;
|
||||
}
|
||||
`)
|
||||
$root.Exchange = (function() {
|
||||
|
||||
/**
|
||||
* 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'
|
||||
|
||||
// @ts-ignore node-forge types not exported
|
||||
require('node-forge/lib/pkcs7')
|
||||
// @ts-ignore node-forge types not exported
|
||||
require('node-forge/lib/pbe')
|
||||
// @ts-ignore node-forge types not exported
|
||||
const forge = require('node-forge/lib/forge')
|
||||
const { certificateForKey, findAsync } = require('./util')
|
||||
const errcode = require('err-code')
|
||||
@@ -85,6 +88,7 @@ class CMS {
|
||||
try {
|
||||
const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'))
|
||||
const obj = forge.asn1.fromDer(buf)
|
||||
// @ts-ignore not defined
|
||||
cms = forge.pkcs7.messageFromAsn1(obj)
|
||||
} catch (err) {
|
||||
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
|
||||
// issued by ipfs (O=ipfs).
|
||||
const recipients = cms.recipients
|
||||
// @ts-ignore cms types not defined
|
||||
.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'))
|
||||
// @ts-ignore cms types not defined
|
||||
.map(r => {
|
||||
return {
|
||||
recipient: r,
|
||||
// @ts-ignore cms types not defined
|
||||
keyId: r.issuer.find(a => a.shortName === 'CN').value
|
||||
}
|
||||
})
|
||||
@@ -113,6 +121,7 @@ class CMS {
|
||||
})
|
||||
|
||||
if (!r) {
|
||||
// @ts-ignore cms types not defined
|
||||
const missingKeys = recipients.map(r => r.keyId)
|
||||
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
|
||||
missingKeys
|
||||
|
@@ -10,11 +10,32 @@ const errcode = require('err-code')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
|
||||
// @ts-ignore node-forge sha512 types not exported
|
||||
require('node-forge/lib/sha512')
|
||||
|
||||
/**
|
||||
* @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/'
|
||||
@@ -38,6 +59,9 @@ const defaultOptions = {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} name
|
||||
*/
|
||||
function validateKeyName (name) {
|
||||
if (!name) return false
|
||||
if (typeof name !== 'string') return false
|
||||
@@ -85,14 +109,6 @@ function DsInfoName (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.
|
||||
*
|
||||
@@ -106,7 +122,7 @@ class Keychain {
|
||||
* Creates a new instance of a key chain.
|
||||
*
|
||||
* @param {Datastore} store - where the key are.
|
||||
* @param {object} options
|
||||
* @param {KeychainOptions} options
|
||||
* @class
|
||||
*/
|
||||
constructor (store, options) {
|
||||
@@ -118,8 +134,8 @@ class Keychain {
|
||||
this.opts = mergeOptions(defaultOptions, options)
|
||||
|
||||
// Enforce NIST SP 800-132
|
||||
if (this.opts.passPhrase && this.opts.passPhrase.length < 20) {
|
||||
throw new Error('passPhrase must be least 20 characters')
|
||||
if (this.opts.pass && this.opts.pass.length < 20) {
|
||||
throw new Error('pass must be least 20 characters')
|
||||
}
|
||||
if (this.opts.dek.keyLength < NIST.minKeyLength) {
|
||||
throw new Error(`dek.keyLength must be least ${NIST.minKeyLength} bytes`)
|
||||
@@ -131,12 +147,14 @@ class Keychain {
|
||||
throw new Error(`dek.iterationCount must be least ${NIST.minIterationCount}`)
|
||||
}
|
||||
|
||||
const dek = this.opts.passPhrase ? crypto.pbkdf2(
|
||||
this.opts.passPhrase,
|
||||
this.opts.dek.salt,
|
||||
this.opts.dek.iterationCount,
|
||||
this.opts.dek.keyLength,
|
||||
this.opts.dek.hash) : ''
|
||||
const dek = this.opts.pass
|
||||
? crypto.pbkdf2(
|
||||
this.opts.pass,
|
||||
this.opts.dek.salt,
|
||||
this.opts.dek.iterationCount,
|
||||
this.opts.dek.keyLength,
|
||||
this.opts.dek.hash)
|
||||
: ''
|
||||
|
||||
privates.set(this, { dek })
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@
|
||||
require('node-forge/lib/x509')
|
||||
const forge = require('node-forge/lib/forge')
|
||||
const pki = forge.pki
|
||||
exports = module.exports
|
||||
|
||||
/**
|
||||
* Gets a self-signed X.509 certificate for the key.
|
||||
@@ -17,7 +16,7 @@ exports = module.exports
|
||||
* @param {RsaPrivateKey} privateKey - The naked key
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
exports.certificateForKey = (key, privateKey) => {
|
||||
const certificateForKey = (key, privateKey) => {
|
||||
const publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e)
|
||||
const cert = pki.createCertificate()
|
||||
cert.publicKey = publicKey
|
||||
@@ -87,4 +86,7 @@ async function findAsync (array, asyncCompare) {
|
||||
return array[index]
|
||||
}
|
||||
|
||||
module.exports.findAsync = findAsync
|
||||
module.exports = {
|
||||
certificateForKey,
|
||||
findAsync
|
||||
}
|
||||
|
@@ -1,10 +1,8 @@
|
||||
// @ts-nocheck
|
||||
'use strict'
|
||||
|
||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
const Big = require('bignumber.js')
|
||||
const { BigNumber: Big } = require('bignumber.js')
|
||||
const MovingAverage = require('moving-average')
|
||||
const retimer = require('retimer')
|
||||
|
||||
@@ -21,24 +19,30 @@ class Stats extends EventEmitter {
|
||||
|
||||
this._options = options
|
||||
this._queue = []
|
||||
this._stats = {}
|
||||
|
||||
/** @type {{ dataReceived: Big, dataSent: Big }} */
|
||||
this._stats = {
|
||||
dataReceived: Big(0),
|
||||
dataSent: Big(0)
|
||||
}
|
||||
|
||||
this._frequencyLastTime = Date.now()
|
||||
this._frequencyAccumulators = {}
|
||||
|
||||
/** @type {{ dataReceived: MovingAverage[], dataSent: MovingAverage[] }} */
|
||||
this._movingAverages = {}
|
||||
|
||||
this._update = this._update.bind(this)
|
||||
|
||||
const intervals = this._options.movingAverageIntervals
|
||||
|
||||
for (var i = 0; i < initialCounters.length; i++) {
|
||||
var key = initialCounters[i]
|
||||
for (let i = 0; i < initialCounters.length; i++) {
|
||||
const key = initialCounters[i]
|
||||
this._stats[key] = Big(0)
|
||||
this._movingAverages[key] = {}
|
||||
for (var k = 0; k < intervals.length; k++) {
|
||||
var interval = intervals[k]
|
||||
var ma = this._movingAverages[key][interval] = MovingAverage(interval)
|
||||
for (let k = 0; k < intervals.length; k++) {
|
||||
const interval = intervals[k]
|
||||
const ma = this._movingAverages[key][interval] = MovingAverage(interval)
|
||||
ma.push(this._frequencyLastTime, 0)
|
||||
}
|
||||
}
|
||||
@@ -72,8 +76,6 @@ class Stats extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Returns a clone of the current stats.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
get snapshot () {
|
||||
return Object.assign({}, this._stats)
|
||||
@@ -81,8 +83,6 @@ class Stats extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Returns a clone of the internal movingAverages
|
||||
*
|
||||
* @returns {MovingAverage}
|
||||
*/
|
||||
get movingAverages () {
|
||||
return Object.assign({}, this._movingAverages)
|
||||
@@ -219,9 +219,9 @@ class Stats extends EventEmitter {
|
||||
|
||||
const intervals = this._options.movingAverageIntervals
|
||||
|
||||
for (var i = 0; i < intervals.length; i++) {
|
||||
var movingAverageInterval = intervals[i]
|
||||
var movingAverage = movingAverages[movingAverageInterval]
|
||||
for (let i = 0; i < intervals.length; i++) {
|
||||
const movingAverageInterval = intervals[i]
|
||||
let movingAverage = movingAverages[movingAverageInterval]
|
||||
if (!movingAverage) {
|
||||
movingAverage = movingAverages[movingAverageInterval] = MovingAverage(movingAverageInterval)
|
||||
}
|
||||
|
@@ -1,14 +1,16 @@
|
||||
'use strict'
|
||||
|
||||
// @ts-ignore nat-api does not export types
|
||||
const NatAPI = require('@motrix/nat-api')
|
||||
const debug = require('debug')
|
||||
const promisify = require('promisify-es6')
|
||||
const Multiaddr = require('multiaddr')
|
||||
const { promisify } = require('es6-promisify')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const log = Object.assign(debug('libp2p:nat'), {
|
||||
error: debug('libp2p:nat:err')
|
||||
})
|
||||
const { isBrowser } = require('ipfs-utils/src/env')
|
||||
const retry = require('p-retry')
|
||||
// @ts-ignore private-api does not export types
|
||||
const isPrivateIp = require('private-ip')
|
||||
const pkg = require('../package.json')
|
||||
const errcode = require('err-code')
|
||||
@@ -17,33 +19,39 @@ const {
|
||||
} = require('./errors')
|
||||
const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback')
|
||||
|
||||
const DEFAULT_TTL = 7200
|
||||
|
||||
/**
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('./transport-manager')} TransportManager
|
||||
* @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) {
|
||||
return Math.floor(Math.random() * (max - min + 1) + min)
|
||||
}
|
||||
|
||||
const DEFAULT_TTL = 7200
|
||||
|
||||
class NatManager {
|
||||
/**
|
||||
* @class
|
||||
* @param {object} 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
|
||||
* @param {NatManagerProperties & NatManagerOptions} options
|
||||
*/
|
||||
constructor ({ peerId, addressManager, transportManager, ...options }) {
|
||||
this._peerId = peerId
|
||||
@@ -89,15 +97,18 @@ class NatManager {
|
||||
|
||||
if (!addr.isThinWaistAddress() || transport !== 'tcp') {
|
||||
// only bare tcp addresses
|
||||
// eslint-disable-next-line no-continue
|
||||
continue
|
||||
}
|
||||
|
||||
if (isLoopback(addr)) {
|
||||
// eslint-disable-next-line no-continue
|
||||
continue
|
||||
}
|
||||
|
||||
if (family !== 'ipv4') {
|
||||
if (family !== 4) {
|
||||
// ignore ipv6
|
||||
// eslint-disable-next-line no-continue
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -119,9 +130,9 @@ class NatManager {
|
||||
})
|
||||
|
||||
this._addressManager.addObservedAddr(Multiaddr.fromNodeAddress({
|
||||
family: 'IPv4',
|
||||
family: 4,
|
||||
address: publicIp,
|
||||
port: `${publicPort}`
|
||||
port: publicPort
|
||||
}, transport))
|
||||
}
|
||||
}
|
||||
@@ -132,14 +143,32 @@ class NatManager {
|
||||
}
|
||||
|
||||
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 = {
|
||||
// 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 }),
|
||||
|
||||
/**
|
||||
* @param {...any} args
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
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 })
|
||||
}
|
||||
|
||||
|
@@ -19,12 +19,25 @@ const filter = require('it-filter')
|
||||
const {
|
||||
setDelayedInterval,
|
||||
clearDelayedInterval
|
||||
// @ts-ignore module with no types
|
||||
} = 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')} 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
|
||||
@@ -33,10 +46,11 @@ class PeerRouting {
|
||||
constructor (libp2p) {
|
||||
this._peerId = libp2p.peerId
|
||||
this._peerStore = libp2p.peerStore
|
||||
/** @type {PeerRoutingModule[]} */
|
||||
this._routers = libp2p._modules.peerRouting || []
|
||||
|
||||
// If we have the dht, add it to the available peer routers
|
||||
if (libp2p._dht) {
|
||||
if (libp2p._dht && libp2p._config.dht.enabled) {
|
||||
this._routers.push(libp2p._dht)
|
||||
}
|
||||
|
||||
@@ -95,6 +109,7 @@ class PeerRouting {
|
||||
...this._routers.map(router => [router.findPeer(id, options)])
|
||||
),
|
||||
(source) => filter(source, Boolean),
|
||||
// @ts-ignore findPeer resolves a Promise
|
||||
(source) => storeAddresses(source, this._peerStore),
|
||||
(source) => first(source)
|
||||
)
|
||||
|
@@ -6,7 +6,7 @@ const log = Object.assign(debug('libp2p:peer-store:address-book'), {
|
||||
})
|
||||
const errcode = require('err-code')
|
||||
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
const Book = require('./book')
|
||||
@@ -18,7 +18,6 @@ const {
|
||||
const Envelope = require('../record/envelope')
|
||||
|
||||
/**
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('./')} PeerStore
|
||||
*/
|
||||
|
||||
@@ -60,7 +59,7 @@ class AddressBook extends Book {
|
||||
if (!data.addresses) {
|
||||
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 id = peerId.toB58String()
|
||||
|
||||
// No addresses to be added
|
||||
if (!addresses.length) {
|
||||
return this
|
||||
}
|
||||
|
||||
const entry = this.data.get(id)
|
||||
|
||||
if (entry && entry.addresses) {
|
||||
@@ -295,17 +299,21 @@ class AddressBook extends Book {
|
||||
}
|
||||
|
||||
// create Address for each address
|
||||
/** @type {Address[]} */
|
||||
const addresses = []
|
||||
multiaddrs.forEach((addr) => {
|
||||
if (!multiaddr.isMultiaddr(addr)) {
|
||||
if (!Multiaddr.isMultiaddr(addr)) {
|
||||
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)
|
||||
}
|
||||
|
||||
addresses.push({
|
||||
multiaddr: addr,
|
||||
isCertified
|
||||
})
|
||||
// Guarantee no replicates
|
||||
if (!addresses.find((a) => a.multiaddr.equals(addr))) {
|
||||
addresses.push({
|
||||
multiaddr: addr,
|
||||
isCertified
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return addresses
|
||||
|
@@ -7,6 +7,9 @@ const {
|
||||
codes: { ERR_INVALID_PARAMETERS }
|
||||
} = require('../errors')
|
||||
|
||||
/**
|
||||
* @param {any} data
|
||||
*/
|
||||
const passthrough = data => data
|
||||
|
||||
/**
|
||||
|
@@ -2,8 +2,6 @@
|
||||
|
||||
const errcode = require('err-code')
|
||||
|
||||
/** @typedef {import('../types').EventEmitterFactory} Events */
|
||||
/** @type Events */
|
||||
const EventEmitter = require('events')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
|
@@ -81,6 +81,9 @@ class MetadataBook extends Book {
|
||||
* Set data into the datastructure
|
||||
*
|
||||
* @override
|
||||
* @param {PeerId} peerId
|
||||
* @param {string} key
|
||||
* @param {Uint8Array} value
|
||||
*/
|
||||
_setValue (peerId, key, value, { emit = true } = {}) {
|
||||
const id = peerId.toB58String()
|
||||
|
@@ -5,7 +5,7 @@ const log = Object.assign(debug('libp2p:persistent-peer-store'), {
|
||||
error: debug('libp2p:persistent-peer-store:err')
|
||||
})
|
||||
const { Key } = require('interface-datastore')
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
const PeerStore = require('..')
|
||||
@@ -18,13 +18,18 @@ const {
|
||||
NAMESPACE_PROTOCOL
|
||||
} = require('./consts')
|
||||
|
||||
const Addresses = require('./pb/address-book.proto')
|
||||
const Protocols = require('./pb/proto-book.proto')
|
||||
const { Addresses } = require('./pb/address-book')
|
||||
const { Protocols } = require('./pb/proto-book')
|
||||
|
||||
/**
|
||||
* @typedef {import('interface-datastore').Batch} Batch
|
||||
* @typedef {import('../address-book.js').Address} Address
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} PersistentPeerStoreProperties
|
||||
* @property {PeerId} peerId
|
||||
* @property {any} datastore
|
||||
* @property {import('interface-datastore').Datastore} datastore
|
||||
*
|
||||
* @typedef {Object} PersistentPeerStoreOptions
|
||||
* @property {number} [threshold = 5] - Number of dirty peers allowed before commit data.
|
||||
@@ -214,7 +219,7 @@ class PersistentPeerStore extends PeerStore {
|
||||
*
|
||||
* @private
|
||||
* @param {PeerId} peerId
|
||||
* @param {Object} batch
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
_batchAddressBook (peerId, batch) {
|
||||
const b32key = peerId.toString()
|
||||
@@ -234,11 +239,13 @@ class PersistentPeerStore extends PeerStore {
|
||||
multiaddr: address.multiaddr.bytes,
|
||||
isCertified: address.isCertified
|
||||
})),
|
||||
certified_record: entry.record ? {
|
||||
seq: entry.record.seqNumber,
|
||||
raw: entry.record.raw
|
||||
} : undefined
|
||||
})
|
||||
certifiedRecord: entry.record
|
||||
? {
|
||||
seq: entry.record.seqNumber,
|
||||
raw: entry.record.raw
|
||||
}
|
||||
: undefined
|
||||
}).finish()
|
||||
|
||||
batch.put(key, encodedData)
|
||||
} catch (err) {
|
||||
@@ -251,7 +258,7 @@ class PersistentPeerStore extends PeerStore {
|
||||
*
|
||||
* @private
|
||||
* @param {PeerId} peerId
|
||||
* @param {Object} batch
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
_batchKeyBook (peerId, batch) {
|
||||
const b32key = peerId.toString()
|
||||
@@ -277,14 +284,14 @@ class PersistentPeerStore extends PeerStore {
|
||||
*
|
||||
* @private
|
||||
* @param {PeerId} peerId
|
||||
* @param {Object} batch
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
_batchMetadataBook (peerId, batch) {
|
||||
const b32key = peerId.toString()
|
||||
const dirtyMetada = this._dirtyMetadata.get(peerId.toB58String()) || []
|
||||
|
||||
try {
|
||||
dirtyMetada.forEach((dirtyKey) => {
|
||||
dirtyMetada.forEach((/** @type {string} */ dirtyKey) => {
|
||||
const key = new Key(`${NAMESPACE_METADATA}${b32key}/${dirtyKey}`)
|
||||
const dirtyValue = this.metadataBook.getValue(peerId, dirtyKey)
|
||||
|
||||
@@ -304,7 +311,7 @@ class PersistentPeerStore extends PeerStore {
|
||||
*
|
||||
* @private
|
||||
* @param {PeerId} peerId
|
||||
* @param {Object} batch
|
||||
* @param {Batch} batch
|
||||
*/
|
||||
_batchProtoBook (peerId, batch) {
|
||||
const b32key = peerId.toString()
|
||||
@@ -319,7 +326,7 @@ class PersistentPeerStore extends PeerStore {
|
||||
return
|
||||
}
|
||||
|
||||
const encodedData = Protocols.encode({ protocols })
|
||||
const encodedData = Protocols.encode({ protocols }).finish()
|
||||
|
||||
batch.put(key, encodedData)
|
||||
} catch (err) {
|
||||
@@ -351,13 +358,15 @@ class PersistentPeerStore extends PeerStore {
|
||||
peerId,
|
||||
{
|
||||
addresses: decoded.addrs.map((address) => ({
|
||||
multiaddr: multiaddr(address.multiaddr),
|
||||
multiaddr: new Multiaddr(address.multiaddr),
|
||||
isCertified: Boolean(address.isCertified)
|
||||
})),
|
||||
record: decoded.certified_record ? {
|
||||
raw: decoded.certified_record.raw,
|
||||
seqNumber: decoded.certified_record.seq
|
||||
} : undefined
|
||||
record: decoded.certifiedRecord
|
||||
? {
|
||||
raw: decoded.certifiedRecord.raw,
|
||||
seqNumber: decoded.certifiedRecord.seq
|
||||
}
|
||||
: undefined
|
||||
},
|
||||
{ emit: false })
|
||||
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 {
|
||||
// Address represents a single multiaddr.
|
||||
message Address {
|
||||
required bytes multiaddr = 1;
|
||||
bytes multiaddr = 1;
|
||||
|
||||
// Flag to indicate if the address comes from a certified source.
|
||||
optional bool isCertified = 2;
|
||||
@@ -27,7 +24,4 @@ message Addresses {
|
||||
|
||||
// The most recently received signed PeerRecord.
|
||||
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 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))
|
||||
|
||||
// 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 { pipe } = require('it-pipe')
|
||||
// @ts-ignore it-buffer has no types exported
|
||||
const { toBuffer } = require('it-buffer')
|
||||
const { collect, take } = require('streaming-iterables')
|
||||
const equals = require('uint8arrays/equals')
|
||||
@@ -16,8 +17,9 @@ const { PROTOCOL, PING_LENGTH } = require('./constants')
|
||||
|
||||
/**
|
||||
* @typedef {import('../')} Libp2p
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('multiaddr').Multiaddr} Multiaddr
|
||||
* @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
|
||||
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 data = crypto.randomBytes(PING_LENGTH)
|
||||
@@ -39,7 +42,7 @@ async function ping (node, peer) {
|
||||
const [result] = await pipe(
|
||||
[data],
|
||||
stream,
|
||||
stream => take(1, stream),
|
||||
(/** @type {MuxedStream} */ stream) => take(1, stream),
|
||||
toBuffer,
|
||||
collect
|
||||
)
|
||||
|
@@ -3,11 +3,16 @@
|
||||
const crypto = require('libp2p-crypto')
|
||||
const constants = require('./constants')
|
||||
|
||||
exports = module.exports
|
||||
|
||||
exports.rnd = (length) => {
|
||||
/**
|
||||
* @param {number} length
|
||||
*/
|
||||
function rnd (length) {
|
||||
if (!length) {
|
||||
length = constants.PING_LENGTH
|
||||
}
|
||||
return crypto.randomBytes(length)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
rnd
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
|
||||
})
|
||||
|
||||
const Errors = require('./errors')
|
||||
// @ts-ignore xsalsa20 has no types exported
|
||||
const xsalsa20 = require('xsalsa20')
|
||||
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
@@ -21,7 +22,8 @@ const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
*/
|
||||
module.exports.createBoxStream = (nonce, psk) => {
|
||||
const xor = xsalsa20(nonce, psk)
|
||||
return (source) => (async function * () {
|
||||
|
||||
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
|
||||
for await (const chunk of source) {
|
||||
yield Uint8Array.from(xor.update(chunk.slice()))
|
||||
}
|
||||
@@ -36,7 +38,7 @@ module.exports.createBoxStream = (nonce, psk) => {
|
||||
* @returns {*} a through iterable
|
||||
*/
|
||||
module.exports.createUnboxStream = (nonce, psk) => {
|
||||
return (source) => (async function * () {
|
||||
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
|
||||
const xor = xsalsa20(nonce, psk)
|
||||
log.trace('Decryption enabled')
|
||||
|
||||
@@ -51,7 +53,7 @@ module.exports.createUnboxStream = (nonce, psk) => {
|
||||
*
|
||||
* @param {Uint8Array} pskBuffer
|
||||
* @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) => {
|
||||
try {
|
||||
|
@@ -6,6 +6,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
|
||||
})
|
||||
const { pipe } = require('it-pipe')
|
||||
const errcode = require('err-code')
|
||||
// @ts-ignore it-pair has no types exported
|
||||
const duplexPair = require('it-pair/duplex')
|
||||
const crypto = require('libp2p-crypto')
|
||||
const Errors = require('./errors')
|
||||
@@ -17,6 +18,7 @@ const {
|
||||
createUnboxStream,
|
||||
decodeV1PSK
|
||||
} = require('./crypto')
|
||||
// @ts-ignore it-handshake has no types exported
|
||||
const handshake = require('it-handshake')
|
||||
const { NONCE_LENGTH } = require('./key-generator')
|
||||
|
||||
|
@@ -22,8 +22,12 @@ module.exports = generate
|
||||
module.exports.NONCE_LENGTH = 24
|
||||
module.exports.KEY_LENGTH = KEY_LENGTH
|
||||
|
||||
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
|
||||
if (require.main === module) {
|
||||
// @ts-ignore
|
||||
generate(process.stdout)
|
||||
try {
|
||||
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
|
||||
if (require.main === module) {
|
||||
// @ts-ignore
|
||||
generate(process.stdout)
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
@@ -1,12 +1,19 @@
|
||||
'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')} 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) {
|
||||
/** @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)
|
||||
pubsub._subscribeAdapter = pubsub.subscribe
|
||||
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 {
|
||||
// public_key is the public key of the keypair the enclosed payload was
|
||||
// signed with.
|
||||
@@ -20,5 +16,4 @@ message Envelope {
|
||||
// the enclosed public key, over the payload, prefixing a domain string for
|
||||
// additional security.
|
||||
bytes signature = 5;
|
||||
}
|
||||
`)
|
||||
}
|
@@ -3,13 +3,14 @@
|
||||
const errCode = require('err-code')
|
||||
const uint8arraysConcat = require('uint8arrays/concat')
|
||||
const uint8arraysFromString = require('uint8arrays/from-string')
|
||||
// @ts-ignore libp2p-crypto does not support types
|
||||
const cryptoKeys = require('libp2p-crypto/src/keys')
|
||||
const PeerId = require('peer-id')
|
||||
const varint = require('varint')
|
||||
const uint8arraysEquals = require('uint8arrays/equals')
|
||||
|
||||
const { codes } = require('../../errors')
|
||||
const Protobuf = require('./envelope.proto')
|
||||
const { Envelope: Protobuf } = require('./envelope')
|
||||
|
||||
/**
|
||||
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||
@@ -49,12 +50,12 @@ class Envelope {
|
||||
|
||||
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
|
||||
|
||||
this._marshal = Protobuf.Envelope.encode({
|
||||
public_key: publicKey,
|
||||
payload_type: this.payloadType,
|
||||
this._marshal = Protobuf.encode({
|
||||
publicKey: publicKey,
|
||||
payloadType: this.payloadType,
|
||||
payload: this.payload,
|
||||
signature: this.signature
|
||||
})
|
||||
}).finish()
|
||||
|
||||
return this._marshal
|
||||
}
|
||||
@@ -124,12 +125,12 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
|
||||
* @returns {Promise<Envelope>}
|
||||
*/
|
||||
Envelope.createFromProtobuf = async (data) => {
|
||||
const envelopeData = Protobuf.Envelope.decode(data)
|
||||
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
||||
const envelopeData = Protobuf.decode(data)
|
||||
const peerId = await PeerId.createFromPubKey(envelopeData.publicKey)
|
||||
|
||||
return new Envelope({
|
||||
peerId,
|
||||
payloadType: envelopeData.payload_type,
|
||||
payloadType: envelopeData.payloadType,
|
||||
payload: envelopeData.payload,
|
||||
signature: envelopeData.signature
|
||||
})
|
||||
|
@@ -1,18 +1,17 @@
|
||||
'use strict'
|
||||
|
||||
const multiaddr = require('multiaddr')
|
||||
const { Multiaddr } = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
const arrayEquals = require('libp2p-utils/src/array-equals')
|
||||
|
||||
const Protobuf = require('./peer-record.proto')
|
||||
const { PeerRecord: Protobuf } = require('./peer-record')
|
||||
const {
|
||||
ENVELOPE_DOMAIN_PEER_RECORD,
|
||||
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
|
||||
} = require('./consts')
|
||||
|
||||
/**
|
||||
* @typedef {import('peer-id')} PeerId
|
||||
* @typedef {import('multiaddr')} Multiaddr
|
||||
* @typedef {import('../../peer-store/address-book.js').Address} Address
|
||||
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||
*/
|
||||
|
||||
@@ -52,13 +51,13 @@ class PeerRecord {
|
||||
return this._marshal
|
||||
}
|
||||
|
||||
this._marshal = Protobuf.PeerRecord.encode({
|
||||
peer_id: this.peerId.toBytes(),
|
||||
this._marshal = Protobuf.encode({
|
||||
peerId: this.peerId.toBytes(),
|
||||
seq: this.seqNumber,
|
||||
addresses: this.multiaddrs.map((m) => ({
|
||||
multiaddr: m.bytes
|
||||
}))
|
||||
})
|
||||
}).finish()
|
||||
|
||||
return this._marshal
|
||||
}
|
||||
@@ -100,12 +99,11 @@ class PeerRecord {
|
||||
* @returns {PeerRecord}
|
||||
*/
|
||||
PeerRecord.createFromProtobuf = (buf) => {
|
||||
// Decode
|
||||
const peerRecord = Protobuf.PeerRecord.decode(buf)
|
||||
const peerRecord = Protobuf.decode(buf)
|
||||
|
||||
const peerId = PeerId.createFromBytes(peerRecord.peer_id)
|
||||
const multiaddrs = (peerRecord.addresses || []).map((a) => multiaddr(a.multiaddr))
|
||||
const seqNumber = peerRecord.seq
|
||||
const peerId = PeerId.createFromBytes(peerRecord.peerId)
|
||||
const multiaddrs = (peerRecord.addresses || []).map((a) => new Multiaddr(a.multiaddr))
|
||||
const seqNumber = Number(peerRecord.seq)
|
||||
|
||||
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