mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-31 08:22:05 +00:00
feat: custom dialer addr sorter (#792)
* feat: custom dialer addr sorter * chore: use libp2p utils sorter via addressBook getMultiaddrsForPeer * chore: use new libp2p utils * chore: apply suggestions from code review Co-authored-by: Jacob Heun <jacobheun@gmail.com> Co-authored-by: Jacob Heun <jacobheun@gmail.com>
This commit is contained in:
committed by
Vasco Santos
parent
e50c6abcf2
commit
585ad52b4c
@@ -4,8 +4,6 @@ const debug = require('debug')
|
||||
const log = debug('libp2p:auto-relay')
|
||||
log.error = debug('libp2p:auto-relay:error')
|
||||
|
||||
const isPrivate = require('libp2p-utils/src/multiaddr/is-private')
|
||||
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
const multiaddr = require('multiaddr')
|
||||
@@ -36,6 +34,7 @@ class AutoRelay {
|
||||
this._peerStore = libp2p.peerStore
|
||||
this._connectionManager = libp2p.connectionManager
|
||||
this._transportManager = libp2p.transportManager
|
||||
this._addressSorter = libp2p.dialer.addressSorter
|
||||
|
||||
this.maxListeners = maxListeners
|
||||
|
||||
@@ -129,37 +128,19 @@ class AutoRelay {
|
||||
return
|
||||
}
|
||||
|
||||
// Create relay listen addr
|
||||
let listenAddr, remoteMultiaddr, remoteAddrs
|
||||
// Get peer known addresses and sort them per public addresses first
|
||||
const remoteAddrs = this._peerStore.addressBook.getMultiaddrsForPeer(
|
||||
connection.remotePeer, this._addressSorter
|
||||
)
|
||||
|
||||
try {
|
||||
// Get peer known addresses and sort them per public addresses first
|
||||
remoteAddrs = this._peerStore.addressBook.get(connection.remotePeer)
|
||||
// TODO: This sort should be customizable in the config (dialer addr sort)
|
||||
remoteAddrs.sort(multiaddrsCompareFunction)
|
||||
|
||||
remoteMultiaddr = remoteAddrs.find(a => a.isCertified).multiaddr // Get first announced address certified
|
||||
// TODO: HOP Relays should avoid advertising private addresses!
|
||||
} catch (_) {
|
||||
log.error(`${id} does not have announced certified multiaddrs`)
|
||||
|
||||
// Attempt first if existing
|
||||
if (!remoteAddrs || !remoteAddrs.length) {
|
||||
return
|
||||
}
|
||||
|
||||
remoteMultiaddr = remoteAddrs[0].multiaddr
|
||||
if (!remoteAddrs || !remoteAddrs.length) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!remoteMultiaddr.protoNames().includes('p2p')) {
|
||||
listenAddr = `${remoteMultiaddr.toString()}/p2p/${connection.remotePeer.toB58String()}/p2p-circuit`
|
||||
} else {
|
||||
listenAddr = `${remoteMultiaddr.toString()}/p2p-circuit`
|
||||
}
|
||||
|
||||
// Attempt to listen on relay
|
||||
const listenAddr = `${remoteAddrs[0].toString()}/p2p-circuit`
|
||||
this._listenRelays.add(id)
|
||||
|
||||
// Attempt to listen on relay
|
||||
try {
|
||||
await this._transportManager.listen([multiaddr(listenAddr)])
|
||||
// Announce multiaddrs will update on listen success by TransportManager event being triggered
|
||||
@@ -269,24 +250,4 @@ class AutoRelay {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare function for array.sort().
|
||||
* This sort aims to move the private adresses to the end of the array.
|
||||
*
|
||||
* @param {Address} a
|
||||
* @param {Address} b
|
||||
* @returns {number}
|
||||
*/
|
||||
function multiaddrsCompareFunction (a, b) {
|
||||
const isAPrivate = isPrivate(a.multiaddr)
|
||||
const isBPrivate = isPrivate(b.multiaddr)
|
||||
|
||||
if (isAPrivate && !isBPrivate) {
|
||||
return 1
|
||||
} else if (!isAPrivate && isBPrivate) {
|
||||
return -1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
module.exports = AutoRelay
|
||||
|
@@ -7,6 +7,7 @@ const Constants = require('./constants')
|
||||
const { AGENT_VERSION } = require('./identify/consts')
|
||||
const RelayConstants = require('./circuit/constants')
|
||||
|
||||
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
||||
const { FaultTolerance } = require('./transport-manager')
|
||||
|
||||
const DefaultConfig = {
|
||||
@@ -27,7 +28,8 @@ const DefaultConfig = {
|
||||
dialTimeout: Constants.DIAL_TIMEOUT,
|
||||
resolvers: {
|
||||
dnsaddr: dnsaddrResolver
|
||||
}
|
||||
},
|
||||
addressSorter: publicAddressesFirst
|
||||
},
|
||||
host: {
|
||||
agentVersion: AGENT_VERSION
|
||||
|
@@ -9,6 +9,7 @@ const log = debug('libp2p:dialer')
|
||||
log.error = debug('libp2p:dialer:error')
|
||||
|
||||
const { DialRequest } = require('./dial-request')
|
||||
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
|
||||
const getPeer = require('../get-peer')
|
||||
|
||||
const { codes } = require('../errors')
|
||||
@@ -24,6 +25,7 @@ class Dialer {
|
||||
* @param {object} 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.
|
||||
@@ -32,6 +34,7 @@ class Dialer {
|
||||
constructor ({
|
||||
transportManager,
|
||||
peerStore,
|
||||
addressSorter = publicAddressesFirst,
|
||||
concurrency = MAX_PARALLEL_DIALS,
|
||||
timeout = DIAL_TIMEOUT,
|
||||
perPeerLimit = MAX_PER_PEER_DIALS,
|
||||
@@ -39,6 +42,7 @@ class Dialer {
|
||||
}) {
|
||||
this.transportManager = transportManager
|
||||
this.peerStore = peerStore
|
||||
this.addressSorter = addressSorter
|
||||
this.concurrency = concurrency
|
||||
this.timeout = timeout
|
||||
this.perPeerLimit = perPeerLimit
|
||||
@@ -120,7 +124,7 @@ class Dialer {
|
||||
this.peerStore.addressBook.add(id, multiaddrs)
|
||||
}
|
||||
|
||||
let knownAddrs = this.peerStore.addressBook.getMultiaddrsForPeer(id) || []
|
||||
let knownAddrs = this.peerStore.addressBook.getMultiaddrsForPeer(id, this.addressSorter) || []
|
||||
|
||||
// If received a multiaddr to dial, it should be the first to use
|
||||
// But, if we know other multiaddrs for the peer, we should try them too.
|
||||
|
@@ -136,7 +136,8 @@ class Libp2p extends EventEmitter {
|
||||
concurrency: this._options.dialer.maxParallelDials,
|
||||
perPeerLimit: this._options.dialer.maxDialsPerPeer,
|
||||
timeout: this._options.dialer.dialTimeout,
|
||||
resolvers: this._options.dialer.resolvers
|
||||
resolvers: this._options.dialer.resolvers,
|
||||
addressSorter: this._options.dialer.addressSorter
|
||||
})
|
||||
|
||||
this._modules.transport.forEach((Transport) => {
|
||||
|
@@ -319,20 +319,22 @@ class AddressBook extends Book {
|
||||
* Returns `undefined` if there are no known multiaddrs for the given peer.
|
||||
*
|
||||
* @param {PeerId} peerId
|
||||
* @param {(addresses: Array<Address) => Array<Address>} [addressSorter]
|
||||
* @returns {Array<Multiaddr>|undefined}
|
||||
*/
|
||||
getMultiaddrsForPeer (peerId) {
|
||||
getMultiaddrsForPeer (peerId, addressSorter = (ms) => ms) {
|
||||
if (!PeerId.isPeerId(peerId)) {
|
||||
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
|
||||
}
|
||||
|
||||
const entry = this.data.get(peerId.toB58String())
|
||||
|
||||
if (!entry || !entry.addresses) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
return entry.addresses.map((address) => {
|
||||
return addressSorter(
|
||||
entry.addresses || []
|
||||
).map((address) => {
|
||||
const multiaddr = address.multiaddr
|
||||
|
||||
const idString = multiaddr.getPeerId()
|
||||
|
Reference in New Issue
Block a user