2019-11-06 15:11:13 +01:00
|
|
|
'use strict'
|
|
|
|
|
2020-02-14 13:42:23 +00:00
|
|
|
const errcode = require('err-code')
|
2019-11-06 15:11:13 +01:00
|
|
|
const debug = require('debug')
|
|
|
|
const log = debug('libp2p:peer-store')
|
|
|
|
log.error = debug('libp2p:peer-store:error')
|
|
|
|
|
|
|
|
const { EventEmitter } = require('events')
|
|
|
|
|
2019-12-02 18:13:14 +01:00
|
|
|
const PeerId = require('peer-id')
|
2019-11-06 15:11:13 +01:00
|
|
|
const PeerInfo = require('peer-info')
|
2020-04-09 16:07:18 +02:00
|
|
|
|
|
|
|
const AddressBook = require('./address-book')
|
|
|
|
const ProtoBook = require('./proto-book')
|
|
|
|
|
2020-02-14 13:42:23 +00:00
|
|
|
const {
|
|
|
|
ERR_INVALID_PARAMETERS
|
|
|
|
} = require('../errors')
|
2019-11-06 15:11:13 +01:00
|
|
|
|
|
|
|
/**
|
2020-04-09 16:07:18 +02:00
|
|
|
* Responsible for managing known peers, as well as their addresses, protocols and metadata.
|
|
|
|
* @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:multiaddrs Emitted when a known peer has a different set of multiaddrs.
|
2019-11-06 15:11:13 +01:00
|
|
|
*/
|
|
|
|
class PeerStore extends EventEmitter {
|
2020-04-09 16:07:18 +02:00
|
|
|
/**
|
|
|
|
* PeerInfo object
|
|
|
|
* @typedef {Object} peerInfo
|
|
|
|
* @property {Array<multiaddrInfo>} multiaddrsInfos peer's information of the multiaddrs.
|
|
|
|
* @property {Array<string>} protocols peer's supported protocols.
|
|
|
|
*/
|
|
|
|
|
2019-11-06 15:11:13 +01:00
|
|
|
constructor () {
|
|
|
|
super()
|
|
|
|
|
|
|
|
/**
|
2020-04-09 16:07:18 +02:00
|
|
|
* AddressBook containing a map of peerIdStr to multiaddrsInfo
|
2019-11-06 15:11:13 +01:00
|
|
|
*/
|
2020-04-09 16:07:18 +02:00
|
|
|
this.addressBook = new AddressBook(this)
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
/**
|
|
|
|
* ProtoBook containing a map of peerIdStr to supported protocols.
|
|
|
|
*/
|
|
|
|
this.protoBook = new ProtoBook(this)
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-11-06 15:11:13 +01:00
|
|
|
/**
|
2020-04-09 16:07:18 +02:00
|
|
|
* Stores the peerInfo of a new peer on each book.
|
2019-11-06 15:11:13 +01:00
|
|
|
* @param {PeerInfo} peerInfo
|
2019-12-15 17:33:16 +01:00
|
|
|
* @param {object} [options]
|
2020-04-09 16:07:18 +02:00
|
|
|
* @param {boolean} [options.replace = true]
|
2019-11-26 16:40:04 +01:00
|
|
|
* @return {PeerInfo}
|
2019-11-06 15:11:13 +01:00
|
|
|
*/
|
2020-04-09 16:07:18 +02:00
|
|
|
put (peerInfo, options) {
|
|
|
|
const multiaddrs = peerInfo.multiaddrs.toArray()
|
|
|
|
const protocols = Array.from(peerInfo.protocols || new Set())
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
this.addressBook.set(peerInfo.id, multiaddrs, options)
|
|
|
|
this.protoBook.set(peerInfo.id, protocols, options)
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
const peer = this.find(peerInfo.id)
|
|
|
|
const pInfo = new PeerInfo(peerInfo.id)
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
if (!peer) {
|
|
|
|
return pInfo
|
2020-02-14 13:42:23 +00:00
|
|
|
}
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
peer.protocols.forEach((p) => pInfo.protocols.add(p))
|
|
|
|
peer.multiaddrInfos.forEach((mi) => pInfo.multiaddrs.add(mi.multiaddr))
|
2019-11-06 15:11:13 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
return pInfo
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-11-06 15:11:13 +01:00
|
|
|
/**
|
2020-04-09 16:07:18 +02:00
|
|
|
* Get the info of the given id.
|
|
|
|
* @param {peerId} peerId
|
2019-11-06 15:11:13 +01:00
|
|
|
* @returns {PeerInfo}
|
|
|
|
*/
|
|
|
|
get (peerId) {
|
2020-04-09 16:07:18 +02:00
|
|
|
const peer = this.find(peerId)
|
2019-12-02 18:13:14 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
const pInfo = new PeerInfo(peerId)
|
|
|
|
peer.protocols.forEach((p) => pInfo.protocols.add(p))
|
|
|
|
peer.multiaddrInfos.forEach((mi) => pInfo.multiaddrs.add(mi.multiaddr))
|
|
|
|
|
|
|
|
return pInfo
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-11-26 16:40:04 +01:00
|
|
|
/**
|
|
|
|
* Has the info to the given id.
|
2020-04-09 16:07:18 +02:00
|
|
|
* @param {PeerId} peerId
|
2019-11-26 16:40:04 +01:00
|
|
|
* @returns {boolean}
|
|
|
|
*/
|
|
|
|
has (peerId) {
|
2020-04-09 16:07:18 +02:00
|
|
|
return Boolean(this.find(peerId))
|
2019-11-26 16:40:04 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-11-06 15:11:13 +01:00
|
|
|
/**
|
2020-04-09 16:07:18 +02:00
|
|
|
* Removes the peer provided.
|
|
|
|
* @param {PeerId} peerId
|
2019-11-06 15:11:13 +01:00
|
|
|
* @returns {boolean} true if found and removed
|
|
|
|
*/
|
|
|
|
remove (peerId) {
|
2020-04-09 16:07:18 +02:00
|
|
|
return this.delete(peerId)
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-11-06 15:11:13 +01:00
|
|
|
/**
|
|
|
|
* Completely replaces the existing peers metadata with the given `peerInfo`
|
|
|
|
* @param {PeerInfo} peerInfo
|
|
|
|
* @returns {void}
|
|
|
|
*/
|
|
|
|
replace (peerInfo) {
|
2020-04-09 16:07:18 +02:00
|
|
|
this.put(peerInfo)
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
2019-12-03 10:28:52 +01:00
|
|
|
|
2020-04-09 16:07:18 +02:00
|
|
|
// TODO: Temporary adapter for modules using PeerStore
|
|
|
|
// This should be removed under a breaking change
|
2019-12-03 10:28:52 +01:00
|
|
|
/**
|
2020-02-11 16:32:40 +01:00
|
|
|
* Returns the known multiaddrs for a given `PeerInfo`. All returned multiaddrs
|
|
|
|
* will include the encapsulated `PeerId` of the peer.
|
2020-04-09 16:07:18 +02:00
|
|
|
* @param {PeerInfo} peerInfo
|
2019-12-03 10:28:52 +01:00
|
|
|
* @returns {Array<Multiaddr>}
|
|
|
|
*/
|
2020-04-09 16:07:18 +02:00
|
|
|
multiaddrsForPeer (peerInfo) {
|
|
|
|
return this.addressBook.getMultiaddrsForPeer(peerInfo.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all the stored information of every peer.
|
|
|
|
* @returns {Map<string, peerInfo>}
|
|
|
|
*/
|
|
|
|
get peers () {
|
|
|
|
const peerInfos = new Map()
|
|
|
|
|
|
|
|
// AddressBook
|
|
|
|
for (const [idStr, multiaddrInfos] of this.addressBook.data.entries()) {
|
|
|
|
// TODO: Remove peerInfo and its usage on peer-info deprecate
|
|
|
|
const peerInfo = new PeerInfo(PeerId.createFromCID(idStr))
|
|
|
|
|
|
|
|
multiaddrInfos.forEach((mi) => peerInfo.multiaddrs.add((mi.multiaddr)))
|
|
|
|
|
|
|
|
const protocols = this.protoBook.data.get(idStr) || []
|
|
|
|
protocols.forEach((p) => peerInfo.protocols.add(p))
|
|
|
|
|
|
|
|
peerInfos.set(idStr, peerInfo)
|
|
|
|
// TODO
|
|
|
|
// peerInfos.set(idStr, {
|
|
|
|
// id: PeerId.createFromCID(idStr),
|
|
|
|
// multiaddrInfos,
|
|
|
|
// protocols: this.protoBook.data.get(idStr) || []
|
|
|
|
// })
|
|
|
|
}
|
|
|
|
|
|
|
|
// ProtoBook
|
|
|
|
for (const [idStr, protocols] of this.protoBook.data.entries()) {
|
|
|
|
// TODO: Remove peerInfo and its usage on peer-info deprecate
|
|
|
|
const peerInfo = peerInfos.get(idStr)
|
|
|
|
|
|
|
|
if (!peerInfo) {
|
|
|
|
const peerInfo = new PeerInfo(PeerId.createFromCID(idStr))
|
|
|
|
|
|
|
|
protocols.forEach((p) => peerInfo.protocols.add(p))
|
|
|
|
peerInfos.set(idStr, peerInfo)
|
|
|
|
// peerInfos.set(idStr, {
|
|
|
|
// id: PeerId.createFromCID(idStr),
|
|
|
|
// multiaddrInfos: [],
|
|
|
|
// protocols: protocols
|
|
|
|
// })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return peerInfos
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Delete the information of the given peer in every book.
|
|
|
|
* @param {PeerId} peerId
|
|
|
|
* @returns {boolean} true if found and removed
|
|
|
|
*/
|
|
|
|
delete (peerId) {
|
|
|
|
const addressesDeleted = this.addressBook.delete(peerId)
|
|
|
|
const protocolsDeleted = this.protoBook.delete(peerId)
|
|
|
|
return addressesDeleted || protocolsDeleted
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Find the stored information of a given peer.
|
|
|
|
* @param {PeerId} peerId
|
|
|
|
* @returns {peerInfo}
|
|
|
|
*/
|
|
|
|
find (peerId) {
|
|
|
|
if (!PeerId.isPeerId(peerId)) {
|
|
|
|
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
|
|
|
}
|
|
|
|
|
|
|
|
const multiaddrInfos = this.addressBook.get(peerId)
|
|
|
|
const protocols = this.protoBook.get(peerId)
|
|
|
|
|
|
|
|
if (!multiaddrInfos && !protocols) {
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
|
|
|
multiaddrInfos: multiaddrInfos || [],
|
|
|
|
protocols: protocols || []
|
|
|
|
}
|
2019-12-03 10:28:52 +01:00
|
|
|
}
|
2019-11-06 15:11:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = PeerStore
|