mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-04-26 02:52:16 +00:00
chore: add typedefs (#802)
This commit is contained in:
parent
117f2b97b0
commit
64124f17ed
67
.github/workflows/main.yml
vendored
Normal file
67
.github/workflows/main.yml
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
name: ci
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: yarn
|
||||||
|
- run: yarn lint
|
||||||
|
- uses: gozala/typescript-error-reporter-action@v1.0.8
|
||||||
|
- run: yarn build
|
||||||
|
- run: yarn aegir dep-check
|
||||||
|
- uses: ipfs/aegir/actions/bundle-size@master
|
||||||
|
name: size
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
test-node:
|
||||||
|
needs: check
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||||
|
node: [12, 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
|
||||||
|
- uses: codecov/codecov-action@v1
|
||||||
|
test-chrome:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: yarn
|
||||||
|
- 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
|
||||||
|
test-interop:
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: yarn
|
||||||
|
- 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
|
58
.travis.yml
58
.travis.yml
@ -1,58 +0,0 @@
|
|||||||
language: node_js
|
|
||||||
cache: npm
|
|
||||||
stages:
|
|
||||||
- check
|
|
||||||
- test
|
|
||||||
- cov
|
|
||||||
|
|
||||||
node_js:
|
|
||||||
- 'lts/*'
|
|
||||||
- '14'
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
script: npx nyc -s npm run test:node -- --bail
|
|
||||||
after_success: npx nyc report --reporter=text-lcov > coverage.lcov && npx codecov
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: check
|
|
||||||
script:
|
|
||||||
- npx aegir build --bundlesize
|
|
||||||
# Remove pull libs once ping is async
|
|
||||||
- npx aegir dep-check -- -i pull-handshake -i pull-stream
|
|
||||||
- npm run lint
|
|
||||||
|
|
||||||
- stage: test
|
|
||||||
name: chrome
|
|
||||||
addons:
|
|
||||||
chrome: stable
|
|
||||||
script:
|
|
||||||
- npx aegir test -t browser -t webworker
|
|
||||||
|
|
||||||
- stage: test
|
|
||||||
name: firefox
|
|
||||||
addons:
|
|
||||||
firefox: latest
|
|
||||||
script:
|
|
||||||
- npx aegir test -t browser -t webworker -- --browsers FirefoxHeadless
|
|
||||||
|
|
||||||
- stage: test
|
|
||||||
name: interop
|
|
||||||
script:
|
|
||||||
- cd node_modules/interop-libp2p
|
|
||||||
- npm install
|
|
||||||
- LIBP2P_JS=${TRAVIS_BUILD_DIR}/src/index.js npx aegir test -t node --bail
|
|
||||||
|
|
||||||
- stage: test
|
|
||||||
if: type = pull_request
|
|
||||||
name: example - auto-relay
|
|
||||||
script:
|
|
||||||
- cd examples
|
|
||||||
- npm install
|
|
||||||
- npm run test -- auto-relay
|
|
||||||
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
15
package.json
15
package.json
@ -4,6 +4,15 @@
|
|||||||
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
||||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
|
"types": "dist/src/index.d.ts",
|
||||||
|
"typesVersions": {
|
||||||
|
"*": {
|
||||||
|
"src/*": [
|
||||||
|
"dist/src/*",
|
||||||
|
"dist/src/*/index"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"dist",
|
"dist",
|
||||||
"src"
|
"src"
|
||||||
@ -53,7 +62,7 @@
|
|||||||
"events": "^3.1.0",
|
"events": "^3.1.0",
|
||||||
"hashlru": "^2.3.0",
|
"hashlru": "^2.3.0",
|
||||||
"interface-datastore": "^2.0.0",
|
"interface-datastore": "^2.0.0",
|
||||||
"ipfs-utils": "^2.2.0",
|
"ipfs-utils": "^5.0.1",
|
||||||
"it-all": "^1.0.1",
|
"it-all": "^1.0.1",
|
||||||
"it-buffer": "^0.1.2",
|
"it-buffer": "^0.1.2",
|
||||||
"it-handshake": "^1.0.1",
|
"it-handshake": "^1.0.1",
|
||||||
@ -61,7 +70,7 @@
|
|||||||
"it-pipe": "^1.1.0",
|
"it-pipe": "^1.1.0",
|
||||||
"it-protocol-buffers": "^0.2.0",
|
"it-protocol-buffers": "^0.2.0",
|
||||||
"libp2p-crypto": "^0.18.0",
|
"libp2p-crypto": "^0.18.0",
|
||||||
"libp2p-interfaces": "^0.7.2",
|
"libp2p-interfaces": "^0.8.0",
|
||||||
"libp2p-utils": "^0.2.2",
|
"libp2p-utils": "^0.2.2",
|
||||||
"mafmt": "^8.0.0",
|
"mafmt": "^8.0.0",
|
||||||
"merge-options": "^2.0.0",
|
"merge-options": "^2.0.0",
|
||||||
@ -88,7 +97,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nodeutils/defaults-deep": "^1.1.0",
|
"@nodeutils/defaults-deep": "^1.1.0",
|
||||||
"abortable-iterator": "^3.0.0",
|
"abortable-iterator": "^3.0.0",
|
||||||
"aegir": "^27.0.0",
|
"aegir": "^29.2.0",
|
||||||
"chai-bytes": "^0.1.2",
|
"chai-bytes": "^0.1.2",
|
||||||
"chai-string": "^1.5.0",
|
"chai-string": "^1.5.0",
|
||||||
"delay": "^4.3.0",
|
"delay": "^4.3.0",
|
||||||
|
@ -1,23 +1,25 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:addresses')
|
|
||||||
log.error = debug('libp2p:addresses:error')
|
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} AddressManagerOptions
|
||||||
|
* @property {string[]} [listen = []] - list of multiaddrs string representation to listen.
|
||||||
|
* @property {string[]} [announce = []] - list of multiaddrs string representation to announce.
|
||||||
|
*/
|
||||||
|
class AddressManager {
|
||||||
|
/**
|
||||||
* Responsible for managing the peer addresses.
|
* Responsible for managing the peer addresses.
|
||||||
* Peers can specify their listen and announce addresses.
|
* Peers can specify their listen and announce addresses.
|
||||||
* The listen addresses will be used by the libp2p transports to listen for new connections,
|
* The listen addresses will be used by the libp2p transports to listen for new connections,
|
||||||
* while the announce addresses will be used for the peer addresses' to other peers in the network.
|
* while the announce addresses will be used for the peer addresses' to other peers in the network.
|
||||||
*/
|
*
|
||||||
class AddressManager {
|
|
||||||
/**
|
|
||||||
* @class
|
* @class
|
||||||
* @param {object} [options]
|
* @param {AddressManagerOptions} [options]
|
||||||
* @param {Array<string>} [options.listen = []] - list of multiaddrs string representation to listen.
|
|
||||||
* @param {Array<string>} [options.announce = []] - list of multiaddrs string representation to announce.
|
|
||||||
*/
|
*/
|
||||||
constructor ({ listen = [], announce = [] } = {}) {
|
constructor ({ listen = [], announce = [] } = {}) {
|
||||||
this.listen = new Set(listen)
|
this.listen = new Set(listen)
|
||||||
@ -27,7 +29,7 @@ class AddressManager {
|
|||||||
/**
|
/**
|
||||||
* Get peer listen multiaddrs.
|
* Get peer listen multiaddrs.
|
||||||
*
|
*
|
||||||
* @returns {Array<Multiaddr>}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
getListenAddrs () {
|
getListenAddrs () {
|
||||||
return Array.from(this.listen).map((a) => multiaddr(a))
|
return Array.from(this.listen).map((a) => multiaddr(a))
|
||||||
@ -36,7 +38,7 @@ class AddressManager {
|
|||||||
/**
|
/**
|
||||||
* Get peer announcing multiaddrs.
|
* Get peer announcing multiaddrs.
|
||||||
*
|
*
|
||||||
* @returns {Array<Multiaddr>}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
getAnnounceAddrs () {
|
getAnnounceAddrs () {
|
||||||
return Array.from(this.announce).map((a) => multiaddr(a))
|
return Array.from(this.announce).map((a) => multiaddr(a))
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:auto-relay')
|
const log = Object.assign(debug('libp2p:auto-relay'), {
|
||||||
log.error = debug('libp2p:auto-relay:error')
|
error: debug('libp2p:auto-relay:err')
|
||||||
|
})
|
||||||
|
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
@ -19,14 +20,25 @@ const {
|
|||||||
RELAY_RENDEZVOUS_NS
|
RELAY_RENDEZVOUS_NS
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('../peer-store/address-book').Address} Address
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} AutoRelayProperties
|
||||||
|
* @property {import('../')} libp2p
|
||||||
|
*
|
||||||
|
* @typedef {Object} AutoRelayOptions
|
||||||
|
* @property {number} [maxListeners = 1] - maximum number of relays to listen.
|
||||||
|
*/
|
||||||
|
|
||||||
class AutoRelay {
|
class AutoRelay {
|
||||||
/**
|
/**
|
||||||
* Creates an instance of AutoRelay.
|
* Creates an instance of AutoRelay.
|
||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {object} props
|
* @param {AutoRelayProperties & AutoRelayOptions} props
|
||||||
* @param {Libp2p} props.libp2p
|
|
||||||
* @param {number} [props.maxListeners = 1] - maximum number of relays to listen.
|
|
||||||
*/
|
*/
|
||||||
constructor ({ libp2p, maxListeners = 1 }) {
|
constructor ({ libp2p, maxListeners = 1 }) {
|
||||||
this._libp2p = libp2p
|
this._libp2p = libp2p
|
||||||
@ -58,7 +70,7 @@ class AutoRelay {
|
|||||||
*
|
*
|
||||||
* @param {Object} props
|
* @param {Object} props
|
||||||
* @param {PeerId} props.peerId
|
* @param {PeerId} props.peerId
|
||||||
* @param {Array<string>} props.protocols
|
* @param {string[]} props.protocols
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async _onProtocolChange ({ peerId, protocols }) {
|
async _onProtocolChange ({ peerId, protocols }) {
|
||||||
@ -78,6 +90,9 @@ class AutoRelay {
|
|||||||
// If protocol, check if can hop, store info in the metadataBook and listen on it
|
// If protocol, check if can hop, store info in the metadataBook and listen on it
|
||||||
try {
|
try {
|
||||||
const connection = this._connectionManager.get(peerId)
|
const connection = this._connectionManager.get(peerId)
|
||||||
|
if (!connection) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Do not hop on a relayed connection
|
// Do not hop on a relayed connection
|
||||||
if (connection.remoteAddr.protoCodes().includes(CIRCUIT_PROTO_CODE)) {
|
if (connection.remoteAddr.protoCodes().includes(CIRCUIT_PROTO_CODE)) {
|
||||||
@ -171,7 +186,7 @@ class AutoRelay {
|
|||||||
* 2. Dial and try to listen on the peers we know that support hop but are not connected.
|
* 2. Dial and try to listen on the peers we know that support hop but are not connected.
|
||||||
* 3. Search the network.
|
* 3. Search the network.
|
||||||
*
|
*
|
||||||
* @param {Array<string>} [peersToIgnore]
|
* @param {string[]} [peersToIgnore]
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async _listenOnAvailableHopRelays (peersToIgnore = []) {
|
async _listenOnAvailableHopRelays (peersToIgnore = []) {
|
||||||
|
@ -1,22 +1,42 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:circuit:hop')
|
const log = Object.assign(debug('libp2p:circuit:hop'), {
|
||||||
log.error = debug('libp2p:circuit:hop:error')
|
error: debug('libp2p:circuit:hop:err')
|
||||||
|
})
|
||||||
|
const errCode = require('err-code')
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const { validateAddrs } = require('./utils')
|
const { validateAddrs } = require('./utils')
|
||||||
const StreamHandler = require('./stream-handler')
|
const StreamHandler = require('./stream-handler')
|
||||||
const { CircuitRelay: CircuitPB } = require('../protocol')
|
const { CircuitRelay: CircuitPB } = require('../protocol')
|
||||||
const pipe = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const errCode = require('err-code')
|
|
||||||
const { codes: Errors } = require('../../errors')
|
const { codes: Errors } = require('../../errors')
|
||||||
|
|
||||||
const { stop } = require('./stop')
|
const { stop } = require('./stop')
|
||||||
|
|
||||||
const multicodec = require('./../multicodec')
|
const multicodec = require('./../multicodec')
|
||||||
|
|
||||||
module.exports.handleHop = async function handleHop ({
|
/**
|
||||||
|
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
|
||||||
|
* @typedef {import('../transport')} Transport
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} HopRequest
|
||||||
|
* @property {Connection} connection
|
||||||
|
* @property {CircuitRequest} request
|
||||||
|
* @property {StreamHandlerT} streamHandler
|
||||||
|
* @property {Transport} circuit
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HopRequest} options
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async function handleHop ({
|
||||||
connection,
|
connection,
|
||||||
request,
|
request,
|
||||||
streamHandler,
|
streamHandler,
|
||||||
@ -51,6 +71,9 @@ module.exports.handleHop = async function handleHop ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Handle being an active relay
|
// TODO: Handle being an active relay
|
||||||
|
if (!destinationConnection) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Handle the incoming HOP request by performing a STOP request
|
// Handle the incoming HOP request by performing a STOP request
|
||||||
const stopRequest = {
|
const stopRequest = {
|
||||||
@ -63,8 +86,7 @@ module.exports.handleHop = async function handleHop ({
|
|||||||
try {
|
try {
|
||||||
destinationStream = await stop({
|
destinationStream = await stop({
|
||||||
connection: destinationConnection,
|
connection: destinationConnection,
|
||||||
request: stopRequest,
|
request: stopRequest
|
||||||
circuit
|
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return log.error(err)
|
return log.error(err)
|
||||||
@ -91,10 +113,10 @@ module.exports.handleHop = async function handleHop ({
|
|||||||
*
|
*
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {Connection} options.connection - Connection to the relay
|
* @param {Connection} options.connection - Connection to the relay
|
||||||
* @param {*} options.request
|
* @param {CircuitRequest} options.request
|
||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
module.exports.hop = async function hop ({
|
async function hop ({
|
||||||
connection,
|
connection,
|
||||||
request
|
request
|
||||||
}) {
|
}) {
|
||||||
@ -123,7 +145,7 @@ module.exports.hop = async function hop ({
|
|||||||
* @param {Connection} options.connection - Connection to the relay
|
* @param {Connection} options.connection - Connection to the relay
|
||||||
* @returns {Promise<boolean>}
|
* @returns {Promise<boolean>}
|
||||||
*/
|
*/
|
||||||
module.exports.canHop = async function canHop ({
|
async function canHop ({
|
||||||
connection
|
connection
|
||||||
}) {
|
}) {
|
||||||
// Create a new stream to the relay
|
// Create a new stream to the relay
|
||||||
@ -149,11 +171,11 @@ module.exports.canHop = async function canHop ({
|
|||||||
*
|
*
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {StreamHandler} options.streamHandler
|
* @param {StreamHandlerT} options.streamHandler
|
||||||
* @param {Circuit} options.circuit
|
* @param {Transport} options.circuit
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
module.exports.handleCanHop = function handleCanHop ({
|
function handleCanHop ({
|
||||||
connection,
|
connection,
|
||||||
streamHandler,
|
streamHandler,
|
||||||
circuit
|
circuit
|
||||||
@ -165,3 +187,10 @@ module.exports.handleCanHop = function handleCanHop ({
|
|||||||
code: canHop ? CircuitPB.Status.SUCCESS : CircuitPB.Status.HOP_CANT_SPEAK_RELAY
|
code: canHop ? CircuitPB.Status.SUCCESS : CircuitPB.Status.HOP_CANT_SPEAK_RELAY
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
handleHop,
|
||||||
|
hop,
|
||||||
|
canHop,
|
||||||
|
handleCanHop
|
||||||
|
}
|
||||||
|
@ -1,23 +1,31 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:circuit:stop'), {
|
||||||
|
error: debug('libp2p:circuit:stop:err')
|
||||||
|
})
|
||||||
|
|
||||||
const { CircuitRelay: CircuitPB } = require('../protocol')
|
const { CircuitRelay: CircuitPB } = require('../protocol')
|
||||||
const multicodec = require('../multicodec')
|
const multicodec = require('../multicodec')
|
||||||
const StreamHandler = require('./stream-handler')
|
const StreamHandler = require('./stream-handler')
|
||||||
const { validateAddrs } = require('./utils')
|
const { validateAddrs } = require('./utils')
|
||||||
|
|
||||||
const debug = require('debug')
|
/**
|
||||||
const log = debug('libp2p:circuit:stop')
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
log.error = debug('libp2p:circuit:stop:error')
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
|
* @typedef {import('../../types').CircuitRequest} CircuitRequest
|
||||||
|
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles incoming STOP requests
|
* Handles incoming STOP requests
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {*} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {*} options.request - The CircuitRelay protobuf request (unencoded)
|
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
|
||||||
* @param {StreamHandler} options.streamHandler
|
* @param {StreamHandlerT} options.streamHandler
|
||||||
* @returns {Promise<*>} Resolves a duplex iterable
|
* @returns {Promise<MuxedStream>|void} Resolves a duplex iterable
|
||||||
*/
|
*/
|
||||||
module.exports.handleStop = function handleStop ({
|
module.exports.handleStop = function handleStop ({
|
||||||
connection,
|
connection,
|
||||||
@ -44,10 +52,10 @@ module.exports.handleStop = function handleStop ({
|
|||||||
* Creates a STOP request
|
* Creates a STOP request
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {*} options
|
* @param {Object} options
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @param {*} options.request - The CircuitRelay protobuf request (unencoded)
|
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
|
||||||
* @returns {Promise<*>} Resolves a duplex iterable
|
* @returns {Promise<MuxedStream|void>} Resolves a duplex iterable
|
||||||
*/
|
*/
|
||||||
module.exports.stop = async function stop ({
|
module.exports.stop = async function stop ({
|
||||||
connection,
|
connection,
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:circuit:stream-handler'), {
|
||||||
|
error: debug('libp2p:circuit:stream-handler:err')
|
||||||
|
})
|
||||||
|
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const { CircuitRelay: CircuitPB } = require('../protocol')
|
const { CircuitRelay: CircuitPB } = require('../protocol')
|
||||||
|
|
||||||
const debug = require('debug')
|
/**
|
||||||
const log = debug('libp2p:circuit:stream-handler')
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
log.error = debug('libp2p:circuit:stream-handler:error')
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T
|
||||||
|
*/
|
||||||
class StreamHandler {
|
class StreamHandler {
|
||||||
/**
|
/**
|
||||||
* Create a stream handler for connection
|
* Create a stream handler for connection
|
||||||
*
|
*
|
||||||
|
* @class
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {*} options.stream - A duplex iterable
|
* @param {MuxedStream} options.stream - A duplex iterable
|
||||||
* @param {number} options.maxLength - max bytes length of message
|
* @param {number} [options.maxLength = 4096] - max bytes length of message
|
||||||
*/
|
*/
|
||||||
constructor ({ stream, maxLength = 4096 }) {
|
constructor ({ stream, maxLength = 4096 }) {
|
||||||
this.stream = stream
|
this.stream = stream
|
||||||
@ -27,7 +36,7 @@ class StreamHandler {
|
|||||||
* Read and decode message
|
* Read and decode message
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @returns {void}
|
* @returns {Promise<T|undefined>}
|
||||||
*/
|
*/
|
||||||
async read () {
|
async read () {
|
||||||
const msg = await this.decoder.next()
|
const msg = await this.decoder.next()
|
||||||
@ -45,10 +54,12 @@ class StreamHandler {
|
|||||||
/**
|
/**
|
||||||
* Encode and write array of buffers
|
* Encode and write array of buffers
|
||||||
*
|
*
|
||||||
* @param {*} msg - An unencoded CircuitRelay protobuf message
|
* @param {CircuitPB} msg - An unencoded CircuitRelay protobuf message
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
write (msg) {
|
write (msg) {
|
||||||
log('write message type %s', msg.type)
|
log('write message type %s', msg.type)
|
||||||
|
// @ts-ignore lp.encode expects type type 'Buffer | BufferList', not 'Uint8Array'
|
||||||
this.shake.write(lp.encode.single(CircuitPB.encode(msg)))
|
this.shake.write(lp.encode.single(CircuitPB.encode(msg)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,11 +3,16 @@
|
|||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const { CircuitRelay } = require('../protocol')
|
const { CircuitRelay } = require('../protocol')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('./stream-handler')} StreamHandler
|
||||||
|
* @typedef {import('../../types').CircuitStatus} CircuitStatus
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a response
|
* Write a response
|
||||||
*
|
*
|
||||||
* @param {StreamHandler} streamHandler
|
* @param {StreamHandler} streamHandler
|
||||||
* @param {CircuitRelay.Status} status
|
* @param {CircuitStatus} status
|
||||||
*/
|
*/
|
||||||
function writeResponse (streamHandler, status) {
|
function writeResponse (streamHandler, status) {
|
||||||
streamHandler.write({
|
streamHandler.write({
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:relay')
|
const log = Object.assign(debug('libp2p:relay'), {
|
||||||
log.error = debug('libp2p:relay:error')
|
error: debug('libp2p:relay:err')
|
||||||
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setDelayedInterval,
|
setDelayedInterval,
|
||||||
@ -17,6 +18,23 @@ const {
|
|||||||
RELAY_RENDEZVOUS_NS
|
RELAY_RENDEZVOUS_NS
|
||||||
} = require('./constants')
|
} = require('./constants')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../')} Libp2p
|
||||||
|
*
|
||||||
|
* @typedef {Object} RelayAdvertiseOptions
|
||||||
|
* @property {number} [bootDelay = ADVERTISE_BOOT_DELAY]
|
||||||
|
* @property {boolean} [enabled = true]
|
||||||
|
* @property {number} [ttl = ADVERTISE_TTL]
|
||||||
|
*
|
||||||
|
* @typedef {Object} HopOptions
|
||||||
|
* @property {boolean} [enabled = false]
|
||||||
|
* @property {boolean} [active = false]
|
||||||
|
*
|
||||||
|
* @typedef {Object} AutoRelayOptions
|
||||||
|
* @property {number} [maxListeners = 2] - maximum number of relays to listen.
|
||||||
|
* @property {boolean} [enabled = false]
|
||||||
|
*/
|
||||||
|
|
||||||
class Relay {
|
class Relay {
|
||||||
/**
|
/**
|
||||||
* Creates an instance of Relay.
|
* Creates an instance of Relay.
|
||||||
|
@ -1,37 +1,27 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const EventEmitter = require('events')
|
const { EventEmitter } = require('events')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
|
|
||||||
const debug = require('debug')
|
/**
|
||||||
const log = debug('libp2p:circuit:listener')
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
log.err = debug('libp2p:circuit:error:listener')
|
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Libp2p} libp2p
|
* @param {import('../')} libp2p
|
||||||
* @returns {Listener} a transport listener
|
* @returns {Listener} a transport listener
|
||||||
*/
|
*/
|
||||||
module.exports = (libp2p) => {
|
module.exports = (libp2p) => {
|
||||||
const listener = new EventEmitter()
|
|
||||||
const listeningAddrs = new Map()
|
const listeningAddrs = new Map()
|
||||||
|
|
||||||
// Remove listeningAddrs when a peer disconnects
|
|
||||||
libp2p.connectionManager.on('peer:disconnect', (connection) => {
|
|
||||||
const deleted = listeningAddrs.delete(connection.remotePeer.toB58String())
|
|
||||||
|
|
||||||
if (deleted) {
|
|
||||||
// Announce listen addresses change
|
|
||||||
listener.emit('close')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add swarm handler and listen for incoming connections
|
* Add swarm handler and listen for incoming connections
|
||||||
*
|
*
|
||||||
* @param {Multiaddr} addr
|
* @param {Multiaddr} addr
|
||||||
* @returns {void}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
listener.listen = async (addr) => {
|
async function listen (addr) {
|
||||||
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
|
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
|
||||||
|
|
||||||
const relayConn = await libp2p.dial(multiaddr(addrString))
|
const relayConn = await libp2p.dial(multiaddr(addrString))
|
||||||
@ -41,13 +31,6 @@ module.exports = (libp2p) => {
|
|||||||
listener.emit('listening')
|
listener.emit('listening')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Remove the peers from our topology
|
|
||||||
*
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
listener.close = () => {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get fixed up multiaddrs
|
* Get fixed up multiaddrs
|
||||||
*
|
*
|
||||||
@ -64,7 +47,7 @@ module.exports = (libp2p) => {
|
|||||||
*
|
*
|
||||||
* @returns {Multiaddr[]}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
listener.getAddrs = () => {
|
function getAddrs () {
|
||||||
const addrs = []
|
const addrs = []
|
||||||
for (const addr of listeningAddrs.values()) {
|
for (const addr of listeningAddrs.values()) {
|
||||||
addrs.push(addr)
|
addrs.push(addr)
|
||||||
@ -72,5 +55,22 @@ module.exports = (libp2p) => {
|
|||||||
return addrs
|
return addrs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @type Listener */
|
||||||
|
const listener = Object.assign(new EventEmitter(), {
|
||||||
|
close: () => Promise.resolve(),
|
||||||
|
listen,
|
||||||
|
getAddrs
|
||||||
|
})
|
||||||
|
|
||||||
|
// Remove listeningAddrs when a peer disconnects
|
||||||
|
libp2p.connectionManager.on('peer:disconnect', (connection) => {
|
||||||
|
const deleted = listeningAddrs.delete(connection.remotePeer.toB58String())
|
||||||
|
|
||||||
|
if (deleted) {
|
||||||
|
// Announce listen addresses change
|
||||||
|
listener.emit('close')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return listener
|
return listener
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
const protobuf = require('protons')
|
const protobuf = require('protons')
|
||||||
|
|
||||||
|
/** @type {{CircuitRelay: import('../../types').CircuitMessageProto}} */
|
||||||
module.exports = protobuf(`
|
module.exports = protobuf(`
|
||||||
message CircuitRelay {
|
message CircuitRelay {
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:circuit')
|
const log = Object.assign(debug('libp2p:circuit'), {
|
||||||
log.error = debug('libp2p:circuit:error')
|
error: debug('libp2p:circuit:err')
|
||||||
|
})
|
||||||
|
|
||||||
const mafmt = require('mafmt')
|
const mafmt = require('mafmt')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const withIs = require('class-is')
|
|
||||||
const { CircuitRelay: CircuitPB } = require('./protocol')
|
const { CircuitRelay: CircuitPB } = require('./protocol')
|
||||||
|
|
||||||
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
|
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
|
||||||
@ -18,14 +18,23 @@ const { handleCanHop, handleHop, hop } = require('./circuit/hop')
|
|||||||
const { handleStop } = require('./circuit/stop')
|
const { handleStop } = require('./circuit/stop')
|
||||||
const StreamHandler = require('./circuit/stream-handler')
|
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 {
|
class Circuit {
|
||||||
/**
|
/**
|
||||||
* Creates an instance of the Circuit Transport.
|
* Creates an instance of the Circuit Transport.
|
||||||
*
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {Libp2p} options.libp2p
|
* @param {import('../')} options.libp2p
|
||||||
* @param {Upgrader} options.upgrader
|
* @param {import('../upgrader')} options.upgrader
|
||||||
*/
|
*/
|
||||||
constructor ({ libp2p, upgrader }) {
|
constructor ({ libp2p, upgrader }) {
|
||||||
this._dialer = libp2p.dialer
|
this._dialer = libp2p.dialer
|
||||||
@ -39,7 +48,13 @@ class Circuit {
|
|||||||
this._registrar.handle(multicodec, this._onProtocol.bind(this))
|
this._registrar.handle(multicodec, this._onProtocol.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} props
|
||||||
|
* @param {Connection} props.connection
|
||||||
|
* @param {MuxedStream} props.stream
|
||||||
|
*/
|
||||||
async _onProtocol ({ connection, stream }) {
|
async _onProtocol ({ connection, stream }) {
|
||||||
|
/** @type {import('./circuit/stream-handler')<CircuitRequest>} */
|
||||||
const streamHandler = new StreamHandler({ stream })
|
const streamHandler = new StreamHandler({ stream })
|
||||||
const request = await streamHandler.read()
|
const request = await streamHandler.read()
|
||||||
|
|
||||||
@ -71,8 +86,7 @@ class Circuit {
|
|||||||
virtualConnection = await handleStop({
|
virtualConnection = await handleStop({
|
||||||
connection,
|
connection,
|
||||||
request,
|
request,
|
||||||
streamHandler,
|
streamHandler
|
||||||
circuit
|
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -89,7 +103,7 @@ class Circuit {
|
|||||||
remoteAddr,
|
remoteAddr,
|
||||||
localAddr
|
localAddr
|
||||||
})
|
})
|
||||||
const type = CircuitPB.Type === CircuitPB.Type.HOP ? 'relay' : 'inbound'
|
const type = request.type === CircuitPB.Type.HOP ? 'relay' : 'inbound'
|
||||||
log('new %s connection %s', type, maConn.remoteAddr)
|
log('new %s connection %s', type, maConn.remoteAddr)
|
||||||
|
|
||||||
const conn = await this._upgrader.upgradeInbound(maConn)
|
const conn = await this._upgrader.upgradeInbound(maConn)
|
||||||
@ -101,10 +115,10 @@ class Circuit {
|
|||||||
/**
|
/**
|
||||||
* Dial a peer over a relay
|
* Dial a peer over a relay
|
||||||
*
|
*
|
||||||
* @param {multiaddr} ma - the multiaddr of the peer to dial
|
* @param {Multiaddr} ma - the multiaddr of the peer to dial
|
||||||
* @param {Object} options - dial options
|
* @param {Object} options - dial options
|
||||||
* @param {AbortSignal} [options.signal] - An optional abort signal
|
* @param {AbortSignal} [options.signal] - An optional abort signal
|
||||||
* @returns {Connection} - the connection
|
* @returns {Promise<Connection>} - the connection
|
||||||
*/
|
*/
|
||||||
async dial (ma, options) {
|
async dial (ma, options) {
|
||||||
// Check the multiaddr to see if it contains a relay and a destination peer
|
// Check the multiaddr to see if it contains a relay and a destination peer
|
||||||
@ -124,7 +138,6 @@ class Circuit {
|
|||||||
try {
|
try {
|
||||||
const virtualConnection = await hop({
|
const virtualConnection = await hop({
|
||||||
connection: relayConnection,
|
connection: relayConnection,
|
||||||
circuit: this,
|
|
||||||
request: {
|
request: {
|
||||||
type: CircuitPB.Type.HOP,
|
type: CircuitPB.Type.HOP,
|
||||||
srcPeer: {
|
srcPeer: {
|
||||||
@ -159,7 +172,7 @@ class Circuit {
|
|||||||
*
|
*
|
||||||
* @param {any} options
|
* @param {any} options
|
||||||
* @param {Function} handler
|
* @param {Function} handler
|
||||||
* @returns {listener}
|
* @returns {import('libp2p-interfaces/src/transport/types').Listener}
|
||||||
*/
|
*/
|
||||||
createListener (options, handler) {
|
createListener (options, handler) {
|
||||||
if (typeof options === 'function') {
|
if (typeof options === 'function') {
|
||||||
@ -170,14 +183,14 @@ class Circuit {
|
|||||||
// Called on successful HOP and STOP requests
|
// Called on successful HOP and STOP requests
|
||||||
this.handler = handler
|
this.handler = handler
|
||||||
|
|
||||||
return createListener(this._libp2p, options)
|
return createListener(this._libp2p)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter check for all Multiaddrs that this transport can dial on
|
* Filter check for all Multiaddrs that this transport can dial on
|
||||||
*
|
*
|
||||||
* @param {Array<Multiaddr>} multiaddrs
|
* @param {Multiaddr[]} multiaddrs
|
||||||
* @returns {Array<Multiaddr>}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
filter (multiaddrs) {
|
filter (multiaddrs) {
|
||||||
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
|
multiaddrs = Array.isArray(multiaddrs) ? multiaddrs : [multiaddrs]
|
||||||
@ -186,9 +199,20 @@ class Circuit {
|
|||||||
return mafmt.Circuit.matches(ma)
|
return mafmt.Circuit.matches(ma)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get [Symbol.toStringTag] () {
|
||||||
|
return 'Circuit'
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given value is a Transport instance.
|
||||||
|
*
|
||||||
|
* @param {any} other
|
||||||
|
* @returns {other is Transport}
|
||||||
|
*/
|
||||||
|
static isTransport (other) {
|
||||||
|
return Boolean(other && other[transportSymbol])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
module.exports = Circuit
|
||||||
* @type {Circuit}
|
|
||||||
*/
|
|
||||||
module.exports = withIs(Circuit, { className: 'Circuit', symbolName: '@libp2p/js-libp2p-circuit/circuit' })
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
const CID = require('cids')
|
const CID = require('cids')
|
||||||
const multihashing = require('multihashing-async')
|
const multihashing = require('multihashing-async')
|
||||||
|
|
||||||
|
const TextEncoder = require('ipfs-utils/src/text-encoder')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a namespace string into a cid.
|
* Convert a namespace string into a cid.
|
||||||
*
|
*
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:connection-manager')
|
const log = Object.assign(debug('libp2p:connection-manager'), {
|
||||||
log.error = debug('libp2p:connection-manager:error')
|
error: debug('libp2p:connection-manager:err')
|
||||||
|
})
|
||||||
|
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
@ -14,7 +15,7 @@ const { EventEmitter } = require('events')
|
|||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ERR_INVALID_PARAMETERS
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
@ -31,29 +32,39 @@ const defaultOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for managing known connections.
|
* @typedef {import('../')} Libp2p
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ConnectionManagerOptions
|
||||||
|
* @property {number} [maxConnections = Infinity] - The maximum number of connections allowed.
|
||||||
|
* @property {number} [minConnections = 0] - The minimum number of connections to avoid pruning.
|
||||||
|
* @property {number} [maxData = Infinity] - The max data (in and out), per average interval to allow.
|
||||||
|
* @property {number} [maxSentData = Infinity] - The max outgoing data, per average interval to allow.
|
||||||
|
* @property {number} [maxReceivedData = Infinity] - The max incoming data, per average interval to allow.
|
||||||
|
* @property {number} [maxEventLoopDelay = Infinity] - The upper limit the event loop can take to run.
|
||||||
|
* @property {number} [pollInterval = 2000] - How often, in milliseconds, metrics and latency should be checked.
|
||||||
|
* @property {number} [movingAverageInterval = 60000] - How often, in milliseconds, to compute averages.
|
||||||
|
* @property {number} [defaultPeerValue = 1] - The value of the peer.
|
||||||
|
* @property {boolean} [autoDial = true] - Should preemptively guarantee connections are above the low watermark.
|
||||||
|
* @property {number} [autoDialInterval = 10000] - How often, in milliseconds, it should preemptively guarantee connections are above the low watermark.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
*
|
*
|
||||||
* @fires ConnectionManager#peer:connect Emitted when a new peer is connected.
|
* @fires ConnectionManager#peer:connect Emitted when a new peer is connected.
|
||||||
* @fires ConnectionManager#peer:disconnect Emitted when a peer is disconnected.
|
* @fires ConnectionManager#peer:disconnect Emitted when a peer is disconnected.
|
||||||
*/
|
*/
|
||||||
class ConnectionManager extends EventEmitter {
|
class ConnectionManager extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
|
* Responsible for managing known connections.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {Libp2p} libp2p
|
* @param {Libp2p} libp2p
|
||||||
* @param {object} options
|
* @param {ConnectionManagerOptions} options
|
||||||
* @param {number} options.maxConnections - The maximum number of connections allowed. Default=Infinity
|
|
||||||
* @param {number} options.minConnections - The minimum number of connections to avoid pruning. Default=0
|
|
||||||
* @param {number} options.maxData - The max data (in and out), per average interval to allow. Default=Infinity
|
|
||||||
* @param {number} options.maxSentData - The max outgoing data, per average interval to allow. Default=Infinity
|
|
||||||
* @param {number} options.maxReceivedData - The max incoming data, per average interval to allow.. Default=Infinity
|
|
||||||
* @param {number} options.maxEventLoopDelay - The upper limit the event loop can take to run. Default=Infinity
|
|
||||||
* @param {number} options.pollInterval - How often, in milliseconds, metrics and latency should be checked. Default=2000
|
|
||||||
* @param {number} options.movingAverageInterval - How often, in milliseconds, to compute averages. Default=60000
|
|
||||||
* @param {number} options.defaultPeerValue - The value of the peer. Default=1
|
|
||||||
* @param {boolean} options.autoDial - Should preemptively guarantee connections are above the low watermark. Default=true
|
|
||||||
* @param {number} options.autoDialInterval - How often, in milliseconds, it should preemptively guarantee connections are above the low watermark. Default=10000
|
|
||||||
*/
|
*/
|
||||||
constructor (libp2p, options) {
|
constructor (libp2p, options = {}) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
this._libp2p = libp2p
|
this._libp2p = libp2p
|
||||||
@ -66,8 +77,6 @@ class ConnectionManager extends EventEmitter {
|
|||||||
|
|
||||||
log('options: %j', this._options)
|
log('options: %j', this._options)
|
||||||
|
|
||||||
this._libp2p = libp2p
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of peer identifiers to their peer value for pruning connections.
|
* Map of peer identifiers to their peer value for pruning connections.
|
||||||
*
|
*
|
||||||
@ -78,7 +87,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Map of connections per peer
|
* Map of connections per peer
|
||||||
*
|
*
|
||||||
* @type {Map<string, Array<conn>>}
|
* @type {Map<string, Connection[]>}
|
||||||
*/
|
*/
|
||||||
this.connections = new Map()
|
this.connections = new Map()
|
||||||
|
|
||||||
@ -159,15 +168,13 @@ class ConnectionManager extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {number} value - A number between 0 and 1
|
* @param {number} value - A number between 0 and 1
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
setPeerValue (peerId, value) {
|
setPeerValue (peerId, value) {
|
||||||
if (value < 0 || value > 1) {
|
if (value < 0 || value > 1) {
|
||||||
throw new Error('value should be a number between 0 and 1')
|
throw new Error('value should be a number between 0 and 1')
|
||||||
}
|
}
|
||||||
if (peerId.toB58String) {
|
this._peerValues.set(peerId.toB58String(), value)
|
||||||
peerId = peerId.toB58String()
|
|
||||||
}
|
|
||||||
this._peerValues.set(peerId, value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -177,6 +184,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
_checkMetrics () {
|
_checkMetrics () {
|
||||||
|
if (this._libp2p.metrics) {
|
||||||
const movingAverages = this._libp2p.metrics.global.movingAverages
|
const movingAverages = this._libp2p.metrics.global.movingAverages
|
||||||
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
|
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
|
||||||
this._checkMaxLimit('maxReceivedData', received)
|
this._checkMaxLimit('maxReceivedData', received)
|
||||||
@ -187,11 +195,13 @@ class ConnectionManager extends EventEmitter {
|
|||||||
log('metrics update', total)
|
log('metrics update', total)
|
||||||
this._timer = retimer(this._checkMetrics, this._options.pollInterval)
|
this._timer = retimer(this._checkMetrics, this._options.pollInterval)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks the incoming connection and check the connection limit
|
* Tracks the incoming connection and check the connection limit
|
||||||
*
|
*
|
||||||
* @param {Connection} connection
|
* @param {Connection} connection
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
onConnect (connection) {
|
onConnect (connection) {
|
||||||
const peerId = connection.remotePeer
|
const peerId = connection.remotePeer
|
||||||
@ -218,6 +228,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
* Removes the connection from tracking
|
* Removes the connection from tracking
|
||||||
*
|
*
|
||||||
* @param {Connection} connection
|
* @param {Connection} connection
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
onDisconnect (connection) {
|
onDisconnect (connection) {
|
||||||
const peerId = connection.remotePeer.toB58String()
|
const peerId = connection.remotePeer.toB58String()
|
||||||
@ -237,7 +248,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
* Get a connection with a peer.
|
* Get a connection with a peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Connection}
|
* @returns {Connection|null}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
const connections = this.getAll(peerId)
|
const connections = this.getAll(peerId)
|
||||||
@ -251,7 +262,7 @@ class ConnectionManager extends EventEmitter {
|
|||||||
* Get all open connections with a peer.
|
* Get all open connections with a peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Array<Connection>}
|
* @returns {Connection[]}
|
||||||
*/
|
*/
|
||||||
getAll (peerId) {
|
getAll (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6,7 +7,7 @@
|
|||||||
|
|
||||||
/* global window */
|
/* global window */
|
||||||
const globalThis = require('ipfs-utils/src/globalthis')
|
const globalThis = require('ipfs-utils/src/globalthis')
|
||||||
const EventEmitter = require('events')
|
const { EventEmitter } = require('events')
|
||||||
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
const VisibilityChangeEmitter = require('./visibility-change-emitter')
|
||||||
const debug = require('debug')('latency-monitor:LatencyMonitor')
|
const debug = require('debug')('latency-monitor:LatencyMonitor')
|
||||||
|
|
||||||
@ -17,6 +18,12 @@ const debug = require('debug')('latency-monitor:LatencyMonitor')
|
|||||||
* @property {number} maxMS What was the max time for a cb to be called
|
* @property {number} maxMS What was the max time for a cb to be called
|
||||||
* @property {number} avgMs What was the average time for a cb to be called
|
* @property {number} avgMs What was the average time for a cb to be called
|
||||||
* @property {number} lengthMs How long this interval was in ms
|
* @property {number} lengthMs How long this interval was in ms
|
||||||
|
*
|
||||||
|
* @typedef {Object} LatencyMonitorOptions
|
||||||
|
* @property {number} [latencyCheckIntervalMs=500] - How often to add a latency check event (ms)
|
||||||
|
* @property {number} [dataEmitIntervalMs=5000] - How often to summarize latency check events. null or 0 disables event firing
|
||||||
|
* @property {Function} [asyncTestFn] - What cb-style async function to use
|
||||||
|
* @property {number} [latencyRandomPercentage=5] - What percent (+/-) of latencyCheckIntervalMs should we randomly use? This helps avoid alignment to other events.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,6 +31,8 @@ const debug = require('debug')('latency-monitor:LatencyMonitor')
|
|||||||
* the asyncTestFn and timing how long it takes the callback to be called. It can also periodically emit stats about this.
|
* the asyncTestFn and timing how long it takes the callback to be called. It can also periodically emit stats about this.
|
||||||
* This can be disabled and stats can be pulled via setting dataEmitIntervalMs = 0.
|
* This can be disabled and stats can be pulled via setting dataEmitIntervalMs = 0.
|
||||||
*
|
*
|
||||||
|
* @extends {EventEmitter}
|
||||||
|
*
|
||||||
* The default implementation is an event loop latency monitor. This works by firing periodic events into the event loop
|
* The default implementation is an event loop latency monitor. This works by firing periodic events into the event loop
|
||||||
* and timing how long it takes to get back.
|
* and timing how long it takes to get back.
|
||||||
*
|
*
|
||||||
@ -37,11 +46,8 @@ const debug = require('debug')('latency-monitor:LatencyMonitor')
|
|||||||
*/
|
*/
|
||||||
class LatencyMonitor extends EventEmitter {
|
class LatencyMonitor extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* @param {object} [options]
|
* @class
|
||||||
* @param {number} [options.latencyCheckIntervalMs=500] - How often to add a latency check event (ms)
|
* @param {LatencyMonitorOptions} [options]
|
||||||
* @param {number} [options.dataEmitIntervalMs=5000] - How often to summarize latency check events. null or 0 disables event firing
|
|
||||||
* @param {Function} [options.asyncTestFn] - What cb-style async function to use
|
|
||||||
* @param {number} [options.latencyRandomPercentage=5] - What percent (+/-) of latencyCheckIntervalMs should we randomly use? This helps avoid alignment to other events.
|
|
||||||
*/
|
*/
|
||||||
constructor ({ latencyCheckIntervalMs, dataEmitIntervalMs, asyncTestFn, latencyRandomPercentage } = {}) {
|
constructor ({ latencyCheckIntervalMs, dataEmitIntervalMs, asyncTestFn, latencyRandomPercentage } = {}) {
|
||||||
super()
|
super()
|
||||||
@ -91,6 +97,7 @@ class LatencyMonitor extends EventEmitter {
|
|||||||
// See: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs
|
// See: http://stackoverflow.com/questions/6032429/chrome-timeouts-interval-suspended-in-background-tabs
|
||||||
if (isBrowser()) {
|
if (isBrowser()) {
|
||||||
that._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
that._visibilityChangeEmitter = new VisibilityChangeEmitter()
|
||||||
|
|
||||||
that._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
that._visibilityChangeEmitter.on('visibilityChange', (pageInFocus) => {
|
||||||
if (pageInFocus) {
|
if (pageInFocus) {
|
||||||
that._startTimers()
|
that._startTimers()
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
|
// @ts-nocheck
|
||||||
/* global document */
|
/* global document */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
|
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
|
||||||
*/
|
*/
|
||||||
'use strict'
|
'use strict'
|
||||||
const EventEmitter = require('events')
|
|
||||||
|
const { EventEmitter } = require('events')
|
||||||
|
|
||||||
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
||||||
|
|
||||||
@ -29,12 +31,12 @@ const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')
|
|||||||
* });
|
* });
|
||||||
* // To access the visibility state directly, call:
|
* // To access the visibility state directly, call:
|
||||||
* console.log('Am I focused now? ' + myVisibilityEmitter.isVisible());
|
* console.log('Am I focused now? ' + myVisibilityEmitter.isVisible());
|
||||||
*
|
|
||||||
* @class VisibilityChangeEmitter
|
|
||||||
*/
|
*/
|
||||||
module.exports = class VisibilityChangeEmitter extends EventEmitter {
|
class VisibilityChangeEmitter extends EventEmitter {
|
||||||
/**
|
/**
|
||||||
* Creates a VisibilityChangeEmitter
|
* Creates a VisibilityChangeEmitter
|
||||||
|
*
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
constructor () {
|
constructor () {
|
||||||
super()
|
super()
|
||||||
@ -119,3 +121,5 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
|
|||||||
this.emit('visibilityChange', visible)
|
this.emit('visibilityChange', visible)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = VisibilityChangeEmitter
|
||||||
|
@ -6,16 +6,34 @@ const { messages, codes } = require('./errors')
|
|||||||
const all = require('it-all')
|
const all = require('it-all')
|
||||||
const pAny = require('p-any')
|
const pAny = require('p-any')
|
||||||
|
|
||||||
module.exports = (node) => {
|
/**
|
||||||
const routers = node._modules.contentRouting || []
|
* @typedef {import('peer-id')} PeerId
|
||||||
const dht = node._dht
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
* @typedef {import('cids')} CID
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} GetData
|
||||||
|
* @property {PeerId} from
|
||||||
|
* @property {Uint8Array} val
|
||||||
|
*/
|
||||||
|
|
||||||
|
class ContentRouting {
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
* @param {import('./')} libp2p
|
||||||
|
*/
|
||||||
|
constructor (libp2p) {
|
||||||
|
this.libp2p = libp2p
|
||||||
|
this.routers = libp2p._modules.contentRouting || []
|
||||||
|
this.dht = libp2p._dht
|
||||||
|
|
||||||
// If we have the dht, make it first
|
// If we have the dht, make it first
|
||||||
if (dht) {
|
if (this.dht) {
|
||||||
routers.unshift(dht)
|
this.routers.unshift(this.dht)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all content routers in series to find providers of the given key.
|
* Iterates over all content routers in series to find providers of the given key.
|
||||||
* Once a content router succeeds, iteration will stop.
|
* Once a content router succeeds, iteration will stop.
|
||||||
@ -27,12 +45,12 @@ module.exports = (node) => {
|
|||||||
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>}
|
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>}
|
||||||
*/
|
*/
|
||||||
async * findProviders (key, options) {
|
async * findProviders (key, options) {
|
||||||
if (!routers.length) {
|
if (!this.routers.length) {
|
||||||
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
throw errCode(new Error('No content this.routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = await pAny(
|
const result = await pAny(
|
||||||
routers.map(async (router) => {
|
this.routers.map(async (router) => {
|
||||||
const provs = await all(router.findProviders(key, options))
|
const provs = await all(router.findProviders(key, options))
|
||||||
|
|
||||||
if (!provs || !provs.length) {
|
if (!provs || !provs.length) {
|
||||||
@ -45,7 +63,7 @@ module.exports = (node) => {
|
|||||||
for (const peer of result) {
|
for (const peer of result) {
|
||||||
yield peer
|
yield peer
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterates over all content routers in parallel to notify it is
|
* Iterates over all content routers in parallel to notify it is
|
||||||
@ -54,13 +72,13 @@ module.exports = (node) => {
|
|||||||
* @param {CID} key - The CID key of the content to find
|
* @param {CID} key - The CID key of the content to find
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async provide (key) { // eslint-disable-line require-await
|
async provide (key) {
|
||||||
if (!routers.length) {
|
if (!this.routers.length) {
|
||||||
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
throw errCode(new Error('No content routers available'), 'NO_ROUTERS_AVAILABLE')
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(routers.map((router) => router.provide(key)))
|
await Promise.all(this.routers.map((router) => router.provide(key)))
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the given key/value pair in the DHT.
|
* Store the given key/value pair in the DHT.
|
||||||
@ -71,13 +89,13 @@ module.exports = (node) => {
|
|||||||
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
* @param {number} [options.minPeers] - minimum number of peers required to successfully put
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async put (key, value, options) { // eslint-disable-line require-await
|
put (key, value, options) {
|
||||||
if (!node.isStarted() || !dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dht.put(key, value, options)
|
return this.dht.put(key, value, options)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value to the given key.
|
* Get the value to the given key.
|
||||||
@ -86,15 +104,15 @@ module.exports = (node) => {
|
|||||||
* @param {Uint8Array} key
|
* @param {Uint8Array} key
|
||||||
* @param {Object} [options] - get options
|
* @param {Object} [options] - get options
|
||||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||||
* @returns {Promise<{from: PeerId, val: Uint8Array}>}
|
* @returns {Promise<GetData>}
|
||||||
*/
|
*/
|
||||||
async get (key, options) { // eslint-disable-line require-await
|
get (key, options) {
|
||||||
if (!node.isStarted() || !dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dht.get(key, options)
|
return this.dht.get(key, options)
|
||||||
},
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the `n` values to the given key without sorting.
|
* Get the `n` values to the given key without sorting.
|
||||||
@ -103,14 +121,15 @@ module.exports = (node) => {
|
|||||||
* @param {number} nVals
|
* @param {number} nVals
|
||||||
* @param {Object} [options] - get options
|
* @param {Object} [options] - get options
|
||||||
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
* @param {number} [options.timeout] - optional timeout (default: 60000)
|
||||||
* @returns {Promise<Array<{from: PeerId, val: Uint8Array}>>}
|
* @returns {Promise<GetData[]>}
|
||||||
*/
|
*/
|
||||||
async getMany (key, nVals, options) { // eslint-disable-line require-await
|
async getMany (key, nVals, options) { // eslint-disable-line require-await
|
||||||
if (!node.isStarted() || !dht.isStarted) {
|
if (!this.libp2p.isStarted() || !this.dht.isStarted) {
|
||||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
throw errCode(new Error(messages.NOT_STARTED_YET), codes.DHT_NOT_STARTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dht.getMany(key, nVals, options)
|
return this.dht.getMany(key, nVals, options)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = ContentRouting
|
||||||
|
@ -1,14 +1,27 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const AbortController = require('abort-controller')
|
|
||||||
const anySignal = require('any-signal')
|
|
||||||
const debug = require('debug')
|
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const log = debug('libp2p:dialer:request')
|
const AbortController = require('abort-controller').default
|
||||||
log.error = debug('libp2p:dialer:request:error')
|
const anySignal = require('any-signal')
|
||||||
const FIFO = require('p-fifo')
|
const FIFO = require('p-fifo')
|
||||||
const pAny = require('p-any')
|
const pAny = require('p-any')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('./')} Dialer
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DialOptions
|
||||||
|
* @property {AbortSignal} signal
|
||||||
|
*
|
||||||
|
* @typedef {Object} DialRequestOptions
|
||||||
|
* @property {Multiaddr[]} addrs
|
||||||
|
* @property {(m: Multiaddr, options: DialOptions) => Promise<Connection>} dialAction
|
||||||
|
* @property {Dialer} dialer
|
||||||
|
*/
|
||||||
|
|
||||||
class DialRequest {
|
class DialRequest {
|
||||||
/**
|
/**
|
||||||
* Manages running the `dialAction` on multiple provided `addrs` in parallel
|
* Manages running the `dialAction` on multiple provided `addrs` in parallel
|
||||||
@ -17,10 +30,8 @@ class DialRequest {
|
|||||||
* started using `DialRequest.run(options)`. Once a single dial has succeeded,
|
* started using `DialRequest.run(options)`. Once a single dial has succeeded,
|
||||||
* all other dials in the request will be cancelled.
|
* all other dials in the request will be cancelled.
|
||||||
*
|
*
|
||||||
* @param {object} options
|
* @class
|
||||||
* @param {Multiaddr[]} options.addrs
|
* @param {DialRequestOptions} options
|
||||||
* @param {function(Multiaddr):Promise<Connection>} options.dialAction
|
|
||||||
* @param {Dialer} options.dialer
|
|
||||||
*/
|
*/
|
||||||
constructor ({
|
constructor ({
|
||||||
addrs,
|
addrs,
|
||||||
@ -34,11 +45,11 @@ class DialRequest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* @param {object} options
|
* @param {object} [options]
|
||||||
* @param {AbortSignal} options.signal - An AbortController signal
|
* @param {AbortSignal} [options.signal] - An AbortController signal
|
||||||
* @returns {Connection}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
async run (options) {
|
async run (options = {}) {
|
||||||
const tokens = this.dialer.getTokens(this.addrs.length)
|
const tokens = this.dialer.getTokens(this.addrs.length)
|
||||||
// If no tokens are available, throw
|
// If no tokens are available, throw
|
||||||
if (tokens.length < 1) {
|
if (tokens.length < 1) {
|
||||||
@ -78,4 +89,4 @@ class DialRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.DialRequest = DialRequest
|
module.exports = DialRequest
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:dialer'), {
|
||||||
|
error: debug('libp2p:dialer:err')
|
||||||
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
|
const multiaddr = require('multiaddr')
|
||||||
const TimeoutController = require('timeout-abort-controller')
|
const TimeoutController = require('timeout-abort-controller')
|
||||||
const anySignal = require('any-signal')
|
const anySignal = require('any-signal')
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:dialer')
|
|
||||||
log.error = debug('libp2p:dialer:error')
|
|
||||||
|
|
||||||
const { DialRequest } = require('./dial-request')
|
const DialRequest = require('./dial-request')
|
||||||
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
||||||
const getPeer = require('../get-peer')
|
const getPeer = require('../get-peer')
|
||||||
|
|
||||||
@ -19,17 +20,44 @@ const {
|
|||||||
MAX_PER_PEER_DIALS
|
MAX_PER_PEER_DIALS
|
||||||
} = require('../constants')
|
} = require('../constants')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
* @typedef {import('../transport-manager')} TransportManager
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} DialerProperties
|
||||||
|
* @property {PeerStore} peerStore
|
||||||
|
* @property {TransportManager} transportManager
|
||||||
|
*
|
||||||
|
* @typedef {(addr:Multiaddr) => Promise<string[]>} Resolver
|
||||||
|
*
|
||||||
|
* @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 {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
|
||||||
|
*
|
||||||
|
* @typedef DialTarget
|
||||||
|
* @property {string} id
|
||||||
|
* @property {Multiaddr[]} addrs
|
||||||
|
*
|
||||||
|
* @typedef PendingDial
|
||||||
|
* @property {DialRequest} dialRequest
|
||||||
|
* @property {TimeoutController} controller
|
||||||
|
* @property {Promise} promise
|
||||||
|
* @property {function():void} destroy
|
||||||
|
*/
|
||||||
|
|
||||||
class Dialer {
|
class Dialer {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {object} options
|
* @param {DialerProperties & DialerOptions} options
|
||||||
* @param {TransportManager} options.transportManager
|
|
||||||
* @param {Peerstore} options.peerStore
|
|
||||||
* @param {(addresses: Array<Address) => Array<Address>} [options.addressSorter = publicAddressesFirst] - Sort the known addresses of a peer before trying to dial.
|
|
||||||
* @param {number} [options.concurrency = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
|
|
||||||
* @param {number} [options.perPeerLimit = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
|
|
||||||
* @param {number} [options.timeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
|
|
||||||
* @param {object} [options.resolvers = {}] - multiaddr resolvers to use when dialing
|
|
||||||
*/
|
*/
|
||||||
constructor ({
|
constructor ({
|
||||||
transportManager,
|
transportManager,
|
||||||
@ -102,12 +130,6 @@ class Dialer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef DialTarget
|
|
||||||
* @property {string} id
|
|
||||||
* @property {Multiaddr[]} addrs
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a DialTarget. The DialTarget is used to create and track
|
* Creates a DialTarget. The DialTarget is used to create and track
|
||||||
* the DialRequest to a given peer.
|
* the DialRequest to a given peer.
|
||||||
@ -145,14 +167,6 @@ class Dialer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef PendingDial
|
|
||||||
* @property {DialRequest} dialRequest
|
|
||||||
* @property {TimeoutController} controller
|
|
||||||
* @property {Promise} promise
|
|
||||||
* @property {function():void} destroy
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a PendingDial that wraps the underlying DialRequest
|
* Creates a PendingDial that wraps the underlying DialRequest
|
||||||
*
|
*
|
||||||
@ -162,7 +176,7 @@ class Dialer {
|
|||||||
* @param {AbortSignal} [options.signal] - An AbortController signal
|
* @param {AbortSignal} [options.signal] - An AbortController signal
|
||||||
* @returns {PendingDial}
|
* @returns {PendingDial}
|
||||||
*/
|
*/
|
||||||
_createPendingDial (dialTarget, options) {
|
_createPendingDial (dialTarget, options = {}) {
|
||||||
const dialAction = (addr, options) => {
|
const dialAction = (addr, options) => {
|
||||||
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
|
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
|
||||||
return this.transportManager.dial(addr, options)
|
return this.transportManager.dial(addr, options)
|
||||||
@ -211,7 +225,7 @@ class Dialer {
|
|||||||
* Resolve multiaddr recursively.
|
* Resolve multiaddr recursively.
|
||||||
*
|
*
|
||||||
* @param {Multiaddr} ma
|
* @param {Multiaddr} ma
|
||||||
* @returns {Promise<Array<Multiaddr>>}
|
* @returns {Promise<Multiaddr[]>}
|
||||||
*/
|
*/
|
||||||
async _resolve (ma) {
|
async _resolve (ma) {
|
||||||
// TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
|
// TODO: recursive logic should live in multiaddr once dns4/dns6 support is in place
|
||||||
@ -228,19 +242,20 @@ class Dialer {
|
|||||||
return this._resolve(nm)
|
return this._resolve(nm)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
return recursiveMultiaddrs.flat().reduce((array, newM) => {
|
const addrs = recursiveMultiaddrs.flat()
|
||||||
|
return addrs.reduce((array, newM) => {
|
||||||
if (!array.find(m => m.equals(newM))) {
|
if (!array.find(m => m.equals(newM))) {
|
||||||
array.push(newM)
|
array.push(newM)
|
||||||
}
|
}
|
||||||
return array
|
return array
|
||||||
}, []) // Unique addresses
|
}, /** @type {Multiaddr[]} */([]))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve a given multiaddr. If this fails, an empty array will be returned
|
* Resolve a given multiaddr. If this fails, an empty array will be returned
|
||||||
*
|
*
|
||||||
* @param {Multiaddr} ma
|
* @param {Multiaddr} ma
|
||||||
* @returns {Promise<Array<Multiaddr>>}
|
* @returns {Promise<Multiaddr[]>}
|
||||||
*/
|
*/
|
||||||
async _resolveRecord (ma) {
|
async _resolveRecord (ma) {
|
||||||
try {
|
try {
|
||||||
|
@ -6,12 +6,16 @@ const errCode = require('err-code')
|
|||||||
|
|
||||||
const { codes } = require('./errors')
|
const { codes } = require('./errors')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given `peer` to a `Peer` object.
|
* Converts the given `peer` to a `Peer` object.
|
||||||
* If a multiaddr is received, the addressBook is updated.
|
* If a multiaddr is received, the addressBook is updated.
|
||||||
*
|
*
|
||||||
* @param {PeerId|Multiaddr|string} peer
|
* @param {PeerId|Multiaddr|string} peer
|
||||||
* @returns {{ id: PeerId, multiaddrs: Array<Multiaddr> }}
|
* @returns {{ id: PeerId, multiaddrs: Multiaddr[]|undefined }}
|
||||||
*/
|
*/
|
||||||
function getPeer (peer) {
|
function getPeer (peer) {
|
||||||
if (typeof peer === 'string') {
|
if (typeof peer === 'string') {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
// @ts-ignore file not listed within the file list of projects
|
||||||
const libp2pVersion = require('../../package.json').version
|
const libp2pVersion = require('../../package.json').version
|
||||||
|
|
||||||
module.exports.PROTOCOL_VERSION = 'ipfs/0.1.0'
|
module.exports.PROTOCOL_VERSION = 'ipfs/0.1.0'
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:identify')
|
const log = Object.assign(debug('libp2p:identify'), {
|
||||||
log.error = debug('libp2p:identify:error')
|
error: debug('libp2p:identify:err')
|
||||||
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const pb = require('it-protocol-buffers')
|
const pb = require('it-protocol-buffers')
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
const pipe = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const { collect, take, consume } = require('streaming-iterables')
|
const { collect, take, consume } = require('streaming-iterables')
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
|
|
||||||
@ -29,49 +29,22 @@ const {
|
|||||||
|
|
||||||
const { codes } = require('../errors')
|
const { codes } = require('../errors')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
|
*/
|
||||||
|
|
||||||
class IdentifyService {
|
class IdentifyService {
|
||||||
/**
|
|
||||||
* Takes the `addr` and converts it to a Multiaddr if possible
|
|
||||||
*
|
|
||||||
* @param {Uint8Array | string} addr
|
|
||||||
* @returns {Multiaddr|null}
|
|
||||||
*/
|
|
||||||
static getCleanMultiaddr (addr) {
|
|
||||||
if (addr && addr.length > 0) {
|
|
||||||
try {
|
|
||||||
return multiaddr(addr)
|
|
||||||
} catch (_) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {object} options
|
* @param {Object} options
|
||||||
* @param {Libp2p} options.libp2p
|
* @param {import('../')} options.libp2p
|
||||||
*/
|
*/
|
||||||
constructor ({ libp2p }) {
|
constructor ({ libp2p }) {
|
||||||
/**
|
|
||||||
* @property {PeerStore}
|
|
||||||
*/
|
|
||||||
this.peerStore = libp2p.peerStore
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {ConnectionManager}
|
|
||||||
*/
|
|
||||||
this.connectionManager = libp2p.connectionManager
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {PeerId}
|
|
||||||
*/
|
|
||||||
this.peerId = libp2p.peerId
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {AddressManager}
|
|
||||||
*/
|
|
||||||
this._libp2p = libp2p
|
this._libp2p = libp2p
|
||||||
|
this.peerStore = libp2p.peerStore
|
||||||
|
this.connectionManager = libp2p.connectionManager
|
||||||
|
this.peerId = libp2p.peerId
|
||||||
|
|
||||||
this.handleMessage = this.handleMessage.bind(this)
|
this.handleMessage = this.handleMessage.bind(this)
|
||||||
|
|
||||||
@ -84,6 +57,7 @@ class IdentifyService {
|
|||||||
|
|
||||||
this.peerStore.metadataBook.set(this.peerId, 'AgentVersion', uint8ArrayFromString(this._host.agentVersion))
|
this.peerStore.metadataBook.set(this.peerId, 'AgentVersion', uint8ArrayFromString(this._host.agentVersion))
|
||||||
this.peerStore.metadataBook.set(this.peerId, 'ProtocolVersion', uint8ArrayFromString(this._host.protocolVersion))
|
this.peerStore.metadataBook.set(this.peerId, 'ProtocolVersion', uint8ArrayFromString(this._host.protocolVersion))
|
||||||
|
// When a new connection happens, trigger identify
|
||||||
this.connectionManager.on('peer:connect', (connection) => {
|
this.connectionManager.on('peer:connect', (connection) => {
|
||||||
this.identify(connection).catch(log.error)
|
this.identify(connection).catch(log.error)
|
||||||
})
|
})
|
||||||
@ -106,8 +80,8 @@ class IdentifyService {
|
|||||||
/**
|
/**
|
||||||
* Send an Identify Push update to the list of connections
|
* Send an Identify Push update to the list of connections
|
||||||
*
|
*
|
||||||
* @param {Array<Connection>} connections
|
* @param {Connection[]} connections
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void[]>}
|
||||||
*/
|
*/
|
||||||
async push (connections) {
|
async push (connections) {
|
||||||
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
|
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
|
||||||
@ -234,11 +208,11 @@ class IdentifyService {
|
|||||||
/**
|
/**
|
||||||
* A handler to register with Libp2p to process identify messages.
|
* A handler to register with Libp2p to process identify messages.
|
||||||
*
|
*
|
||||||
* @param {object} options
|
* @param {Object} options
|
||||||
* @param {string} options.protocol
|
|
||||||
* @param {*} options.stream
|
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
* @returns {Promise<void>}
|
* @param {MuxedStream} options.stream
|
||||||
|
* @param {string} options.protocol
|
||||||
|
* @returns {Promise<void>|undefined}
|
||||||
*/
|
*/
|
||||||
handleMessage ({ connection, stream, protocol }) {
|
handleMessage ({ connection, stream, protocol }) {
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
@ -256,9 +230,10 @@ class IdentifyService {
|
|||||||
* to the requesting peer over the given `connection`
|
* to the requesting peer over the given `connection`
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {object} options
|
* @param {Object} options
|
||||||
* @param {*} options.stream
|
* @param {MuxedStream} options.stream
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async _handleIdentify ({ connection, stream }) {
|
async _handleIdentify ({ connection, stream }) {
|
||||||
let publicKey = new Uint8Array(0)
|
let publicKey = new Uint8Array(0)
|
||||||
@ -296,8 +271,9 @@ class IdentifyService {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {*} options.stream
|
* @param {MuxedStream} options.stream
|
||||||
* @param {Connection} options.connection
|
* @param {Connection} options.connection
|
||||||
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async _handlePush ({ connection, stream }) {
|
async _handlePush ({ connection, stream }) {
|
||||||
let message
|
let message
|
||||||
@ -337,16 +313,36 @@ class IdentifyService {
|
|||||||
// Update the protocols
|
// Update the protocols
|
||||||
this.peerStore.protoBook.set(id, message.protocols)
|
this.peerStore.protoBook.set(id, message.protocols)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the `addr` and converts it to a Multiaddr if possible
|
||||||
|
*
|
||||||
|
* @param {Uint8Array | string} addr
|
||||||
|
* @returns {multiaddr|null}
|
||||||
|
*/
|
||||||
|
static getCleanMultiaddr (addr) {
|
||||||
|
if (addr && addr.length > 0) {
|
||||||
|
try {
|
||||||
|
return multiaddr(addr)
|
||||||
|
} catch (_) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports.IdentifyService = IdentifyService
|
|
||||||
/**
|
/**
|
||||||
* The protocols the IdentifyService supports
|
* The protocols the IdentifyService supports
|
||||||
*
|
*
|
||||||
* @property multicodecs
|
* @property multicodecs
|
||||||
*/
|
*/
|
||||||
module.exports.multicodecs = {
|
const multicodecs = {
|
||||||
IDENTIFY: MULTICODEC_IDENTIFY,
|
IDENTIFY: MULTICODEC_IDENTIFY,
|
||||||
IDENTIFY_PUSH: MULTICODEC_IDENTIFY_PUSH
|
IDENTIFY_PUSH: MULTICODEC_IDENTIFY_PUSH
|
||||||
}
|
}
|
||||||
module.exports.Message = Message
|
|
||||||
|
IdentifyService.multicodecs = multicodecs
|
||||||
|
IdentifyService.Messsage = Message
|
||||||
|
|
||||||
|
module.exports = IdentifyService
|
||||||
|
145
src/index.js
145
src/index.js
@ -1,16 +1,17 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const { EventEmitter } = require('events')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p'), {
|
||||||
|
error: debug('libp2p:err')
|
||||||
|
})
|
||||||
|
const { EventEmitter } = require('events')
|
||||||
const globalThis = require('ipfs-utils/src/globalthis')
|
const globalThis = require('ipfs-utils/src/globalthis')
|
||||||
const log = debug('libp2p')
|
|
||||||
log.error = debug('libp2p:error')
|
|
||||||
|
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const PeerRouting = require('./peer-routing')
|
const PeerRouting = require('./peer-routing')
|
||||||
const contentRouting = require('./content-routing')
|
const ContentRouting = require('./content-routing')
|
||||||
const getPeer = require('./get-peer')
|
const getPeer = require('./get-peer')
|
||||||
const { validate: validateConfig } = require('./config')
|
const { validate: validateConfig } = require('./config')
|
||||||
const { codes, messages } = require('./errors')
|
const { codes, messages } = require('./errors')
|
||||||
@ -29,22 +30,95 @@ const PubsubAdapter = require('./pubsub-adapter')
|
|||||||
const PersistentPeerStore = require('./peer-store/persistent')
|
const PersistentPeerStore = require('./peer-store/persistent')
|
||||||
const Registrar = require('./registrar')
|
const Registrar = require('./registrar')
|
||||||
const ping = require('./ping')
|
const ping = require('./ping')
|
||||||
const {
|
const IdentifyService = require('./identify')
|
||||||
IdentifyService,
|
const IDENTIFY_PROTOCOLS = IdentifyService.multicodecs
|
||||||
multicodecs: IDENTIFY_PROTOCOLS
|
|
||||||
} = require('./identify')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @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/stream-muxer/types').MuxerFactory} MuxerFactory
|
||||||
|
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
||||||
|
* @typedef {import('libp2p-interfaces/src/pubsub')} Pubsub
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PeerStoreOptions
|
||||||
|
* @property {boolean} persistence
|
||||||
|
*
|
||||||
|
* @typedef {Object} PeerDiscoveryOptions
|
||||||
|
* @property {boolean} autoDial
|
||||||
|
*
|
||||||
|
* @typedef {Object} RelayOptions
|
||||||
|
* @property {boolean} enabled
|
||||||
|
* @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 {PeerDiscoveryOptions} [peerDiscovery]
|
||||||
|
* @property {Pubsub} [pubsub] pubsub module options
|
||||||
|
* @property {RelayOptions} [relay]
|
||||||
|
* @property {Record<string, Object>} [transport] transport options indexed by transport key
|
||||||
|
*
|
||||||
|
* @typedef {Object} Libp2pModules
|
||||||
|
* @property {TransportFactory[]} transport
|
||||||
|
* @property {MuxerFactory[]} streamMuxer
|
||||||
|
* @property {Crypto[]} connEncryption
|
||||||
|
*
|
||||||
|
* @typedef {Object} Libp2pOptions
|
||||||
|
* @property {Libp2pModules} modules libp2p modules to use
|
||||||
|
* @property {import('./address-manager').AddressManagerOptions} [addresses]
|
||||||
|
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
|
||||||
|
* @property {import('./dialer').DialerOptions} [dialer]
|
||||||
|
* @property {import('./metrics').MetricsOptions} [metrics]
|
||||||
|
* @property {Object} [keychain]
|
||||||
|
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
|
||||||
|
* @property {PeerStoreOptions & import('./peer-store/persistent').PersistentPeerStoreOptions} [peerStore]
|
||||||
|
* @property {Libp2pConfig} [config]
|
||||||
|
* @property {PeerId} peerId
|
||||||
|
*
|
||||||
|
* @typedef {Object} CreateOptions
|
||||||
|
* @property {PeerId} peerId
|
||||||
|
*
|
||||||
|
* @extends {EventEmitter}
|
||||||
* @fires Libp2p#error Emitted when an error occurs
|
* @fires Libp2p#error Emitted when an error occurs
|
||||||
* @fires Libp2p#peer:discovery Emitted when a peer is discovered
|
* @fires Libp2p#peer:discovery Emitted when a peer is discovered
|
||||||
*/
|
*/
|
||||||
class Libp2p extends EventEmitter {
|
class Libp2p extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Like `new Libp2p(options)` except it will create a `PeerId`
|
||||||
|
* instance if one is not provided in options.
|
||||||
|
*
|
||||||
|
* @param {Libp2pOptions & CreateOptions} options - Libp2p configuration options
|
||||||
|
* @returns {Promise<Libp2p>}
|
||||||
|
*/
|
||||||
|
static async create (options) {
|
||||||
|
if (options.peerId) {
|
||||||
|
return new Libp2p(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
const peerId = await PeerId.create()
|
||||||
|
|
||||||
|
options.peerId = peerId
|
||||||
|
return new Libp2p(options)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Libp2p node.
|
||||||
|
*
|
||||||
|
* @class
|
||||||
|
* @param {Libp2pOptions} _options
|
||||||
|
*/
|
||||||
constructor (_options) {
|
constructor (_options) {
|
||||||
super()
|
super()
|
||||||
// validateConfig will ensure the config is correct,
|
// validateConfig will ensure the config is correct,
|
||||||
// and add default values where appropriate
|
// and add default values where appropriate
|
||||||
this._options = validateConfig(_options)
|
this._options = validateConfig(_options)
|
||||||
|
|
||||||
|
/** @type {PeerId} */
|
||||||
this.peerId = this._options.peerId
|
this.peerId = this._options.peerId
|
||||||
this.datastore = this._options.datastore
|
this.datastore = this._options.datastore
|
||||||
|
|
||||||
@ -147,6 +221,7 @@ class Libp2p extends EventEmitter {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (this._config.relay.enabled) {
|
if (this._config.relay.enabled) {
|
||||||
|
// @ts-ignore Circuit prototype
|
||||||
this.transportManager.add(Circuit.prototype[Symbol.toStringTag], Circuit)
|
this.transportManager.add(Circuit.prototype[Symbol.toStringTag], Circuit)
|
||||||
this.relay = new Relay(this)
|
this.relay = new Relay(this)
|
||||||
}
|
}
|
||||||
@ -188,13 +263,14 @@ class Libp2p extends EventEmitter {
|
|||||||
if (this._modules.pubsub) {
|
if (this._modules.pubsub) {
|
||||||
const Pubsub = this._modules.pubsub
|
const Pubsub = this._modules.pubsub
|
||||||
// using pubsub adapter with *DEPRECATED* handlers functionality
|
// using pubsub adapter with *DEPRECATED* handlers functionality
|
||||||
|
/** @type {Pubsub} */
|
||||||
this.pubsub = PubsubAdapter(Pubsub, this, this._config.pubsub)
|
this.pubsub = PubsubAdapter(Pubsub, this, this._config.pubsub)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach remaining APIs
|
// Attach remaining APIs
|
||||||
// peer and content routing will automatically get modules from _modules and _dht
|
// peer and content routing will automatically get modules from _modules and _dht
|
||||||
this.peerRouting = new PeerRouting(this)
|
this.peerRouting = new PeerRouting(this)
|
||||||
this.contentRouting = contentRouting(this)
|
this.contentRouting = new ContentRouting(this)
|
||||||
|
|
||||||
// Mount default protocols
|
// Mount default protocols
|
||||||
ping.mount(this)
|
ping.mount(this)
|
||||||
@ -208,13 +284,16 @@ class Libp2p extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @param {string} eventName
|
* @param {string} eventName
|
||||||
* @param {...any} args
|
* @param {...any} args
|
||||||
* @returns {void}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
emit (eventName, ...args) {
|
emit (eventName, ...args) {
|
||||||
|
// TODO: do we still need this?
|
||||||
|
// @ts-ignore _events does not exist in libp2p
|
||||||
if (eventName === 'error' && !this._events.error) {
|
if (eventName === 'error' && !this._events.error) {
|
||||||
log.error(...args)
|
log.error(args)
|
||||||
|
return false
|
||||||
} else {
|
} else {
|
||||||
super.emit(eventName, ...args)
|
return super.emit(eventName, ...args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,9 +367,13 @@ class Libp2p extends EventEmitter {
|
|||||||
* Imports the private key as 'self', if needed.
|
* Imports the private key as 'self', if needed.
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @returns {void}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async loadKeychain () {
|
async loadKeychain () {
|
||||||
|
if (!this.keychain) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.keychain.findKeyByName('self')
|
await this.keychain.findKeyByName('self')
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -317,12 +400,12 @@ class Libp2p extends EventEmitter {
|
|||||||
* peer will be added to the nodes `peerStore`
|
* peer will be added to the nodes `peerStore`
|
||||||
*
|
*
|
||||||
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||||
* @param {object} options
|
* @param {object} [options]
|
||||||
* @param {AbortSignal} [options.signal]
|
* @param {AbortSignal} [options.signal]
|
||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
dial (peer, options) {
|
dial (peer, options) {
|
||||||
return this.dialProtocol(peer, null, options)
|
return this.dialProtocol(peer, [], options)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -333,7 +416,7 @@ class Libp2p extends EventEmitter {
|
|||||||
* @async
|
* @async
|
||||||
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
* @param {PeerId|Multiaddr|string} peer - The peer to dial
|
||||||
* @param {string[]|string} protocols
|
* @param {string[]|string} protocols
|
||||||
* @param {object} options
|
* @param {object} [options]
|
||||||
* @param {AbortSignal} [options.signal]
|
* @param {AbortSignal} [options.signal]
|
||||||
* @returns {Promise<Connection|*>}
|
* @returns {Promise<Connection|*>}
|
||||||
*/
|
*/
|
||||||
@ -353,7 +436,7 @@ class Libp2p extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If a protocol was provided, create a new stream
|
// If a protocol was provided, create a new stream
|
||||||
if (protocols) {
|
if (protocols && protocols.length) {
|
||||||
return connection.newStream(protocols)
|
return connection.newStream(protocols)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -365,7 +448,7 @@ class Libp2p extends EventEmitter {
|
|||||||
* by transports to listen with the announce addresses.
|
* by transports to listen with the announce addresses.
|
||||||
* Duplicated addresses and noAnnounce addresses are filtered out.
|
* Duplicated addresses and noAnnounce addresses are filtered out.
|
||||||
*
|
*
|
||||||
* @returns {Array<Multiaddr>}
|
* @returns {Multiaddr[]}
|
||||||
*/
|
*/
|
||||||
get multiaddrs () {
|
get multiaddrs () {
|
||||||
const announceAddrs = this.addressManager.getAnnounceAddrs()
|
const announceAddrs = this.addressManager.getAnnounceAddrs()
|
||||||
@ -382,7 +465,7 @@ class Libp2p extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Disconnects all connections to the given `peer`
|
* Disconnects all connections to the given `peer`
|
||||||
*
|
*
|
||||||
* @param {PeerId|multiaddr|string} peer - the peer to close connections to
|
* @param {PeerId|Multiaddr|string} peer - the peer to close connections to
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async hangUp (peer) {
|
async hangUp (peer) {
|
||||||
@ -422,7 +505,7 @@ class Libp2p extends EventEmitter {
|
|||||||
* Registers the `handler` for each protocol
|
* Registers the `handler` for each protocol
|
||||||
*
|
*
|
||||||
* @param {string[]|string} protocols
|
* @param {string[]|string} protocols
|
||||||
* @param {function({ connection:*, stream:*, protocol:string })} handler
|
* @param {({ connection: Connection, stream: MuxedStream, protocol: string }) => void} handler
|
||||||
*/
|
*/
|
||||||
handle (protocols, handler) {
|
handle (protocols, handler) {
|
||||||
protocols = Array.isArray(protocols) ? protocols : [protocols]
|
protocols = Array.isArray(protocols) ? protocols : [protocols]
|
||||||
@ -510,7 +593,7 @@ class Libp2p extends EventEmitter {
|
|||||||
* Known peers may be emitted.
|
* Known peers may be emitted.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {{ id: PeerId, multiaddrs: Array<Multiaddr>, protocols: Array<string> }} peer
|
* @param {{ id: PeerId, multiaddrs: Multiaddr[], protocols: string[] }} peer
|
||||||
*/
|
*/
|
||||||
_onDiscoveryPeer (peer) {
|
_onDiscoveryPeer (peer) {
|
||||||
if (peer.id.toB58String() === this.peerId.toB58String()) {
|
if (peer.id.toB58String() === this.peerId.toB58String()) {
|
||||||
@ -588,7 +671,9 @@ class Libp2p extends EventEmitter {
|
|||||||
|
|
||||||
// Transport modules with discovery
|
// Transport modules with discovery
|
||||||
for (const Transport of this.transportManager.getTransports()) {
|
for (const Transport of this.transportManager.getTransports()) {
|
||||||
|
// @ts-ignore Transport interface does not include discovery
|
||||||
if (Transport.discovery) {
|
if (Transport.discovery) {
|
||||||
|
// @ts-ignore Transport interface does not include discovery
|
||||||
setupService(Transport.discovery)
|
setupService(Transport.discovery)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -597,22 +682,4 @@ class Libp2p extends EventEmitter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Like `new Libp2p(options)` except it will create a `PeerId`
|
|
||||||
* instance if one is not provided in options.
|
|
||||||
*
|
|
||||||
* @param {object} options - Libp2p configuration options
|
|
||||||
* @returns {Promise<Libp2p>}
|
|
||||||
*/
|
|
||||||
Libp2p.create = async function create (options = {}) {
|
|
||||||
if (options.peerId) {
|
|
||||||
return new Libp2p(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
const peerId = await PeerId.create()
|
|
||||||
|
|
||||||
options.peerId = peerId
|
|
||||||
return new Libp2p(options)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Libp2p
|
module.exports = Libp2p
|
||||||
|
@ -1,21 +1,33 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:plaintext'), {
|
||||||
|
error: debug('libp2p:plaintext:err')
|
||||||
|
})
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const lp = require('it-length-prefixed')
|
const lp = require('it-length-prefixed')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:plaintext')
|
|
||||||
log.error = debug('libp2p:plaintext:error')
|
|
||||||
const { UnexpectedPeerError, InvalidCryptoExchangeError } = require('libp2p-interfaces/src/crypto/errors')
|
const { UnexpectedPeerError, InvalidCryptoExchangeError } = require('libp2p-interfaces/src/crypto/errors')
|
||||||
|
|
||||||
const { Exchange, KeyType } = require('./proto')
|
const { Exchange, KeyType } = require('./proto')
|
||||||
const protocol = '/plaintext/2.0.0'
|
const protocol = '/plaintext/2.0.0'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
*/
|
||||||
|
|
||||||
function lpEncodeExchange (exchange) {
|
function lpEncodeExchange (exchange) {
|
||||||
const pb = Exchange.encode(exchange)
|
const pb = Exchange.encode(exchange)
|
||||||
return lp.encode.single(pb)
|
return lp.encode.single(pb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt connection.
|
||||||
|
*
|
||||||
|
* @param {PeerId} localId
|
||||||
|
* @param {Connection} conn
|
||||||
|
* @param {PeerId} [remoteId]
|
||||||
|
*/
|
||||||
async function encrypt (localId, conn, remoteId) {
|
async function encrypt (localId, conn, remoteId) {
|
||||||
const shake = handshake(conn)
|
const shake = handshake(conn)
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
require('node-forge/lib/pkcs7')
|
require('node-forge/lib/pkcs7')
|
||||||
@ -21,7 +22,7 @@ class CMS {
|
|||||||
/**
|
/**
|
||||||
* Creates a new instance with a keychain
|
* Creates a new instance with a keychain
|
||||||
*
|
*
|
||||||
* @param {Keychain} keychain - the available keys
|
* @param {import('./index')} keychain - the available keys
|
||||||
*/
|
*/
|
||||||
constructor (keychain) {
|
constructor (keychain) {
|
||||||
if (!keychain) {
|
if (!keychain) {
|
||||||
@ -38,7 +39,7 @@ class CMS {
|
|||||||
*
|
*
|
||||||
* @param {string} name - The local key name.
|
* @param {string} name - The local key name.
|
||||||
* @param {Uint8Array} plain - The data to encrypt.
|
* @param {Uint8Array} plain - The data to encrypt.
|
||||||
* @returns {undefined}
|
* @returns {Promise<Uint8Array>}
|
||||||
*/
|
*/
|
||||||
async encrypt (name, plain) {
|
async encrypt (name, plain) {
|
||||||
if (!(plain instanceof Uint8Array)) {
|
if (!(plain instanceof Uint8Array)) {
|
||||||
@ -68,7 +69,7 @@ class CMS {
|
|||||||
* exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
|
* exists, an Error is returned with the property 'missingKeys'. It is array of key ids.
|
||||||
*
|
*
|
||||||
* @param {Uint8Array} cmsData - The CMS encrypted data to decrypt.
|
* @param {Uint8Array} cmsData - The CMS encrypted data to decrypt.
|
||||||
* @returns {undefined}
|
* @returns {Promise<Uint8Array>}
|
||||||
*/
|
*/
|
||||||
async decrypt (cmsData) {
|
async decrypt (cmsData) {
|
||||||
if (!(cmsData instanceof Uint8Array)) {
|
if (!(cmsData instanceof Uint8Array)) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
/* eslint max-nested-callbacks: ["error", 5] */
|
/* eslint max-nested-callbacks: ["error", 5] */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
@ -101,7 +102,8 @@ class Keychain {
|
|||||||
* Creates a new instance of a key chain.
|
* Creates a new instance of a key chain.
|
||||||
*
|
*
|
||||||
* @param {DS} store - where the key are.
|
* @param {DS} store - where the key are.
|
||||||
* @param {object} options - ???
|
* @param {object} options
|
||||||
|
* @class
|
||||||
*/
|
*/
|
||||||
constructor (store, options) {
|
constructor (store, options) {
|
||||||
if (!store) {
|
if (!store) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
require('node-forge/lib/x509')
|
require('node-forge/lib/x509')
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const mergeOptions = require('merge-options')
|
const mergeOptions = require('merge-options')
|
||||||
const pipe = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const { tap } = require('streaming-iterables')
|
const { tap } = require('streaming-iterables')
|
||||||
const oldPeerLRU = require('./old-peers')
|
const oldPeerLRU = require('./old-peers')
|
||||||
const { METRICS: defaultOptions } = require('../constants')
|
const { METRICS: defaultOptions } = require('../constants')
|
||||||
@ -17,15 +18,26 @@ const directionToEvent = {
|
|||||||
out: 'dataSent'
|
out: 'dataSent'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef MetricsProperties
|
||||||
|
* @property {import('../connection-manager')} connectionManager
|
||||||
|
*
|
||||||
|
* @typedef MetricsOptions
|
||||||
|
* @property {number} [computeThrottleMaxQueueSize = defaultOptions.computeThrottleMaxQueueSize]
|
||||||
|
* @property {number} [computeThrottleTimeout = defaultOptions.computeThrottleTimeout]
|
||||||
|
* @property {number[]} [movingAverageIntervals = defaultOptions.movingAverageIntervals]
|
||||||
|
* @property {number} [maxOldPeersRetention = defaultOptions.maxOldPeersRetention]
|
||||||
|
*/
|
||||||
|
|
||||||
class Metrics {
|
class Metrics {
|
||||||
/**
|
/**
|
||||||
*
|
* @class
|
||||||
* @param {object} options
|
* @param {MetricsProperties & MetricsOptions} options
|
||||||
* @param {ConnectionManager} options.connectionManager
|
|
||||||
* @param {number} options.computeThrottleMaxQueueSize
|
|
||||||
* @param {number} options.computeThrottleTimeout
|
|
||||||
* @param {Array<number>} options.movingAverageIntervals
|
|
||||||
* @param {number} options.maxOldPeersRetention
|
|
||||||
*/
|
*/
|
||||||
constructor (options) {
|
constructor (options) {
|
||||||
this._options = mergeOptions(defaultOptions, options)
|
this._options = mergeOptions(defaultOptions, options)
|
||||||
@ -76,7 +88,7 @@ class Metrics {
|
|||||||
/**
|
/**
|
||||||
* Returns a list of `PeerId` strings currently being tracked
|
* Returns a list of `PeerId` strings currently being tracked
|
||||||
*
|
*
|
||||||
* @returns {Array<string>}
|
* @returns {string[]}
|
||||||
*/
|
*/
|
||||||
get peers () {
|
get peers () {
|
||||||
return Array.from(this._peerStats.keys())
|
return Array.from(this._peerStats.keys())
|
||||||
@ -97,7 +109,7 @@ class Metrics {
|
|||||||
/**
|
/**
|
||||||
* Returns a list of all protocol strings currently being tracked.
|
* Returns a list of all protocol strings currently being tracked.
|
||||||
*
|
*
|
||||||
* @returns {Array<string>}
|
* @returns {string[]}
|
||||||
*/
|
*/
|
||||||
get protocols () {
|
get protocols () {
|
||||||
return Array.from(this._protocolStats.keys())
|
return Array.from(this._protocolStats.keys())
|
||||||
@ -176,6 +188,7 @@ class Metrics {
|
|||||||
*
|
*
|
||||||
* @param {PeerId} placeholder - A peerId string
|
* @param {PeerId} placeholder - A peerId string
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
updatePlaceholder (placeholder, peerId) {
|
updatePlaceholder (placeholder, peerId) {
|
||||||
if (!this._running) return
|
if (!this._running) return
|
||||||
@ -205,10 +218,10 @@ class Metrics {
|
|||||||
* with the placeholder string returned from here, and the known `PeerId`.
|
* with the placeholder string returned from here, and the known `PeerId`.
|
||||||
*
|
*
|
||||||
* @param {Object} options
|
* @param {Object} options
|
||||||
* @param {{ sink: function(*), source: function() }} options.stream - A duplex iterable stream
|
* @param {MultiaddrConnection} options.stream - A duplex iterable stream
|
||||||
* @param {PeerId} [options.remotePeer] - The id of the remote peer that's connected
|
* @param {PeerId} [options.remotePeer] - The id of the remote peer that's connected
|
||||||
* @param {string} [options.protocol] - The protocol the stream is running
|
* @param {string} [options.protocol] - The protocol the stream is running
|
||||||
* @returns {string} The peerId string or placeholder string
|
* @returns {MultiaddrConnection} The peerId string or placeholder string
|
||||||
*/
|
*/
|
||||||
trackStream ({ stream, remotePeer, protocol }) {
|
trackStream ({ stream, remotePeer, protocol }) {
|
||||||
const metrics = this
|
const metrics = this
|
||||||
|
@ -6,9 +6,10 @@ const LRU = require('hashlru')
|
|||||||
* Creates and returns a Least Recently Used Cache
|
* Creates and returns a Least Recently Used Cache
|
||||||
*
|
*
|
||||||
* @param {number} maxSize
|
* @param {number} maxSize
|
||||||
* @returns {LRUCache}
|
* @returns {any}
|
||||||
*/
|
*/
|
||||||
module.exports = (maxSize) => {
|
module.exports = (maxSize) => {
|
||||||
|
// @ts-ignore LRU expression is not callable
|
||||||
const patched = LRU(maxSize)
|
const patched = LRU(maxSize)
|
||||||
patched.delete = patched.remove
|
patched.delete = patched.remove
|
||||||
return patched
|
return patched
|
||||||
|
@ -1,17 +1,19 @@
|
|||||||
|
// @ts-nocheck
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const EventEmitter = require('events')
|
const { EventEmitter } = require('events')
|
||||||
const Big = require('bignumber.js')
|
const Big = require('bignumber.js')
|
||||||
const MovingAverage = require('moving-average')
|
const MovingAverage = require('moving-average')
|
||||||
const retimer = require('retimer')
|
const retimer = require('retimer')
|
||||||
|
|
||||||
/**
|
class Stats extends EventEmitter {
|
||||||
|
/**
|
||||||
* A queue based manager for stat processing
|
* A queue based manager for stat processing
|
||||||
*
|
*
|
||||||
* @param {Array<string>} initialCounters
|
* @class
|
||||||
|
* @param {string[]} initialCounters
|
||||||
* @param {any} options
|
* @param {any} options
|
||||||
*/
|
*/
|
||||||
class Stats extends EventEmitter {
|
|
||||||
constructor (initialCounters, options) {
|
constructor (initialCounters, options) {
|
||||||
super()
|
super()
|
||||||
|
|
||||||
@ -21,6 +23,7 @@ class Stats extends EventEmitter {
|
|||||||
|
|
||||||
this._frequencyLastTime = Date.now()
|
this._frequencyLastTime = Date.now()
|
||||||
this._frequencyAccumulators = {}
|
this._frequencyAccumulators = {}
|
||||||
|
|
||||||
this._movingAverages = {}
|
this._movingAverages = {}
|
||||||
|
|
||||||
this._update = this._update.bind(this)
|
this._update = this._update.bind(this)
|
||||||
@ -68,7 +71,7 @@ class Stats extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Returns a clone of the current stats.
|
* Returns a clone of the current stats.
|
||||||
*
|
*
|
||||||
* @returns {Map<string, Stat>}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
get snapshot () {
|
get snapshot () {
|
||||||
return Object.assign({}, this._stats)
|
return Object.assign({}, this._stats)
|
||||||
@ -77,7 +80,7 @@ class Stats extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Returns a clone of the internal movingAverages
|
* Returns a clone of the internal movingAverages
|
||||||
*
|
*
|
||||||
* @returns {Array<MovingAverage>}
|
* @returns {MovingAverage}
|
||||||
*/
|
*/
|
||||||
get movingAverages () {
|
get movingAverages () {
|
||||||
return Object.assign({}, this._movingAverages)
|
return Object.assign({}, this._movingAverages)
|
||||||
@ -229,7 +232,7 @@ class Stats extends EventEmitter {
|
|||||||
* will be updated or initialized if they don't already exist.
|
* will be updated or initialized if they don't already exist.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Array<string, number>} op
|
* @param {{string, number}[]} op
|
||||||
* @throws {InvalidNumber}
|
* @throws {InvalidNumber}
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
@ -238,7 +241,7 @@ class Stats extends EventEmitter {
|
|||||||
const inc = op[1]
|
const inc = op[1]
|
||||||
|
|
||||||
if (typeof inc !== 'number') {
|
if (typeof inc !== 'number') {
|
||||||
throw new Error('invalid increment number:', inc)
|
throw new Error(`invalid increment number: ${inc}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
let n
|
let n
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errCode = require('err-code')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:peer-routing')
|
const log = Object.assign(debug('libp2p:peer-routing'), {
|
||||||
log.error = debug('libp2p:peer-routing:error')
|
error: debug('libp2p:peer-routing:err')
|
||||||
|
})
|
||||||
|
const errCode = require('err-code')
|
||||||
|
|
||||||
const all = require('it-all')
|
const all = require('it-all')
|
||||||
const pAny = require('p-any')
|
const pAny = require('p-any')
|
||||||
@ -13,12 +14,13 @@ const {
|
|||||||
} = require('set-delayed-interval')
|
} = require('set-delayed-interval')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for managing the usage of the available Peer Routing modules.
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
*/
|
*/
|
||||||
class PeerRouting {
|
class PeerRouting {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {Libp2p} libp2p
|
* @param {import('./')} libp2p
|
||||||
*/
|
*/
|
||||||
constructor (libp2p) {
|
constructor (libp2p) {
|
||||||
this._peerId = libp2p.peerId
|
this._peerId = libp2p.peerId
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errcode = require('err-code')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:peer-store:address-book')
|
const log = Object.assign(debug('libp2p:peer-store:address-book'), {
|
||||||
log.error = debug('libp2p:peer-store:address-book:error')
|
error: debug('libp2p:peer-store:address-book:err')
|
||||||
|
})
|
||||||
|
const errcode = require('err-code')
|
||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
@ -17,35 +18,31 @@ const {
|
|||||||
const Envelope = require('../record/envelope')
|
const Envelope = require('../record/envelope')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The AddressBook is responsible for keeping the known multiaddrs
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
* of a peer.
|
* @typedef {import('./')} PeerStore
|
||||||
*/
|
*/
|
||||||
class AddressBook extends Book {
|
|
||||||
/**
|
/**
|
||||||
* Address object
|
|
||||||
*
|
|
||||||
* @typedef {Object} Address
|
* @typedef {Object} Address
|
||||||
* @property {Multiaddr} multiaddr peer multiaddr.
|
* @property {Multiaddr} multiaddr peer multiaddr.
|
||||||
* @property {boolean} isCertified obtained from a signed peer record.
|
* @property {boolean} isCertified obtained from a signed peer record.
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CertifiedRecord object
|
|
||||||
*
|
*
|
||||||
* @typedef {Object} CertifiedRecord
|
* @typedef {Object} CertifiedRecord
|
||||||
* @property {Uint8Array} raw raw envelope.
|
* @property {Uint8Array} raw raw envelope.
|
||||||
* @property {number} seqNumber seq counter.
|
* @property {number} seqNumber seq counter.
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Entry object for the addressBook
|
|
||||||
*
|
*
|
||||||
* @typedef {Object} Entry
|
* @typedef {Object} Entry
|
||||||
* @property {Array<Address>} addresses peer Addresses.
|
* @property {Address[]} addresses peer Addresses.
|
||||||
* @property {CertifiedRecord} record certified peer record.
|
* @property {CertifiedRecord} record certified peer record.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {Book}
|
||||||
|
*/
|
||||||
|
class AddressBook extends Book {
|
||||||
/**
|
/**
|
||||||
|
* The AddressBook is responsible for keeping the known multiaddrs of a peer.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {PeerStore} peerStore
|
* @param {PeerStore} peerStore
|
||||||
*/
|
*/
|
||||||
@ -70,7 +67,7 @@ class AddressBook extends Book {
|
|||||||
/**
|
/**
|
||||||
* Map known peers to their known Address Entries.
|
* Map known peers to their known Address Entries.
|
||||||
*
|
*
|
||||||
* @type {Map<string, Array<Entry>>}
|
* @type {Map<string, Entry>}
|
||||||
*/
|
*/
|
||||||
this.data = new Map()
|
this.data = new Map()
|
||||||
}
|
}
|
||||||
@ -105,7 +102,7 @@ class AddressBook extends Book {
|
|||||||
|
|
||||||
const peerId = peerRecord.peerId
|
const peerId = peerRecord.peerId
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
const entry = this.data.get(id) || {}
|
const entry = this.data.get(id) || { record: undefined }
|
||||||
const storedRecord = entry.record
|
const storedRecord = entry.record
|
||||||
|
|
||||||
// ensure seq is greater than, or equal to, the last received
|
// ensure seq is greater than, or equal to, the last received
|
||||||
@ -151,7 +148,7 @@ class AddressBook extends Book {
|
|||||||
* Returns undefined if no record exists.
|
* Returns undefined if no record exists.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Promise<Envelope|void>}
|
* @returns {Promise<Envelope|void>|undefined}
|
||||||
*/
|
*/
|
||||||
getPeerRecord (peerId) {
|
getPeerRecord (peerId) {
|
||||||
const raw = this.getRawEnvelope(peerId)
|
const raw = this.getRawEnvelope(peerId)
|
||||||
@ -171,7 +168,7 @@ class AddressBook extends Book {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<Multiaddr>} multiaddrs
|
* @param {Multiaddr[]} multiaddrs
|
||||||
* @returns {AddressBook}
|
* @returns {AddressBook}
|
||||||
*/
|
*/
|
||||||
set (peerId, multiaddrs) {
|
set (peerId, multiaddrs) {
|
||||||
@ -181,22 +178,22 @@ class AddressBook extends Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const addresses = this._toAddresses(multiaddrs)
|
const addresses = this._toAddresses(multiaddrs)
|
||||||
const id = peerId.toB58String()
|
|
||||||
const entry = this.data.get(id) || {}
|
|
||||||
const rec = entry.addresses
|
|
||||||
|
|
||||||
// Not replace multiaddrs
|
// Not replace multiaddrs
|
||||||
if (!addresses.length) {
|
if (!addresses.length) {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const id = peerId.toB58String()
|
||||||
|
const entry = this.data.get(id)
|
||||||
|
|
||||||
// Already knows the peer
|
// Already knows the peer
|
||||||
if (rec && rec.length === addresses.length) {
|
if (entry && entry.addresses && entry.addresses.length === addresses.length) {
|
||||||
const intersection = rec.filter((addr) => addresses.some((newAddr) => addr.multiaddr.equals(newAddr.multiaddr)))
|
const intersection = entry.addresses.filter((addr) => addresses.some((newAddr) => addr.multiaddr.equals(newAddr.multiaddr)))
|
||||||
|
|
||||||
// Are new addresses equal to the old ones?
|
// Are new addresses equal to the old ones?
|
||||||
// If yes, no changes needed!
|
// If yes, no changes needed!
|
||||||
if (intersection.length === rec.length) {
|
if (intersection.length === entry.addresses.length) {
|
||||||
log(`the addresses provided to store are equal to the already stored for ${id}`)
|
log(`the addresses provided to store are equal to the already stored for ${id}`)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
@ -204,12 +201,12 @@ class AddressBook extends Book {
|
|||||||
|
|
||||||
this._setData(peerId, {
|
this._setData(peerId, {
|
||||||
addresses,
|
addresses,
|
||||||
record: entry.record
|
record: entry && entry.record
|
||||||
})
|
})
|
||||||
log(`stored provided multiaddrs for ${id}`)
|
log(`stored provided multiaddrs for ${id}`)
|
||||||
|
|
||||||
// Notify the existance of a new peer
|
// Notify the existance of a new peer
|
||||||
if (!rec) {
|
if (!entry) {
|
||||||
this._ps.emit('peer', peerId)
|
this._ps.emit('peer', peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +218,7 @@ class AddressBook extends Book {
|
|||||||
* If the peer is not known, it is set with the given addresses.
|
* If the peer is not known, it is set with the given addresses.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<Multiaddr>} multiaddrs
|
* @param {Multiaddr[]} multiaddrs
|
||||||
* @returns {AddressBook}
|
* @returns {AddressBook}
|
||||||
*/
|
*/
|
||||||
add (peerId, multiaddrs) {
|
add (peerId, multiaddrs) {
|
||||||
@ -233,11 +230,11 @@ class AddressBook extends Book {
|
|||||||
const addresses = this._toAddresses(multiaddrs)
|
const addresses = this._toAddresses(multiaddrs)
|
||||||
const id = peerId.toB58String()
|
const id = peerId.toB58String()
|
||||||
|
|
||||||
const entry = this.data.get(id) || {}
|
const entry = this.data.get(id)
|
||||||
const rec = entry.addresses || []
|
|
||||||
|
|
||||||
|
if (entry && entry.addresses) {
|
||||||
// Add recorded uniquely to the new array (Union)
|
// Add recorded uniquely to the new array (Union)
|
||||||
rec.forEach((addr) => {
|
entry.addresses.forEach((addr) => {
|
||||||
if (!addresses.find(r => r.multiaddr.equals(addr.multiaddr))) {
|
if (!addresses.find(r => r.multiaddr.equals(addr.multiaddr))) {
|
||||||
addresses.push(addr)
|
addresses.push(addr)
|
||||||
}
|
}
|
||||||
@ -245,20 +242,21 @@ class AddressBook extends Book {
|
|||||||
|
|
||||||
// If the recorded length is equal to the new after the unique union
|
// If the recorded length is equal to the new after the unique union
|
||||||
// The content is the same, no need to update.
|
// The content is the same, no need to update.
|
||||||
if (rec && rec.length === addresses.length) {
|
if (entry.addresses.length === addresses.length) {
|
||||||
log(`the addresses provided to store are already stored for ${id}`)
|
log(`the addresses provided to store are already stored for ${id}`)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this._setData(peerId, {
|
this._setData(peerId, {
|
||||||
addresses,
|
addresses,
|
||||||
record: entry.record
|
record: entry && entry.record
|
||||||
})
|
})
|
||||||
|
|
||||||
log(`added provided multiaddrs for ${id}`)
|
log(`added provided multiaddrs for ${id}`)
|
||||||
|
|
||||||
// Notify the existance of a new peer
|
// Notify the existance of a new peer
|
||||||
if (!entry.addresses) {
|
if (!(entry && entry.addresses)) {
|
||||||
this._ps.emit('peer', peerId)
|
this._ps.emit('peer', peerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +268,7 @@ class AddressBook extends Book {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Array<Address>|undefined}
|
* @returns {Address[]|undefined}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
@ -286,9 +284,9 @@ class AddressBook extends Book {
|
|||||||
* Transforms received multiaddrs into Address.
|
* Transforms received multiaddrs into Address.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {Array<Multiaddr>} multiaddrs
|
* @param {Multiaddr[]} multiaddrs
|
||||||
* @param {boolean} [isCertified]
|
* @param {boolean} [isCertified]
|
||||||
* @returns {Array<Address>}
|
* @returns {Address[]}
|
||||||
*/
|
*/
|
||||||
_toAddresses (multiaddrs, isCertified = false) {
|
_toAddresses (multiaddrs, isCertified = false) {
|
||||||
if (!multiaddrs) {
|
if (!multiaddrs) {
|
||||||
@ -319,8 +317,8 @@ class AddressBook extends Book {
|
|||||||
* Returns `undefined` if there are no known multiaddrs for the given peer.
|
* Returns `undefined` if there are no known multiaddrs for the given peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {(addresses: Array<Address) => Array<Address>} [addressSorter]
|
* @param {(addresses: Address[]) => Address[]} [addressSorter]
|
||||||
* @returns {Array<Multiaddr>|undefined}
|
* @returns {Multiaddr[]|undefined}
|
||||||
*/
|
*/
|
||||||
getMultiaddrsForPeer (peerId, addressSorter = (ms) => ms) {
|
getMultiaddrsForPeer (peerId, addressSorter = (ms) => ms) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
@ -10,16 +10,19 @@ const {
|
|||||||
const passthrough = data => data
|
const passthrough = data => data
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Book is the skeleton for the PeerStore books.
|
* @typedef {import('./')} PeerStore
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Book {
|
class Book {
|
||||||
/**
|
/**
|
||||||
|
* The Book is the skeleton for the PeerStore books.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {Object} properties
|
* @param {Object} properties
|
||||||
* @param {PeerStore} properties.peerStore - PeerStore instance.
|
* @param {PeerStore} properties.peerStore - PeerStore instance.
|
||||||
* @param {string} properties.eventName - Name of the event to emit by the PeerStore.
|
* @param {string} properties.eventName - Name of the event to emit by the PeerStore.
|
||||||
* @param {string} properties.eventProperty - Name of the property to emit by the PeerStore.
|
* @param {string} properties.eventProperty - Name of the property to emit by the PeerStore.
|
||||||
* @param {Function} [properties.eventTransformer] - Transformer function of the provided data for being emitted.
|
* @param {(data: any) => any[]} [properties.eventTransformer] - Transformer function of the provided data for being emitted.
|
||||||
*/
|
*/
|
||||||
constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough }) {
|
constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough }) {
|
||||||
this._ps = peerStore
|
this._ps = peerStore
|
||||||
@ -30,7 +33,7 @@ class Book {
|
|||||||
/**
|
/**
|
||||||
* Map known peers to their data.
|
* Map known peers to their data.
|
||||||
*
|
*
|
||||||
* @type {Map<string, Array<Data>}
|
* @type {Map<string, any[]|any>}
|
||||||
*/
|
*/
|
||||||
this.data = new Map()
|
this.data = new Map()
|
||||||
}
|
}
|
||||||
@ -39,7 +42,7 @@ class Book {
|
|||||||
* Set known data of a provided peer.
|
* Set known data of a provided peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<Data>|Data} data
|
* @param {any[]|any} data
|
||||||
*/
|
*/
|
||||||
set (peerId, data) {
|
set (peerId, data) {
|
||||||
throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED')
|
throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED')
|
||||||
@ -48,9 +51,9 @@ class Book {
|
|||||||
/**
|
/**
|
||||||
* Set data into the datastructure, persistence and emit it using the provided transformers.
|
* Set data into the datastructure, persistence and emit it using the provided transformers.
|
||||||
*
|
*
|
||||||
* @private
|
* @protected
|
||||||
* @param {PeerId} peerId - peerId of the data to store
|
* @param {PeerId} peerId - peerId of the data to store
|
||||||
* @param {*} data - data to store.
|
* @param {any} data - data to store.
|
||||||
* @param {Object} [options] - storing options.
|
* @param {Object} [options] - storing options.
|
||||||
* @param {boolean} [options.emit = true] - emit the provided data.
|
* @param {boolean} [options.emit = true] - emit the provided data.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
@ -68,9 +71,9 @@ class Book {
|
|||||||
/**
|
/**
|
||||||
* Emit data.
|
* Emit data.
|
||||||
*
|
*
|
||||||
* @private
|
* @protected
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {*} data
|
* @param {any} [data]
|
||||||
*/
|
*/
|
||||||
_emit (peerId, data) {
|
_emit (peerId, data) {
|
||||||
this._ps.emit(this.eventName, {
|
this._ps.emit(this.eventName, {
|
||||||
@ -84,7 +87,7 @@ class Book {
|
|||||||
* Returns `undefined` if there is no available data for the given peer.
|
* Returns `undefined` if there is no available data for the given peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Array<Data>|undefined}
|
* @returns {any[]|any|undefined}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
@ -93,6 +96,7 @@ class Book {
|
|||||||
|
|
||||||
const rec = this.data.get(peerId.toB58String())
|
const rec = this.data.get(peerId.toB58String())
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
return rec ? [...rec] : undefined
|
return rec ? [...rec] : undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:peer-store')
|
|
||||||
log.error = debug('libp2p:peer-store:error')
|
|
||||||
|
|
||||||
const { EventEmitter } = require('events')
|
const { EventEmitter } = require('events')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
@ -14,11 +11,15 @@ const MetadataBook = require('./metadata-book')
|
|||||||
const ProtoBook = require('./proto-book')
|
const ProtoBook = require('./proto-book')
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ERR_INVALID_PARAMETERS
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for managing known peers, as well as their addresses, protocols and metadata.
|
* @typedef {import('./address-book').Address} Address
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {EventEmitter}
|
||||||
*
|
*
|
||||||
* @fires PeerStore#peer Emitted when a new peer is added.
|
* @fires PeerStore#peer Emitted when a new peer is added.
|
||||||
* @fires PeerStore#change:protocols Emitted when a known peer supports a different set of protocols.
|
* @fires PeerStore#change:protocols Emitted when a known peer supports a different set of protocols.
|
||||||
@ -32,12 +33,14 @@ class PeerStore extends EventEmitter {
|
|||||||
*
|
*
|
||||||
* @typedef {Object} Peer
|
* @typedef {Object} Peer
|
||||||
* @property {PeerId} id peer's peer-id instance.
|
* @property {PeerId} id peer's peer-id instance.
|
||||||
* @property {Array<Address>} addresses peer's addresses containing its multiaddrs and metadata.
|
* @property {Address[]} addresses peer's addresses containing its multiaddrs and metadata.
|
||||||
* @property {Array<string>} protocols peer's supported protocols.
|
* @property {string[]} protocols peer's supported protocols.
|
||||||
* @property {Map<string, Buffer>} metadata peer's metadata map.
|
* @property {Map<string, Uint8Array>|undefined} metadata peer's metadata map.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Responsible for managing known peers, as well as their addresses, protocols and metadata.
|
||||||
|
*
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {PeerId} options.peerId
|
* @param {PeerId} options.peerId
|
||||||
* @class
|
* @class
|
||||||
@ -121,7 +124,7 @@ class PeerStore extends EventEmitter {
|
|||||||
* Get the stored information of a given peer.
|
* Get the stored information of a given peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Peer}
|
* @returns {Peer|undefined}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errcode = require('err-code')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:peer-store:key-book')
|
const log = Object.assign(debug('libp2p:peer-store:key-book'), {
|
||||||
log.error = debug('libp2p:peer-store:key-book:error')
|
error: debug('libp2p:peer-store:key-book:err')
|
||||||
|
})
|
||||||
|
const errcode = require('err-code')
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
@ -14,10 +15,17 @@ const {
|
|||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The KeyBook is responsible for keeping the known public keys of a peer.
|
* @typedef {import('./')} PeerStore
|
||||||
|
* @typedef {import('libp2p-crypto').PublicKey} PublicKey
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {Book}
|
||||||
*/
|
*/
|
||||||
class KeyBook extends Book {
|
class KeyBook extends Book {
|
||||||
/**
|
/**
|
||||||
|
* The KeyBook is responsible for keeping the known public keys of a peer.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {PeerStore} peerStore
|
* @param {PeerStore} peerStore
|
||||||
*/
|
*/
|
||||||
@ -42,7 +50,7 @@ class KeyBook extends Book {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey} publicKey
|
* @param {PublicKey} publicKey
|
||||||
* @returns {KeyBook}
|
* @returns {KeyBook}
|
||||||
*/
|
*/
|
||||||
set (peerId, publicKey) {
|
set (peerId, publicKey) {
|
||||||
@ -72,7 +80,7 @@ class KeyBook extends Book {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {RsaPublicKey|Ed25519PublicKey|Secp256k1PublicKey}
|
* @returns {PublicKey | undefined}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errcode = require('err-code')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:peer-store:proto-book')
|
const log = Object.assign(debug('libp2p:peer-store:proto-book'), {
|
||||||
log.error = debug('libp2p:peer-store:proto-book:error')
|
error: debug('libp2p:peer-store:proto-book:err')
|
||||||
|
})
|
||||||
|
const errcode = require('err-code')
|
||||||
const uint8ArrayEquals = require('uint8arrays/equals')
|
const uint8ArrayEquals = require('uint8arrays/equals')
|
||||||
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
@ -15,13 +16,19 @@ const {
|
|||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The MetadataBook is responsible for keeping the known supported
|
* @typedef {import('./')} PeerStore
|
||||||
* protocols of a peer.
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {Book}
|
||||||
*
|
*
|
||||||
* @fires MetadataBook#change:metadata
|
* @fires MetadataBook#change:metadata
|
||||||
*/
|
*/
|
||||||
class MetadataBook extends Book {
|
class MetadataBook extends Book {
|
||||||
/**
|
/**
|
||||||
|
* The MetadataBook is responsible for keeping the known supported
|
||||||
|
* protocols of a peer.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {PeerStore} peerStore
|
* @param {PeerStore} peerStore
|
||||||
*/
|
*/
|
||||||
@ -51,8 +58,9 @@ class MetadataBook extends Book {
|
|||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {string} key - metadata key
|
* @param {string} key - metadata key
|
||||||
* @param {Uint8Array} value - metadata value
|
* @param {Uint8Array} value - metadata value
|
||||||
* @returns {ProtoBook}
|
* @returns {MetadataBook}
|
||||||
*/
|
*/
|
||||||
|
// @ts-ignore override with more then the parameters expected in Book
|
||||||
set (peerId, key, value) {
|
set (peerId, key, value) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
log.error('peerId must be an instance of peer-id to store data')
|
log.error('peerId must be an instance of peer-id to store data')
|
||||||
@ -95,7 +103,7 @@ class MetadataBook extends Book {
|
|||||||
* Get the known data of a provided peer.
|
* Get the known data of a provided peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Map<string, Uint8Array>}
|
* @returns {Map<string, Uint8Array>|undefined}
|
||||||
*/
|
*/
|
||||||
get (peerId) {
|
get (peerId) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
@ -110,7 +118,7 @@ class MetadataBook extends Book {
|
|||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array | undefined}
|
||||||
*/
|
*/
|
||||||
getValue (peerId, key) {
|
getValue (peerId, key) {
|
||||||
if (!PeerId.isPeerId(peerId)) {
|
if (!PeerId.isPeerId(peerId)) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:persistent-peer-store')
|
const log = Object.assign(debug('libp2p:persistent-peer-store'), {
|
||||||
log.error = debug('libp2p:persistent-peer-store:error')
|
error: debug('libp2p:persistent-peer-store:err')
|
||||||
|
})
|
||||||
const { Key } = require('interface-datastore')
|
const { Key } = require('interface-datastore')
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
@ -21,16 +21,22 @@ const {
|
|||||||
const Addresses = require('./pb/address-book.proto')
|
const Addresses = require('./pb/address-book.proto')
|
||||||
const Protocols = require('./pb/proto-book.proto')
|
const Protocols = require('./pb/proto-book.proto')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} PersistentPeerStoreProperties
|
||||||
|
* @property {PeerId} peerId
|
||||||
|
* @property {any} datastore
|
||||||
|
*
|
||||||
|
* @typedef {Object} PersistentPeerStoreOptions
|
||||||
|
* @property {number} [threshold = 5] - Number of dirty peers allowed before commit data.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for managing the persistence of data in the PeerStore.
|
* Responsible for managing the persistence of data in the PeerStore.
|
||||||
*/
|
*/
|
||||||
class PersistentPeerStore extends PeerStore {
|
class PersistentPeerStore extends PeerStore {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {Object} properties
|
* @param {PersistentPeerStoreProperties & PersistentPeerStoreOptions} properties
|
||||||
* @param {PeerId} properties.peerId
|
|
||||||
* @param {Datastore} properties.datastore - Datastore to persist data.
|
|
||||||
* @param {number} [properties.threshold = 5] - Number of dirty peers allowed before commit data.
|
|
||||||
*/
|
*/
|
||||||
constructor ({ peerId, datastore, threshold = 5 }) {
|
constructor ({ peerId, datastore, threshold = 5 }) {
|
||||||
super({ peerId })
|
super({ peerId })
|
||||||
@ -340,6 +346,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
case 'addrs':
|
case 'addrs':
|
||||||
decoded = Addresses.decode(value)
|
decoded = Addresses.decode(value)
|
||||||
|
|
||||||
|
// @ts-ignore protected function
|
||||||
this.addressBook._setData(
|
this.addressBook._setData(
|
||||||
peerId,
|
peerId,
|
||||||
{
|
{
|
||||||
@ -357,6 +364,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
case 'keys':
|
case 'keys':
|
||||||
decoded = await PeerId.createFromPubKey(value)
|
decoded = await PeerId.createFromPubKey(value)
|
||||||
|
|
||||||
|
// @ts-ignore protected function
|
||||||
this.keyBook._setData(
|
this.keyBook._setData(
|
||||||
decoded,
|
decoded,
|
||||||
decoded,
|
decoded,
|
||||||
@ -372,6 +380,7 @@ class PersistentPeerStore extends PeerStore {
|
|||||||
case 'protos':
|
case 'protos':
|
||||||
decoded = Protocols.decode(value)
|
decoded = Protocols.decode(value)
|
||||||
|
|
||||||
|
// @ts-ignore protected function
|
||||||
this.protoBook._setData(
|
this.protoBook._setData(
|
||||||
peerId,
|
peerId,
|
||||||
new Set(decoded.protocols),
|
new Set(decoded.protocols),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const errcode = require('err-code')
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:peer-store:proto-book')
|
const log = Object.assign(debug('libp2p:peer-store:proto-book'), {
|
||||||
log.error = debug('libp2p:peer-store:proto-book:error')
|
error: debug('libp2p:peer-store:proto-book:err')
|
||||||
|
})
|
||||||
|
const errcode = require('err-code')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
|
|
||||||
const Book = require('./book')
|
const Book = require('./book')
|
||||||
@ -14,13 +14,19 @@ const {
|
|||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ProtoBook is responsible for keeping the known supported
|
* @typedef {import('./')} PeerStore
|
||||||
* protocols of a peer.
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {Book}
|
||||||
*
|
*
|
||||||
* @fires ProtoBook#change:protocols
|
* @fires ProtoBook#change:protocols
|
||||||
*/
|
*/
|
||||||
class ProtoBook extends Book {
|
class ProtoBook extends Book {
|
||||||
/**
|
/**
|
||||||
|
* The ProtoBook is responsible for keeping the known supported
|
||||||
|
* protocols of a peer.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {PeerStore} peerStore
|
* @param {PeerStore} peerStore
|
||||||
*/
|
*/
|
||||||
@ -50,7 +56,7 @@ class ProtoBook extends Book {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<string>} protocols
|
* @param {string[]} protocols
|
||||||
* @returns {ProtoBook}
|
* @returns {ProtoBook}
|
||||||
*/
|
*/
|
||||||
set (peerId, protocols) {
|
set (peerId, protocols) {
|
||||||
@ -88,7 +94,7 @@ class ProtoBook extends Book {
|
|||||||
* If the peer was not known before, it will be added.
|
* If the peer was not known before, it will be added.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<string>} protocols
|
* @param {string[]} protocols
|
||||||
* @returns {ProtoBook}
|
* @returns {ProtoBook}
|
||||||
*/
|
*/
|
||||||
add (peerId, protocols) {
|
add (peerId, protocols) {
|
||||||
@ -123,7 +129,7 @@ class ProtoBook extends Book {
|
|||||||
* If the protocols did not exist before, nothing will be done.
|
* If the protocols did not exist before, nothing will be done.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @param {Array<string>} protocols
|
* @param {string[]} protocols
|
||||||
* @returns {ProtoBook}
|
* @returns {ProtoBook}
|
||||||
*/
|
*/
|
||||||
remove (peerId, protocols) {
|
remove (peerId, protocols) {
|
||||||
|
@ -1,30 +1,39 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p-ping')
|
const log = Object.assign(debug('libp2p:ping'), {
|
||||||
log.error = debug('libp2p-ping:error')
|
error: debug('libp2p:ping:err')
|
||||||
|
})
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
|
|
||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
const pipe = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const { toBuffer } = require('it-buffer')
|
const { toBuffer } = require('it-buffer')
|
||||||
const { collect, take } = require('streaming-iterables')
|
const { collect, take } = require('streaming-iterables')
|
||||||
|
const equals = require('uint8arrays/equals')
|
||||||
|
|
||||||
const { PROTOCOL, PING_LENGTH } = require('./constants')
|
const { PROTOCOL, PING_LENGTH } = require('./constants')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../')} Libp2p
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ping a given peer and wait for its response, getting the operation latency.
|
* Ping a given peer and wait for its response, getting the operation latency.
|
||||||
*
|
*
|
||||||
* @param {Libp2p} node
|
* @param {Libp2p} node
|
||||||
* @param {PeerId|multiaddr} peer
|
* @param {PeerId|Multiaddr} peer
|
||||||
* @returns {Promise<number>}
|
* @returns {Promise<number>}
|
||||||
*/
|
*/
|
||||||
async function ping (node, peer) {
|
async function ping (node, peer) {
|
||||||
|
// @ts-ignore multiaddr might not have toB58String
|
||||||
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
|
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
|
||||||
|
|
||||||
const { stream } = await node.dialProtocol(peer, PROTOCOL)
|
const { stream } = await node.dialProtocol(peer, PROTOCOL)
|
||||||
|
|
||||||
const start = new Date()
|
const start = Date.now()
|
||||||
const data = crypto.randomBytes(PING_LENGTH)
|
const data = crypto.randomBytes(PING_LENGTH)
|
||||||
|
|
||||||
const [result] = await pipe(
|
const [result] = await pipe(
|
||||||
@ -36,7 +45,7 @@ async function ping (node, peer) {
|
|||||||
)
|
)
|
||||||
const end = Date.now()
|
const end = Date.now()
|
||||||
|
|
||||||
if (!data.equals(result)) {
|
if (!equals(data, result)) {
|
||||||
throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK')
|
throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:pnet'), {
|
||||||
|
trace: debug('libp2p:pnet:trace'),
|
||||||
|
error: debug('libp2p:pnet:err')
|
||||||
|
})
|
||||||
|
|
||||||
const Errors = require('./errors')
|
const Errors = require('./errors')
|
||||||
const xsalsa20 = require('xsalsa20')
|
const xsalsa20 = require('xsalsa20')
|
||||||
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
|
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
|
||||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||||
|
|
||||||
const log = debug('libp2p:pnet')
|
|
||||||
log.trace = debug('libp2p:pnet:trace')
|
|
||||||
log.error = debug('libp2p:pnet:err')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a stream iterable to encrypt messages in a private network
|
* Creates a stream iterable to encrypt messages in a private network
|
||||||
*
|
*
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const pipe = require('it-pipe')
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:pnet'), {
|
||||||
|
error: debug('libp2p:pnet:err')
|
||||||
|
})
|
||||||
|
const { pipe } = require('it-pipe')
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const duplexPair = require('it-pair/duplex')
|
const duplexPair = require('it-pair/duplex')
|
||||||
const crypto = require('libp2p-crypto')
|
const crypto = require('libp2p-crypto')
|
||||||
const Errors = require('./errors')
|
const Errors = require('./errors')
|
||||||
const {
|
const {
|
||||||
ERR_INVALID_PARAMETERS
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('../errors')
|
} = require('../errors')
|
||||||
const {
|
const {
|
||||||
createBoxStream,
|
createBoxStream,
|
||||||
@ -15,16 +19,16 @@ const {
|
|||||||
} = require('./crypto')
|
} = require('./crypto')
|
||||||
const handshake = require('it-handshake')
|
const handshake = require('it-handshake')
|
||||||
const { NONCE_LENGTH } = require('./key-generator')
|
const { NONCE_LENGTH } = require('./key-generator')
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:pnet')
|
|
||||||
log.error = debug('libp2p:pnet:err')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a Private Shared Key (psk) and provides a `protect` method
|
* @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection
|
||||||
* for wrapping existing connections in a private encryption stream
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Protector {
|
class Protector {
|
||||||
/**
|
/**
|
||||||
|
* Takes a Private Shared Key (psk) and provides a `protect` method
|
||||||
|
* for wrapping existing connections in a private encryption stream.
|
||||||
|
*
|
||||||
* @param {Uint8Array} keyBuffer - The private shared key buffer
|
* @param {Uint8Array} keyBuffer - The private shared key buffer
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
@ -39,8 +43,8 @@ class Protector {
|
|||||||
* between its two peers from the PSK the Protector instance was
|
* between its two peers from the PSK the Protector instance was
|
||||||
* created with.
|
* created with.
|
||||||
*
|
*
|
||||||
* @param {Connection} connection - The connection to protect
|
* @param {MultiaddrConnection} connection - The connection to protect
|
||||||
* @returns {*} A protected duplex iterable
|
* @returns {Promise<MultiaddrConnection>} A protected duplex iterable
|
||||||
*/
|
*/
|
||||||
async protect (connection) {
|
async protect (connection) {
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
|
@ -22,6 +22,8 @@ module.exports = generate
|
|||||||
module.exports.NONCE_LENGTH = 24
|
module.exports.NONCE_LENGTH = 24
|
||||||
module.exports.KEY_LENGTH = KEY_LENGTH
|
module.exports.KEY_LENGTH = KEY_LENGTH
|
||||||
|
|
||||||
|
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
|
||||||
if (require.main === module) {
|
if (require.main === module) {
|
||||||
|
// @ts-ignore
|
||||||
generate(process.stdout)
|
generate(process.stdout)
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,28 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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.
|
// Pubsub adapter to keep API with handlers while not removed.
|
||||||
module.exports = (PubsubRouter, libp2p, options) => {
|
function pubsubAdapter (PubsubRouter, libp2p, options) {
|
||||||
class Pubsub extends PubsubRouter {
|
const pubsub = new PubsubRouter(libp2p, options)
|
||||||
|
pubsub._subscribeAdapter = pubsub.subscribe
|
||||||
|
pubsub._unsubscribeAdapter = pubsub.unsubscribe
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subscribes to a given topic.
|
* Subscribes to a given topic.
|
||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {string} topic
|
* @param {string} topic
|
||||||
* @param {function(msg: InMessage)} [handler]
|
* @param {(msg: InMessage) => void} [handler]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
subscribe (topic, handler) {
|
function subscribe (topic, handler) {
|
||||||
// Bind provided handler
|
// Bind provided handler
|
||||||
handler && this.on(topic, handler)
|
handler && pubsub.on(topic, handler)
|
||||||
super.subscribe(topic)
|
pubsub._subscribeAdapter(topic)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,21 +30,25 @@ module.exports = (PubsubRouter, libp2p, options) => {
|
|||||||
*
|
*
|
||||||
* @override
|
* @override
|
||||||
* @param {string} topic
|
* @param {string} topic
|
||||||
* @param {function(msg: InMessage)} [handler]
|
* @param {(msg: InMessage) => void} [handler]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
unsubscribe (topic, handler) {
|
function unsubscribe (topic, handler) {
|
||||||
if (!handler) {
|
if (!handler) {
|
||||||
this.removeAllListeners(topic)
|
pubsub.removeAllListeners(topic)
|
||||||
} else {
|
} else {
|
||||||
this.removeListener(topic, handler)
|
pubsub.removeListener(topic, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.listenerCount(topic) === 0) {
|
if (pubsub.listenerCount(topic) === 0) {
|
||||||
super.unsubscribe(topic)
|
pubsub._unsubscribeAdapter(topic)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Pubsub(libp2p, options)
|
pubsub.subscribe = subscribe
|
||||||
|
pubsub.unsubscribe = unsubscribe
|
||||||
|
|
||||||
|
return pubsub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = pubsubAdapter
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
const protons = require('protons')
|
const protons = require('protons')
|
||||||
|
|
||||||
const message = `
|
/** @type {{Envelope: import('../../types').MessageProto}} */
|
||||||
|
module.exports = protons(`
|
||||||
message Envelope {
|
message Envelope {
|
||||||
// public_key is the public key of the keypair the enclosed payload was
|
// public_key is the public key of the keypair the enclosed payload was
|
||||||
// signed with.
|
// signed with.
|
||||||
@ -20,6 +21,4 @@ message Envelope {
|
|||||||
// additional security.
|
// additional security.
|
||||||
bytes signature = 5;
|
bytes signature = 5;
|
||||||
}
|
}
|
||||||
`
|
`)
|
||||||
|
|
||||||
module.exports = protons(message).Envelope
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:envelope')
|
|
||||||
log.error = debug('libp2p:envelope:error')
|
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const uint8arraysConcat = require('uint8arrays/concat')
|
const uint8arraysConcat = require('uint8arrays/concat')
|
||||||
const uint8arraysFromString = require('uint8arrays/from-string')
|
const uint8arraysFromString = require('uint8arrays/from-string')
|
||||||
@ -15,11 +12,14 @@ const { codes } = require('../../errors')
|
|||||||
const Protobuf = require('./envelope.proto')
|
const Protobuf = require('./envelope.proto')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Envelope is responsible for keeping an arbitrary signed record
|
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||||
* by a libp2p peer.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Envelope {
|
class Envelope {
|
||||||
/**
|
/**
|
||||||
|
* The Envelope is responsible for keeping an arbitrary signed record
|
||||||
|
* by a libp2p peer.
|
||||||
|
*
|
||||||
* @class
|
* @class
|
||||||
* @param {object} params
|
* @param {object} params
|
||||||
* @param {PeerId} params.peerId
|
* @param {PeerId} params.peerId
|
||||||
@ -49,7 +49,7 @@ class Envelope {
|
|||||||
|
|
||||||
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
|
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
|
||||||
|
|
||||||
this._marshal = Protobuf.encode({
|
this._marshal = Protobuf.Envelope.encode({
|
||||||
public_key: publicKey,
|
public_key: publicKey,
|
||||||
payload_type: this.payloadType,
|
payload_type: this.payloadType,
|
||||||
payload: this.payload,
|
payload: this.payload,
|
||||||
@ -102,14 +102,14 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
|
|||||||
// - The length of the payload field in bytes
|
// - The length of the payload field in bytes
|
||||||
// - The value of the payload field
|
// - The value of the payload field
|
||||||
|
|
||||||
domain = uint8arraysFromString(domain)
|
const domainUint8Array = uint8arraysFromString(domain)
|
||||||
const domainLength = varint.encode(domain.byteLength)
|
const domainLength = varint.encode(domainUint8Array.byteLength)
|
||||||
const payloadTypeLength = varint.encode(payloadType.length)
|
const payloadTypeLength = varint.encode(payloadType.length)
|
||||||
const payloadLength = varint.encode(payload.length)
|
const payloadLength = varint.encode(payload.length)
|
||||||
|
|
||||||
return uint8arraysConcat([
|
return uint8arraysConcat([
|
||||||
new Uint8Array(domainLength),
|
new Uint8Array(domainLength),
|
||||||
domain,
|
domainUint8Array,
|
||||||
new Uint8Array(payloadTypeLength),
|
new Uint8Array(payloadTypeLength),
|
||||||
payloadType,
|
payloadType,
|
||||||
new Uint8Array(payloadLength),
|
new Uint8Array(payloadLength),
|
||||||
@ -124,7 +124,7 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
|
|||||||
* @returns {Promise<Envelope>}
|
* @returns {Promise<Envelope>}
|
||||||
*/
|
*/
|
||||||
Envelope.createFromProtobuf = async (data) => {
|
Envelope.createFromProtobuf = async (data) => {
|
||||||
const envelopeData = Protobuf.decode(data)
|
const envelopeData = Protobuf.Envelope.decode(data)
|
||||||
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
|
||||||
|
|
||||||
return new Envelope({
|
return new Envelope({
|
||||||
@ -142,7 +142,7 @@ Envelope.createFromProtobuf = async (data) => {
|
|||||||
* @async
|
* @async
|
||||||
* @param {Record} record
|
* @param {Record} record
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Envelope}
|
* @returns {Promise<Envelope>}
|
||||||
*/
|
*/
|
||||||
Envelope.seal = async (record, peerId) => {
|
Envelope.seal = async (record, peerId) => {
|
||||||
const domain = record.domain
|
const domain = record.domain
|
||||||
@ -166,7 +166,7 @@ Envelope.seal = async (record, peerId) => {
|
|||||||
*
|
*
|
||||||
* @param {Uint8Array} data
|
* @param {Uint8Array} data
|
||||||
* @param {string} domain
|
* @param {string} domain
|
||||||
* @returns {Envelope}
|
* @returns {Promise<Envelope>}
|
||||||
*/
|
*/
|
||||||
Envelope.openAndCertify = async (data, domain) => {
|
Envelope.openAndCertify = async (data, domain) => {
|
||||||
const envelope = await Envelope.createFromProtobuf(data)
|
const envelope = await Envelope.createFromProtobuf(data)
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
const multiaddr = require('multiaddr')
|
const multiaddr = require('multiaddr')
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const Record = require('libp2p-interfaces/src/record')
|
|
||||||
const arrayEquals = require('libp2p-utils/src/array-equals')
|
const arrayEquals = require('libp2p-utils/src/array-equals')
|
||||||
|
|
||||||
const Protobuf = require('./peer-record.proto')
|
const Protobuf = require('./peer-record.proto')
|
||||||
@ -12,19 +11,28 @@ const {
|
|||||||
} = require('./consts')
|
} = require('./consts')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements {Record}
|
||||||
|
*/
|
||||||
|
class PeerRecord {
|
||||||
|
/**
|
||||||
* The PeerRecord is used for distributing peer routing records across the network.
|
* The PeerRecord is used for distributing peer routing records across the network.
|
||||||
* It contains the peer's reachable listen addresses.
|
* It contains the peer's reachable listen addresses.
|
||||||
*/
|
*
|
||||||
class PeerRecord extends Record {
|
|
||||||
/**
|
|
||||||
* @class
|
* @class
|
||||||
* @param {object} params
|
* @param {Object} params
|
||||||
* @param {PeerId} params.peerId
|
* @param {PeerId} params.peerId
|
||||||
* @param {Array<multiaddr>} params.multiaddrs - addresses of the associated peer.
|
* @param {Multiaddr[]} params.multiaddrs - addresses of the associated peer.
|
||||||
* @param {number} [params.seqNumber] - monotonically-increasing sequence counter that's used to order PeerRecords in time.
|
* @param {number} [params.seqNumber] - monotonically-increasing sequence counter that's used to order PeerRecords in time.
|
||||||
*/
|
*/
|
||||||
constructor ({ peerId, multiaddrs = [], seqNumber = Date.now() }) {
|
constructor ({ peerId, multiaddrs = [], seqNumber = Date.now() }) {
|
||||||
super(ENVELOPE_DOMAIN_PEER_RECORD, ENVELOPE_PAYLOAD_TYPE_PEER_RECORD)
|
this.domain = ENVELOPE_DOMAIN_PEER_RECORD
|
||||||
|
this.codec = ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
|
||||||
|
|
||||||
this.peerId = peerId
|
this.peerId = peerId
|
||||||
this.multiaddrs = multiaddrs
|
this.multiaddrs = multiaddrs
|
||||||
@ -44,7 +52,7 @@ class PeerRecord extends Record {
|
|||||||
return this._marshal
|
return this._marshal
|
||||||
}
|
}
|
||||||
|
|
||||||
this._marshal = Protobuf.encode({
|
this._marshal = Protobuf.PeerRecord.encode({
|
||||||
peer_id: this.peerId.toBytes(),
|
peer_id: this.peerId.toBytes(),
|
||||||
seq: this.seqNumber,
|
seq: this.seqNumber,
|
||||||
addresses: this.multiaddrs.map((m) => ({
|
addresses: this.multiaddrs.map((m) => ({
|
||||||
@ -58,10 +66,14 @@ class PeerRecord extends Record {
|
|||||||
/**
|
/**
|
||||||
* Returns true if `this` record equals the `other`.
|
* Returns true if `this` record equals the `other`.
|
||||||
*
|
*
|
||||||
* @param {Record} other
|
* @param {unknown} other
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
equals (other) {
|
equals (other) {
|
||||||
|
if (!(other instanceof PeerRecord)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Validate PeerId
|
// Validate PeerId
|
||||||
if (!this.peerId.equals(other.peerId)) {
|
if (!this.peerId.equals(other.peerId)) {
|
||||||
return false
|
return false
|
||||||
@ -89,7 +101,7 @@ class PeerRecord extends Record {
|
|||||||
*/
|
*/
|
||||||
PeerRecord.createFromProtobuf = (buf) => {
|
PeerRecord.createFromProtobuf = (buf) => {
|
||||||
// Decode
|
// Decode
|
||||||
const peerRecord = Protobuf.decode(buf)
|
const peerRecord = Protobuf.PeerRecord.decode(buf)
|
||||||
|
|
||||||
const peerId = PeerId.createFromBytes(peerRecord.peer_id)
|
const peerId = PeerId.createFromBytes(peerRecord.peer_id)
|
||||||
const multiaddrs = (peerRecord.addresses || []).map((a) => multiaddr(a.multiaddr))
|
const multiaddrs = (peerRecord.addresses || []).map((a) => multiaddr(a.multiaddr))
|
||||||
|
@ -7,7 +7,8 @@ const protons = require('protons')
|
|||||||
// is expected to expand to include other information in the future.
|
// is expected to expand to include other information in the future.
|
||||||
// PeerRecords are designed to be serialized to bytes and placed inside of
|
// PeerRecords are designed to be serialized to bytes and placed inside of
|
||||||
// SignedEnvelopes before sharing with other peers.
|
// SignedEnvelopes before sharing with other peers.
|
||||||
const message = `
|
/** @type {{PeerRecord: import('../../types').MessageProto}} */
|
||||||
|
module.exports = protons(`
|
||||||
message PeerRecord {
|
message PeerRecord {
|
||||||
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
|
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
|
||||||
// separate message to allow us to add per-address metadata in the future.
|
// separate message to allow us to add per-address metadata in the future.
|
||||||
@ -24,6 +25,4 @@ message PeerRecord {
|
|||||||
// addresses is a list of public listen addresses for the peer.
|
// addresses is a list of public listen addresses for the peer.
|
||||||
repeated AddressInfo addresses = 3;
|
repeated AddressInfo addresses = 3;
|
||||||
}
|
}
|
||||||
`
|
`)
|
||||||
|
|
||||||
module.exports = protons(message).PeerRecord
|
|
||||||
|
@ -3,10 +3,14 @@
|
|||||||
const Envelope = require('./envelope')
|
const Envelope = require('./envelope')
|
||||||
const PeerRecord = require('./peer-record')
|
const PeerRecord = require('./peer-record')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('../')} Libp2p
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create (or update if existing) self peer record and store it in the AddressBook.
|
* Create (or update if existing) self peer record and store it in the AddressBook.
|
||||||
*
|
*
|
||||||
* @param {libp2p} libp2p
|
* @param {Libp2p} libp2p
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async function updateSelfPeerRecord (libp2p) {
|
async function updateSelfPeerRecord (libp2p) {
|
||||||
|
@ -1,15 +1,24 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:peer-store'), {
|
||||||
|
error: debug('libp2p:peer-store:err')
|
||||||
|
})
|
||||||
const errcode = require('err-code')
|
const errcode = require('err-code')
|
||||||
const log = debug('libp2p:peer-store')
|
|
||||||
log.error = debug('libp2p:peer-store:error')
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ERR_INVALID_PARAMETERS
|
codes: { ERR_INVALID_PARAMETERS }
|
||||||
} = require('./errors')
|
} = require('./errors')
|
||||||
const Topology = require('libp2p-interfaces/src/topology')
|
const Topology = require('libp2p-interfaces/src/topology')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('peer-id')} PeerId
|
||||||
|
* @typedef {import('./peer-store')} PeerStore
|
||||||
|
* @typedef {import('./connection-manager')} ConnectionManager
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('libp2p-interfaces/src/topology')} Topology
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responsible for notifying registered protocols of events in the network.
|
* Responsible for notifying registered protocols of events in the network.
|
||||||
*/
|
*/
|
||||||
@ -17,7 +26,7 @@ class Registrar {
|
|||||||
/**
|
/**
|
||||||
* @param {Object} props
|
* @param {Object} props
|
||||||
* @param {PeerStore} props.peerStore
|
* @param {PeerStore} props.peerStore
|
||||||
* @param {connectionManager} props.connectionManager
|
* @param {ConnectionManager} props.connectionManager
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
constructor ({ peerStore, connectionManager }) {
|
constructor ({ peerStore, connectionManager }) {
|
||||||
@ -51,7 +60,7 @@ class Registrar {
|
|||||||
* Get a connection with a peer.
|
* Get a connection with a peer.
|
||||||
*
|
*
|
||||||
* @param {PeerId} peerId
|
* @param {PeerId} peerId
|
||||||
* @returns {Connection}
|
* @returns {Connection | null}
|
||||||
*/
|
*/
|
||||||
getConnection (peerId) {
|
getConnection (peerId) {
|
||||||
return this.connectionManager.get(peerId)
|
return this.connectionManager.get(peerId)
|
||||||
@ -65,11 +74,12 @@ class Registrar {
|
|||||||
*/
|
*/
|
||||||
register (topology) {
|
register (topology) {
|
||||||
if (!Topology.isTopology(topology)) {
|
if (!Topology.isTopology(topology)) {
|
||||||
|
log.error('topology must be an instance of interfaces/topology')
|
||||||
throw errcode(new Error('topology must be an instance of interfaces/topology'), ERR_INVALID_PARAMETERS)
|
throw errcode(new Error('topology must be an instance of interfaces/topology'), ERR_INVALID_PARAMETERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create topology
|
// Create topology
|
||||||
const id = (parseInt(Math.random() * 1e9)).toString(36) + Date.now()
|
const id = (Math.random() * 1e9).toString(36) + Date.now()
|
||||||
|
|
||||||
this.topologies.set(id, topology)
|
this.topologies.set(id, topology)
|
||||||
|
|
||||||
|
@ -1,25 +1,39 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const debug = require('debug')
|
||||||
|
const log = Object.assign(debug('libp2p:transports'), {
|
||||||
|
error: debug('libp2p:transports:err')
|
||||||
|
})
|
||||||
|
|
||||||
const pSettle = require('p-settle')
|
const pSettle = require('p-settle')
|
||||||
const { codes } = require('./errors')
|
const { codes } = require('./errors')
|
||||||
const errCode = require('err-code')
|
const errCode = require('err-code')
|
||||||
const debug = require('debug')
|
|
||||||
const log = debug('libp2p:transports')
|
|
||||||
log.error = debug('libp2p:transports:error')
|
|
||||||
|
|
||||||
const { updateSelfPeerRecord } = require('./record/utils')
|
const { updateSelfPeerRecord } = require('./record/utils')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
|
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
|
||||||
|
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory} TransportFactory
|
||||||
|
* @typedef {import('libp2p-interfaces/src/transport/types').Transport} Transport
|
||||||
|
*
|
||||||
|
* @typedef {Object} TransportManagerProperties
|
||||||
|
* @property {import('./')} libp2p
|
||||||
|
* @property {import('./upgrader')} upgrader
|
||||||
|
*
|
||||||
|
* @typedef {Object} TransportManagerOptions
|
||||||
|
* @property {number} [faultTolerance = FAULT_TOLERANCE.FATAL_ALL] - Address listen error tolerance.
|
||||||
|
*/
|
||||||
|
|
||||||
class TransportManager {
|
class TransportManager {
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @param {object} options
|
* @param {TransportManagerProperties & TransportManagerOptions} options
|
||||||
* @param {Libp2p} options.libp2p - The Libp2p instance. It will be passed to the transports.
|
|
||||||
* @param {Upgrader} options.upgrader - The upgrader to provide to the transports
|
|
||||||
* @param {boolean} [options.faultTolerance = FAULT_TOLERANCE.FATAL_ALL] - Address listen error tolerance.
|
|
||||||
*/
|
*/
|
||||||
constructor ({ libp2p, upgrader, faultTolerance = FAULT_TOLERANCE.FATAL_ALL }) {
|
constructor ({ libp2p, upgrader, faultTolerance = FAULT_TOLERANCE.FATAL_ALL }) {
|
||||||
this.libp2p = libp2p
|
this.libp2p = libp2p
|
||||||
this.upgrader = upgrader
|
this.upgrader = upgrader
|
||||||
|
/** @type {Map<string, Transport>} */
|
||||||
this._transports = new Map()
|
this._transports = new Map()
|
||||||
this._listeners = new Map()
|
this._listeners = new Map()
|
||||||
this._listenerOptions = new Map()
|
this._listenerOptions = new Map()
|
||||||
@ -30,7 +44,7 @@ class TransportManager {
|
|||||||
* Adds a `Transport` to the manager
|
* Adds a `Transport` to the manager
|
||||||
*
|
*
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {Transport} Transport
|
* @param {TransportFactory} Transport
|
||||||
* @param {*} transportOptions - Additional options to pass to the transport
|
* @param {*} transportOptions - Additional options to pass to the transport
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
@ -119,7 +133,7 @@ class TransportManager {
|
|||||||
/**
|
/**
|
||||||
* Returns all the transports instances.
|
* Returns all the transports instances.
|
||||||
*
|
*
|
||||||
* @returns {Iterator<Transport>}
|
* @returns {IterableIterator<Transport>}
|
||||||
*/
|
*/
|
||||||
getTransports () {
|
getTransports () {
|
||||||
return this._transports.values()
|
return this._transports.values()
|
||||||
@ -143,7 +157,7 @@ class TransportManager {
|
|||||||
* Starts listeners for each listen Multiaddr.
|
* Starts listeners for each listen Multiaddr.
|
||||||
*
|
*
|
||||||
* @async
|
* @async
|
||||||
* @param {Array<Multiaddr>} addrs - addresses to attempt to listen on
|
* @param {Multiaddr[]} addrs - addresses to attempt to listen on
|
||||||
*/
|
*/
|
||||||
async listen (addrs) {
|
async listen (addrs) {
|
||||||
if (!addrs || addrs.length === 0) {
|
if (!addrs || addrs.length === 0) {
|
||||||
@ -159,7 +173,7 @@ class TransportManager {
|
|||||||
// For each supported multiaddr, create a listener
|
// For each supported multiaddr, create a listener
|
||||||
for (const addr of supportedAddrs) {
|
for (const addr of supportedAddrs) {
|
||||||
log('creating listener for %s on %s', key, addr)
|
log('creating listener for %s on %s', key, addr)
|
||||||
const listener = transport.createListener(this._listenerOptions.get(key), this.onConnection)
|
const listener = transport.createListener(this._listenerOptions.get(key))
|
||||||
this._listeners.get(key).push(listener)
|
this._listeners.get(key).push(listener)
|
||||||
|
|
||||||
// Track listen/close events
|
// Track listen/close events
|
||||||
|
84
src/types.ts
Normal file
84
src/types.ts
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
|
||||||
|
// Insecure Message types
|
||||||
|
export enum KeyType {
|
||||||
|
RSA = 0,
|
||||||
|
Ed25519 = 1,
|
||||||
|
Secp256k1 = 2,
|
||||||
|
ECDSA = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protobufs
|
||||||
|
export type MessageProto = {
|
||||||
|
encode(value: any): Uint8Array
|
||||||
|
decode(bytes: Uint8Array): any
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SUCCESS = 100;
|
||||||
|
export type HOP_SRC_ADDR_TOO_LONG = 220;
|
||||||
|
export type HOP_DST_ADDR_TOO_LONG = 221;
|
||||||
|
export type HOP_SRC_MULTIADDR_INVALID = 250;
|
||||||
|
export type HOP_DST_MULTIADDR_INVALID = 251;
|
||||||
|
export type HOP_NO_CONN_TO_DST = 260;
|
||||||
|
export type HOP_CANT_DIAL_DST = 261;
|
||||||
|
export type HOP_CANT_OPEN_DST_STREAM = 262;
|
||||||
|
export type HOP_CANT_SPEAK_RELAY = 270;
|
||||||
|
export type HOP_CANT_RELAY_TO_SELF = 280;
|
||||||
|
export type STOP_SRC_ADDR_TOO_LONG = 320;
|
||||||
|
export type STOP_DST_ADDR_TOO_LONG = 321;
|
||||||
|
export type STOP_SRC_MULTIADDR_INVALID = 350;
|
||||||
|
export type STOP_DST_MULTIADDR_INVALID = 351;
|
||||||
|
export type STOP_RELAY_REFUSED = 390;
|
||||||
|
export type MALFORMED_MESSAGE = 400;
|
||||||
|
|
||||||
|
export type CircuitStatus = SUCCESS | HOP_SRC_ADDR_TOO_LONG | HOP_DST_ADDR_TOO_LONG
|
||||||
|
| HOP_SRC_MULTIADDR_INVALID | HOP_DST_MULTIADDR_INVALID | HOP_NO_CONN_TO_DST
|
||||||
|
| HOP_CANT_DIAL_DST | HOP_CANT_OPEN_DST_STREAM | HOP_CANT_SPEAK_RELAY | HOP_CANT_RELAY_TO_SELF
|
||||||
|
| STOP_SRC_ADDR_TOO_LONG | STOP_DST_ADDR_TOO_LONG | STOP_SRC_MULTIADDR_INVALID
|
||||||
|
| STOP_DST_MULTIADDR_INVALID | STOP_RELAY_REFUSED | MALFORMED_MESSAGE
|
||||||
|
|
||||||
|
export type HOP = 1;
|
||||||
|
export type STOP = 2;
|
||||||
|
export type STATUS = 3;
|
||||||
|
export type CAN_HOP = 4;
|
||||||
|
|
||||||
|
export type CircuitType = HOP | STOP | STATUS | CAN_HOP
|
||||||
|
|
||||||
|
export type CircuitPeer = {
|
||||||
|
id: Uint8Array
|
||||||
|
addrs: Uint8Array[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CircuitRequest = {
|
||||||
|
type: CircuitType
|
||||||
|
dstPeer: CircuitPeer
|
||||||
|
srcPeer: CircuitPeer
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CircuitMessageProto = {
|
||||||
|
encode(value: any): Uint8Array
|
||||||
|
decode(bytes: Uint8Array): any
|
||||||
|
Status: {
|
||||||
|
SUCCESS: SUCCESS,
|
||||||
|
HOP_SRC_ADDR_TOO_LONG: HOP_SRC_ADDR_TOO_LONG,
|
||||||
|
HOP_DST_ADDR_TOO_LONG: HOP_DST_ADDR_TOO_LONG,
|
||||||
|
HOP_SRC_MULTIADDR_INVALID: HOP_SRC_MULTIADDR_INVALID,
|
||||||
|
HOP_DST_MULTIADDR_INVALID: HOP_DST_MULTIADDR_INVALID,
|
||||||
|
HOP_NO_CONN_TO_DST: HOP_NO_CONN_TO_DST,
|
||||||
|
HOP_CANT_DIAL_DST: HOP_CANT_DIAL_DST,
|
||||||
|
HOP_CANT_OPEN_DST_STREAM: HOP_CANT_OPEN_DST_STREAM,
|
||||||
|
HOP_CANT_SPEAK_RELAY: HOP_CANT_SPEAK_RELAY,
|
||||||
|
HOP_CANT_RELAY_TO_SELF: HOP_CANT_RELAY_TO_SELF,
|
||||||
|
STOP_SRC_ADDR_TOO_LONG: STOP_SRC_ADDR_TOO_LONG,
|
||||||
|
STOP_DST_ADDR_TOO_LONG: STOP_DST_ADDR_TOO_LONG,
|
||||||
|
STOP_SRC_MULTIADDR_INVALID: STOP_SRC_MULTIADDR_INVALID,
|
||||||
|
STOP_DST_MULTIADDR_INVALID: STOP_DST_MULTIADDR_INVALID,
|
||||||
|
STOP_RELAY_REFUSED: STOP_RELAY_REFUSED,
|
||||||
|
MALFORMED_MESSAGE: MALFORMED_MESSAGE
|
||||||
|
},
|
||||||
|
Type: {
|
||||||
|
HOP: HOP,
|
||||||
|
STOP: STOP,
|
||||||
|
STATUS: STATUS,
|
||||||
|
CAN_HOP: CAN_HOP
|
||||||
|
}
|
||||||
|
}
|
@ -1,29 +1,30 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const debug = require('debug')
|
const debug = require('debug')
|
||||||
const log = debug('libp2p:upgrader')
|
const log = Object.assign(debug('libp2p:upgrader'), {
|
||||||
log.error = debug('libp2p:upgrader:error')
|
error: debug('libp2p:upgrader:err')
|
||||||
|
})
|
||||||
|
const errCode = require('err-code')
|
||||||
const Multistream = require('multistream-select')
|
const Multistream = require('multistream-select')
|
||||||
const { Connection } = require('libp2p-interfaces/src/connection')
|
const { Connection } = require('libp2p-interfaces/src/connection')
|
||||||
const ConnectionStatus = require('libp2p-interfaces/src/connection/status')
|
|
||||||
const PeerId = require('peer-id')
|
const PeerId = require('peer-id')
|
||||||
const pipe = require('it-pipe')
|
const { pipe } = require('it-pipe')
|
||||||
const errCode = require('err-code')
|
|
||||||
const mutableProxy = require('mutable-proxy')
|
const mutableProxy = require('mutable-proxy')
|
||||||
|
|
||||||
const { codes } = require('./errors')
|
const { codes } = require('./errors')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef MultiaddrConnection
|
* @typedef {import('libp2p-interfaces/src/transport/types').MultiaddrConnection} MultiaddrConnection
|
||||||
* @property {Function} sink
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxerFactory} MuxerFactory
|
||||||
* @property {AsyncIterator} source
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').Muxer} Muxer
|
||||||
* @property {*} conn
|
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
|
||||||
* @property {Multiaddr} remoteAddr
|
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
|
||||||
|
* @typedef {import('multiaddr')} Multiaddr
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef CryptoResult
|
* @typedef CryptoResult
|
||||||
* @property {*} conn A duplex iterable
|
* @property {MultiaddrConnection} conn A duplex iterable
|
||||||
* @property {PeerId} remotePeer
|
* @property {PeerId} remotePeer
|
||||||
* @property {string} protocol
|
* @property {string} protocol
|
||||||
*/
|
*/
|
||||||
@ -32,24 +33,24 @@ class Upgrader {
|
|||||||
/**
|
/**
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {PeerId} options.localPeer
|
* @param {PeerId} options.localPeer
|
||||||
* @param {Metrics} options.metrics
|
* @param {import('./metrics')} [options.metrics]
|
||||||
* @param {Map<string, Crypto>} options.cryptos
|
* @param {Map<string, Crypto>} [options.cryptos]
|
||||||
* @param {Map<string, Muxer>} options.muxers
|
* @param {Map<string, MuxerFactory>} [options.muxers]
|
||||||
* @param {function(Connection)} options.onConnection - Called when a connection is upgraded
|
* @param {(Connection) => void} options.onConnection - Called when a connection is upgraded
|
||||||
* @param {function(Connection)} options.onConnectionEnd
|
* @param {(Connection) => void} options.onConnectionEnd
|
||||||
*/
|
*/
|
||||||
constructor ({
|
constructor ({
|
||||||
localPeer,
|
localPeer,
|
||||||
metrics,
|
metrics,
|
||||||
cryptos,
|
cryptos = new Map(),
|
||||||
muxers,
|
muxers = new Map(),
|
||||||
onConnectionEnd = () => {},
|
onConnectionEnd = () => {},
|
||||||
onConnection = () => {}
|
onConnection = () => {}
|
||||||
}) {
|
}) {
|
||||||
this.localPeer = localPeer
|
this.localPeer = localPeer
|
||||||
this.metrics = metrics
|
this.metrics = metrics
|
||||||
this.cryptos = cryptos || new Map()
|
this.cryptos = cryptos
|
||||||
this.muxers = muxers || new Map()
|
this.muxers = muxers
|
||||||
this.protector = null
|
this.protector = null
|
||||||
this.protocols = new Map()
|
this.protocols = new Map()
|
||||||
this.onConnection = onConnection
|
this.onConnection = onConnection
|
||||||
@ -74,7 +75,7 @@ class Upgrader {
|
|||||||
|
|
||||||
if (this.metrics) {
|
if (this.metrics) {
|
||||||
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy())
|
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy())
|
||||||
const idString = (parseInt(Math.random() * 1e9)).toString(36) + Date.now()
|
const idString = (Math.random() * 1e9).toString(36) + Date.now()
|
||||||
setPeer({ toB58String: () => idString })
|
setPeer({ toB58String: () => idString })
|
||||||
maConn = this.metrics.trackStream({ stream: maConn, remotePeer: proxyPeer })
|
maConn = this.metrics.trackStream({ stream: maConn, remotePeer: proxyPeer })
|
||||||
}
|
}
|
||||||
@ -132,12 +133,7 @@ class Upgrader {
|
|||||||
* @returns {Promise<Connection>}
|
* @returns {Promise<Connection>}
|
||||||
*/
|
*/
|
||||||
async upgradeOutbound (maConn) {
|
async upgradeOutbound (maConn) {
|
||||||
let remotePeerId
|
const remotePeerId = PeerId.createFromB58String(maConn.remoteAddr.getPeerId())
|
||||||
try {
|
|
||||||
remotePeerId = PeerId.createFromB58String(maConn.remoteAddr.getPeerId())
|
|
||||||
} catch (err) {
|
|
||||||
log.error('multiaddr did not contain a valid peer id', err)
|
|
||||||
}
|
|
||||||
|
|
||||||
let encryptedConn
|
let encryptedConn
|
||||||
let remotePeer
|
let remotePeer
|
||||||
@ -149,7 +145,7 @@ class Upgrader {
|
|||||||
|
|
||||||
if (this.metrics) {
|
if (this.metrics) {
|
||||||
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy())
|
({ setTarget: setPeer, proxy: proxyPeer } = mutableProxy())
|
||||||
const idString = (parseInt(Math.random() * 1e9)).toString(36) + Date.now()
|
const idString = (Math.random() * 1e9).toString(36) + Date.now()
|
||||||
setPeer({ toB58String: () => idString })
|
setPeer({ toB58String: () => idString })
|
||||||
maConn = this.metrics.trackStream({ stream: maConn, remotePeer: proxyPeer })
|
maConn = this.metrics.trackStream({ stream: maConn, remotePeer: proxyPeer })
|
||||||
}
|
}
|
||||||
@ -207,8 +203,8 @@ class Upgrader {
|
|||||||
* @param {string} options.cryptoProtocol - The crypto protocol that was negotiated
|
* @param {string} options.cryptoProtocol - The crypto protocol that was negotiated
|
||||||
* @param {string} options.direction - One of ['inbound', 'outbound']
|
* @param {string} options.direction - One of ['inbound', 'outbound']
|
||||||
* @param {MultiaddrConnection} options.maConn - The transport layer connection
|
* @param {MultiaddrConnection} options.maConn - The transport layer connection
|
||||||
* @param {*} options.upgradedConn - A duplex connection returned from multiplexer and/or crypto selection
|
* @param {MuxedStream | MultiaddrConnection} options.upgradedConn - A duplex connection returned from multiplexer and/or crypto selection
|
||||||
* @param {Muxer} options.Muxer - The muxer to be used for muxing
|
* @param {MuxerFactory} [options.Muxer] - The muxer to be used for muxing
|
||||||
* @param {PeerId} options.remotePeer - The peer the connection is with
|
* @param {PeerId} options.remotePeer - The peer the connection is with
|
||||||
* @returns {Connection}
|
* @returns {Connection}
|
||||||
*/
|
*/
|
||||||
@ -272,7 +268,7 @@ class Upgrader {
|
|||||||
// Wait for close to finish before notifying of the closure
|
// Wait for close to finish before notifying of the closure
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
if (connection.stat.status === ConnectionStatus.OPEN) {
|
if (connection.stat.status === 'open') {
|
||||||
await connection.close()
|
await connection.close()
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@ -300,6 +296,7 @@ class Upgrader {
|
|||||||
remotePeer: remotePeer,
|
remotePeer: remotePeer,
|
||||||
stat: {
|
stat: {
|
||||||
direction,
|
direction,
|
||||||
|
// @ts-ignore
|
||||||
timeline: maConn.timeline,
|
timeline: maConn.timeline,
|
||||||
multiplexer: Muxer && Muxer.multicodec,
|
multiplexer: Muxer && Muxer.multicodec,
|
||||||
encryption: cryptoProtocol
|
encryption: cryptoProtocol
|
||||||
@ -326,7 +323,7 @@ class Upgrader {
|
|||||||
* @private
|
* @private
|
||||||
* @param {object} options
|
* @param {object} options
|
||||||
* @param {Connection} options.connection - The connection the stream belongs to
|
* @param {Connection} options.connection - The connection the stream belongs to
|
||||||
* @param {Stream} options.stream
|
* @param {MuxedStream} options.stream
|
||||||
* @param {string} options.protocol
|
* @param {string} options.protocol
|
||||||
*/
|
*/
|
||||||
_onStream ({ connection, stream, protocol }) {
|
_onStream ({ connection, stream, protocol }) {
|
||||||
@ -342,7 +339,7 @@ class Upgrader {
|
|||||||
* @param {PeerId} localPeer - The initiators PeerId
|
* @param {PeerId} localPeer - The initiators PeerId
|
||||||
* @param {*} connection
|
* @param {*} connection
|
||||||
* @param {Map<string, Crypto>} cryptos
|
* @param {Map<string, Crypto>} cryptos
|
||||||
* @returns {CryptoResult} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used
|
* @returns {Promise<CryptoResult>} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used
|
||||||
*/
|
*/
|
||||||
async _encryptInbound (localPeer, connection, cryptos) {
|
async _encryptInbound (localPeer, connection, cryptos) {
|
||||||
const mss = new Multistream.Listener(connection)
|
const mss = new Multistream.Listener(connection)
|
||||||
@ -354,6 +351,10 @@ class Upgrader {
|
|||||||
const crypto = cryptos.get(protocol)
|
const crypto = cryptos.get(protocol)
|
||||||
log('encrypting inbound connection...')
|
log('encrypting inbound connection...')
|
||||||
|
|
||||||
|
if (!crypto) {
|
||||||
|
throw new Error(`no crypto module found for ${protocol}`)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...await crypto.secureInbound(localPeer, stream),
|
...await crypto.secureInbound(localPeer, stream),
|
||||||
protocol
|
protocol
|
||||||
@ -373,7 +374,7 @@ class Upgrader {
|
|||||||
* @param {*} connection
|
* @param {*} connection
|
||||||
* @param {PeerId} remotePeerId
|
* @param {PeerId} remotePeerId
|
||||||
* @param {Map<string, Crypto>} cryptos
|
* @param {Map<string, Crypto>} cryptos
|
||||||
* @returns {CryptoResult} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used
|
* @returns {Promise<CryptoResult>} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used
|
||||||
*/
|
*/
|
||||||
async _encryptOutbound (localPeer, connection, remotePeerId, cryptos) {
|
async _encryptOutbound (localPeer, connection, remotePeerId, cryptos) {
|
||||||
const mss = new Multistream.Dialer(connection)
|
const mss = new Multistream.Dialer(connection)
|
||||||
@ -385,6 +386,10 @@ class Upgrader {
|
|||||||
const crypto = cryptos.get(protocol)
|
const crypto = cryptos.get(protocol)
|
||||||
log('encrypting outbound connection to %j', remotePeerId)
|
log('encrypting outbound connection to %j', remotePeerId)
|
||||||
|
|
||||||
|
if (!crypto) {
|
||||||
|
throw new Error(`no crypto module found for ${protocol}`)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...await crypto.secureOutbound(localPeer, stream, remotePeerId),
|
...await crypto.secureOutbound(localPeer, stream, remotePeerId),
|
||||||
protocol
|
protocol
|
||||||
@ -400,9 +405,9 @@ class Upgrader {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @async
|
* @async
|
||||||
* @param {*} connection - A basic duplex connection to multiplex
|
* @param {MultiaddrConnection} connection - A basic duplex connection to multiplex
|
||||||
* @param {Map<string, Muxer>} muxers - The muxers to attempt multiplexing with
|
* @param {Map<string, MuxerFactory>} muxers - The muxers to attempt multiplexing with
|
||||||
* @returns {*} A muxed connection
|
* @returns {Promise<{ stream: MuxedStream, Muxer?: MuxerFactory}>} A muxed connection
|
||||||
*/
|
*/
|
||||||
async _multiplexOutbound (connection, muxers) {
|
async _multiplexOutbound (connection, muxers) {
|
||||||
const dialer = new Multistream.Dialer(connection)
|
const dialer = new Multistream.Dialer(connection)
|
||||||
@ -424,9 +429,9 @@ class Upgrader {
|
|||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @async
|
* @async
|
||||||
* @param {*} connection - A basic duplex connection to multiplex
|
* @param {MultiaddrConnection} connection - A basic duplex connection to multiplex
|
||||||
* @param {Map<string, Muxer>} muxers - The muxers to attempt multiplexing with
|
* @param {Map<string, MuxerFactory>} muxers - The muxers to attempt multiplexing with
|
||||||
* @returns {*} A muxed connection
|
* @returns {Promise<{ stream: MuxedStream, Muxer?: MuxerFactory}>} A muxed connection
|
||||||
*/
|
*/
|
||||||
async _multiplexInbound (connection, muxers) {
|
async _multiplexInbound (connection, muxers) {
|
||||||
const listener = new Multistream.Listener(connection)
|
const listener = new Multistream.Listener(connection)
|
||||||
|
@ -10,7 +10,7 @@ const AggregateError = require('aggregate-error')
|
|||||||
const pDefer = require('p-defer')
|
const pDefer = require('p-defer')
|
||||||
const delay = require('delay')
|
const delay = require('delay')
|
||||||
|
|
||||||
const { DialRequest } = require('../../src/dialer/dial-request')
|
const DialRequest = require('../../src/dialer/dial-request')
|
||||||
const createMockConnection = require('../utils/mockConnection')
|
const createMockConnection = require('../utils/mockConnection')
|
||||||
const error = new Error('dial failes')
|
const error = new Error('dial failes')
|
||||||
|
|
||||||
|
@ -12,7 +12,8 @@ const pWaitFor = require('p-wait-for')
|
|||||||
const unit8ArrayToString = require('uint8arrays/to-string')
|
const unit8ArrayToString = require('uint8arrays/to-string')
|
||||||
|
|
||||||
const { codes: Errors } = require('../../src/errors')
|
const { codes: Errors } = require('../../src/errors')
|
||||||
const { IdentifyService, multicodecs } = require('../../src/identify')
|
const IdentifyService = require('../../src/identify')
|
||||||
|
const multicodecs = IdentifyService.multicodecs
|
||||||
const Peers = require('../fixtures/peers')
|
const Peers = require('../fixtures/peers')
|
||||||
const Libp2p = require('../../src')
|
const Libp2p = require('../../src')
|
||||||
const Envelope = require('../../src/record/envelope')
|
const Envelope = require('../../src/record/envelope')
|
||||||
@ -54,7 +55,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: localPeerStore,
|
peerStore: localPeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const remoteIdentify = new IdentifyService({
|
const remoteIdentify = new IdentifyService({
|
||||||
@ -63,7 +65,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: remotePeerStore,
|
peerStore: remotePeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -109,7 +112,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: localPeerStore,
|
peerStore: localPeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -119,7 +123,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: remotePeerStore,
|
peerStore: remotePeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -167,7 +172,8 @@ describe('Identify', () => {
|
|||||||
peerId: localPeer,
|
peerId: localPeer,
|
||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: localPeerStore,
|
peerStore: localPeerStore,
|
||||||
multiaddrs: []
|
multiaddrs: [],
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const remoteIdentify = new IdentifyService({
|
const remoteIdentify = new IdentifyService({
|
||||||
@ -175,7 +181,8 @@ describe('Identify', () => {
|
|||||||
peerId: remotePeer,
|
peerId: remotePeer,
|
||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: remotePeerStore,
|
peerStore: remotePeerStore,
|
||||||
multiaddrs: []
|
multiaddrs: [],
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -246,7 +253,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: localPeerStore,
|
peerStore: localPeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -259,7 +267,8 @@ describe('Identify', () => {
|
|||||||
connectionManager,
|
connectionManager,
|
||||||
peerStore: remotePeerStore,
|
peerStore: remotePeerStore,
|
||||||
multiaddrs: [],
|
multiaddrs: [],
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -316,7 +325,8 @@ describe('Identify', () => {
|
|||||||
connectionManager: new EventEmitter(),
|
connectionManager: new EventEmitter(),
|
||||||
peerStore: localPeerStore,
|
peerStore: localPeerStore,
|
||||||
multiaddrs: listenMaddrs,
|
multiaddrs: listenMaddrs,
|
||||||
isStarted: () => true
|
isStarted: () => true,
|
||||||
|
_options: { host: {} }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -6,7 +6,6 @@ chai.use(require('chai-bytes'))
|
|||||||
const uint8arrayFromString = require('uint8arrays/from-string')
|
const uint8arrayFromString = require('uint8arrays/from-string')
|
||||||
const uint8arrayEquals = require('uint8arrays/equals')
|
const uint8arrayEquals = require('uint8arrays/equals')
|
||||||
const Envelope = require('../../src/record/envelope')
|
const Envelope = require('../../src/record/envelope')
|
||||||
const Record = require('libp2p-interfaces/src/record')
|
|
||||||
const { codes: ErrorCodes } = require('../../src/errors')
|
const { codes: ErrorCodes } = require('../../src/errors')
|
||||||
|
|
||||||
const peerUtils = require('../utils/creators/peer')
|
const peerUtils = require('../utils/creators/peer')
|
||||||
@ -14,9 +13,10 @@ const peerUtils = require('../utils/creators/peer')
|
|||||||
const domain = 'libp2p-testing'
|
const domain = 'libp2p-testing'
|
||||||
const codec = uint8arrayFromString('/libp2p/testdata')
|
const codec = uint8arrayFromString('/libp2p/testdata')
|
||||||
|
|
||||||
class TestRecord extends Record {
|
class TestRecord {
|
||||||
constructor (data) {
|
constructor (data) {
|
||||||
super(domain, codec)
|
this.domain = domain
|
||||||
|
this.codec = codec
|
||||||
this.data = data
|
this.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@ describe('Transport Manager (TCP)', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('should be able to listen', async () => {
|
it('should be able to listen', async () => {
|
||||||
sinon.spy(tm, '_createSelfPeerRecord')
|
|
||||||
|
|
||||||
tm.add(Transport.prototype[Symbol.toStringTag], Transport, { listenerOptions: { listen: 'carefully' } })
|
tm.add(Transport.prototype[Symbol.toStringTag], Transport, { listenerOptions: { listen: 'carefully' } })
|
||||||
const transport = tm._transports.get(Transport.prototype[Symbol.toStringTag])
|
const transport = tm._transports.get(Transport.prototype[Symbol.toStringTag])
|
||||||
const spyListener = sinon.spy(transport, 'createListener')
|
const spyListener = sinon.spy(transport, 'createListener')
|
||||||
|
@ -56,28 +56,6 @@ describe('Upgrader', () => {
|
|||||||
sinon.restore()
|
sinon.restore()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should ignore a missing remote peer id', async () => {
|
|
||||||
const { inbound, outbound } = mockMultiaddrConnPair({ addrs, remotePeer })
|
|
||||||
|
|
||||||
const muxers = new Map([[Muxer.multicodec, Muxer]])
|
|
||||||
sinon.stub(localUpgrader, 'muxers').value(muxers)
|
|
||||||
sinon.stub(remoteUpgrader, 'muxers').value(muxers)
|
|
||||||
|
|
||||||
const cryptos = new Map([[Crypto.protocol, Crypto]])
|
|
||||||
sinon.stub(localUpgrader, 'cryptos').value(cryptos)
|
|
||||||
sinon.stub(remoteUpgrader, 'cryptos').value(cryptos)
|
|
||||||
|
|
||||||
// Remove the peer id from the remote address
|
|
||||||
outbound.remoteAddr = outbound.remoteAddr.decapsulateCode(421)
|
|
||||||
|
|
||||||
const connections = await Promise.all([
|
|
||||||
localUpgrader.upgradeOutbound(outbound),
|
|
||||||
remoteUpgrader.upgradeInbound(inbound)
|
|
||||||
])
|
|
||||||
|
|
||||||
expect(connections).to.have.length(2)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should upgrade with valid muxers and crypto', async () => {
|
it('should upgrade with valid muxers and crypto', async () => {
|
||||||
const { inbound, outbound } = mockMultiaddrConnPair({ addrs, remotePeer })
|
const { inbound, outbound } = mockMultiaddrConnPair({ addrs, remotePeer })
|
||||||
|
|
||||||
|
9
tsconfig.json
Normal file
9
tsconfig.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "./node_modules/aegir/src/config/tsconfig.aegir.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src"
|
||||||
|
]
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user