chore: add typedefs

This commit is contained in:
Vasco Santos 2020-11-16 11:56:18 +01:00
parent dfcce961bd
commit 26c40c8dfd
30 changed files with 385 additions and 186 deletions

View File

@ -7,17 +7,19 @@ log.error = debug('libp2p:addresses:error')
const multiaddr = require('multiaddr') const multiaddr = require('multiaddr')
/** /**
* Responsible for managing the peer addresses. * @typedef {Object} AddressManagerOptions
* Peers can specify their listen and announce addresses. * @property {Array<string>} [listen = []] - list of multiaddrs string representation to listen.
* The listen addresses will be used by the libp2p transports to listen for new connections, * @property {Array<string>} [announce = []] - list of multiaddrs string representation to announce.
* while the announce addresses will be used for the peer addresses' to other peers in the network.
*/ */
class AddressManager { class AddressManager {
/** /**
* Responsible for managing the peer addresses.
* Peers can specify their listen and announce addresses.
* 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.
*
* @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 {Array<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 {Array<multiaddr>}
*/ */
getAnnounceAddrs () { getAnnounceAddrs () {
return Array.from(this.announce).map((a) => multiaddr(a)) return Array.from(this.announce).map((a) => multiaddr(a))

View File

@ -19,14 +19,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

View File

@ -17,6 +17,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.

View File

@ -31,29 +31,40 @@ 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.
*/
/**
* @extends {EventEmitter}
* *
* @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, Array<Connection>>}
*/ */
this.connections = new Map() this.connections = new Map()

View File

@ -6,7 +6,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 +17,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 +30,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 +45,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 +96,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()

View File

@ -4,13 +4,16 @@
* 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')
/** /**
* Listen to page visibility change events (i.e. when the page is focused / blurred) by an event emitter. * Listen to page visibility change events (i.e. when the page is focused / blurred) by an event emitter.
* *
* @extends {EventEmitter}
*
* Warning: This does not work on all browsers, but should work on all modern browsers * Warning: This does not work on all browsers, but should work on all modern browsers
* *
* @example * @example
@ -29,12 +32,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 +122,5 @@ module.exports = class VisibilityChangeEmitter extends EventEmitter {
this.emit('visibilityChange', visible) this.emit('visibilityChange', visible)
} }
} }
module.exports = VisibilityChangeEmitter

View File

@ -6,6 +6,11 @@ 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')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr')} multiaddr
*/
module.exports = (node) => { module.exports = (node) => {
const routers = node._modules.contentRouting || [] const routers = node._modules.contentRouting || []
const dht = node._dht const dht = node._dht
@ -24,7 +29,7 @@ module.exports = (node) => {
* @param {object} [options] * @param {object} [options]
* @param {number} [options.timeout] - How long the query should run * @param {number} [options.timeout] - How long the query should run
* @param {number} [options.maxNumProviders] - maximum number of providers to find * @param {number} [options.maxNumProviders] - maximum number of providers to find
* @returns {AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>} * @returns {AsyncIterable<{ id: PeerId, multiaddrs: Array<multiaddr> }>}
*/ */
async * findProviders (key, options) { async * findProviders (key, options) {
if (!routers.length) { if (!routers.length) {

View File

@ -9,6 +9,16 @@ log.error = debug('libp2p:dialer:request:error')
const FIFO = require('p-fifo') const FIFO = require('p-fifo')
const pAny = require('p-any') const pAny = require('p-any')
/**
* @typedef {import('./')} Dialer
*/
/**
* @typedef {Object} DialRequestOptions
* @property {Multiaddr[]} addrs
* @property {function(Multiaddr):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 +27,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,8 +42,8 @@ class DialRequest {
/** /**
* @async * @async
* @param {object} options * @param {object} [options]
* @param {AbortSignal} options.signal - An AbortController signal * @param {AbortSignal} [options.signal] - An AbortController signal
* @returns {Connection} * @returns {Connection}
*/ */
async run (options) { async run (options) {

View File

@ -19,17 +19,40 @@ const {
MAX_PER_PEER_DIALS MAX_PER_PEER_DIALS
} = require('../constants') } = require('../constants')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('../peer-store')} PeerStore
* @typedef {import('../transport-manager')} TransportManager
* @typedef {import('./dial-request')} DialRequest
*/
/**
* @typedef {Object} DialerProperties
* @property {PeerStore} peerStore
* @property {TransportManager} transportManager
*
* @typedef {Object} DialerOptions
* @param {(addresses: Array<Address) => Array<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 {Object} [resolvers = {}] - multiaddr resolvers to use when dialing
*
* @typedef DialTarget
* @property {string} id
* @property {Array<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,
@ -73,7 +96,7 @@ class Dialer {
* The dial to the first address that is successfully able to upgrade a connection * The dial to the first address that is successfully able to upgrade a connection
* will be used. * will be used.
* *
* @param {PeerId|Multiaddr|string} peer - The peer to dial * @param {PeerId|multiaddr|string} peer - The peer to dial
* @param {object} [options] * @param {object} [options]
* @param {AbortSignal} [options.signal] - An AbortController signal * @param {AbortSignal} [options.signal] - An AbortController signal
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
@ -102,19 +125,13 @@ 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.
* If a multiaddr is received it should be the first address attempted. * If a multiaddr is received it should be the first address attempted.
* *
* @private * @private
* @param {PeerId|Multiaddr|string} peer - A PeerId or Multiaddr * @param {PeerId|multiaddr|string} peer - A PeerId or Multiaddr
* @returns {Promise<DialTarget>} * @returns {Promise<DialTarget>}
*/ */
async _createDialTarget (peer) { async _createDialTarget (peer) {
@ -145,14 +162,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
* *
@ -210,8 +219,8 @@ class Dialer {
/** /**
* Resolve multiaddr recursively. * Resolve multiaddr recursively.
* *
* @param {Multiaddr} ma * @param {multiaddr} ma
* @returns {Promise<Array<Multiaddr>>} * @returns {Promise<Array<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
@ -239,8 +248,8 @@ class Dialer {
/** /**
* 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<Array<multiaddr>>}
*/ */
async _resolveRecord (ma) { async _resolveRecord (ma) {
try { try {

View File

@ -6,12 +6,17 @@ const errCode = require('err-code')
const { codes } = require('./errors') const { codes } = require('./errors')
/**
* @typedef {import('peer-id')} PeerId
* @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: Array<multiaddr> }}
*/ */
function getPeer (peer) { function getPeer (peer) {
if (typeof peer === 'string') { if (typeof peer === 'string') {

View File

@ -29,49 +29,23 @@ const {
const { codes } = require('../errors') const { codes } = require('../errors')
/**
* @typedef {import('../')} Libp2p
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('../').DuplexIterable} DuplexIterable
*/
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 {Libp2p} 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)
@ -228,9 +202,9 @@ class IdentifyService {
/** /**
* A handler to register with Libp2p to process identify messages. * A handler to register with Libp2p to process identify messages.
* *
* @param {object} options * @param {Object} options
* @param {string} options.protocol * @param {string} options.protocol
* @param {*} options.stream * @param {DuplexIterable} options.stream
* @param {Connection} options.connection * @param {Connection} options.connection
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
@ -250,8 +224,8 @@ 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 {DuplexIterable} options.stream
* @param {Connection} options.connection * @param {Connection} options.connection
*/ */
async _handleIdentify ({ connection, stream }) { async _handleIdentify ({ connection, stream }) {
@ -290,7 +264,7 @@ class IdentifyService {
* *
* @private * @private
* @param {object} options * @param {object} options
* @param {*} options.stream * @param {DuplexIterable} options.stream
* @param {Connection} options.connection * @param {Connection} options.connection
*/ */
async _handlePush ({ connection, stream }) { async _handlePush ({ connection, stream }) {
@ -331,6 +305,23 @@ 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 module.exports.IdentifyService = IdentifyService

View File

@ -35,16 +35,55 @@ const {
} = require('./identify') } = require('./identify')
/** /**
* @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 {Object} [pubsub] pubsub module options
* @property {RelayOptions} [relay]
* @property {Object} [transport] transport options indexed by transport key
*
* @typedef {Object} Libp2pOptions
* @property {Array<Object>} 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
*
* @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 {
/**
* 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
@ -592,11 +631,16 @@ class Libp2p extends EventEmitter {
} }
} }
/**
* @typedef {Object} CreateOptions
* @property {PeerId} peerId
*/
/** /**
* Like `new Libp2p(options)` except it will create a `PeerId` * Like `new Libp2p(options)` except it will create a `PeerId`
* instance if one is not provided in options. * instance if one is not provided in options.
* *
* @param {object} options - Libp2p configuration options * @param {Libp2pOptions & CreateOptions} [options] - Libp2p configuration options
* @returns {Libp2p} * @returns {Libp2p}
*/ */
Libp2p.create = async function create (options = {}) { Libp2p.create = async function create (options = {}) {
@ -610,4 +654,10 @@ Libp2p.create = async function create (options = {}) {
return new Libp2p(options) return new Libp2p(options)
} }
/**
* @typedef {Object} DuplexIterable
* @property {(source: AsyncIterator<*>) => Promise} sink
* @property {AsyncIterator<*>} source
*/
module.exports = Libp2p module.exports = Libp2p

View File

@ -16,6 +16,17 @@ function lpEncodeExchange (exchange) {
return lp.encode.single(pb) return lp.encode.single(pb)
} }
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
*/
/**
* 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)

View File

@ -17,15 +17,21 @@ const directionToEvent = {
out: 'dataSent' out: 'dataSent'
} }
/**
* @typedef MetricsProperties
* @property {ConnectionManager} connectionManager
*
* @typedef MetricsOptions
* @property {number} [computeThrottleMaxQueueSize = defaultOptions.computeThrottleMaxQueueSize]
* @property {number} [computeThrottleTimeout = defaultOptions.computeThrottleTimeout]
* @property {Array<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)

View File

@ -12,6 +12,11 @@ const {
clearDelayedInterval clearDelayedInterval
} = require('set-delayed-interval') } = require('set-delayed-interval')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr')} Multiaddr
*/
/** /**
* Responsible for managing the usage of the available Peer Routing modules. * Responsible for managing the usage of the available Peer Routing modules.
*/ */

View File

@ -17,35 +17,36 @@ const {
const Envelope = require('../record/envelope') const Envelope = require('../record/envelope')
/** /**
* The AddressBook is responsible for keeping the known multiaddrs * Address object
* of a peer. *
* @typedef {Object} Address
* @property {multiaddr} multiaddr peer multiaddr.
* @property {boolean} isCertified obtained from a signed peer record.
*/
/**
* CertifiedRecord object
*
* @typedef {Object} CertifiedRecord
* @property {Uint8Array} raw raw envelope.
* @property {number} seqNumber seq counter.
*/
/**
* Entry object for the addressBook
*
* @typedef {Object} Entry
* @property {Array<Address>} addresses peer Addresses.
* @property {CertifiedRecord} record certified peer record.
*/
/**
* @extends {Book}
*/ */
class AddressBook extends Book { class AddressBook extends Book {
/** /**
* Address object * The AddressBook is responsible for keeping the known multiaddrs of a peer.
* *
* @typedef {Object} Address
* @property {Multiaddr} multiaddr peer multiaddr.
* @property {boolean} isCertified obtained from a signed peer record.
*/
/**
* CertifiedRecord object
*
* @typedef {Object} CertifiedRecord
* @property {Uint8Array} raw raw envelope.
* @property {number} seqNumber seq counter.
*/
/**
* Entry object for the addressBook
*
* @typedef {Object} Entry
* @property {Array<Address>} addresses peer Addresses.
* @property {CertifiedRecord} record certified peer record.
*/
/**
* @class * @class
* @param {PeerStore} peerStore * @param {PeerStore} peerStore
*/ */
@ -171,7 +172,7 @@ class AddressBook extends Book {
* *
* @override * @override
* @param {PeerId} peerId * @param {PeerId} peerId
* @param {Array<Multiaddr>} multiaddrs * @param {Array<multiaddr>} multiaddrs
* @returns {AddressBook} * @returns {AddressBook}
*/ */
set (peerId, multiaddrs) { set (peerId, multiaddrs) {
@ -221,7 +222,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 {Array<multiaddr>} multiaddrs
* @returns {AddressBook} * @returns {AddressBook}
*/ */
add (peerId, multiaddrs) { add (peerId, multiaddrs) {
@ -286,7 +287,7 @@ class AddressBook extends Book {
* Transforms received multiaddrs into Address. * Transforms received multiaddrs into Address.
* *
* @private * @private
* @param {Array<Multiaddr>} multiaddrs * @param {Array<multiaddr>} multiaddrs
* @param {boolean} [isCertified] * @param {boolean} [isCertified]
* @returns {Array<Address>} * @returns {Array<Address>}
*/ */

View File

@ -9,17 +9,16 @@ const {
const passthrough = data => data const passthrough = data => data
/**
* The Book is the skeleton for the PeerStore books.
*/
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: *) => Array<*>} [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 +29,7 @@ class Book {
/** /**
* Map known peers to their data. * Map known peers to their data.
* *
* @type {Map<string, Array<Data>} * @type {Map<string, Array<*>}
*/ */
this.data = new Map() this.data = new Map()
} }

View File

@ -18,7 +18,7 @@ const {
} = require('../errors') } = require('../errors')
/** /**
* Responsible for managing known peers, as well as their addresses, protocols and metadata. * @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.
@ -38,6 +38,8 @@ class PeerStore extends EventEmitter {
*/ */
/** /**
* 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

View File

@ -14,10 +14,12 @@ const {
} = require('../errors') } = require('../errors')
/** /**
* The KeyBook is responsible for keeping the known public keys of a peer. * @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
*/ */

View File

@ -15,13 +15,15 @@ const {
} = require('../errors') } = require('../errors')
/** /**
* The MetadataBook is responsible for keeping the known supported * @extends {Book}
* protocols of a peer.
* *
* @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
*/ */

View File

@ -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 {Datastore} 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 })

View File

@ -14,13 +14,15 @@ const {
} = require('../errors') } = require('../errors')
/** /**
* The ProtoBook is responsible for keeping the known supported * @extends {Book}
* protocols of a peer.
* *
* @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
*/ */

View File

@ -12,6 +12,12 @@ const { collect, take } = require('streaming-iterables')
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.
* *

View File

@ -20,11 +20,15 @@ const log = debug('libp2p:pnet')
log.error = debug('libp2p:pnet:err') log.error = debug('libp2p:pnet:err')
/** /**
* Takes a Private Shared Key (psk) and provides a `protect` method * @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* for wrapping existing connections in a private encryption stream * @typedef {import('../').DuplexIterable} DuplexIterable
*/ */
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
*/ */
@ -40,7 +44,7 @@ class Protector {
* created with. * created with.
* *
* @param {Connection} connection - The connection to protect * @param {Connection} connection - The connection to protect
* @returns {*} A protected duplex iterable * @returns {DuplexIterable} A protected duplex iterable
*/ */
async protect (connection) { async protect (connection) {
if (!connection) { if (!connection) {

View File

@ -15,11 +15,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('peer-id')} PeerId
* 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

View File

@ -12,13 +12,20 @@ const {
} = require('./consts') } = require('./consts')
/** /**
* The PeerRecord is used for distributing peer routing records across the network. * @typedef {import('peer-id')} PeerId
* It contains the peer's reachable listen addresses. * @typedef {import('multiaddr')} multiaddr
*/
/**
* @extends {Record}
*/ */
class PeerRecord extends Record { class PeerRecord extends Record {
/** /**
* The PeerRecord is used for distributing peer routing records across the network.
* It contains the peer's reachable listen addresses.
*
* @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 {Array<multiaddr>} params.multiaddrs - addresses of the associated peer.
* @param {number} [params.seqNumber] - monotonically-increasing sequence counter that's used to order PeerRecords in time. * @param {number} [params.seqNumber] - monotonically-increasing sequence counter that's used to order PeerRecords in time.

View File

@ -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) {

View File

@ -10,6 +10,14 @@ const {
} = 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 +25,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 }) {

View File

@ -9,13 +9,22 @@ 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 {Object} TransportManagerProperties
* @property {import('./')} libp2p
* @property {import('./upgrader')} upgrader
*
* @typedef {Object} TransportManagerOptions
* @property {boolean} [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
@ -81,7 +90,7 @@ class TransportManager {
/** /**
* Dials the given Multiaddr over it's supported transport * Dials the given Multiaddr over it's supported transport
* *
* @param {Multiaddr} ma * @param {multiaddr} ma
* @param {*} options * @param {*} options
* @returns {Promise<Connection>} * @returns {Promise<Connection>}
*/ */
@ -102,7 +111,7 @@ class TransportManager {
/** /**
* Returns all Multiaddr's the listeners are using * Returns all Multiaddr's the listeners are using
* *
* @returns {Multiaddr[]} * @returns {Array<multiaddr>}
*/ */
getAddrs () { getAddrs () {
let addrs = [] let addrs = []
@ -126,7 +135,7 @@ class TransportManager {
/** /**
* Finds a transport that matches the given Multiaddr * Finds a transport that matches the given Multiaddr
* *
* @param {Multiaddr} ma * @param {multiaddr} ma
* @returns {Transport|null} * @returns {Transport|null}
*/ */
transportForMultiaddr (ma) { transportForMultiaddr (ma) {
@ -141,7 +150,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 {Array<multiaddr>} addrs - addresses to attempt to listen on
*/ */
async listen (addrs) { async listen (addrs) {
if (!addrs || addrs.length === 0) { if (!addrs || addrs.length === 0) {

View File

@ -13,6 +13,10 @@ const mutableProxy = require('mutable-proxy')
const { codes } = require('./errors') const { codes } = require('./errors')
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
*/
/** /**
* @typedef MultiaddrConnection * @typedef MultiaddrConnection
* @property {Function} sink * @property {Function} sink